crypto: add KeyPair wrapper class

Add a `KeyPair` class which wraps the `secp256k1_keypair`. This keeps
the secret data in secure memory and enables passing the
`KeyPair` object directly to libsecp256k1 functions expecting a
`secp256k1_keypair`.

Motivation: when passing `CKeys` for taproot outputs to libsecp256k1 functions,
the first step is to create a `secp256k1_keypair` data type and use that
instead. This is so the libsecp256k1 function can determine if the key
needs to be negated, e.g., when signing.

This is a bit clunky in that it creates an extra step when using a `CKey`
for a taproot output and also involves copying the secret data into a
temporary object, which the caller must then take care to cleanse. In
addition, the logic for applying the merkle_root tweak currently
only exists in the `SignSchnorr` function.

In a later commit, we will add the merkle_root tweaking logic to this
function, which will make the merkle_root logic reusable outside of
signing by using the `KeyPair` class directly.

Co-authored-by: Cory Fields <cory-nospam-@coryfields.com>
This commit is contained in:
josibake
2024-07-16 18:34:10 +02:00
parent 5d507a0091
commit c39fd39ba8
2 changed files with 74 additions and 0 deletions

View File

@@ -363,6 +363,11 @@ ECDHSecret CKey::ComputeBIP324ECDHSecret(const EllSwiftPubKey& their_ellswift, c
return output;
}
KeyPair CKey::ComputeKeyPair() const
{
return KeyPair(*this);
}
CKey GenerateRandomKey(bool compressed) noexcept
{
CKey key;
@@ -420,6 +425,16 @@ void CExtKey::Decode(const unsigned char code[BIP32_EXTKEY_SIZE]) {
if ((nDepth == 0 && (nChild != 0 || ReadLE32(vchFingerprint) != 0)) || code[41] != 0) key = CKey();
}
KeyPair::KeyPair(const CKey& key)
{
static_assert(std::tuple_size<KeyType>() == sizeof(secp256k1_keypair));
MakeKeyPairData();
auto keypair = reinterpret_cast<secp256k1_keypair*>(m_keypair->data());
bool success = secp256k1_keypair_create(secp256k1_context_sign, keypair, UCharCast(key.data()));
if (!success) ClearKeyPairData();
}
bool ECC_InitSanityCheck() {
CKey key = GenerateRandomKey();
CPubKey pubkey = key.GetPubKey();