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) 2023-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_BIP324_H6#define BITCOIN_BIP324_H8#include <array>9#include <cstddef>10#include <optional>12#include <crypto/chacha20.h>13#include <crypto/chacha20poly1305.h>14#include <key.h>15#include <pubkey.h>16#include <span.h>18inline constexpr unsigned BIP324_SHORTIDS_IMPLEMENTED{38};20/** The BIP324 packet cipher, encapsulating its key derivation, stream cipher, and AEAD. */21class BIP324Cipher22{23public:24static constexpr unsigned SESSION_ID_LEN{32};25static constexpr unsigned GARBAGE_TERMINATOR_LEN{16};26static constexpr unsigned REKEY_INTERVAL{224};27static constexpr unsigned LENGTH_LEN{3};28static constexpr unsigned HEADER_LEN{1};29static constexpr unsigned EXPANSION = LENGTH_LEN + HEADER_LEN + FSChaCha20Poly1305::EXPANSION;30static constexpr std::byte IGNORE_BIT{0x80};32private:33std::optional<FSChaCha20> m_send_l_cipher;34std::optional<FSChaCha20> m_recv_l_cipher;35std::optional<FSChaCha20Poly1305> m_send_p_cipher;36std::optional<FSChaCha20Poly1305> m_recv_p_cipher;38CKey m_key;39EllSwiftPubKey m_our_pubkey;41std::array<std::byte, SESSION_ID_LEN> m_session_id;42std::array<std::byte, GARBAGE_TERMINATOR_LEN> m_send_garbage_terminator;43std::array<std::byte, GARBAGE_TERMINATOR_LEN> m_recv_garbage_terminator;45public:46/** No default constructor; keys must be provided to create a BIP324Cipher. */47BIP324Cipher() = delete;49/** Initialize a BIP324 cipher with specified key and encoding entropy (testing only). */50BIP324Cipher(const CKey& key, std::span<const std::byte> ent32) noexcept;52/** Initialize a BIP324 cipher with specified key (testing only). */53BIP324Cipher(const CKey& key, const EllSwiftPubKey& pubkey) noexcept;55/** Retrieve our public key. */56const EllSwiftPubKey& GetOurPubKey() const noexcept { return m_our_pubkey; }58/** Initialize when the other side's public key is received. Can only be called once.59*60* initiator is set to true if we are the initiator establishing the v2 P2P connection.61* self_decrypt is only for testing, and swaps encryption/decryption keys, so that encryption62* and decryption can be tested without knowing the other side's private key.63*/64void Initialize(const EllSwiftPubKey& their_pubkey, bool initiator, bool self_decrypt = false) noexcept;66/** Determine whether this cipher is fully initialized. */67explicit operator bool() const noexcept { return m_send_l_cipher.has_value(); }69/** Encrypt a packet. Only after Initialize().70*71* It must hold that output.size() == contents.size() + EXPANSION.72*/73void Encrypt(std::span<const std::byte> contents, std::span<const std::byte> aad, bool ignore, std::span<std::byte> output) noexcept;75/** Decrypt the length of a packet. Only after Initialize().76*77* It must hold that input.size() == LENGTH_LEN.78*/79unsigned DecryptLength(std::span<const std::byte> input) noexcept;81/** Decrypt a packet. Only after Initialize().82*83* It must hold that input.size() + LENGTH_LEN == contents.size() + EXPANSION.84* Contents.size() must equal the length returned by DecryptLength.85*/86bool Decrypt(std::span<const std::byte> input, std::span<const std::byte> aad, bool& ignore, std::span<std::byte> contents) noexcept;88/** Get the Session ID. Only after Initialize(). */89std::span<const std::byte> GetSessionID() const noexcept { return m_session_id; }91/** Get the Garbage Terminator to send. Only after Initialize(). */92std::span<const std::byte> GetSendGarbageTerminator() const noexcept { return m_send_garbage_terminator; }94/** Get the expected Garbage Terminator to receive. Only after Initialize(). */95std::span<const std::byte> GetReceiveGarbageTerminator() const noexcept { return m_recv_garbage_terminator; }96};98#endif // BITCOIN_BIP324_H