diff options
Diffstat (limited to 'src/key.h')
-rw-r--r-- | src/key.h | 87 |
1 files changed, 81 insertions, 6 deletions
@@ -28,6 +28,8 @@ constexpr static size_t ECDH_SECRET_SIZE = CSHA256::OUTPUT_SIZE; // Used to represent ECDH shared secret (ECDH_SECRET_SIZE bytes) using ECDHSecret = std::array<std::byte, ECDH_SECRET_SIZE>; +class KeyPair; + /** An encapsulated private key. */ class CKey { @@ -75,13 +77,15 @@ public: CKey& operator=(const CKey& other) { - if (other.keydata) { - MakeKeyData(); - *keydata = *other.keydata; - } else { - ClearKeyData(); + if (this != &other) { + if (other.keydata) { + MakeKeyData(); + *keydata = *other.keydata; + } else { + ClearKeyData(); + } + fCompressed = other.fCompressed; } - fCompressed = other.fCompressed; return *this; } @@ -200,6 +204,22 @@ public: ECDHSecret ComputeBIP324ECDHSecret(const EllSwiftPubKey& their_ellswift, const EllSwiftPubKey& our_ellswift, bool initiating) const; + /** Compute a KeyPair + * + * Wraps a `secp256k1_keypair` type. + * + * `merkle_root` is used to optionally perform tweaking of + * the internal key, as specified in BIP341: + * + * - If merkle_root == nullptr: no tweaking is done, use the internal key directly (this is + * used for signatures in BIP342 script). + * - If merkle_root->IsNull(): tweak the internal key with H_TapTweak(pubkey) (this is used for + * key path spending when no scripts are present). + * - Otherwise: tweak the internal key with H_TapTweak(pubkey || *merkle_root) + * (this is used for key path spending with the + * Merkle root of the script tree). + */ + KeyPair ComputeKeyPair(const uint256* merkle_root) const; }; CKey GenerateRandomKey(bool compressed = true) noexcept; @@ -233,6 +253,61 @@ struct CExtKey { void SetSeed(Span<const std::byte> seed); }; +/** KeyPair + * + * Wraps a `secp256k1_keypair` type, an opaque data structure for holding a secret and public key. + * This is intended for BIP340 keys and allows us to easily determine if the secret key needs to + * be negated by checking the parity of the public key. This class primarily intended for passing + * secret keys to libsecp256k1 functions expecting a `secp256k1_keypair`. For all other cases, + * CKey should be preferred. + * + * A KeyPair can be created from a CKey with an optional merkle_root tweak (per BIP342). See + * CKey::ComputeKeyPair for more details. + */ +class KeyPair +{ +public: + KeyPair() noexcept = default; + KeyPair(KeyPair&&) noexcept = default; + KeyPair& operator=(KeyPair&&) noexcept = default; + KeyPair& operator=(const KeyPair& other) + { + if (this != &other) { + if (other.m_keypair) { + MakeKeyPairData(); + *m_keypair = *other.m_keypair; + } else { + ClearKeyPairData(); + } + } + return *this; + } + + KeyPair(const KeyPair& other) { *this = other; } + + friend KeyPair CKey::ComputeKeyPair(const uint256* merkle_root) const; + [[nodiscard]] bool SignSchnorr(const uint256& hash, Span<unsigned char> sig, const uint256& aux) const; + + //! Check whether this keypair is valid. + bool IsValid() const { return !!m_keypair; } + +private: + KeyPair(const CKey& key, const uint256* merkle_root); + + using KeyType = std::array<unsigned char, 96>; + secure_unique_ptr<KeyType> m_keypair; + + void MakeKeyPairData() + { + if (!m_keypair) m_keypair = make_secure_unique<KeyType>(); + } + + void ClearKeyPairData() + { + m_keypair.reset(); + } +}; + /** Check that required EC support is available at runtime. */ bool ECC_InitSanityCheck(); |