Inside Bitcoin
Opening the selected file…
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2017-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#ifndef BITCOIN_CRYPTO_CHACHA20_H6#define BITCOIN_CRYPTO_CHACHA20_H8#include <array>9#include <cstddef>10#include <cstdint>11#include <span>12#include <utility>14// classes for ChaCha20 256-bit stream cipher developed by Daniel J. Bernstein15// https://cr.yp.to/chacha/chacha-20080128.pdf.16//17// The 128-bit input is here implemented as a 96-bit nonce and a 32-bit block18// counter, as in RFC8439 Section 2.3. When the 32-bit block counter overflows19// the first 32-bit part of the nonce is automatically incremented, making it20// conceptually compatible with variants that use a 64/64 split instead.22/** ChaCha20 cipher that only operates on multiples of 64 bytes. */23class ChaCha20Aligned24{25private:26uint32_t input[12];28public:29/** Expected key length in constructor and SetKey. */30static constexpr unsigned KEYLEN{32};32/** Block size (inputs/outputs to Keystream / Crypt should be multiples of this). */33static constexpr unsigned BLOCKLEN{64};35/** For safety, disallow initialization without key. */36ChaCha20Aligned() noexcept = delete;38/** Initialize a cipher with specified 32-byte key. */39ChaCha20Aligned(std::span<const std::byte> key) noexcept;41/** Destructor to clean up private memory. */42~ChaCha20Aligned();44/** Set 32-byte key, and seek to nonce 0 and block position 0. */45void SetKey(std::span<const std::byte> key) noexcept;47/** Type for 96-bit nonces used by the Set function below.48*49* The first field corresponds to the LE32-encoded first 4 bytes of the nonce, also referred50* to as the '32-bit fixed-common part' in Example 2.8.2 of RFC8439.51*52* The second field corresponds to the LE64-encoded last 8 bytes of the nonce.53*54*/55using Nonce96 = std::pair<uint32_t, uint64_t>;57/** Set the 96-bit nonce and 32-bit block counter.58*59* Block_counter selects a position to seek to (to byte BLOCKLEN*block_counter). After 256 GiB,60* the block counter overflows, and nonce.first is incremented.61*/62void Seek(Nonce96 nonce, uint32_t block_counter) noexcept;64/** outputs the keystream into out, whose length must be a multiple of BLOCKLEN. */65void Keystream(std::span<std::byte> out) noexcept;67/** en/deciphers the message <input> and write the result into <output>68*69* The size of input and output must be equal, and be a multiple of BLOCKLEN.70*/71void Crypt(std::span<const std::byte> input, std::span<std::byte> output) noexcept;72};74/** Unrestricted ChaCha20 cipher. */75class ChaCha2076{77private:78ChaCha20Aligned m_aligned;79std::array<std::byte, ChaCha20Aligned::BLOCKLEN> m_buffer;80unsigned m_bufleft{0};82public:83/** Expected key length in constructor and SetKey. */84static constexpr unsigned KEYLEN = ChaCha20Aligned::KEYLEN;86/** For safety, disallow initialization without key. */87ChaCha20() noexcept = delete;89/** Initialize a cipher with specified 32-byte key. */90ChaCha20(std::span<const std::byte> key) noexcept : m_aligned(key) {}92/** Destructor to clean up private memory. */93~ChaCha20();95/** Set 32-byte key, and seek to nonce 0 and block position 0. */96void SetKey(std::span<const std::byte> key) noexcept;98/** 96-bit nonce type. */99using Nonce96 = ChaCha20Aligned::Nonce96;101/** Set the 96-bit nonce and 32-bit block counter. See ChaCha20Aligned::Seek. */102void Seek(Nonce96 nonce, uint32_t block_counter) noexcept103{104m_aligned.Seek(nonce, block_counter);105m_bufleft = 0;106}108/** en/deciphers the message <in_bytes> and write the result into <out_bytes>109*110* The size of in_bytes and out_bytes must be equal.111*/112void Crypt(std::span<const std::byte> in_bytes, std::span<std::byte> out_bytes) noexcept;114/** outputs the keystream to out. */115void Keystream(std::span<std::byte> out) noexcept;116};118/** Forward-secure ChaCha20119*120* This implements a stream cipher that automatically transitions to a new stream with a new key121* and new nonce after a predefined number of encryptions or decryptions.122*123* See BIP324 for details.124*/125class FSChaCha20126{127private:128/** Internal stream cipher. */129ChaCha20 m_chacha20;131/** The number of encryptions/decryptions before a rekey happens. */132const uint32_t m_rekey_interval;134/** The number of encryptions/decryptions since the last rekey. */135uint32_t m_chunk_counter{0};137/** The number of rekey operations that have happened. */138uint64_t m_rekey_counter{0};140public:141/** Length of keys expected by the constructor. */142static constexpr unsigned KEYLEN = 32;144// No copy or move to protect the secret.145FSChaCha20(const FSChaCha20&) = delete;146FSChaCha20(FSChaCha20&&) = delete;147FSChaCha20& operator=(const FSChaCha20&) = delete;148FSChaCha20& operator=(FSChaCha20&&) = delete;150/** Construct an FSChaCha20 cipher that rekeys every rekey_interval Crypt() calls. */151FSChaCha20(std::span<const std::byte> key, uint32_t rekey_interval) noexcept;153/** Encrypt or decrypt a chunk. */154void Crypt(std::span<const std::byte> input, std::span<std::byte> output) noexcept;155};157#endif // BITCOIN_CRYPTO_CHACHA20_H