| 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 | { |
no test coverage detected