Bitcoin Core  27.99.0
P2P Digital Currency
chacha20.h
Go to the documentation of this file.
1 // Copyright (c) 2017-2022 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #ifndef BITCOIN_CRYPTO_CHACHA20_H
6 #define BITCOIN_CRYPTO_CHACHA20_H
7 
8 #include <span.h>
9 
10 #include <array>
11 #include <cstddef>
12 #include <cstdlib>
13 #include <stdint.h>
14 #include <utility>
15 
16 // classes for ChaCha20 256-bit stream cipher developed by Daniel J. Bernstein
17 // https://cr.yp.to/chacha/chacha-20080128.pdf.
18 //
19 // The 128-bit input is here implemented as a 96-bit nonce and a 32-bit block
20 // counter, as in RFC8439 Section 2.3. When the 32-bit block counter overflows
21 // the first 32-bit part of the nonce is automatically incremented, making it
22 // conceptually compatible with variants that use a 64/64 split instead.
23 
26 {
27 private:
28  uint32_t input[12];
29 
30 public:
32  static constexpr unsigned KEYLEN{32};
33 
35  static constexpr unsigned BLOCKLEN{64};
36 
38  ChaCha20Aligned() noexcept = delete;
39 
41  ChaCha20Aligned(Span<const std::byte> key) noexcept;
42 
44  ~ChaCha20Aligned();
45 
47  void SetKey(Span<const std::byte> key) noexcept;
48 
57  using Nonce96 = std::pair<uint32_t, uint64_t>;
58 
64  void Seek(Nonce96 nonce, uint32_t block_counter) noexcept;
65 
67  void Keystream(Span<std::byte> out) noexcept;
68 
73  void Crypt(Span<const std::byte> input, Span<std::byte> output) noexcept;
74 };
75 
77 class ChaCha20
78 {
79 private:
81  std::array<std::byte, ChaCha20Aligned::BLOCKLEN> m_buffer;
82  unsigned m_bufleft{0};
83 
84 public:
86  static constexpr unsigned KEYLEN = ChaCha20Aligned::KEYLEN;
87 
89  ChaCha20() noexcept = delete;
90 
92  ChaCha20(Span<const std::byte> key) noexcept : m_aligned(key) {}
93 
95  ~ChaCha20();
96 
98  void SetKey(Span<const std::byte> key) noexcept;
99 
102 
104  void Seek(Nonce96 nonce, uint32_t block_counter) noexcept
105  {
106  m_aligned.Seek(nonce, block_counter);
107  m_bufleft = 0;
108  }
109 
114  void Crypt(Span<const std::byte> in_bytes, Span<std::byte> out_bytes) noexcept;
115 
117  void Keystream(Span<std::byte> out) noexcept;
118 };
119 
128 {
129 private:
132 
134  const uint32_t m_rekey_interval;
135 
137  uint32_t m_chunk_counter{0};
138 
140  uint64_t m_rekey_counter{0};
141 
142 public:
144  static constexpr unsigned KEYLEN = 32;
145 
146  // No copy or move to protect the secret.
147  FSChaCha20(const FSChaCha20&) = delete;
148  FSChaCha20(FSChaCha20&&) = delete;
149  FSChaCha20& operator=(const FSChaCha20&) = delete;
151 
153  FSChaCha20(Span<const std::byte> key, uint32_t rekey_interval) noexcept;
154 
156  void Crypt(Span<const std::byte> input, Span<std::byte> output) noexcept;
157 };
158 
159 #endif // BITCOIN_CRYPTO_CHACHA20_H
ChaCha20 cipher that only operates on multiples of 64 bytes.
Definition: chacha20.h:26
void Keystream(Span< std::byte > out) noexcept
outputs the keystream into out, whose length must be a multiple of BLOCKLEN.
Definition: chacha20.cpp:60
void Crypt(Span< const std::byte > input, Span< std::byte > output) noexcept
en/deciphers the message <input> and write the result into <output>
Definition: chacha20.cpp:161
ChaCha20Aligned() noexcept=delete
For safety, disallow initialization without key.
std::pair< uint32_t, uint64_t > Nonce96
Type for 96-bit nonces used by the Set function below.
Definition: chacha20.h:57
void SetKey(Span< const std::byte > key) noexcept
Set 32-byte key, and seek to nonce 0 and block position 0.
Definition: chacha20.cpp:25
uint32_t input[12]
Definition: chacha20.h:28
void Seek(Nonce96 nonce, uint32_t block_counter) noexcept
Set the 96-bit nonce and 32-bit block counter.
Definition: chacha20.cpp:52
static constexpr unsigned BLOCKLEN
Block size (inputs/outputs to Keystream / Crypt should be multiples of this).
Definition: chacha20.h:35
static constexpr unsigned KEYLEN
Expected key length in constructor and SetKey.
Definition: chacha20.h:32
Unrestricted ChaCha20 cipher.
Definition: chacha20.h:78
ChaCha20() noexcept=delete
For safety, disallow initialization without key.
std::array< std::byte, ChaCha20Aligned::BLOCKLEN > m_buffer
Definition: chacha20.h:81
void Seek(Nonce96 nonce, uint32_t block_counter) noexcept
Set the 96-bit nonce and 32-bit block counter.
Definition: chacha20.h:104
ChaCha20Aligned m_aligned
Definition: chacha20.h:80
ChaCha20Aligned::Nonce96 Nonce96
96-bit nonce type.
Definition: chacha20.h:101
Forward-secure ChaCha20.
Definition: chacha20.h:128
ChaCha20 m_chacha20
Internal stream cipher.
Definition: chacha20.h:131
FSChaCha20 & operator=(FSChaCha20 &&)=delete
FSChaCha20(FSChaCha20 &&)=delete
FSChaCha20 & operator=(const FSChaCha20 &)=delete
const uint32_t m_rekey_interval
The number of encryptions/decryptions before a rekey happens.
Definition: chacha20.h:134
FSChaCha20(const FSChaCha20 &)=delete
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:98
unsigned int nonce
Definition: miner_tests.cpp:71