bip324.cpp raw

   1  // Copyright (c) 2023-present 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>
   9  #include <crypto/chacha20poly1305.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 <cassert>
  20  #include <cstddef>
  21  #include <cstdint>
  22  #include <iterator>
  23  #include <string>
  24  
  25  BIP324Cipher::BIP324Cipher(const CKey& key, std::span<const std::byte> ent32) noexcept
  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(std::span<const std::byte> contents, std::span<const std::byte> aad, bool ignore, std::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  
  89  uint32_t BIP324Cipher::DecryptLength(std::span<const std::byte> input) noexcept
  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(std::span<const std::byte> input, std::span<const std::byte> aad, bool& ignore, std::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  }
 110