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-2020 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 
22 class CKeyID : public uint160
23 {
24 public:
25  CKeyID() : uint160() {}
26  explicit CKeyID(const uint160& in) : uint160(in) {}
27 };
28 
30 
32 class CPubKey
33 {
34 public:
38  static constexpr unsigned int SIZE = 65;
39  static constexpr unsigned int COMPRESSED_SIZE = 33;
40  static constexpr unsigned int SIGNATURE_SIZE = 72;
41  static constexpr unsigned int COMPACT_SIGNATURE_SIZE = 65;
46  static_assert(
48  "COMPRESSED_SIZE is larger than SIZE");
49 
50 private:
51 
56  unsigned char vch[SIZE];
57 
59  unsigned int static GetLen(unsigned char chHeader)
60  {
61  if (chHeader == 2 || chHeader == 3)
62  return COMPRESSED_SIZE;
63  if (chHeader == 4 || chHeader == 6 || chHeader == 7)
64  return SIZE;
65  return 0;
66  }
67 
69  void Invalidate()
70  {
71  vch[0] = 0xFF;
72  }
73 
74 public:
75 
76  bool static ValidSize(const std::vector<unsigned char> &vch) {
77  return vch.size() > 0 && GetLen(vch[0]) == vch.size();
78  }
79 
82  {
83  Invalidate();
84  }
85 
87  template <typename T>
88  void Set(const T pbegin, const T pend)
89  {
90  int len = pend == pbegin ? 0 : GetLen(pbegin[0]);
91  if (len && len == (pend - pbegin))
92  memcpy(vch, (unsigned char*)&pbegin[0], len);
93  else
94  Invalidate();
95  }
96 
98  template <typename T>
99  CPubKey(const T pbegin, const T pend)
100  {
101  Set(pbegin, pend);
102  }
103 
106  {
107  Set(_vch.begin(), _vch.end());
108  }
109 
111  unsigned int size() const { return GetLen(vch[0]); }
112  const unsigned char* data() const { return vch; }
113  const unsigned char* begin() const { return vch; }
114  const unsigned char* end() const { return vch + size(); }
115  const unsigned char& operator[](unsigned int pos) const { return vch[pos]; }
116 
118  friend bool operator==(const CPubKey& a, const CPubKey& b)
119  {
120  return a.vch[0] == b.vch[0] &&
121  memcmp(a.vch, b.vch, a.size()) == 0;
122  }
123  friend bool operator!=(const CPubKey& a, const CPubKey& b)
124  {
125  return !(a == b);
126  }
127  friend bool operator<(const CPubKey& a, const CPubKey& b)
128  {
129  return a.vch[0] < b.vch[0] ||
130  (a.vch[0] == b.vch[0] && memcmp(a.vch, b.vch, a.size()) < 0);
131  }
132 
134  template <typename Stream>
135  void Serialize(Stream& s) const
136  {
137  unsigned int len = size();
138  ::WriteCompactSize(s, len);
139  s.write((char*)vch, len);
140  }
141  template <typename Stream>
142  void Unserialize(Stream& s)
143  {
144  unsigned int len = ::ReadCompactSize(s);
145  if (len <= SIZE) {
146  s.read((char*)vch, len);
147  if (len != size()) {
148  Invalidate();
149  }
150  } else {
151  // invalid pubkey, skip available data
152  char dummy;
153  while (len--)
154  s.read(&dummy, 1);
155  Invalidate();
156  }
157  }
158 
160  CKeyID GetID() const
161  {
162  return CKeyID(Hash160(MakeSpan(vch).first(size())));
163  }
164 
166  uint256 GetHash() const
167  {
168  return Hash(MakeSpan(vch).first(size()));
169  }
170 
171  /*
172  * Check syntactic correctness.
173  *
174  * When setting a pubkey (Set()) or deserializing fails (its header bytes
175  * don't match the length of the data), the size is set to 0. Thus,
176  * by checking size, one can observe whether Set() or deserialization has
177  * failed.
178  *
179  * This does not check for more than that. In particular, it does not verify
180  * that the coordinates correspond to a point on the curve (see IsFullyValid()
181  * for that instead).
182  *
183  * Note that this is consensus critical as CheckECDSASignature() calls it!
184  */
185  bool IsValid() const
186  {
187  return size() > 0;
188  }
189 
191  bool IsFullyValid() const;
192 
194  bool IsCompressed() const
195  {
196  return size() == COMPRESSED_SIZE;
197  }
198 
203  bool Verify(const uint256& hash, const std::vector<unsigned char>& vchSig) const;
204 
208  static bool CheckLowS(const std::vector<unsigned char>& vchSig);
209 
211  bool RecoverCompact(const uint256& hash, const std::vector<unsigned char>& vchSig);
212 
214  bool Decompress();
215 
217  bool Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const;
218 };
219 
221 {
222 private:
224 
225 public:
227  XOnlyPubKey() = default;
228 
229  XOnlyPubKey(const XOnlyPubKey&) = default;
230  XOnlyPubKey& operator=(const XOnlyPubKey&) = default;
231 
235  bool IsFullyValid() const;
236 
239  bool IsNull() const { return m_keydata.IsNull(); }
240 
242  explicit XOnlyPubKey(Span<const unsigned char> bytes);
243 
245  explicit XOnlyPubKey(const CPubKey& pubkey) : XOnlyPubKey(Span<const unsigned char>(pubkey.begin() + 1, pubkey.begin() + 33)) {}
246 
251  bool VerifySchnorr(const uint256& msg, Span<const unsigned char> sigbytes) const;
252 
261  uint256 ComputeTapTweakHash(const uint256* merkle_root) const;
262 
265  bool CheckTapTweak(const XOnlyPubKey& internal, const uint256& merkle_root, bool parity) const;
266 
268  std::optional<std::pair<XOnlyPubKey, bool>> CreateTapTweak(const uint256* merkle_root) const;
269 
270  const unsigned char& operator[](int pos) const { return *(m_keydata.begin() + pos); }
271  const unsigned char* data() const { return m_keydata.begin(); }
272  static constexpr size_t size() { return decltype(m_keydata)::size(); }
273  const unsigned char* begin() const { return m_keydata.begin(); }
274  const unsigned char* end() const { return m_keydata.end(); }
275  unsigned char* begin() { return m_keydata.begin(); }
276  unsigned char* end() { return m_keydata.end(); }
277  bool operator==(const XOnlyPubKey& other) const { return m_keydata == other.m_keydata; }
278  bool operator!=(const XOnlyPubKey& other) const { return m_keydata != other.m_keydata; }
279  bool operator<(const XOnlyPubKey& other) const { return m_keydata < other.m_keydata; }
280 };
281 
282 struct CExtPubKey {
283  unsigned char nDepth;
284  unsigned char vchFingerprint[4];
285  unsigned int nChild;
288 
289  friend bool operator==(const CExtPubKey &a, const CExtPubKey &b)
290  {
291  return a.nDepth == b.nDepth &&
292  memcmp(a.vchFingerprint, b.vchFingerprint, sizeof(vchFingerprint)) == 0 &&
293  a.nChild == b.nChild &&
294  a.chaincode == b.chaincode &&
295  a.pubkey == b.pubkey;
296  }
297 
298  friend bool operator!=(const CExtPubKey &a, const CExtPubKey &b)
299  {
300  return !(a == b);
301  }
302 
303  void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
304  void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
305  bool Derive(CExtPubKey& out, unsigned int nChild) const;
306 };
307 
311 {
312  static int refcount;
313 
314 public:
315  ECCVerifyHandle();
317 };
318 
320 
324 
325 #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:210
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:40
XOnlyPubKey::VerifySchnorr
bool VerifySchnorr(const uint256 &msg, Span< const unsigned char > sigbytes) const
Verify a Schnorr signature against this public key.
Definition: pubkey.cpp:189
CKeyID::CKeyID
CKeyID()
Definition: pubkey.h:25
secp256k1_context_struct
Definition: secp256k1.c:69
CPubKey::Invalidate
void Invalidate()
Set this key data to be invalid.
Definition: pubkey.h:69
CPubKey::SIZE
static constexpr unsigned int SIZE
secp256k1:
Definition: pubkey.h:38
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:88
CPubKey::Derive
bool Derive(CPubKey &pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode &cc) const
Derive BIP32 child pubkey.
Definition: pubkey.cpp:298
CPubKey::data
const unsigned char * data() const
Definition: pubkey.h:112
XOnlyPubKey::data
const unsigned char * data() const
Definition: pubkey.h:271
XOnlyPubKey
Definition: pubkey.h:220
CPubKey::vch
unsigned char vch[SIZE]
see www.keylength.com script supports up to 75 for single byte push
Definition: pubkey.h:48
ECCVerifyHandle::ECCVerifyHandle
ECCVerifyHandle()
Definition: pubkey.cpp:357
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:283
CPubKey::CPubKey
CPubKey(Span< const uint8_t > _vch)
Construct a public key from a byte vector.
Definition: pubkey.h:105
CKeyID
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:22
CExtPubKey::nDepth
unsigned char nDepth
Definition: pubkey.h:283
CExtPubKey::operator!=
friend bool operator!=(const CExtPubKey &a, const CExtPubKey &b)
Definition: pubkey.h:298
ReadCompactSize
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
Definition: serialize.h:282
ECCVerifyHandle::refcount
static int refcount
Definition: pubkey.h:312
CPubKey::ValidSize
static bool ValidSize(const std::vector< unsigned char > &vch)
Definition: pubkey.h:76
CExtPubKey::Decode
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE])
Definition: pubkey.cpp:330
CExtPubKey::Derive
bool Derive(CExtPubKey &out, unsigned int nChild) const
Definition: pubkey.cpp:338
ECCVerifyHandle::~ECCVerifyHandle
~ECCVerifyHandle()
Definition: pubkey.cpp:367
GetVerifyContext
const secp256k1_context * GetVerifyContext()
Access to the internal secp256k1 context used for verification.
Definition: pubkey.cpp:377
XOnlyPubKey::end
unsigned char * end()
Definition: pubkey.h:276
CExtPubKey::nChild
unsigned int nChild
Definition: pubkey.h:285
Span
A Span is an object that can refer to a contiguous sequence of objects.
Definition: span.h:92
XOnlyPubKey::begin
const unsigned char * begin() const
Definition: pubkey.h:273
CPubKey::begin
const unsigned char * begin() const
Definition: pubkey.h:113
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:289
XOnlyPubKey::m_keydata
uint256 m_keydata
Definition: pubkey.h:223
XOnlyPubKey::operator!=
bool operator!=(const XOnlyPubKey &other) const
Definition: pubkey.h:278
CPubKey::GetLen
unsigned static int GetLen(unsigned char chHeader)
Compute the length of a pubkey with a given first byte.
Definition: pubkey.h:59
CExtPubKey::vchFingerprint
unsigned char vchFingerprint[4]
Definition: pubkey.h:284
CPubKey::Verify
bool Verify(const uint256 &hash, const std::vector< unsigned char > &vchSig) const
Verify a DER signature (~72 bytes).
Definition: pubkey.cpp:236
CPubKey::end
const unsigned char * end() const
Definition: pubkey.h:114
XOnlyPubKey::XOnlyPubKey
XOnlyPubKey(const CPubKey &pubkey)
Construct an x-only pubkey from a normal pubkey.
Definition: pubkey.h:245
XOnlyPubKey::end
const unsigned char * end() const
Definition: pubkey.h:274
WriteCompactSize
void WriteCompactSize(CSizeComputer &os, uint64_t nSize)
Definition: serialize.h:1074
span.h
CPubKey::GetHash
uint256 GetHash() const
Get the 256-bit hash of this public key.
Definition: pubkey.h:166
CPubKey::Unserialize
void Unserialize(Stream &s)
Definition: pubkey.h:142
Span::begin
constexpr C * begin() const noexcept
Definition: span.h:170
CPubKey::Serialize
void Serialize(Stream &s) const
Implement serialization, as if this was a byte vector.
Definition: pubkey.h:135
CPubKey::CPubKey
CPubKey()
Construct an invalid public key.
Definition: pubkey.h:81
XOnlyPubKey::begin
unsigned char * begin()
Definition: pubkey.h:275
ChainCode
uint256 ChainCode
Definition: pubkey.h:29
CPubKey::size
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
Definition: pubkey.h:111
CPubKey::COMPRESSED_SIZE
static constexpr unsigned int COMPRESSED_SIZE
Definition: pubkey.h:39
uint256
256-bit opaque blob.
Definition: uint256.h:124
XOnlyPubKey::IsNull
bool IsNull() const
Test whether this is the 0 key (the result of default construction).
Definition: pubkey.h:239
CExtPubKey::Encode
void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const
Definition: pubkey.cpp:320
CPubKey::RecoverCompact
bool RecoverCompact(const uint256 &hash, const std::vector< unsigned char > &vchSig)
Recover a public key from a compact signature.
Definition: pubkey.cpp:254
CPubKey::IsCompressed
bool IsCompressed() const
Check whether this is a compressed public key.
Definition: pubkey.h:194
XOnlyPubKey::IsFullyValid
bool IsFullyValid() const
Determine if this pubkey is fully valid.
Definition: pubkey.cpp:183
CPubKey::operator==
friend bool operator==(const CPubKey &a, const CPubKey &b)
Comparator implementation.
Definition: pubkey.h:118
uint160
160-bit opaque blob.
Definition: uint256.h:113
CPubKey
An encapsulated public key.
Definition: pubkey.h:32
base_blob::IsNull
bool IsNull() const
Definition: uint256.h:31
ECCVerifyHandle
Users of this module must hold an ECCVerifyHandle.
Definition: pubkey.h:310
CExtPubKey::chaincode
ChainCode chaincode
Definition: pubkey.h:286
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:41
CPubKey::operator<
friend bool operator<(const CPubKey &a, const CPubKey &b)
Definition: pubkey.h:127
XOnlyPubKey::operator==
bool operator==(const XOnlyPubKey &other) const
Definition: pubkey.h:277
CPubKey::IsFullyValid
bool IsFullyValid() const
fully validate whether this is a valid public key (more expensive than IsValid())
Definition: pubkey.cpp:275
CPubKey::CPubKey
CPubKey(const T pbegin, const T pend)
Construct a public key using begin/end iterators to byte data.
Definition: pubkey.h:99
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:199
serialize.h
XOnlyPubKey::operator<
bool operator<(const XOnlyPubKey &other) const
Definition: pubkey.h:279
XOnlyPubKey::size
static constexpr size_t size()
Definition: pubkey.h:272
CKeyID::CKeyID
CKeyID(const uint160 &in)
Definition: pubkey.h:26
CPubKey::IsValid
bool IsValid() const
Definition: pubkey.h:185
CExtPubKey::pubkey
CPubKey pubkey
Definition: pubkey.h:287
XOnlyPubKey::operator[]
const unsigned char & operator[](int pos) const
Definition: pubkey.h:270
CPubKey::operator[]
const unsigned char & operator[](unsigned int pos) const
Definition: pubkey.h:115
MakeSpan
constexpr Span< A > MakeSpan(A(&a)[N])
MakeSpan for arrays:
Definition: span.h:222
CExtPubKey
Definition: pubkey.h:282
XOnlyPubKey::operator=
XOnlyPubKey & operator=(const XOnlyPubKey &)=default
Span::end
constexpr C * end() const noexcept
Definition: span.h:171
base_blob::begin
unsigned char * begin()
Definition: uint256.h:58
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:218
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:346
CPubKey::operator!=
friend bool operator!=(const CPubKey &a, const CPubKey &b)
Definition: pubkey.h:123
base_blob::end
unsigned char * end()
Definition: uint256.h:63