<p>It doesn't matter. The old version has a 64-bit nonce and 64-bit counter, while the new one replaces it with a 96-bit nonce and 32-bit counter. For our purposes however, they can reasonably both be thought of as a single 128-bit number that should just never repeat.</p>
<p>The ChaCha20 implementation in Bitcoin Core is used as basis for the random number generator, and not (yet) as a stream cypher for encryption, where the nonce/IV and block counter are used for somewhat distinct purposes.</p>
<p>In the RNG, the 256-bit key is randomly generated (using OS and system randomness), and the nonce and counter are both just set to 0. The block counter then increments every time 64 bytes are generated. If we'd switch to a 32-bit counter instead, we'd need to deal with the situation where the counter overflows, and most likely the way to do that would be to increment the nonce when that happens. And all of that is still exactly identical as just thinking of it as a 64-bit nonce and counter with incrementing non-overflowing counter instead.</p>

CC BY-SA 4.0
2021-09-14T18:19:57.757Z
2021-09-14T18:40:06.060Z
2021-09-14T18:40:06.060Z
Pieter Wuille
<p>The <a href="https://datatracker.ietf.org/doc/html/draft-agl-tls-chacha20poly1305-04#section-7" rel="nofollow noreferrer">draft of chacha20</a> uses a 64-bit nonce, but the <a href="https://datatracker.ietf.org/doc/html/rfc8439#section-2.3" rel="nofollow noreferrer">final version</a> of chacha20 specification uses a 96-bit nonce.</p>
<p>The <a href="https://github.com/bitcoin/bitcoin/pull/9792" rel="nofollow noreferrer">#9792 PR</a> adds chacha20 to Bitcoin Core. We can see the function <a href="https://github.com/bitcoin/bitcoin/commit/e04326fe6652543dc26d90eba4a48fbdc935fd0c#diff-99af15ec91b0a679121abec2572519c1d327d8d9a3db3e678f44f1a26003fa6cR62" rel="nofollow noreferrer"><code>ChaCha20::SetIV(uint64_t iv)</code></a> is using 64 bits for setting the nonce value. The <a href="https://github.com/bitcoin/bitcoin/commit/e04326fe6652543dc26d90eba4a48fbdc935fd0c#diff-99af15ec91b0a679121abec2572519c1d327d8d9a3db3e678f44f1a26003fa6cR6" rel="nofollow noreferrer"><code>chacha20.cpp</code></a> mentions that it follows the chacha20 implementation from <a href="https://cr.yp.to/streamciphers/timings/estreambench/submissions/salsa20/chacha8/merged/chacha.c" rel="nofollow noreferrer">here</a>.</p>
<p>Is there any specific reason for bitcoin using a 64-bit nonce? Wouldn't it be better to use a 96-bit nonce as recommended?</p>

<bitcoin-core><bitcoin-core-development><cryptography><encryption><c++>
Why does the chacha20 implemented in the Bitcoin Core use a 64 bit nonce?
siv2r
# Why does the chacha20 implemented in the Bitcoin Core use a 64 bit nonce?

(Asked by: username_0 on 2021-09-14)

The [draft of chacha20](https://datatracker.ietf.org/doc/html/draft-agl-tls-chacha20poly1305-04#section-7) uses a 64-bit nonce, but the [final version](https://datatracker.ietf.org/doc/html/rfc8439#section-2.3) of chacha20 specification uses a 96-bit nonce.

The [#9792 PR](https://github.com/bitcoin/bitcoin/pull/9792) adds chacha20 to Bitcoin Core. We can see the function [`ChaCha20::SetIV(uint64_t iv)`](https://github.com/bitcoin/bitcoin/commit/e04326fe6652543dc26d90eba4a48fbdc935fd0c#diff-99af15ec91b0a679121abec2572519c1d327d8d9a3db3e678f44f1a26003fa6cR62) is using 64 bits for setting the nonce value. The [`chacha20.cpp`](https://github.com/bitcoin/bitcoin/commit/e04326fe6652543dc26d90eba4a48fbdc935fd0c#diff-99af15ec91b0a679121abec2572519c1d327d8d9a3db3e678f44f1a26003fa6cR6) mentions that it follows the chacha20 implementation from [here](https://cr.yp.to/streamciphers/timings/estreambench/submissions/salsa20/chacha8/merged/chacha.c).

Is there any specific reason for bitcoin using a 64-bit nonce? Wouldn't it be better to use a 96-bit nonce as recommended?

**Tags:** bitcoin-core, bitcoin-core-development, cryptography, encryption, c++


---

## 1 answers

### Answer by username_1 on 2021-09-14. Score: 3 | Accepted answer

It doesn't matter. The old version has a 64-bit nonce and 64-bit counter, while the new one replaces it with a 96-bit nonce and 32-bit counter. For our purposes however, they can reasonably both be thought of as a single 128-bit number that should just never repeat.

The ChaCha20 implementation in Bitcoin Core is used as basis for the random number generator, and not (yet) as a stream cypher for encryption, where the nonce/IV and block counter are used for somewhat distinct purposes.

In the RNG, the 256-bit key is randomly generated (using OS and system randomness), and the nonce and counter are both just set to 0. The block counter then increments every time 64 bytes are generated. If we'd switch to a 32-bit counter instead, we'd need to deal with the situation where the counter overflows, and most likely the way to do that would be to increment the nonce when that happens. And all of that is still exactly identical as just thinking of it as a 64-bit nonce and counter with incrementing non-overflowing counter instead.


---

