mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-26 11:13:23 -03:00
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:
parent
5d507a0091
commit
c39fd39ba8
2 changed files with 74 additions and 0 deletions
15
src/key.cpp
15
src/key.cpp
|
@ -363,6 +363,11 @@ ECDHSecret CKey::ComputeBIP324ECDHSecret(const EllSwiftPubKey& their_ellswift, c
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyPair CKey::ComputeKeyPair() const
|
||||||
|
{
|
||||||
|
return KeyPair(*this);
|
||||||
|
}
|
||||||
|
|
||||||
CKey GenerateRandomKey(bool compressed) noexcept
|
CKey GenerateRandomKey(bool compressed) noexcept
|
||||||
{
|
{
|
||||||
CKey key;
|
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();
|
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() {
|
bool ECC_InitSanityCheck() {
|
||||||
CKey key = GenerateRandomKey();
|
CKey key = GenerateRandomKey();
|
||||||
CPubKey pubkey = key.GetPubKey();
|
CPubKey pubkey = key.GetPubKey();
|
||||||
|
|
59
src/key.h
59
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)
|
// Used to represent ECDH shared secret (ECDH_SECRET_SIZE bytes)
|
||||||
using ECDHSecret = std::array<std::byte, ECDH_SECRET_SIZE>;
|
using ECDHSecret = std::array<std::byte, ECDH_SECRET_SIZE>;
|
||||||
|
|
||||||
|
class KeyPair;
|
||||||
|
|
||||||
/** An encapsulated private key. */
|
/** An encapsulated private key. */
|
||||||
class CKey
|
class CKey
|
||||||
{
|
{
|
||||||
|
@ -202,6 +204,11 @@ public:
|
||||||
ECDHSecret ComputeBIP324ECDHSecret(const EllSwiftPubKey& their_ellswift,
|
ECDHSecret ComputeBIP324ECDHSecret(const EllSwiftPubKey& their_ellswift,
|
||||||
const EllSwiftPubKey& our_ellswift,
|
const EllSwiftPubKey& our_ellswift,
|
||||||
bool initiating) const;
|
bool initiating) const;
|
||||||
|
/** Compute a KeyPair
|
||||||
|
*
|
||||||
|
* Wraps a `secp256k1_keypair` type.
|
||||||
|
*/
|
||||||
|
KeyPair ComputeKeyPair() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
CKey GenerateRandomKey(bool compressed = true) noexcept;
|
CKey GenerateRandomKey(bool compressed = true) noexcept;
|
||||||
|
@ -235,6 +242,58 @@ struct CExtKey {
|
||||||
void SetSeed(Span<const std::byte> seed);
|
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.
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
[[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);
|
||||||
|
|
||||||
|
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. */
|
/** Check that required EC support is available at runtime. */
|
||||||
bool ECC_InitSanityCheck();
|
bool ECC_InitSanityCheck();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue