aboutsummaryrefslogtreecommitdiff
path: root/src/key.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/key.h')
-rw-r--r--src/key.h87
1 files changed, 81 insertions, 6 deletions
diff --git a/src/key.h b/src/key.h
index c802e1ebb8..6ed6fd0fc3 100644
--- a/src/key.h
+++ b/src/key.h
@@ -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();