LCOV - code coverage report
Current view: top level - src - key.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 43 45 95.6 %
Date: 2026-06-25 07:23:43 Functions: 32 32 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2009-2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2021 The Bitcoin Core developers
       3             : // Copyright (c) 2017 The Zcash developers
       4             : // Distributed under the MIT software license, see the accompanying
       5             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       6             : 
       7             : #ifndef BITCOIN_KEY_H
       8             : #define BITCOIN_KEY_H
       9             : 
      10             : #include <pubkey.h>
      11             : #include <serialize.h>
      12             : #include <support/allocators/secure.h>
      13             : #include <uint256.h>
      14             : 
      15             : #include <stdexcept>
      16             : #include <vector>
      17             : 
      18             : 
      19             : /**
      20             :  * CPrivKey is a serialized private key, with all parameters included
      21             :  * (SIZE bytes)
      22             :  */
      23             : typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;
      24             : 
      25             : /** Size of ECDH shared secrets. */
      26             : constexpr static size_t ECDH_SECRET_SIZE = CSHA256::OUTPUT_SIZE;
      27             : 
      28             : // Used to represent ECDH shared secret (ECDH_SECRET_SIZE bytes)
      29             : using ECDHSecret = std::array<std::byte, ECDH_SECRET_SIZE>;
      30             : 
      31             : /** An encapsulated private key. */
      32             : class CKey
      33             : {
      34             : public:
      35             :     /**
      36             :      * secp256k1:
      37             :      */
      38             :     static const unsigned int SIZE            = 279;
      39             :     static const unsigned int COMPRESSED_SIZE = 214;
      40             :     /**
      41             :      * see www.keylength.com
      42             :      * script supports up to 75 for single byte push
      43             :      */
      44             :     static_assert(
      45             :         SIZE >= COMPRESSED_SIZE,
      46             :         "COMPRESSED_SIZE is larger than SIZE");
      47             : 
      48             : private:
      49             :     /** Internal data container for private key material. */
      50             :     using KeyType = std::array<unsigned char, 32>;
      51             : 
      52             :     //! Whether the public key corresponding to this private key is (to be) compressed.
      53     3091948 :     bool fCompressed{false};
      54             : 
      55             :     //! The actual byte data. nullptr for invalid keys.
      56             :     secure_unique_ptr<KeyType> keydata;
      57             : 
      58             :     //! Check whether the 32-byte array pointed to by vch is valid keydata.
      59             :     bool static Check(const unsigned char* vch);
      60             : 
      61     3097125 :     void MakeKeyData()
      62             :     {
      63     3097125 :         if (!keydata) keydata = make_secure_unique<KeyType>();
      64     3097125 :     }
      65             : 
      66           2 :     void ClearKeyData()
      67             :     {
      68           2 :         keydata.reset();
      69           2 :     }
      70             : 
      71             : public:
      72     8941554 :     CKey() noexcept = default;
      73        9066 :     CKey(CKey&&) noexcept = default;
      74        1537 :     CKey& operator=(CKey&&) noexcept = default;
      75             : 
      76     1684187 :     CKey& operator=(const CKey& other)
      77             :     {
      78     1684187 :         if (other.keydata) {
      79     1684187 :             MakeKeyData();
      80     1684187 :             *keydata = *other.keydata;
      81     1684187 :         } else {
      82           0 :             ClearKeyData();
      83             :         }
      84     1684187 :         fCompressed = other.fCompressed;
      85     1684187 :         return *this;
      86             :     }
      87             : 
      88      334290 :     CKey(const CKey& other) { *this = other; }
      89             : 
      90        2121 :     friend bool operator==(const CKey& a, const CKey& b)
      91             :     {
      92        4242 :         return a.fCompressed == b.fCompressed &&
      93        2121 :             a.size() == b.size() &&
      94        2121 :             memcmp(a.data(), b.data(), a.size()) == 0;
      95             :     }
      96             : 
      97             :     //! Initialize using begin and end iterators to byte data.
      98             :     template <typename T>
      99     1395467 :     void Set(const T pbegin, const T pend, bool fCompressedIn)
     100             :     {
     101     1395467 :         if (size_t(pend - pbegin) != std::tuple_size_v<KeyType>) {
     102           0 :             ClearKeyData();
     103     1395467 :         } else if (Check(&pbegin[0])) {
     104     1395465 :             MakeKeyData();
     105     1395465 :             memcpy(keydata->data(), (unsigned char*)&pbegin[0], keydata->size());
     106     1395465 :             fCompressed = fCompressedIn;
     107     1395465 :         } else {
     108           2 :             ClearKeyData();
     109             :         }
     110     1395467 :     }
     111             : 
     112             :     //! Simple read-only vector-like interface.
     113      220085 :     unsigned int size() const { return keydata ? keydata->size() : 0; }
     114        4266 :     const std::byte* data() const { return keydata ? reinterpret_cast<const std::byte*>(keydata->data()) : nullptr; }
     115     3684472 :     const unsigned char* begin() const { return keydata ? keydata->data() : nullptr; }
     116        4577 :     const unsigned char* end() const { return begin() + size(); }
     117             : 
     118             :     //! Check whether this private key is valid.
     119     1376736 :     bool IsValid() const { return !!keydata; }
     120             : 
     121             :     //! Check whether the public key corresponding to this private key is (to be) compressed.
     122      341679 :     bool IsCompressed() const { return fCompressed; }
     123             : 
     124             :     //! Generate a new private key using a cryptographic PRNG.
     125             :     void MakeNewKey(bool fCompressed);
     126             : 
     127             :     //! Negate private key
     128             :     bool Negate();
     129             : 
     130             :     /**
     131             :      * Convert the private key to a CPrivKey (serialized OpenSSL private key data).
     132             :      * This is expensive.
     133             :      */
     134             :     CPrivKey GetPrivKey() const;
     135             : 
     136             :     /**
     137             :      * Compute the public key from a private key.
     138             :      * This is expensive.
     139             :      */
     140             :     CPubKey GetPubKey() const;
     141             : 
     142             :     /**
     143             :      * Create a DER-serialized signature.
     144             :      * The test_case parameter tweaks the deterministic nonce.
     145             :      */
     146             :     bool Sign(const uint256& hash, std::vector<unsigned char>& vchSig, bool grind = true, uint32_t test_case = 0) const;
     147             : 
     148             :     /**
     149             :      * Create a compact signature (65 bytes), which allows reconstructing the used public key.
     150             :      * The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
     151             :      * The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
     152             :      *                  0x1D = second key with even y, 0x1E = second key with odd y,
     153             :      *                  add 0x04 for compressed keys.
     154             :      */
     155             :     bool SignCompact(const uint256& hash, std::vector<unsigned char>& vchSig) const;
     156             : 
     157             :     //! Derive BIP32 child key.
     158             :     [[nodiscard]] bool Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
     159             : 
     160             :     /**
     161             :      * Verify thoroughly whether a private key and a public key match.
     162             :      * This is done using a different mechanism than just regenerating it.
     163             :      */
     164             :     bool VerifyPubKey(const CPubKey& vchPubKey) const;
     165             : 
     166             :     //! Load private key and check that public key matches.
     167             :     bool Load(const CPrivKey& privkey, const CPubKey& vchPubKey, bool fSkipCheck);
     168             : 
     169             :     /** Create an ellswift-encoded public key for this key, with specified entropy.
     170             :      *
     171             :      *  entropy must be a 32-byte span with additional entropy to use in the encoding. Every
     172             :      *  public key has ~2^256 different encodings, and this function will deterministically pick
     173             :      *  one of them, based on entropy. Note that even without truly random entropy, the
     174             :      *  resulting encoding will be indistinguishable from uniform to any adversary who does not
     175             :      *  know the private key (because the private key itself is always used as entropy as well).
     176             :      */
     177             :     EllSwiftPubKey EllSwiftCreate(Span<const std::byte> entropy) const;
     178             : 
     179             :     /** Compute a BIP324-style ECDH shared secret.
     180             :      *
     181             :      *  - their_ellswift: EllSwiftPubKey that was received from the other side.
     182             :      *  - our_ellswift: EllSwiftPubKey that was sent to the other side (must have been generated
     183             :      *                  from *this using EllSwiftCreate()).
     184             :      *  - initiating: whether we are the initiating party (true) or responding party (false).
     185             :      */
     186             :     ECDHSecret ComputeBIP324ECDHSecret(const EllSwiftPubKey& their_ellswift,
     187             :                                        const EllSwiftPubKey& our_ellswift,
     188             :                                        bool initiating) const;
     189             : };
     190             : 
     191             : CKey GenerateRandomKey(bool compressed = true) noexcept;
     192             : 
     193             : struct CExtKey {
     194             :     unsigned char nDepth;
     195             :     unsigned char vchFingerprint[4];
     196             :     unsigned int nChild;
     197             :     ChainCode chaincode;
     198             :     CKey key;
     199             : 
     200        1196 :     friend bool operator==(const CExtKey& a, const CExtKey& b)
     201             :     {
     202        2392 :         return a.nDepth == b.nDepth &&
     203        1196 :             memcmp(a.vchFingerprint, b.vchFingerprint, sizeof(vchFingerprint)) == 0 &&
     204        1196 :             a.nChild == b.nChild &&
     205        1196 :             a.chaincode == b.chaincode &&
     206        1196 :             a.key == b.key;
     207             :     }
     208             : 
     209             :     void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
     210             :     void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
     211             :     [[nodiscard]] bool Derive(CExtKey& out, unsigned int nChild) const;
     212             :     CExtPubKey Neuter() const;
     213             :     void SetSeed(Span<const std::byte> seed);
     214             : };
     215             : 
     216             : /** Initialize the elliptic curve support. May not be called twice without calling ECC_Stop first. */
     217             : void ECC_Start();
     218             : 
     219             : /** Deinitialize the elliptic curve support. No-op if ECC_Start wasn't called first. */
     220             : void ECC_Stop();
     221             : 
     222             : /** Check that required EC support is available at runtime. */
     223             : bool ECC_InitSanityCheck();
     224             : 
     225             : #endif // BITCOIN_KEY_H

Generated by: LCOV version 1.16