Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2009-2010 Satoshi Nakamoto2// Copyright (c) 2009-present The Bitcoin Core developers3// Copyright (c) 2017 The Zcash developers4// Distributed under the MIT software license, see the accompanying5// file COPYING or http://www.opensource.org/licenses/mit-license.php.7#ifndef BITCOIN_KEY_H8#define BITCOIN_KEY_H10#include <pubkey.h>11#include <script/keyorigin.h>12#include <serialize.h>13#include <support/allocators/secure.h>14#include <uint256.h>16#include <optional>17#include <stdexcept>18#include <utility>19#include <vector>21struct secp256k1_context_struct;22typedef struct secp256k1_context_struct secp256k1_context;24/**25* CPrivKey is a serialized private key, with all parameters included26* (SIZE bytes)27*/28typedef std::vector<unsigned char, secure_allocator<unsigned char> > CPrivKey;30/** Size of ECDH shared secrets. */31inline constexpr size_t ECDH_SECRET_SIZE = CSHA256::OUTPUT_SIZE;33// Used to represent ECDH shared secret (ECDH_SECRET_SIZE bytes)34using ECDHSecret = std::array<std::byte, ECDH_SECRET_SIZE>;36class KeyPair;38/** An encapsulated private key. */39class CKey40{41public:42/**43* secp256k1:44*/45static constexpr unsigned int SIZE{279};46static constexpr unsigned int COMPRESSED_SIZE{214};47/**48* see www.keylength.com49* script supports up to 75 for single byte push50*/51static_assert(52SIZE >= COMPRESSED_SIZE,53"COMPRESSED_SIZE is larger than SIZE");55private:56/** Internal data container for private key material. */57using KeyType = std::array<unsigned char, 32>;59//! Whether the public key corresponding to this private key is (to be) compressed.60bool fCompressed{false};62//! The actual byte data. nullptr for invalid keys.63secure_unique_ptr<KeyType> keydata;65//! Check whether the 32-byte array pointed to by vch is valid keydata.66bool static Check(const unsigned char* vch);68void MakeKeyData()69{70if (!keydata) keydata = make_secure_unique<KeyType>();71}73void ClearKeyData()74{75keydata.reset();76}78public:79CKey() noexcept = default;80CKey(CKey&&) noexcept = default;81CKey& operator=(CKey&&) noexcept = default;83CKey& operator=(const CKey& other)84{85if (this != &other) {86if (other.keydata) {87MakeKeyData();88*keydata = *other.keydata;89} else {90ClearKeyData();91}92fCompressed = other.fCompressed;93}94return *this;95}97CKey(const CKey& other) { *this = other; }99friend bool operator==(const CKey& a, const CKey& b)100{101return a.fCompressed == b.fCompressed &&102a.size() == b.size() &&103memcmp(a.data(), b.data(), a.size()) == 0;104}106//! Initialize using begin and end iterators to byte data.107template <typename T>108void Set(const T pbegin, const T pend, bool fCompressedIn)109{110if (size_t(pend - pbegin) != std::tuple_size_v<KeyType>) {111ClearKeyData();112} else if (Check(UCharCast(&pbegin[0]))) {113MakeKeyData();114memcpy(keydata->data(), (unsigned char*)&pbegin[0], keydata->size());115fCompressed = fCompressedIn;116} else {117ClearKeyData();118}119}121//! Simple read-only vector-like interface.122unsigned int size() const { return keydata ? keydata->size() : 0; }123const std::byte* data() const { return keydata ? reinterpret_cast<const std::byte*>(keydata->data()) : nullptr; }124const std::byte* begin() const { return data(); }125const std::byte* end() const { return data() + size(); }127//! Check whether this private key is valid.128bool IsValid() const { return !!keydata; }130//! Check whether the public key corresponding to this private key is (to be) compressed.131bool IsCompressed() const { return fCompressed; }133//! Generate a new private key using a cryptographic PRNG.134void MakeNewKey(bool fCompressed);136/**137* Convert the private key to a CPrivKey (serialized OpenSSL private key data).138* This is expensive.139*/140CPrivKey GetPrivKey() const;142/**143* Compute the public key from a private key.144* This is expensive.145*/146CPubKey GetPubKey() const;148/**149* Create a DER-serialized signature.150* The test_case parameter tweaks the deterministic nonce.151*/152bool Sign(const uint256& hash, std::vector<unsigned char>& vchSig, bool grind = true, uint32_t test_case = 0) const;154/**155* Create a compact signature (65 bytes), which allows reconstructing the used public key.156* The format is one header byte, followed by two times 32 bytes for the serialized r and s values.157* The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,158* 0x1D = second key with even y, 0x1E = second key with odd y,159* add 0x04 for compressed keys.160*/161bool SignCompact(const uint256& hash, std::vector<unsigned char>& vchSig) const;163/**164* Create a BIP-340 Schnorr signature, for the xonly-pubkey corresponding to *this,165* optionally tweaked by *merkle_root. Additional nonce entropy is provided through166* aux.167*168* merkle_root is used to optionally perform tweaking of the private key, as specified169* in BIP341:170* - If merkle_root == nullptr: no tweaking is done, sign with key directly (this is171* used for signatures in BIP342 script).172* - If merkle_root->IsNull(): sign with key + H_TapTweak(pubkey) (this is used for173* key path spending when no scripts are present).174* - Otherwise: sign with key + H_TapTweak(pubkey || *merkle_root)175* (this is used for key path spending, with specific176* Merkle root of the script tree).177*/178bool SignSchnorr(const uint256& hash, std::span<unsigned char> sig, const uint256* merkle_root, const uint256& aux) const;180//! Derive BIP32 child key.181[[nodiscard]] bool Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;183/**184* Verify thoroughly whether a private key and a public key match.185* This is done using a different mechanism than just regenerating it.186*/187bool VerifyPubKey(const CPubKey& vchPubKey) const;189//! Load private key and check that public key matches.190bool Load(const CPrivKey& privkey, const CPubKey& vchPubKey, bool fSkipCheck);192/** Create an ellswift-encoded public key for this key, with specified entropy.193*194* entropy must be a 32-byte span with additional entropy to use in the encoding. Every195* public key has ~2^256 different encodings, and this function will deterministically pick196* one of them, based on entropy. Note that even without truly random entropy, the197* resulting encoding will be indistinguishable from uniform to any adversary who does not198* know the private key (because the private key itself is always used as entropy as well).199*/200EllSwiftPubKey EllSwiftCreate(std::span<const std::byte> entropy) const;202/** Compute a BIP324-style ECDH shared secret.203*204* - their_ellswift: EllSwiftPubKey that was received from the other side.205* - our_ellswift: EllSwiftPubKey that was sent to the other side (must have been generated206* from *this using EllSwiftCreate()).207* - initiating: whether we are the initiating party (true) or responding party (false).208*/209ECDHSecret ComputeBIP324ECDHSecret(const EllSwiftPubKey& their_ellswift,210const EllSwiftPubKey& our_ellswift,211bool initiating) const;212/** Compute a KeyPair213*214* Wraps a `secp256k1_keypair` type.215*216* `merkle_root` is used to optionally perform tweaking of217* the internal key, as specified in BIP341:218*219* - If merkle_root == nullptr: no tweaking is done, use the internal key directly (this is220* used for signatures in BIP342 script).221* - If merkle_root->IsNull(): tweak the internal key with H_TapTweak(pubkey) (this is used for222* key path spending when no scripts are present).223* - Otherwise: tweak the internal key with H_TapTweak(pubkey || *merkle_root)224* (this is used for key path spending with the225* Merkle root of the script tree).226*/227KeyPair ComputeKeyPair(const uint256* merkle_root) const;228};230CKey GenerateRandomKey(bool compressed = true) noexcept;232struct CExtKey {233unsigned char nDepth;234KeyFingerprint fingerprint;235unsigned int nChild;236ChainCode chaincode;237CKey key;239friend bool operator==(const CExtKey& a, const CExtKey& b)240{241return a.nDepth == b.nDepth &&242a.fingerprint == b.fingerprint &&243a.nChild == b.nChild &&244a.chaincode == b.chaincode &&245a.key == b.key;246}248CExtKey() = default;249CExtKey(const CExtPubKey& xpub, const CKey& key_in) : nDepth(xpub.nDepth), fingerprint(xpub.fingerprint), nChild(xpub.nChild), chaincode(xpub.chaincode), key(key_in) {}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.