Bitcoin Core  27.99.0
P2P Digital Currency
bip324.cpp
Go to the documentation of this file.
1 // Copyright (c) 2023 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 #include <bip324.h>
6 
7 #include <chainparams.h>
8 #include <crypto/chacha20.h>
10 #include <crypto/hkdf_sha256_32.h>
11 #include <key.h>
12 #include <pubkey.h>
13 #include <random.h>
14 #include <span.h>
15 #include <support/cleanse.h>
16 #include <uint256.h>
17 
18 #include <algorithm>
19 #include <assert.h>
20 #include <cstdint>
21 #include <cstddef>
22 #include <iterator>
23 #include <string>
24 
26  m_key(key)
27 {
28  m_our_pubkey = m_key.EllSwiftCreate(ent32);
29 }
30 
31 BIP324Cipher::BIP324Cipher(const CKey& key, const EllSwiftPubKey& pubkey) noexcept :
32  m_key(key), m_our_pubkey(pubkey) {}
33 
34 void BIP324Cipher::Initialize(const EllSwiftPubKey& their_pubkey, bool initiator, bool self_decrypt) noexcept
35 {
36  // Determine salt (fixed string + network magic bytes)
37  const auto& message_header = Params().MessageStart();
38  std::string salt = std::string{"bitcoin_v2_shared_secret"} + std::string(std::begin(message_header), std::end(message_header));
39 
40  // Perform ECDH to derive shared secret.
41  ECDHSecret ecdh_secret = m_key.ComputeBIP324ECDHSecret(their_pubkey, m_our_pubkey, initiator);
42 
43  // Derive encryption keys from shared secret, and initialize stream ciphers and AEADs.
44  bool side = (initiator != self_decrypt);
45  CHKDF_HMAC_SHA256_L32 hkdf(UCharCast(ecdh_secret.data()), ecdh_secret.size(), salt);
46  std::array<std::byte, 32> hkdf_32_okm;
47  hkdf.Expand32("initiator_L", UCharCast(hkdf_32_okm.data()));
48  (side ? m_send_l_cipher : m_recv_l_cipher).emplace(hkdf_32_okm, REKEY_INTERVAL);
49  hkdf.Expand32("initiator_P", UCharCast(hkdf_32_okm.data()));
50  (side ? m_send_p_cipher : m_recv_p_cipher).emplace(hkdf_32_okm, REKEY_INTERVAL);
51  hkdf.Expand32("responder_L", UCharCast(hkdf_32_okm.data()));
52  (side ? m_recv_l_cipher : m_send_l_cipher).emplace(hkdf_32_okm, REKEY_INTERVAL);
53  hkdf.Expand32("responder_P", UCharCast(hkdf_32_okm.data()));
54  (side ? m_recv_p_cipher : m_send_p_cipher).emplace(hkdf_32_okm, REKEY_INTERVAL);
55 
56  // Derive garbage terminators from shared secret.
57  hkdf.Expand32("garbage_terminators", UCharCast(hkdf_32_okm.data()));
58  std::copy(std::begin(hkdf_32_okm), std::begin(hkdf_32_okm) + GARBAGE_TERMINATOR_LEN,
59  (initiator ? m_send_garbage_terminator : m_recv_garbage_terminator).begin());
60  std::copy(std::end(hkdf_32_okm) - GARBAGE_TERMINATOR_LEN, std::end(hkdf_32_okm),
61  (initiator ? m_recv_garbage_terminator : m_send_garbage_terminator).begin());
62 
63  // Derive session id from shared secret.
64  hkdf.Expand32("session_id", UCharCast(m_session_id.data()));
65 
66  // Wipe all variables that contain information which could be used to re-derive encryption keys.
67  memory_cleanse(ecdh_secret.data(), ecdh_secret.size());
68  memory_cleanse(hkdf_32_okm.data(), sizeof(hkdf_32_okm));
69  memory_cleanse(&hkdf, sizeof(hkdf));
70  m_key = CKey();
71 }
72 
73 void BIP324Cipher::Encrypt(Span<const std::byte> contents, Span<const std::byte> aad, bool ignore, Span<std::byte> output) noexcept
74 {
75  assert(output.size() == contents.size() + EXPANSION);
76 
77  // Encrypt length.
78  std::byte len[LENGTH_LEN];
79  len[0] = std::byte{(uint8_t)(contents.size() & 0xFF)};
80  len[1] = std::byte{(uint8_t)((contents.size() >> 8) & 0xFF)};
81  len[2] = std::byte{(uint8_t)((contents.size() >> 16) & 0xFF)};
82  m_send_l_cipher->Crypt(len, output.first(LENGTH_LEN));
83 
84  // Encrypt plaintext.
85  std::byte header[HEADER_LEN] = {ignore ? IGNORE_BIT : std::byte{0}};
86  m_send_p_cipher->Encrypt(header, contents, aad, output.subspan(LENGTH_LEN));
87 }
88 
90 {
91  assert(input.size() == LENGTH_LEN);
92 
93  std::byte buf[LENGTH_LEN];
94  // Decrypt length
95  m_recv_l_cipher->Crypt(input, buf);
96  // Convert to number.
97  return uint32_t(buf[0]) + (uint32_t(buf[1]) << 8) + (uint32_t(buf[2]) << 16);
98 }
99 
100 bool BIP324Cipher::Decrypt(Span<const std::byte> input, Span<const std::byte> aad, bool& ignore, Span<std::byte> contents) noexcept
101 {
102  assert(input.size() + LENGTH_LEN == contents.size() + EXPANSION);
103 
104  std::byte header[HEADER_LEN];
105  if (!m_recv_p_cipher->Decrypt(input, aad, header, contents)) return false;
106 
107  ignore = (header[0] & IGNORE_BIT) == IGNORE_BIT;
108  return true;
109 }
const CChainParams & Params()
Return the currently selected parameters.
unsigned DecryptLength(Span< const std::byte > input) noexcept
Decrypt the length of a packet.
Definition: bip324.cpp:89
BIP324Cipher()=delete
No default constructor; keys must be provided to create a BIP324Cipher.
bool Decrypt(Span< const std::byte > input, Span< const std::byte > aad, bool &ignore, Span< std::byte > contents) noexcept
Decrypt a packet.
Definition: bip324.cpp:100
void Encrypt(Span< const std::byte > contents, Span< const std::byte > aad, bool ignore, Span< std::byte > output) noexcept
Encrypt a packet.
Definition: bip324.cpp:73
void Initialize(const EllSwiftPubKey &their_pubkey, bool initiator, bool self_decrypt=false) noexcept
Initialize when the other side's public key is received.
Definition: bip324.cpp:34
const MessageStartChars & MessageStart() const
Definition: chainparams.h:94
A rfc5869 HKDF implementation with HMAC_SHA256 and fixed key output length of 32 bytes (L=32)
void Expand32(const std::string &info, unsigned char hash[OUTPUT_SIZE])
An encapsulated private key.
Definition: key.h:33
void memory_cleanse(void *ptr, size_t len)
Secure overwrite a buffer (possibly containing secret data) with zero-bytes.
Definition: cleanse.cpp:14
std::array< std::byte, ECDH_SECRET_SIZE > ECDHSecret
Definition: key.h:29
unsigned char * UCharCast(char *c)
Definition: span.h:288
An ElligatorSwift-encoded public key.
Definition: pubkey.h:305
assert(!tx.IsCoinBase())