bip324.h 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  #ifndef BITCOIN_BIP324_H
   6  #define BITCOIN_BIP324_H
   7  
   8  #include <array>
   9  #include <cstddef>
  10  #include <optional>
  11  
  12  #include <crypto/chacha20.h>
  13  #include <crypto/chacha20poly1305.h>
  14  #include <key.h>
  15  #include <pubkey.h>
  16  #include <span.h>
  17  
  18  static constexpr unsigned BIP324_SHORTIDS_IMPLEMENTED{38};
  19  
  20  /** The BIP324 packet cipher, encapsulating its key derivation, stream cipher, and AEAD. */
  21  class BIP324Cipher
  22  {
  23  public:
  24      static constexpr unsigned SESSION_ID_LEN{32};
  25      static constexpr unsigned GARBAGE_TERMINATOR_LEN{16};
  26      static constexpr unsigned REKEY_INTERVAL{224};
  27      static constexpr unsigned LENGTH_LEN{3};
  28      static constexpr unsigned HEADER_LEN{1};
  29      static constexpr unsigned EXPANSION = LENGTH_LEN + HEADER_LEN + FSChaCha20Poly1305::EXPANSION;
  30      static constexpr std::byte IGNORE_BIT{0x80};
  31  
  32  private:
  33      std::optional<FSChaCha20> m_send_l_cipher;
  34      std::optional<FSChaCha20> m_recv_l_cipher;
  35      std::optional<FSChaCha20Poly1305> m_send_p_cipher;
  36      std::optional<FSChaCha20Poly1305> m_recv_p_cipher;
  37  
  38      CKey m_key;
  39      EllSwiftPubKey m_our_pubkey;
  40  
  41      std::array<std::byte, SESSION_ID_LEN> m_session_id;
  42      std::array<std::byte, GARBAGE_TERMINATOR_LEN> m_send_garbage_terminator;
  43      std::array<std::byte, GARBAGE_TERMINATOR_LEN> m_recv_garbage_terminator;
  44  
  45  public:
  46      /** No default constructor; keys must be provided to create a BIP324Cipher. */
  47      BIP324Cipher() = delete;
  48  
  49      /** Initialize a BIP324 cipher with specified key and encoding entropy (testing only). */
  50      BIP324Cipher(const CKey& key, std::span<const std::byte> ent32) noexcept;
  51  
  52      /** Initialize a BIP324 cipher with specified key (testing only). */
  53      BIP324Cipher(const CKey& key, const EllSwiftPubKey& pubkey) noexcept;
  54  
  55      /** Retrieve our public key. */
  56      const EllSwiftPubKey& GetOurPubKey() const noexcept { return m_our_pubkey; }
  57  
  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 encryption
  62       * and decryption can be tested without knowing the other side's private key.
  63       */
  64      void Initialize(const EllSwiftPubKey& their_pubkey, bool initiator, bool self_decrypt = false) noexcept;
  65  
  66      /** Determine whether this cipher is fully initialized. */
  67      explicit operator bool() const noexcept { return m_send_l_cipher.has_value(); }
  68  
  69      /** Encrypt a packet. Only after Initialize().
  70       *
  71       * It must hold that output.size() == contents.size() + EXPANSION.
  72       */
  73      void Encrypt(std::span<const std::byte> contents, std::span<const std::byte> aad, bool ignore, std::span<std::byte> output) noexcept;
  74  
  75      /** Decrypt the length of a packet. Only after Initialize().
  76       *
  77       * It must hold that input.size() == LENGTH_LEN.
  78       */
  79      unsigned DecryptLength(std::span<const std::byte> input) noexcept;
  80  
  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       */
  86      bool Decrypt(std::span<const std::byte> input, std::span<const std::byte> aad, bool& ignore, std::span<std::byte> contents) noexcept;
  87  
  88      /** Get the Session ID. Only after Initialize(). */
  89      std::span<const std::byte> GetSessionID() const noexcept { return m_session_id; }
  90  
  91      /** Get the Garbage Terminator to send. Only after Initialize(). */
  92      std::span<const std::byte> GetSendGarbageTerminator() const noexcept { return m_send_garbage_terminator; }
  93  
  94      /** Get the expected Garbage Terminator to receive. Only after Initialize(). */
  95      std::span<const std::byte> GetReceiveGarbageTerminator() const noexcept { return m_recv_garbage_terminator; }
  96  };
  97  
  98  #endif // BITCOIN_BIP324_H
  99