Bitcoin Core  22.99.0
P2P Digital Currency
key.cpp
Go to the documentation of this file.
1 // Copyright (c) 2020 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <chainparams.h>
6 #include <chainparamsbase.h>
7 #include <key.h>
8 #include <key_io.h>
9 #include <outputtype.h>
10 #include <policy/policy.h>
11 #include <pubkey.h>
12 #include <rpc/util.h>
13 #include <script/keyorigin.h>
14 #include <script/script.h>
15 #include <script/sign.h>
16 #include <script/signingprovider.h>
17 #include <script/standard.h>
18 #include <streams.h>
19 #include <test/fuzz/fuzz.h>
20 #include <util/strencodings.h>
21 
22 #include <cassert>
23 #include <cstdint>
24 #include <numeric>
25 #include <string>
26 #include <vector>
27 
29 {
30  static const ECCVerifyHandle ecc_verify_handle;
31  ECC_Start();
33 }
34 
36 {
37  const CKey key = [&] {
38  CKey k;
39  k.Set(buffer.begin(), buffer.end(), true);
40  return k;
41  }();
42  if (!key.IsValid()) {
43  return;
44  }
45 
46  {
47  assert(key.begin() + key.size() == key.end());
48  assert(key.IsCompressed());
49  assert(key.size() == 32);
50  assert(DecodeSecret(EncodeSecret(key)) == key);
51  }
52 
53  {
54  CKey invalid_key;
55  assert(!(invalid_key == key));
56  assert(!invalid_key.IsCompressed());
57  assert(!invalid_key.IsValid());
58  assert(invalid_key.size() == 0);
59  }
60 
61  {
62  CKey uncompressed_key;
63  uncompressed_key.Set(buffer.begin(), buffer.end(), false);
64  assert(!(uncompressed_key == key));
65  assert(!uncompressed_key.IsCompressed());
66  assert(key.size() == 32);
67  assert(uncompressed_key.begin() + uncompressed_key.size() == uncompressed_key.end());
68  assert(uncompressed_key.IsValid());
69  }
70 
71  {
72  CKey copied_key;
73  copied_key.Set(key.begin(), key.end(), key.IsCompressed());
74  assert(copied_key == key);
75  }
76 
77  {
78  CKey negated_key = key;
79  negated_key.Negate();
80  assert(negated_key.IsValid());
81  assert(!(negated_key == key));
82 
83  negated_key.Negate();
84  assert(negated_key == key);
85  }
86 
87  const uint256 random_uint256 = Hash(buffer);
88 
89  {
90  CKey child_key;
91  ChainCode child_chaincode;
92  const bool ok = key.Derive(child_key, child_chaincode, 0, random_uint256);
93  assert(ok);
94  assert(child_key.IsValid());
95  assert(!(child_key == key));
96  assert(child_chaincode != random_uint256);
97  }
98 
99  const CPubKey pubkey = key.GetPubKey();
100 
101  {
102  assert(pubkey.size() == 33);
103  assert(key.VerifyPubKey(pubkey));
104  assert(pubkey.GetHash() != random_uint256);
105  assert(pubkey.begin() + pubkey.size() == pubkey.end());
106  assert(pubkey.data() == pubkey.begin());
107  assert(pubkey.IsCompressed());
108  assert(pubkey.IsValid());
109  assert(pubkey.IsFullyValid());
110  assert(HexToPubKey(HexStr(pubkey)) == pubkey);
111  assert(GetAllDestinationsForKey(pubkey).size() == 3);
112  }
113 
114  {
116  pubkey.Serialize(data_stream);
117 
118  CPubKey pubkey_deserialized;
119  pubkey_deserialized.Unserialize(data_stream);
120  assert(pubkey_deserialized == pubkey);
121  }
122 
123  {
124  const CScript tx_pubkey_script = GetScriptForRawPubKey(pubkey);
125  assert(!tx_pubkey_script.IsPayToScriptHash());
126  assert(!tx_pubkey_script.IsPayToWitnessScriptHash());
127  assert(!tx_pubkey_script.IsPushOnly());
128  assert(!tx_pubkey_script.IsUnspendable());
129  assert(tx_pubkey_script.HasValidOps());
130  assert(tx_pubkey_script.size() == 35);
131 
132  const CScript tx_multisig_script = GetScriptForMultisig(1, {pubkey});
133  assert(!tx_multisig_script.IsPayToScriptHash());
134  assert(!tx_multisig_script.IsPayToWitnessScriptHash());
135  assert(!tx_multisig_script.IsPushOnly());
136  assert(!tx_multisig_script.IsUnspendable());
137  assert(tx_multisig_script.HasValidOps());
138  assert(tx_multisig_script.size() == 37);
139 
140  FillableSigningProvider fillable_signing_provider;
141  assert(IsSolvable(fillable_signing_provider, tx_pubkey_script));
142  assert(IsSolvable(fillable_signing_provider, tx_multisig_script));
143  assert(!IsSegWitOutput(fillable_signing_provider, tx_pubkey_script));
144  assert(!IsSegWitOutput(fillable_signing_provider, tx_multisig_script));
145  assert(fillable_signing_provider.GetKeys().size() == 0);
146  assert(!fillable_signing_provider.HaveKey(pubkey.GetID()));
147 
148  const bool ok_add_key = fillable_signing_provider.AddKey(key);
149  assert(ok_add_key);
150  assert(fillable_signing_provider.HaveKey(pubkey.GetID()));
151 
152  FillableSigningProvider fillable_signing_provider_pub;
153  assert(!fillable_signing_provider_pub.HaveKey(pubkey.GetID()));
154 
155  const bool ok_add_key_pubkey = fillable_signing_provider_pub.AddKeyPubKey(key, pubkey);
156  assert(ok_add_key_pubkey);
157  assert(fillable_signing_provider_pub.HaveKey(pubkey.GetID()));
158 
159  TxoutType which_type_tx_pubkey;
160  const bool is_standard_tx_pubkey = IsStandard(tx_pubkey_script, which_type_tx_pubkey);
161  assert(is_standard_tx_pubkey);
162  assert(which_type_tx_pubkey == TxoutType::PUBKEY);
163 
164  TxoutType which_type_tx_multisig;
165  const bool is_standard_tx_multisig = IsStandard(tx_multisig_script, which_type_tx_multisig);
166  assert(is_standard_tx_multisig);
167  assert(which_type_tx_multisig == TxoutType::MULTISIG);
168 
169  std::vector<std::vector<unsigned char>> v_solutions_ret_tx_pubkey;
170  const TxoutType outtype_tx_pubkey = Solver(tx_pubkey_script, v_solutions_ret_tx_pubkey);
171  assert(outtype_tx_pubkey == TxoutType::PUBKEY);
172  assert(v_solutions_ret_tx_pubkey.size() == 1);
173  assert(v_solutions_ret_tx_pubkey[0].size() == 33);
174 
175  std::vector<std::vector<unsigned char>> v_solutions_ret_tx_multisig;
176  const TxoutType outtype_tx_multisig = Solver(tx_multisig_script, v_solutions_ret_tx_multisig);
177  assert(outtype_tx_multisig == TxoutType::MULTISIG);
178  assert(v_solutions_ret_tx_multisig.size() == 3);
179  assert(v_solutions_ret_tx_multisig[0].size() == 1);
180  assert(v_solutions_ret_tx_multisig[1].size() == 33);
181  assert(v_solutions_ret_tx_multisig[2].size() == 1);
182 
183  OutputType output_type{};
184  const CTxDestination tx_destination = GetDestinationForKey(pubkey, output_type);
185  assert(output_type == OutputType::LEGACY);
186  assert(IsValidDestination(tx_destination));
187  assert(CTxDestination{PKHash{pubkey}} == tx_destination);
188 
189  const CScript script_for_destination = GetScriptForDestination(tx_destination);
190  assert(script_for_destination.size() == 25);
191 
192  const std::string destination_address = EncodeDestination(tx_destination);
193  assert(DecodeDestination(destination_address) == tx_destination);
194 
195  const CPubKey pubkey_from_address_string = AddrToPubKey(fillable_signing_provider, destination_address);
196  assert(pubkey_from_address_string == pubkey);
197 
198  CKeyID key_id = pubkey.GetID();
199  assert(!key_id.IsNull());
200  assert(key_id == CKeyID{key_id});
201  assert(key_id == GetKeyForDestination(fillable_signing_provider, tx_destination));
202 
203  CPubKey pubkey_out;
204  const bool ok_get_pubkey = fillable_signing_provider.GetPubKey(key_id, pubkey_out);
205  assert(ok_get_pubkey);
206 
207  CKey key_out;
208  const bool ok_get_key = fillable_signing_provider.GetKey(key_id, key_out);
209  assert(ok_get_key);
210  assert(fillable_signing_provider.GetKeys().size() == 1);
211  assert(fillable_signing_provider.HaveKey(key_id));
212 
213  KeyOriginInfo key_origin_info;
214  const bool ok_get_key_origin = fillable_signing_provider.GetKeyOrigin(key_id, key_origin_info);
215  assert(!ok_get_key_origin);
216  }
217 
218  {
219  const std::vector<unsigned char> vch_pubkey{pubkey.begin(), pubkey.end()};
220  assert(CPubKey::ValidSize(vch_pubkey));
221  assert(!CPubKey::ValidSize({pubkey.begin(), pubkey.begin() + pubkey.size() - 1}));
222 
223  const CPubKey pubkey_ctor_1{vch_pubkey};
224  assert(pubkey == pubkey_ctor_1);
225 
226  const CPubKey pubkey_ctor_2{vch_pubkey.begin(), vch_pubkey.end()};
227  assert(pubkey == pubkey_ctor_2);
228 
229  CPubKey pubkey_set;
230  pubkey_set.Set(vch_pubkey.begin(), vch_pubkey.end());
231  assert(pubkey == pubkey_set);
232  }
233 
234  {
235  const CPubKey invalid_pubkey{};
236  assert(!invalid_pubkey.IsValid());
237  assert(!invalid_pubkey.IsFullyValid());
238  assert(!(pubkey == invalid_pubkey));
239  assert(pubkey != invalid_pubkey);
240  assert(pubkey < invalid_pubkey);
241  }
242 
243  {
244  // Cover CPubKey's operator[](unsigned int pos)
245  unsigned int sum = 0;
246  for (size_t i = 0; i < pubkey.size(); ++i) {
247  sum += pubkey[i];
248  }
249  assert(std::accumulate(pubkey.begin(), pubkey.end(), 0U) == sum);
250  }
251 
252  {
253  CPubKey decompressed_pubkey = pubkey;
254  assert(decompressed_pubkey.IsCompressed());
255 
256  const bool ok = decompressed_pubkey.Decompress();
257  assert(ok);
258  assert(!decompressed_pubkey.IsCompressed());
259  assert(decompressed_pubkey.size() == 65);
260  }
261 
262  {
263  std::vector<unsigned char> vch_sig;
264  const bool ok = key.Sign(random_uint256, vch_sig, false);
265  assert(ok);
266  assert(pubkey.Verify(random_uint256, vch_sig));
267  assert(CPubKey::CheckLowS(vch_sig));
268 
269  const std::vector<unsigned char> vch_invalid_sig{vch_sig.begin(), vch_sig.begin() + vch_sig.size() - 1};
270  assert(!pubkey.Verify(random_uint256, vch_invalid_sig));
271  assert(!CPubKey::CheckLowS(vch_invalid_sig));
272  }
273 
274  {
275  std::vector<unsigned char> vch_compact_sig;
276  const bool ok_sign_compact = key.SignCompact(random_uint256, vch_compact_sig);
277  assert(ok_sign_compact);
278 
279  CPubKey recover_pubkey;
280  const bool ok_recover_compact = recover_pubkey.RecoverCompact(random_uint256, vch_compact_sig);
281  assert(ok_recover_compact);
282  assert(recover_pubkey == pubkey);
283  }
284 
285  {
286  CPubKey child_pubkey;
287  ChainCode child_chaincode;
288  const bool ok = pubkey.Derive(child_pubkey, child_chaincode, 0, random_uint256);
289  assert(ok);
290  assert(child_pubkey != pubkey);
291  assert(child_pubkey.IsCompressed());
292  assert(child_pubkey.IsFullyValid());
293  assert(child_pubkey.IsValid());
294  assert(child_pubkey.size() == 33);
295  assert(child_chaincode != random_uint256);
296  }
297 
298  const CPrivKey priv_key = key.GetPrivKey();
299 
300  {
301  for (const bool skip_check : {true, false}) {
302  CKey loaded_key;
303  const bool ok = loaded_key.Load(priv_key, pubkey, skip_check);
304  assert(ok);
305  assert(key == loaded_key);
306  }
307  }
308 }
CKey::IsCompressed
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
Definition: key.h:95
policy.h
OutputType
OutputType
Definition: outputtype.h:18
assert
assert(!tx.IsCoinBase())
Solver
TxoutType Solver(const CScript &scriptPubKey, std::vector< std::vector< unsigned char >> &vSolutionsRet)
Parse a scriptPubKey and identify script type for standard scripts.
Definition: standard.cpp:144
FillableSigningProvider::GetKeys
virtual std::set< CKeyID > GetKeys() const
Definition: signingprovider.cpp:132
IsStandard
bool IsStandard(const CScript &scriptPubKey, TxoutType &whichType)
Definition: policy.cpp:53
TxoutType
TxoutType
Definition: standard.h:59
key_io.h
streams.h
OutputType::LEGACY
@ LEGACY
CScript::IsPayToWitnessScriptHash
bool IsPayToWitnessScriptHash() const
Definition: script.cpp:210
FillableSigningProvider
Fillable signing provider that keeps keys in an address->secret map.
Definition: signingprovider.h:91
GetScriptForDestination
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
Definition: standard.cpp:351
CKey::GetPrivKey
CPrivKey GetPrivKey() const
Convert the private key to a CPrivKey (serialized OpenSSL private key data).
Definition: key.cpp:174
outputtype.h
CPubKey::Set
void Set(const T pbegin, const T pend)
Initialize a public key using begin/end iterators to byte data.
Definition: pubkey.h:88
chainparamsbase.h
CKey::Set
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
Definition: key.h:73
CPrivKey
std::vector< unsigned char, secure_allocator< unsigned char > > CPrivKey
CPrivKey is a serialized private key, with all parameters included (SIZE bytes)
Definition: key.h:23
CScript::HasValidOps
bool HasValidOps() const
Check if the script contains valid OP_CODES.
Definition: script.cpp:270
CPubKey::Derive
bool Derive(CPubKey &pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode &cc) const
Derive BIP32 child pubkey.
Definition: pubkey.cpp:315
CPubKey::data
const unsigned char * data() const
Definition: pubkey.h:112
CPubKey::Decompress
bool Decompress()
Turn this public key into an uncompressed public key.
Definition: pubkey.cpp:300
HexToPubKey
CPubKey HexToPubKey(const std::string &hex_in)
Definition: util.cpp:191
CKey::Derive
bool Derive(CKey &keyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode &cc) const
Derive BIP32 child key.
Definition: key.cpp:294
CKeyID
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:22
CScript::IsPayToScriptHash
bool IsPayToScriptHash() const
Definition: script.cpp:201
GetDestinationForKey
CTxDestination GetDestinationForKey(const CPubKey &key, OutputType type)
Get a destination of the requested type (if possible) to the specified key.
Definition: outputtype.cpp:49
pubkey.h
chainparams.h
CPubKey::ValidSize
static bool ValidSize(const std::vector< unsigned char > &vch)
Definition: pubkey.h:76
FillableSigningProvider::AddKey
virtual bool AddKey(const CKey &key)
Definition: signingprovider.h:152
CKey::end
const unsigned char * end() const
Definition: key.h:89
FUZZ_TARGET_INIT
FUZZ_TARGET_INIT(key, initialize_key)
Definition: key.cpp:35
CScript::IsPushOnly
bool IsPushOnly(const_iterator pc) const
Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical).
Definition: script.cpp:236
signingprovider.h
CPubKey::begin
const unsigned char * begin() const
Definition: pubkey.h:113
CKey::begin
const unsigned char * begin() const
Definition: key.h:88
strencodings.h
Hash
uint256 Hash(const T &in1)
Compute the 256-bit hash of an object.
Definition: hash.h:75
TxoutType::PUBKEY
@ PUBKEY
CTxDestination
std::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:157
IsValidDestination
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:373
FillableSigningProvider::GetPubKey
virtual bool GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const override
Definition: signingprovider.cpp:108
EncodeSecret
std::string EncodeSecret(const CKey &key)
Definition: key_io.cpp:196
SigningProvider::GetKeyOrigin
virtual bool GetKeyOrigin(const CKeyID &keyid, KeyOriginInfo &info) const
Definition: signingprovider.h:27
GetScriptForRawPubKey
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
Definition: standard.cpp:356
GetScriptForMultisig
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
Definition: standard.cpp:361
CPubKey::Verify
bool Verify(const uint256 &hash, const std::vector< unsigned char > &vchSig) const
Verify a DER signature (~72 bytes).
Definition: pubkey.cpp:253
CPubKey::end
const unsigned char * end() const
Definition: pubkey.h:114
IsSegWitOutput
bool IsSegWitOutput(const SigningProvider &provider, const CScript &script)
Check whether a scriptPubKey is known to be segwit.
Definition: sign.cpp:599
CPubKey::GetHash
uint256 GetHash() const
Get the 256-bit hash of this public key.
Definition: pubkey.h:166
CKey::SignCompact
bool SignCompact(const uint256 &hash, std::vector< unsigned char > &vchSig) const
Create a compact signature (65 bytes), which allows reconstructing the used public key.
Definition: key.cpp:249
CBaseChainParams::REGTEST
static const std::string REGTEST
Definition: chainparamsbase.h:25
initialize_key
void initialize_key()
Definition: key.cpp:28
CKey::IsValid
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:92
sign.h
CPubKey::Unserialize
void Unserialize(Stream &s)
Definition: pubkey.h:142
CKey::Sign
bool Sign(const uint256 &hash, std::vector< unsigned char > &vchSig, bool grind=true, uint32_t test_case=0) const
Create a DER-serialized signature.
Definition: key.cpp:213
standard.h
CPubKey::Serialize
void Serialize(Stream &s) const
Implement serialization, as if this was a byte vector.
Definition: pubkey.h:135
GetKeyForDestination
CKeyID GetKeyForDestination(const SigningProvider &store, const CTxDestination &dest)
Return the CKeyID of the key involved in a script (if there is a unique one).
Definition: signingprovider.cpp:191
SelectParams
void SelectParams(const std::string &network)
Sets the params returned by Params() to those for the given chain name.
Definition: chainparams.cpp:578
DecodeSecret
CKey DecodeSecret(const std::string &str)
Definition: key_io.cpp:178
CPubKey::size
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
Definition: pubkey.h:111
uint256
256-bit opaque blob.
Definition: uint256.h:124
DecodeDestination
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg)
Definition: key_io.cpp:261
CKey::GetPubKey
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:187
CScript
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:405
script.h
CPubKey::RecoverCompact
bool RecoverCompact(const uint256 &hash, const std::vector< unsigned char > &vchSig)
Recover a public key from a compact signature.
Definition: pubkey.cpp:271
CKey::Negate
bool Negate()
Negate private key.
Definition: key.cpp:168
CPubKey::IsCompressed
bool IsCompressed() const
Check whether this is a compressed public key.
Definition: pubkey.h:194
PKHash
Definition: standard.h:79
ECC_Start
void ECC_Start()
Initialize the elliptic curve support.
Definition: key.cpp:370
key.h
CPubKey
An encapsulated public key.
Definition: pubkey.h:32
CKey::size
unsigned int size() const
Simple read-only vector-like interface.
Definition: key.h:87
base_blob::IsNull
bool IsNull() const
Definition: uint256.h:31
ECCVerifyHandle
Users of this module must hold an ECCVerifyHandle.
Definition: pubkey.h:315
CKey
An encapsulated private key.
Definition: key.h:26
CKey::VerifyPubKey
bool VerifyPubKey(const CPubKey &vchPubKey) const
Verify thoroughly whether a private key and a public key match.
Definition: key.cpp:235
FillableSigningProvider::GetKey
virtual bool GetKey(const CKeyID &address, CKey &keyOut) const override
Definition: signingprovider.cpp:142
IsSolvable
bool IsSolvable(const SigningProvider &provider, const CScript &script)
Definition: sign.cpp:580
sum
volatile double sum
Definition: examples.cpp:10
fuzz.h
prevector::size
size_type size() const
Definition: prevector.h:282
FillableSigningProvider::AddKeyPubKey
virtual bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey)
Definition: signingprovider.cpp:118
TxoutType::MULTISIG
@ MULTISIG
CPubKey::IsFullyValid
bool IsFullyValid() const
fully validate whether this is a valid public key (more expensive than IsValid())
Definition: pubkey.cpp:292
CDataStream
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:204
SER_NETWORK
@ SER_NETWORK
Definition: serialize.h:138
util.h
CPubKey::IsValid
bool IsValid() const
Definition: pubkey.h:185
FillableSigningProvider::HaveKey
virtual bool HaveKey(const CKeyID &address) const override
Definition: signingprovider.cpp:126
CKey::Load
bool Load(const CPrivKey &privkey, const CPubKey &vchPubKey, bool fSkipCheck)
Load private key and check that public key matches.
Definition: key.cpp:282
CScript::IsUnspendable
bool IsUnspendable() const
Returns whether the script is guaranteed to fail at execution, regardless of the initial stack.
Definition: script.h:544
keyorigin.h
HexStr
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
Definition: strencodings.cpp:594
GetAllDestinationsForKey
std::vector< CTxDestination > GetAllDestinationsForKey(const CPubKey &key)
Get all destinations (potentially) supported by the wallet for the given key.
Definition: outputtype.cpp:69
AddrToPubKey
CPubKey AddrToPubKey(const FillableSigningProvider &keystore, const std::string &addr_in)
Definition: util.cpp:204
EncodeDestination
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:256
KeyOriginInfo
Definition: keyorigin.h:11
CPubKey::GetID
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:160
CPubKey::CheckLowS
static bool CheckLowS(const std::vector< unsigned char > &vchSig)
Check whether a signature is normalized (lower-S).
Definition: pubkey.cpp:364
INIT_PROTO_VERSION
static const int INIT_PROTO_VERSION
initial proto version, to be increased after version/verack negotiation
Definition: version.h:15