diff options
author | Pieter Wuille <pieter@wuille.net> | 2023-06-27 16:24:02 -0400 |
---|---|---|
committer | Pieter Wuille <pieter@wuille.net> | 2023-07-07 17:16:27 -0400 |
commit | 511a8d406e3115b97c6d35e2c603af53b3f9da13 (patch) | |
tree | ac07eef627e584972f4f24f2ef426a9234421cd7 /src/crypto/chacha20.h | |
parent | cf4da5ec29f9e8cd6cc6577e5ecbd87174edba62 (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.h | 37 |
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; } |