Bitcoin Core  22.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-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_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 <cstring>
16 #include <optional>
17 #include <vector>
18 
19 const unsigned int BIP32_EXTKEY_SIZE = 74;
20 const unsigned int BIP32_EXTKEY_WITH_VERSION_SIZE = 78;
21 
23 class CKeyID : public uint160
24 {
25 public:
26  CKeyID() : uint160() {}
27  explicit CKeyID(const uint160& in) : uint160(in) {}
28 };
29 
31 
33 class CPubKey
34 {
35 public:
39  static constexpr unsigned int SIZE = 65;
40  static constexpr unsigned int COMPRESSED_SIZE = 33;
41  static constexpr unsigned int SIGNATURE_SIZE = 72;
42  static constexpr unsigned int COMPACT_SIGNATURE_SIZE = 65;
47  static_assert(
49  "COMPRESSED_SIZE is larger than SIZE");
50 
51 private:
52 
57  unsigned char vch[SIZE];
58 
60  unsigned int static GetLen(unsigned char chHeader)
61  {
62  if (chHeader == 2 || chHeader == 3)
63  return COMPRESSED_SIZE;
64  if (chHeader == 4 || chHeader == 6 || chHeader == 7)
65  return SIZE;
66  return 0;
67  }
68 
70  void Invalidate()
71  {
72  vch[0] = 0xFF;
73  }
74 
75 public:
76 
77  bool static ValidSize(const std::vector<unsigned char> &vch) {
78  return vch.size() > 0 && GetLen(vch[0]) == vch.size();
79  }
80 
83  {
84  Invalidate();
85  }
86 
88  template <typename T>
89  void Set(const T pbegin, const T pend)
90  {
91  int len = pend == pbegin ? 0 : GetLen(pbegin[0]);
92  if (len && len == (pend - pbegin))
93  memcpy(vch, (unsigned char*)&pbegin[0], len);
94  else
95  Invalidate();
96  }
97 
99  template <typename T>
100  CPubKey(const T pbegin, const T pend)
101  {
102  Set(pbegin, pend);
103  }
104 
107  {
108  Set(_vch.begin(), _vch.end());
109  }
110 
112  unsigned int size() const { return GetLen(vch[0]); }
113  const unsigned char* data() const { return vch; }
114  const unsigned char* begin() const { return vch; }
115  const unsigned char* end() const { return vch + size(); }
116  const unsigned char& operator[](unsigned int pos) const { return vch[pos]; }
117 
119  friend bool operator==(const CPubKey& a, const CPubKey& b)
120  {
121  return a.vch[0] == b.vch[0] &&
122  memcmp(a.vch, b.vch, a.size()) == 0;
123  }
124  friend bool operator!=(const CPubKey& a, const CPubKey& b)
125  {
126  return !(a == b);
127  }
128  friend bool operator<(const CPubKey& a, const CPubKey& b)
129  {
130  return a.vch[0] < b.vch[0] ||
131  (a.vch[0] == b.vch[0] && 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 
140  template <typename Stream>
141  void Serialize(Stream& s) const
142  {
143  unsigned int len = size();
144  ::WriteCompactSize(s, len);
145  s.write(AsBytes(Span{vch, len}));
146  }
147  template <typename Stream>
148  void Unserialize(Stream& s)
149  {
150  const unsigned int len(::ReadCompactSize(s));
151  if (len <= SIZE) {
152  s.read(AsWritableBytes(Span{vch, len}));
153  if (len != size()) {
154  Invalidate();
155  }
156  } else {
157  // invalid pubkey, skip available data
158  s.ignore(len);
159  Invalidate();
160  }
161  }
162 
164  CKeyID GetID() const
165  {
166  return CKeyID(Hash160(Span{vch}.first(size())));
167  }
168 
170  uint256 GetHash() const
171  {
172  return Hash(Span{vch}.first(size()));
173  }
174 
175  /*
176  * Check syntactic correctness.
177  *
178  * When setting a pubkey (Set()) or deserializing fails (its header bytes
179  * don't match the length of the data), the size is set to 0. Thus,
180  * by checking size, one can observe whether Set() or deserialization has
181  * failed.
182  *
183  * This does not check for more than that. In particular, it does not verify
184  * that the coordinates correspond to a point on the curve (see IsFullyValid()
185  * for that instead).
186  *
187  * Note that this is consensus critical as CheckECDSASignature() calls it!
188  */
189  bool IsValid() const
190  {
191  return size() > 0;
192  }
193 
195  bool IsFullyValid() const;
196 
198  bool IsCompressed() const
199  {
200  return size() == COMPRESSED_SIZE;
201  }
202 
207  bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const;
208 
212  static bool CheckLowS(const std::vector<unsigned char>& vchSig);
213 
215  bool RecoverCompact(const uint256& hash, const std::vector<unsigned char>& vchSig);
216 
218  bool Decompress();
219 
221  bool Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
222 };
223 
225 {
226 private:
228 
229 public:
231  XOnlyPubKey() = default;
232 
233  XOnlyPubKey(const XOnlyPubKey&) = default;
234  XOnlyPubKey& operator=(const XOnlyPubKey&) = default;
235 
239  bool IsFullyValid() const;
240 
243  bool IsNull() const { return m_keydata.IsNull(); }
244 
246  explicit XOnlyPubKey(Span<const unsigned char> bytes);
247 
249  explicit XOnlyPubKey(const CPubKey& pubkey) : XOnlyPubKey(Span{pubkey}.subspan(1, 32)) {}
250 
255  bool VerifySchnorr(const uint256& msg, Span<const unsigned char> sigbytes) const;
256 
265  uint256 ComputeTapTweakHash(const uint256* merkle_root) const;
266 
269  bool CheckTapTweak(const XOnlyPubKey& internal, const uint256& merkle_root, bool parity) const;
270 
272  std::optional<std::pair<XOnlyPubKey, bool>> CreateTapTweak(const uint256* merkle_root) const;
273 
277  std::vector<CKeyID> GetKeyIDs() const;
278 
279  const unsigned char& operator[](int pos) const { return *(m_keydata.begin() + pos); }
280  const unsigned char* data() const { return m_keydata.begin(); }
281  static constexpr size_t size() { return decltype(m_keydata)::size(); }
282  const unsigned char* begin() const { return m_keydata.begin(); }
283  const unsigned char* end() const { return m_keydata.end(); }
284  unsigned char* begin() { return m_keydata.begin(); }
285  unsigned char* end() { return m_keydata.end(); }
286  bool operator==(const XOnlyPubKey& other) const { return m_keydata == other.m_keydata; }
287  bool operator!=(const XOnlyPubKey& other) const { return m_keydata != other.m_keydata; }
288  bool operator<(const XOnlyPubKey& other) const { return m_keydata < other.m_keydata; }
289 };
290 
291 struct CExtPubKey {
292  unsigned char version[4];
293  unsigned char nDepth;
294  unsigned char vchFingerprint[4];
295  unsigned int nChild;
298 
299  friend bool operator==(const CExtPubKey &a, const CExtPubKey &b)
300  {
301  return a.nDepth == b.nDepth &&
302  memcmp(a.vchFingerprint, b.vchFingerprint, sizeof(vchFingerprint)) == 0 &&
303  a.nChild == b.nChild &&
304  a.chaincode == b.chaincode &&
305  a.pubkey == b.pubkey;
306  }
307 
308  friend bool operator!=(const CExtPubKey &a, const CExtPubKey &b)
309  {
310  return !(a == b);
311  }
312 
313  friend bool operator<(const CExtPubKey &a, const CExtPubKey &b)
314  {
315  if (a.pubkey < b.pubkey) {
316  return true;
317  } else if (a.pubkey > b.pubkey) {
318  return false;
319  }
320  return a.chaincode < b.chaincode;
321  }
322 
323  void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
324  void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
325  void EncodeWithVersion(unsigned char code[BIP32_EXTKEY_WITH_VERSION_SIZE]) const;
326  void DecodeWithVersion(const unsigned char code[BIP32_EXTKEY_WITH_VERSION_SIZE]);
327  bool Derive(CExtPubKey& out, unsigned int nChild) const;
328 };
329 
333 {
334  static int refcount;
335 
336 public:
337  ECCVerifyHandle();
339 };
340 
342 
346 
347 #endif // BITCOIN_PUBKEY_H
XOnlyPubKey::CheckTapTweak
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:227
BIP32_EXTKEY_SIZE
const unsigned int BIP32_EXTKEY_SIZE
Definition: pubkey.h:19
CPubKey::SIGNATURE_SIZE
static constexpr unsigned int SIGNATURE_SIZE
Definition: pubkey.h:41
XOnlyPubKey::VerifySchnorr
bool VerifySchnorr(const uint256 &msg, Span< const unsigned char > sigbytes) const
Verify a Schnorr signature against this public key.
Definition: pubkey.cpp:206
CKeyID::CKeyID
CKeyID()
Definition: pubkey.h:26
CExtPubKey::version
unsigned char version[4]
Definition: pubkey.h:292
secp256k1_context_struct
Definition: secp256k1.c:47
CPubKey::Invalidate
void Invalidate()
Set this key data to be invalid.
Definition: pubkey.h:70
CPubKey::SIZE
static constexpr unsigned int SIZE
secp256k1:
Definition: pubkey.h:39
uint256.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:89
CExtPubKey::operator<
friend bool operator<(const CExtPubKey &a, const CExtPubKey &b)
Definition: pubkey.h:313
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:113
XOnlyPubKey::data
const unsigned char * data() const
Definition: pubkey.h:280
XOnlyPubKey
Definition: pubkey.h:224
CPubKey::vch
unsigned char vch[SIZE]
see www.keylength.com script supports up to 75 for single byte push
Definition: pubkey.h:49
ECCVerifyHandle::ECCVerifyHandle
ECCVerifyHandle()
Definition: pubkey.cpp:386
XOnlyPubKey::XOnlyPubKey
XOnlyPubKey()=default
Construct an empty x-only pubkey.
CPubKey::Decompress
bool Decompress()
Turn this public key into an uncompressed public key.
Definition: pubkey.cpp:300
CExtPubKey::EncodeWithVersion
void EncodeWithVersion(unsigned char code[BIP32_EXTKEY_WITH_VERSION_SIZE]) const
Definition: pubkey.cpp:355
CPubKey::CPubKey
CPubKey(Span< const uint8_t > _vch)
Construct a public key from a byte vector.
Definition: pubkey.h:106
CKeyID
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:23
CExtPubKey::nDepth
unsigned char nDepth
Definition: pubkey.h:293
CExtPubKey::operator!=
friend bool operator!=(const CExtPubKey &a, const CExtPubKey &b)
Definition: pubkey.h:308
ReadCompactSize
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
Definition: serialize.h:275
ECCVerifyHandle::refcount
static int refcount
Definition: pubkey.h:334
CPubKey::ValidSize
static bool ValidSize(const std::vector< unsigned char > &vch)
Definition: pubkey.h:77
AsWritableBytes
Span< std::byte > AsWritableBytes(Span< T > s) noexcept
Definition: span.h:258
CExtPubKey::Decode
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE])
Definition: pubkey.cpp:346
CExtPubKey::Derive
bool Derive(CExtPubKey &out, unsigned int nChild) const
Definition: pubkey.cpp:367
ECCVerifyHandle::~ECCVerifyHandle
~ECCVerifyHandle()
Definition: pubkey.cpp:396
GetVerifyContext
const secp256k1_context * GetVerifyContext()
Access to the internal secp256k1 context used for verification.
Definition: pubkey.cpp:406
XOnlyPubKey::end
unsigned char * end()
Definition: pubkey.h:285
CExtPubKey::nChild
unsigned int nChild
Definition: pubkey.h:295
Span
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:96
XOnlyPubKey::begin
const unsigned char * begin() const
Definition: pubkey.h:282
CPubKey::begin
const unsigned char * begin() const
Definition: pubkey.h:114
Hash
uint256 Hash(const T &in1)
Compute the 256-bit hash of an object.
Definition: hash.h:75
CExtPubKey::operator==
friend bool operator==(const CExtPubKey &a, const CExtPubKey &b)
Definition: pubkey.h:299
XOnlyPubKey::m_keydata
uint256 m_keydata
Definition: pubkey.h:227
XOnlyPubKey::operator!=
bool operator!=(const XOnlyPubKey &other) const
Definition: pubkey.h:287
BIP32_EXTKEY_WITH_VERSION_SIZE
const unsigned int BIP32_EXTKEY_WITH_VERSION_SIZE
Definition: pubkey.h:20
CPubKey::GetLen
unsigned static int GetLen(unsigned char chHeader)
Compute the length of a pubkey with a given first byte.
Definition: pubkey.h:60
CExtPubKey::vchFingerprint
unsigned char vchFingerprint[4]
Definition: pubkey.h:294
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:115
XOnlyPubKey::XOnlyPubKey
XOnlyPubKey(const CPubKey &pubkey)
Construct an x-only pubkey from a normal pubkey.
Definition: pubkey.h:249
XOnlyPubKey::end
const unsigned char * end() const
Definition: pubkey.h:283
WriteCompactSize
void WriteCompactSize(CSizeComputer &os, uint64_t nSize)
Definition: serialize.h:1080
span.h
CPubKey::GetHash
uint256 GetHash() const
Get the 256-bit hash of this public key.
Definition: pubkey.h:170
CPubKey::Unserialize
void Unserialize(Stream &s)
Definition: pubkey.h:148
Span::begin
constexpr C * begin() const noexcept
Definition: span.h:174
CPubKey::Serialize
void Serialize(Stream &s) const
Implement serialization, as if this was a byte vector.
Definition: pubkey.h:141
CPubKey::CPubKey
CPubKey()
Construct an invalid public key.
Definition: pubkey.h:82
XOnlyPubKey::begin
unsigned char * begin()
Definition: pubkey.h:284
ChainCode
uint256 ChainCode
Definition: pubkey.h:30
CPubKey::size
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
Definition: pubkey.h:112
CPubKey::COMPRESSED_SIZE
static constexpr unsigned int COMPRESSED_SIZE
Definition: pubkey.h:40
uint256
256-bit opaque blob.
Definition: uint256.h:126
XOnlyPubKey::IsNull
bool IsNull() const
Test whether this is the 0 key (the result of default construction).
Definition: pubkey.h:243
CExtPubKey::Encode
void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const
Definition: pubkey.cpp:337
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
AsBytes
Span< const std::byte > AsBytes(Span< T > s) noexcept
Definition: span.h:253
CPubKey::IsCompressed
bool IsCompressed() const
Check whether this is a compressed public key.
Definition: pubkey.h:198
XOnlyPubKey::IsFullyValid
bool IsFullyValid() const
Determine if this pubkey is fully valid.
Definition: pubkey.cpp:200
CPubKey::operator==
friend bool operator==(const CPubKey &a, const CPubKey &b)
Comparator implementation.
Definition: pubkey.h:119
uint160
160-bit opaque blob.
Definition: uint256.h:115
CPubKey
An encapsulated public key.
Definition: pubkey.h:33
CExtPubKey::DecodeWithVersion
void DecodeWithVersion(const unsigned char code[BIP32_EXTKEY_WITH_VERSION_SIZE])
Definition: pubkey.cpp:361
base_blob::IsNull
bool IsNull() const
Definition: uint256.h:33
ECCVerifyHandle
Users of this module must hold an ECCVerifyHandle.
Definition: pubkey.h:332
CExtPubKey::chaincode
ChainCode chaincode
Definition: pubkey.h:296
Hash160
uint160 Hash160(const T1 &in1)
Compute the 160-bit hash an object.
Definition: hash.h:92
CPubKey::COMPACT_SIGNATURE_SIZE
static constexpr unsigned int COMPACT_SIGNATURE_SIZE
Definition: pubkey.h:42
CPubKey::operator<
friend bool operator<(const CPubKey &a, const CPubKey &b)
Definition: pubkey.h:128
ByteUnit::T
@ T
XOnlyPubKey::GetKeyIDs
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:183
XOnlyPubKey::operator==
bool operator==(const XOnlyPubKey &other) const
Definition: pubkey.h:286
CPubKey::IsFullyValid
bool IsFullyValid() const
fully validate whether this is a valid public key (more expensive than IsValid())
Definition: pubkey.cpp:292
CPubKey::CPubKey
CPubKey(const T pbegin, const T pend)
Construct a public key using begin/end iterators to byte data.
Definition: pubkey.h:100
hash.h
XOnlyPubKey::ComputeTapTweakHash
uint256 ComputeTapTweakHash(const uint256 *merkle_root) const
Compute the Taproot tweak as specified in BIP341, with *this as internal key:
Definition: pubkey.cpp:216
serialize.h
XOnlyPubKey::operator<
bool operator<(const XOnlyPubKey &other) const
Definition: pubkey.h:288
XOnlyPubKey::size
static constexpr size_t size()
Definition: pubkey.h:281
CKeyID::CKeyID
CKeyID(const uint160 &in)
Definition: pubkey.h:27
CPubKey::IsValid
bool IsValid() const
Definition: pubkey.h:189
CExtPubKey::pubkey
CPubKey pubkey
Definition: pubkey.h:297
XOnlyPubKey::operator[]
const unsigned char & operator[](int pos) const
Definition: pubkey.h:279
CPubKey::operator[]
const unsigned char & operator[](unsigned int pos) const
Definition: pubkey.h:116
CPubKey::operator>
friend bool operator>(const CPubKey &a, const CPubKey &b)
Definition: pubkey.h:133
CExtPubKey
Definition: pubkey.h:291
XOnlyPubKey::operator=
XOnlyPubKey & operator=(const XOnlyPubKey &)=default
Span::end
constexpr C * end() const noexcept
Definition: span.h:175
base_blob::begin
unsigned char * begin()
Definition: uint256.h:60
XOnlyPubKey::CreateTapTweak
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:235
CPubKey::GetID
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:164
CPubKey::CheckLowS
static bool CheckLowS(const std::vector< unsigned char > &vchSig)
Check whether a signature is normalized (lower-S).
Definition: pubkey.cpp:375
CPubKey::operator!=
friend bool operator!=(const CPubKey &a, const CPubKey &b)
Definition: pubkey.h:124
base_blob::end
unsigned char * end()
Definition: uint256.h:65