diff options
author | Pieter Wuille <pieter@wuille.net> | 2023-07-06 14:19:29 -0400 |
---|---|---|
committer | Pieter Wuille <pieter@wuille.net> | 2023-07-26 17:09:23 -0400 |
commit | 990f0f8da92a2d11828a7c05ca93bf0520b2a95e (patch) | |
tree | ff4be5b1637ac8dcf941f339b08bc167ffe84038 /src/bip324.h | |
parent | c91cedf281e5207fb5fd2ca81feec9760f7c2ed0 (diff) |
Add BIP324Cipher, encapsulating key agreement, derivation, and stream/AEAD ciphers
Co-authored-by: dhruv <856960+dhruv@users.noreply.github.com>
Diffstat (limited to 'src/bip324.h')
-rw-r--r-- | src/bip324.h | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/src/bip324.h b/src/bip324.h new file mode 100644 index 0000000000..1738356ee5 --- /dev/null +++ b/src/bip324.h @@ -0,0 +1,90 @@ +// Copyright (c) 2023 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_BIP324_H +#define BITCOIN_BIP324_H + +#include <cstddef> +#include <optional> + +#include <crypto/chacha20.h> +#include <crypto/chacha20poly1305.h> +#include <key.h> +#include <pubkey.h> +#include <span.h> + +/** The BIP324 packet cipher, encapsulating its key derivation, stream cipher, and AEAD. */ +class BIP324Cipher +{ +public: + static constexpr unsigned SESSION_ID_LEN{32}; + static constexpr unsigned GARBAGE_TERMINATOR_LEN{16}; + static constexpr unsigned REKEY_INTERVAL{224}; + static constexpr unsigned LENGTH_LEN{3}; + static constexpr unsigned HEADER_LEN{1}; + static constexpr unsigned EXPANSION = LENGTH_LEN + HEADER_LEN + FSChaCha20Poly1305::EXPANSION; + static constexpr std::byte IGNORE_BIT{0x80}; + +private: + std::optional<FSChaCha20> m_send_l_cipher; + std::optional<FSChaCha20> m_recv_l_cipher; + std::optional<FSChaCha20Poly1305> m_send_p_cipher; + std::optional<FSChaCha20Poly1305> m_recv_p_cipher; + + CKey m_key; + EllSwiftPubKey m_our_pubkey; + + std::array<std::byte, SESSION_ID_LEN> m_session_id; + std::array<std::byte, GARBAGE_TERMINATOR_LEN> m_send_garbage_terminator; + std::array<std::byte, GARBAGE_TERMINATOR_LEN> m_recv_garbage_terminator; + +public: + /** Initialize a BIP324 cipher with securely generated random keys. */ + BIP324Cipher() noexcept; + + /** Initialize a BIP324 cipher with specified key and encoding entropy (testing only). */ + BIP324Cipher(const CKey& key, Span<const std::byte> ent32) noexcept; + + /** Initialize a BIP324 cipher with specified key (testing only). */ + BIP324Cipher(const CKey& key, const EllSwiftPubKey& pubkey) noexcept; + + /** Retrieve our public key. */ + const EllSwiftPubKey& GetOurPubKey() const noexcept { return m_our_pubkey; } + + /** Initialize when the other side's public key is received. Can only be called once. */ + void Initialize(const EllSwiftPubKey& their_pubkey, bool initiator) noexcept; + + /** Determine whether this cipher is fully initialized. */ + explicit operator bool() const noexcept { return m_send_l_cipher.has_value(); } + + /** Encrypt a packet. Only after Initialize(). + * + * It must hold that output.size() == contents.size() + EXPANSION. + */ + void Encrypt(Span<const std::byte> contents, Span<const std::byte> aad, bool ignore, Span<std::byte> output) noexcept; + + /** Decrypt the length of a packet. Only after Initialize(). + * + * It must hold that input.size() == LENGTH_LEN. + */ + unsigned DecryptLength(Span<const std::byte> input) noexcept; + + /** Decrypt a packet. Only after Initialize(). + * + * It must hold that input.size() + LENGTH_LEN == contents.size() + EXPANSION. + * Contents.size() must equal the length returned by DecryptLength. + */ + bool Decrypt(Span<const std::byte> input, Span<const std::byte> aad, bool& ignore, Span<std::byte> contents) noexcept; + + /** Get the Session ID. Only after Initialize(). */ + Span<const std::byte> GetSessionID() const noexcept { return m_session_id; } + + /** Get the Garbage Terminator to send. Only after Initialize(). */ + Span<const std::byte> GetSendGarbageTerminator() const noexcept { return m_send_garbage_terminator; } + + /** Get the expected Garbage Terminator to receive. Only after Initialize(). */ + Span<const std::byte> GetReceiveGarbageTerminator() const noexcept { return m_recv_garbage_terminator; } +}; + +#endif // BITCOIN_BIP324_H |