Bitcoin Core 32.99.0
P2P Digital Currency
pubkey.h
Go to the documentation of this file.
1// Copyright (c) 2009-2010 Satoshi Nakamoto
2// Copyright (c) 2009-present 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_PUBKEY_H
8#define BITCOIN_PUBKEY_H
9
10#include <hash.h>
11#include <serialize.h>
12#include <span.h>
13#include <uint256.h>
14
15#include <array>
16#include <cassert>
17#include <cstring>
18#include <optional>
19#include <span>
20#include <vector>
21
22inline constexpr unsigned int BIP32_EXTKEY_SIZE = 74;
23inline constexpr unsigned int BIP32_EXTKEY_WITH_VERSION_SIZE = 78;
24
25using KeyFingerprint = std::array<unsigned char, 4>;
26
28class CKeyID : public uint160
29{
30public:
31 CKeyID() : uint160() {}
32 explicit CKeyID(const uint160& in) : uint160(in) {}
34 {
36 std::copy_n(begin(), ret.size(), ret.begin());
37 return ret;
38 }
39};
40
43{
44public:
48 static constexpr unsigned int SIZE = 65;
49 static constexpr unsigned int COMPRESSED_SIZE = 33;
50 static constexpr unsigned int SIGNATURE_SIZE = 72;
51 static constexpr unsigned int COMPACT_SIGNATURE_SIZE = 65;
56 static_assert(
58 "COMPRESSED_SIZE is larger than SIZE");
59
60private:
61
66 unsigned char vch[SIZE];
67
69 unsigned int static GetLen(unsigned char chHeader)
70 {
71 if (chHeader == 2 || chHeader == 3)
72 return COMPRESSED_SIZE;
73 if (chHeader == 4 || chHeader == 6 || chHeader == 7)
74 return SIZE;
75 return 0;
76 }
77
80 {
81 vch[0] = 0xFF;
82 }
83
84public:
85
86 bool static ValidSize(const std::vector<unsigned char> &vch) {
87 return vch.size() > 0 && GetLen(vch[0]) == vch.size();
88 }
89
92 {
93 Invalidate();
94 }
95
97 template <typename T>
98 void Set(const T pbegin, const T pend)
99 {
100 int len = pend == pbegin ? 0 : GetLen(pbegin[0]);
101 if (len && len == (pend - pbegin))
102 memcpy(vch, (unsigned char*)&pbegin[0], len);
103 else
104 Invalidate();
105 }
106
108 template <typename T>
109 CPubKey(const T pbegin, const T pend)
110 {
111 Set(pbegin, pend);
112 }
113
115 explicit CPubKey(std::span<const uint8_t> _vch)
116 {
117 Set(_vch.begin(), _vch.end());
118 }
119
121 unsigned int size() const { return GetLen(vch[0]); }
122 const unsigned char* data() const { return vch; }
123 const unsigned char* begin() const { return vch; }
124 const unsigned char* end() const { return vch + size(); }
125 const unsigned char& operator[](unsigned int pos) const { return vch[pos]; }
126
128 friend bool operator==(const CPubKey& a, const CPubKey& b)
129 {
130 return a.vch[0] == b.vch[0] &&
131 memcmp(a.vch, b.vch, a.size()) == 0;
132 }
133 friend bool operator<(const CPubKey& a, const CPubKey& b)
134 {
135 return a.vch[0] < b.vch[0] ||
136 (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0);
137 }
138 friend bool operator>(const CPubKey& a, const CPubKey& b)
139 {
140 return a.vch[0] > b.vch[0] ||
141 (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) > 0);
142 }
143
145 template <typename Stream>
146 void Serialize(Stream& s) const
147 {
148 unsigned int len = size();
149 ::WriteCompactSize(s, len);
150 s << std::span{vch, len};
151 }
152 template <typename Stream>
154 {
155 const unsigned int len(::ReadCompactSize(s));
156 if (len <= SIZE) {
157 s >> std::span{vch, len};
158 if (len != size()) {
159 Invalidate();
160 }
161 } else {
162 // invalid pubkey, skip available data
163 s.ignore(len);
164 Invalidate();
165 }
166 }
167
169 CKeyID GetID() const
170 {
171 return CKeyID(Hash160(std::span{vch}.first(size())));
172 }
173
176 {
177 return Hash(std::span{vch}.first(size()));
178 }
179
180 /*
181 * Check syntactic correctness.
182 *
183 * When setting a pubkey (Set()) or deserializing fails (its header bytes
184 * don't match the length of the data), the size is set to 0. Thus,
185 * by checking size, one can observe whether Set() or deserialization has
186 * failed.
187 *
188 * This does not check for more than that. In particular, it does not verify
189 * that the coordinates correspond to a point on the curve (see IsFullyValid()
190 * for that instead).
191 *
192 * Note that this is consensus critical as CheckECDSASignature() calls it!
193 */
194 bool IsValid() const
195 {
196 return size() > 0;
197 }
198
200 bool IsValidNonHybrid() const noexcept
201 {
202 return size() > 0 && (vch[0] == 0x02 || vch[0] == 0x03 || vch[0] == 0x04);
203 }
204
206 bool IsFullyValid() const;
207
209 bool IsCompressed() const
210 {
211 return size() == COMPRESSED_SIZE;
212 }
213
218 bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const;
219
223 static bool CheckLowS(const std::vector<unsigned char>& vchSig);
224
226 bool RecoverCompact(const uint256& hash, const std::vector<unsigned char>& vchSig);
227
229 bool Decompress();
230
232 [[nodiscard]] bool Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc, uint256* bip32_tweak_out = nullptr) const;
233};
234
236{
237private:
239
240public:
244 static const XOnlyPubKey NUMS_H;
245
247 XOnlyPubKey() = default;
248
249 XOnlyPubKey(const XOnlyPubKey&) = default;
251
255 bool IsFullyValid() const;
256
259 bool IsNull() const { return m_keydata.IsNull(); }
260
262 constexpr explicit XOnlyPubKey(std::span<const unsigned char> bytes) : m_keydata{bytes} {}
263
265 explicit XOnlyPubKey(const CPubKey& pubkey) : XOnlyPubKey(std::span{pubkey}.subspan(1, 32)) {}
266
271 bool VerifySchnorr(const uint256& msg, std::span<const unsigned char> sigbytes) const;
272
281 uint256 ComputeTapTweakHash(const uint256* merkle_root) const;
282
285 bool CheckTapTweak(const XOnlyPubKey& internal, const uint256& merkle_root, bool parity) const;
286
288 std::optional<std::pair<XOnlyPubKey, bool>> CreateTapTweak(const uint256* merkle_root) const;
289
295 std::vector<CKeyID> GetKeyIDs() const;
297 std::vector<CPubKey> GetCPubKeys() const;
298
300
301 const unsigned char& operator[](int pos) const { return *(m_keydata.begin() + pos); }
302 static constexpr size_t size() { return decltype(m_keydata)::size(); }
303 const unsigned char* data() const { return m_keydata.begin(); }
304 const unsigned char* begin() const { return m_keydata.begin(); }
305 const unsigned char* end() const { return m_keydata.end(); }
306 unsigned char* data() { return m_keydata.begin(); }
307 unsigned char* begin() { return m_keydata.begin(); }
308 unsigned char* end() { return m_keydata.end(); }
309 bool operator==(const XOnlyPubKey& other) const { return m_keydata == other.m_keydata; }
310 bool operator<(const XOnlyPubKey& other) const { return m_keydata < other.m_keydata; }
311
313 SERIALIZE_METHODS(XOnlyPubKey, obj) { READWRITE(obj.m_keydata); }
314};
315
318{
319private:
320 static constexpr size_t SIZE = 64;
321 std::array<std::byte, SIZE> m_pubkey;
322
323public:
325 EllSwiftPubKey() noexcept = default;
326
328 EllSwiftPubKey(std::span<const std::byte> ellswift) noexcept;
329
331 CPubKey Decode() const;
332
333 // Read-only access for serialization.
334 const std::byte* data() const { return m_pubkey.data(); }
335 static constexpr size_t size() { return SIZE; }
336 auto begin() const { return m_pubkey.cbegin(); }
337 auto end() const { return m_pubkey.cend(); }
338
339 bool friend operator==(const EllSwiftPubKey& a, const EllSwiftPubKey& b)
340 {
341 return a.m_pubkey == b.m_pubkey;
342 }
343};
344
346 unsigned char version[4];
347 unsigned char nDepth;
349 unsigned int nChild;
352
353 friend bool operator==(const CExtPubKey &a, const CExtPubKey &b)
354 {
355 return a.nDepth == b.nDepth &&
356 a.fingerprint == b.fingerprint &&
357 a.nChild == b.nChild &&
358 a.chaincode == b.chaincode &&
359 a.pubkey == b.pubkey;
360 }
361
362 friend bool operator<(const CExtPubKey &a, const CExtPubKey &b)
363 {
364 if (a.pubkey < b.pubkey) {
365 return true;
366 } else if (a.pubkey > b.pubkey) {
367 return false;
368 }
369 return a.chaincode < b.chaincode;
370 }
371
373 {
374 return pubkey.GetID().fingerprint();
375 }
376
378 template <typename Stream>
379 void Serialize(Stream& s) const
380 {
382 s << nDepth << fingerprint << Using<BigEndianFormatter<4>>(nChild) << chaincode << std::span{pubkey.data(), CPubKey::COMPRESSED_SIZE};
383 }
384 template <typename Stream>
386 {
387 std::array<unsigned char, CPubKey::COMPRESSED_SIZE> ser_pubkey;
388 s >> nDepth >> fingerprint >> Using<BigEndianFormatter<4>>(nChild) >> chaincode >> ser_pubkey;
389 pubkey.Set(ser_pubkey.begin(), ser_pubkey.end());
390 if ((nDepth == 0 && (nChild != 0 || fingerprint != KeyFingerprint{})) || !pubkey.IsFullyValid()) pubkey = CPubKey();
391 }
392 [[nodiscard]] bool Derive(CExtPubKey& out, unsigned int nChild, uint256* bip32_tweak_out = nullptr) const;
393};
394
395#endif // BITCOIN_PUBKEY_H
int ret
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:29
CKeyID()
Definition: pubkey.h:31
CKeyID(const uint160 &in)
Definition: pubkey.h:32
KeyFingerprint fingerprint() const
Definition: pubkey.h:33
An encapsulated public key.
Definition: pubkey.h:43
const unsigned char * data() const
Definition: pubkey.h:122
bool RecoverCompact(const uint256 &hash, const std::vector< unsigned char > &vchSig)
Recover a public key from a compact signature.
Definition: pubkey.cpp:300
bool IsCompressed() const
Check whether this is a compressed public key.
Definition: pubkey.h:209
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:169
static constexpr unsigned int COMPRESSED_SIZE
Definition: pubkey.h:49
CPubKey()
Construct an invalid public key.
Definition: pubkey.h:91
static bool CheckLowS(const std::vector< unsigned char > &vchSig)
Check whether a signature is normalized (lower-S).
Definition: pubkey.cpp:393
CPubKey(std::span< const uint8_t > _vch)
Construct a public key from a byte vector.
Definition: pubkey.h:115
bool IsValid() const
Definition: pubkey.h:194
friend bool operator>(const CPubKey &a, const CPubKey &b)
Definition: pubkey.h:138
bool Decompress()
Turn this public key into an uncompressed public key.
Definition: pubkey.cpp:327
const unsigned char * end() const
Definition: pubkey.h:124
bool Verify(const uint256 &hash, const std::vector< unsigned char > &vchSig) const
Verify a DER signature (~72 bytes).
Definition: pubkey.cpp:283
static constexpr unsigned int SIZE
secp256k1:
Definition: pubkey.h:48
bool IsFullyValid() const
fully validate whether this is a valid public key (more expensive than IsValid())
Definition: pubkey.cpp:320
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
Definition: pubkey.h:121
const unsigned char * begin() const
Definition: pubkey.h:123
bool Derive(CPubKey &pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode &cc, uint256 *bip32_tweak_out=nullptr) const
Derive BIP32 child pubkey.
Definition: pubkey.cpp:341
static bool ValidSize(const std::vector< unsigned char > &vch)
Definition: pubkey.h:86
unsigned static int GetLen(unsigned char chHeader)
Compute the length of a pubkey with a given first byte.
Definition: pubkey.h:69
friend bool operator==(const CPubKey &a, const CPubKey &b)
Comparator implementation.
Definition: pubkey.h:128
void Serialize(Stream &s) const
Implement serialization, as if this was a byte vector.
Definition: pubkey.h:146
unsigned char vch[SIZE]
see www.keylength.com script supports up to 75 for single byte push
Definition: pubkey.h:66
CPubKey(const T pbegin, const T pend)
Construct a public key using begin/end iterators to byte data.
Definition: pubkey.h:109
void Invalidate()
Set this key data to be invalid.
Definition: pubkey.h:79
void Unserialize(Stream &s)
Definition: pubkey.h:153
uint256 GetHash() const
Get the 256-bit hash of this public key.
Definition: pubkey.h:175
const unsigned char & operator[](unsigned int pos) const
Definition: pubkey.h:125
static constexpr unsigned int SIGNATURE_SIZE
Definition: pubkey.h:50
bool IsValidNonHybrid() const noexcept
Check if a public key is a syntactically valid compressed or uncompressed key.
Definition: pubkey.h:200
static constexpr unsigned int COMPACT_SIGNATURE_SIZE
Definition: pubkey.h:51
void Set(const T pbegin, const T pend)
Initialize a public key using begin/end iterators to byte data.
Definition: pubkey.h:98
friend bool operator<(const CPubKey &a, const CPubKey &b)
Definition: pubkey.h:133
A BIP32 chain code.
Definition: hash.h:23
unsigned char * end()
Definition: pubkey.h:308
unsigned char * begin()
Definition: pubkey.h:307
XOnlyPubKey & operator=(const XOnlyPubKey &)=default
const unsigned char * end() const
Definition: pubkey.h:305
std::vector< CPubKey > GetCPubKeys() const
Returns this XOnlyPubKey with 0x02 and 0x03 prefixes.
Definition: pubkey.cpp:200
bool IsNull() const
Test whether this is the 0 key (the result of default construction).
Definition: pubkey.h:259
unsigned char * data()
Definition: pubkey.h:306
const unsigned char * begin() const
Definition: pubkey.h:304
std::optional< std::pair< XOnlyPubKey, bool > > CreateTapTweak(const uint256 *merkle_root) const
Construct a Taproot tweaked output point with this point as internal key.
Definition: pubkey.cpp:265
bool CheckTapTweak(const XOnlyPubKey &internal, const uint256 &merkle_root, bool parity) const
Verify that this is a Taproot tweaked output point, against a specified internal key,...
Definition: pubkey.cpp:257
static const XOnlyPubKey NUMS_H
Nothing Up My Sleeve point H Used as an internal key for provably disabling the key path spend see BI...
Definition: pubkey.h:244
static constexpr size_t size()
Definition: pubkey.h:302
constexpr XOnlyPubKey(std::span< const unsigned char > bytes)
Construct an x-only pubkey from exactly 32 bytes.
Definition: pubkey.h:262
const unsigned char * data() const
Definition: pubkey.h:303
bool VerifySchnorr(const uint256 &msg, std::span< const unsigned char > sigbytes) const
Verify a Schnorr signature against this public key.
Definition: pubkey.cpp:236
SERIALIZE_METHODS(XOnlyPubKey, obj)
Implement serialization without length prefixes since it is a fixed length.
Definition: pubkey.h:313
CPubKey GetEvenCorrespondingCPubKey() const
Definition: pubkey.cpp:223
uint256 m_keydata
Definition: pubkey.h:238
XOnlyPubKey(const XOnlyPubKey &)=default
XOnlyPubKey(const CPubKey &pubkey)
Construct an x-only pubkey from a normal pubkey.
Definition: pubkey.h:265
bool operator<(const XOnlyPubKey &other) const
Definition: pubkey.h:310
bool IsFullyValid() const
Determine if this pubkey is fully valid.
Definition: pubkey.cpp:230
std::vector< CKeyID > GetKeyIDs() const
Returns a list of CKeyIDs for the CPubKeys that could have been used to create this XOnlyPubKey.
Definition: pubkey.cpp:214
uint256 ComputeTapTweakHash(const uint256 *merkle_root) const
Compute the Taproot tweak as specified in BIP341, with *this as internal key:
Definition: pubkey.cpp:246
const unsigned char & operator[](int pos) const
Definition: pubkey.h:301
XOnlyPubKey()=default
Construct an empty x-only pubkey.
bool operator==(const XOnlyPubKey &other) const
Definition: pubkey.h:309
constexpr bool IsNull() const
Definition: uint256.h:50
constexpr unsigned char * end()
Definition: uint256.h:102
constexpr unsigned char * begin()
Definition: uint256.h:101
160-bit opaque blob.
Definition: uint256.h:184
256-bit opaque blob.
Definition: uint256.h:196
uint160 Hash160(const T1 &in1)
Compute the 160-bit hash an object.
Definition: hash.h:100
uint256 Hash(const T &in1)
Compute the 256-bit hash of an object.
Definition: hash.h:83
SocketId Stream
Definition: util.h:30
constexpr unsigned int BIP32_EXTKEY_SIZE
Definition: pubkey.h:22
constexpr unsigned int BIP32_EXTKEY_WITH_VERSION_SIZE
Definition: pubkey.h:23
std::array< unsigned char, 4 > KeyFingerprint
Definition: pubkey.h:25
void WriteCompactSize(SizeComputer &os, uint64_t nSize)
Definition: serialize.h:1151
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
Definition: serialize.h:333
#define READWRITE(...)
Definition: serialize.h:148
friend bool operator==(const CExtPubKey &a, const CExtPubKey &b)
Definition: pubkey.h:353
unsigned char version[4]
Definition: pubkey.h:346
ChainCode chaincode
Definition: pubkey.h:350
KeyFingerprint fingerprint
Definition: pubkey.h:348
unsigned char nDepth
Definition: pubkey.h:347
void Serialize(Stream &s) const
BIP32 serialization without the version bytes (BIP32_EXTKEY_SIZE bytes)
Definition: pubkey.h:379
KeyFingerprint id_key_fingerprint() const
Definition: pubkey.h:372
void Unserialize(Stream &s)
Definition: pubkey.h:385
CPubKey pubkey
Definition: pubkey.h:351
unsigned int nChild
Definition: pubkey.h:349
friend bool operator<(const CExtPubKey &a, const CExtPubKey &b)
Definition: pubkey.h:362
bool Derive(CExtPubKey &out, unsigned int nChild, uint256 *bip32_tweak_out=nullptr) const
Definition: pubkey.cpp:385
An ElligatorSwift-encoded public key.
Definition: pubkey.h:318
auto begin() const
Definition: pubkey.h:336
bool friend operator==(const EllSwiftPubKey &a, const EllSwiftPubKey &b)
Definition: pubkey.h:339
std::array< std::byte, SIZE > m_pubkey
Definition: pubkey.h:321
CPubKey Decode() const
Decode to normal compressed CPubKey (for debugging purposes).
Definition: pubkey.cpp:371
static constexpr size_t SIZE
Definition: pubkey.h:320
static constexpr size_t size()
Definition: pubkey.h:335
const std::byte * data() const
Definition: pubkey.h:334
EllSwiftPubKey() noexcept=default
Default constructor creates all-zero pubkey (which is valid).
auto end() const
Definition: pubkey.h:337
assert(!tx.IsCoinBase())