aboutsummaryrefslogtreecommitdiff
path: root/src/crypto/chacha20.h
diff options
context:
space:
mode:
authorPieter Wuille <pieter@wuille.net>2023-06-27 16:24:02 -0400
committerPieter Wuille <pieter@wuille.net>2023-07-07 17:16:27 -0400
commit511a8d406e3115b97c6d35e2c603af53b3f9da13 (patch)
treeac07eef627e584972f4f24f2ef426a9234421cd7 /src/crypto/chacha20.h
parentcf4da5ec29f9e8cd6cc6577e5ecbd87174edba62 (diff)
crypto: Implement RFC8439-compatible variant of ChaCha20
There are two variants of ChaCha20 in use. The original one uses a 64-bit nonce and a 64-bit block counter, while the one used in RFC8439 uses a 96-bit nonce and 32-bit block counter. This commit changes the interface to use the 96/32 split (but automatically incrementing the first 32-bit part of the nonce when the 32-bit block counter overflows, so to retain compatibility with >256 GiB output). Simultaneously, also merge the SetIV and Seek64 functions, as we almost always call both anyway. Co-authored-by: dhruv <856960+dhruv@users.noreply.github.com>
Diffstat (limited to 'src/crypto/chacha20.h')
-rw-r--r--src/crypto/chacha20.h37
1 files changed, 27 insertions, 10 deletions
diff --git a/src/crypto/chacha20.h b/src/crypto/chacha20.h
index b286ef59fe..f2ec21d82e 100644
--- a/src/crypto/chacha20.h
+++ b/src/crypto/chacha20.h
@@ -7,9 +7,15 @@
#include <cstdlib>
#include <stdint.h>
+#include <utility>
// classes for ChaCha20 256-bit stream cipher developed by Daniel J. Bernstein
-// https://cr.yp.to/chacha/chacha-20080128.pdf */
+// https://cr.yp.to/chacha/chacha-20080128.pdf.
+//
+// The 128-bit input is here implemented as a 96-bit nonce and a 32-bit block
+// counter, as in RFC8439 Section 2.3. When the 32-bit block counter overflows
+// the first 32-bit part of the nonce is automatically incremented, making it
+// conceptually compatible with variants that use a 64/64 split instead.
/** ChaCha20 cipher that only operates on multiples of 64 bytes. */
class ChaCha20Aligned
@@ -26,11 +32,22 @@ public:
/** set 32-byte key. */
void SetKey32(const unsigned char* key32);
- /** set the 64-bit nonce. */
- void SetIV(uint64_t iv);
+ /** Type for 96-bit nonces used by the Set function below.
+ *
+ * The first field corresponds to the LE32-encoded first 4 bytes of the nonce, also referred
+ * to as the '32-bit fixed-common part' in Example 2.8.2 of RFC8439.
+ *
+ * The second field corresponds to the LE64-encoded last 8 bytes of the nonce.
+ *
+ */
+ using Nonce96 = std::pair<uint32_t, uint64_t>;
- /** set the 64bit block counter (pos seeks to byte position 64*pos). */
- void Seek64(uint64_t pos);
+ /** Set the 96-bit nonce and 32-bit block counter.
+ *
+ * Block_counter selects a position to seek to (to byte 64*block_counter). After 256 GiB, the
+ * block counter overflows, and nonce.first is incremented.
+ */
+ void Seek64(Nonce96 nonce, uint32_t block_counter);
/** outputs the keystream of size <64*blocks> into <c> */
void Keystream64(unsigned char* c, size_t blocks);
@@ -62,13 +79,13 @@ public:
m_bufleft = 0;
}
- /** set the 64-bit nonce. */
- void SetIV(uint64_t iv) { m_aligned.SetIV(iv); }
+ /** 96-bit nonce type. */
+ using Nonce96 = ChaCha20Aligned::Nonce96;
- /** set the 64bit block counter (pos seeks to byte position 64*pos). */
- void Seek64(uint64_t pos)
+ /** Set the 96-bit nonce and 32-bit block counter. */
+ void Seek64(Nonce96 nonce, uint32_t block_counter)
{
- m_aligned.Seek64(pos);
+ m_aligned.Seek64(nonce, block_counter);
m_bufleft = 0;
}