Bitcoin ABC  0.22.12
P2P Digital Currency
pubkey.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2016 The Bitcoin Core developers
2 // Copyright (c) 2017 The Zcash developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include <pubkey.h>
7 
8 #include <secp256k1.h>
9 #include <secp256k1_recovery.h>
10 #include <secp256k1_schnorr.h>
11 
12 namespace {
13 /* Global secp256k1_context object used for verification. */
14 secp256k1_context *secp256k1_context_verify = nullptr;
15 } // namespace
16 
30  const uint8_t *input,
31  size_t inputlen) {
32  size_t rpos, rlen, spos, slen;
33  size_t pos = 0;
34  size_t lenbyte;
35  uint8_t tmpsig[64] = {0};
36  int overflow = 0;
37 
38  /* Hack to initialize sig with a correctly-parsed but invalid signature. */
40 
41  /* Sequence tag byte */
42  if (pos == inputlen || input[pos] != 0x30) {
43  return 0;
44  }
45  pos++;
46 
47  /* Sequence length bytes */
48  if (pos == inputlen) {
49  return 0;
50  }
51  lenbyte = input[pos++];
52  if (lenbyte & 0x80) {
53  lenbyte -= 0x80;
54  if (lenbyte > inputlen - pos) {
55  return 0;
56  }
57  pos += lenbyte;
58  }
59 
60  /* Integer tag byte for R */
61  if (pos == inputlen || input[pos] != 0x02) {
62  return 0;
63  }
64  pos++;
65 
66  /* Integer length for R */
67  if (pos == inputlen) {
68  return 0;
69  }
70  lenbyte = input[pos++];
71  if (lenbyte & 0x80) {
72  lenbyte -= 0x80;
73  if (lenbyte > inputlen - pos) {
74  return 0;
75  }
76  while (lenbyte > 0 && input[pos] == 0) {
77  pos++;
78  lenbyte--;
79  }
80  static_assert(sizeof(size_t) >= 4, "size_t too small");
81  if (lenbyte >= 4) {
82  return 0;
83  }
84  rlen = 0;
85  while (lenbyte > 0) {
86  rlen = (rlen << 8) + input[pos];
87  pos++;
88  lenbyte--;
89  }
90  } else {
91  rlen = lenbyte;
92  }
93  if (rlen > inputlen - pos) {
94  return 0;
95  }
96  rpos = pos;
97  pos += rlen;
98 
99  /* Integer tag byte for S */
100  if (pos == inputlen || input[pos] != 0x02) {
101  return 0;
102  }
103  pos++;
104 
105  /* Integer length for S */
106  if (pos == inputlen) {
107  return 0;
108  }
109  lenbyte = input[pos++];
110  if (lenbyte & 0x80) {
111  lenbyte -= 0x80;
112  if (lenbyte > inputlen - pos) {
113  return 0;
114  }
115  while (lenbyte > 0 && input[pos] == 0) {
116  pos++;
117  lenbyte--;
118  }
119  static_assert(sizeof(size_t) >= 4, "size_t too small");
120  if (lenbyte >= 4) {
121  return 0;
122  }
123  slen = 0;
124  while (lenbyte > 0) {
125  slen = (slen << 8) + input[pos];
126  pos++;
127  lenbyte--;
128  }
129  } else {
130  slen = lenbyte;
131  }
132  if (slen > inputlen - pos) {
133  return 0;
134  }
135  spos = pos;
136 
137  /* Ignore leading zeroes in R */
138  while (rlen > 0 && input[rpos] == 0) {
139  rlen--;
140  rpos++;
141  }
142  /* Copy R value */
143  if (rlen > 32) {
144  overflow = 1;
145  } else {
146  memcpy(tmpsig + 32 - rlen, input + rpos, rlen);
147  }
148 
149  /* Ignore leading zeroes in S */
150  while (slen > 0 && input[spos] == 0) {
151  slen--;
152  spos++;
153  }
154  /* Copy S value */
155  if (slen > 32) {
156  overflow = 1;
157  } else {
158  memcpy(tmpsig + 64 - slen, input + spos, slen);
159  }
160 
161  if (!overflow) {
162  overflow = !secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
163  }
164  if (overflow) {
165  /* Overwrite the result again with a correctly-parsed but invalid
166  signature if parsing failed. */
167  memset(tmpsig, 0, 64);
168  secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
169  }
170  return 1;
171 }
172 
173 bool CPubKey::VerifyECDSA(const uint256 &hash,
174  const std::vector<uint8_t> &vchSig) const {
175  if (!IsValid()) {
176  return false;
177  }
178 
179  secp256k1_pubkey pubkey;
181  assert(secp256k1_context_verify &&
182  "secp256k1_context_verify must be initialized to use CPubKey.");
183  if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, vch,
184  size())) {
185  return false;
186  }
187  if (!ecdsa_signature_parse_der_lax(secp256k1_context_verify, &sig,
188  vchSig.data(), vchSig.size())) {
189  return false;
190  }
195  secp256k1_ecdsa_signature_normalize(secp256k1_context_verify, &sig, &sig);
196  return secp256k1_ecdsa_verify(secp256k1_context_verify, &sig, hash.begin(),
197  &pubkey);
198 }
199 
201  const uint256 &hash, const std::array<uint8_t, SCHNORR_SIZE> &sig) const {
202  if (!IsValid()) {
203  return false;
204  }
205 
206  secp256k1_pubkey pubkey;
207  if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey,
208  &(*this)[0], size())) {
209  return false;
210  }
211 
212  return secp256k1_schnorr_verify(secp256k1_context_verify, sig.data(),
213  hash.begin(), &pubkey);
214 }
215 
217  const std::vector<uint8_t> &vchSig) const {
218  if (vchSig.size() != SCHNORR_SIZE) {
219  return false;
220  }
221 
222  std::array<uint8_t, SCHNORR_SIZE> sig;
223  std::copy(vchSig.begin(), vchSig.end(), sig.begin());
224 
225  return VerifySchnorr(hash, sig);
226 }
227 
229  const std::vector<uint8_t> &vchSig) {
230  if (vchSig.size() != COMPACT_SIGNATURE_SIZE) {
231  return false;
232  }
233 
234  int recid = (vchSig[0] - 27) & 3;
235  bool fComp = ((vchSig[0] - 27) & 4) != 0;
236  secp256k1_pubkey pubkey;
238  assert(secp256k1_context_verify &&
239  "secp256k1_context_verify must be initialized to use CPubKey.");
241  secp256k1_context_verify, &sig, &vchSig[1], recid)) {
242  return false;
243  }
244  if (!secp256k1_ecdsa_recover(secp256k1_context_verify, &pubkey, &sig,
245  hash.begin())) {
246  return false;
247  }
248  uint8_t pub[SIZE];
249  size_t publen = SIZE;
251  secp256k1_context_verify, pub, &publen, &pubkey,
253  Set(pub, pub + publen);
254  return true;
255 }
256 
257 bool CPubKey::IsFullyValid() const {
258  if (!IsValid()) {
259  return false;
260  }
261  secp256k1_pubkey pubkey;
262  assert(secp256k1_context_verify &&
263  "secp256k1_context_verify must be initialized to use CPubKey.");
264  return secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, vch,
265  size());
266 }
267 
269  if (!IsValid()) {
270  return false;
271  }
272  secp256k1_pubkey pubkey;
273  assert(secp256k1_context_verify &&
274  "secp256k1_context_verify must be initialized to use CPubKey.");
275  if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, vch,
276  size())) {
277  return false;
278  }
279  uint8_t pub[SIZE];
280  size_t publen = SIZE;
281  secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen,
282  &pubkey, SECP256K1_EC_UNCOMPRESSED);
283  Set(pub, pub + publen);
284  return true;
285 }
286 
287 bool CPubKey::Derive(CPubKey &pubkeyChild, ChainCode &ccChild,
288  unsigned int nChild, const ChainCode &cc) const {
289  assert(IsValid());
290  assert((nChild >> 31) == 0);
291  assert(size() == COMPRESSED_SIZE);
292  uint8_t out[64];
293  BIP32Hash(cc, nChild, *begin(), begin() + 1, out);
294  memcpy(ccChild.begin(), out + 32, 32);
295  secp256k1_pubkey pubkey;
296  assert(secp256k1_context_verify &&
297  "secp256k1_context_verify must be initialized to use CPubKey.");
298  if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, vch,
299  size())) {
300  return false;
301  }
302  if (!secp256k1_ec_pubkey_tweak_add(secp256k1_context_verify, &pubkey,
303  out)) {
304  return false;
305  }
306  uint8_t pub[COMPRESSED_SIZE];
307  size_t publen = COMPRESSED_SIZE;
308  secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen,
309  &pubkey, SECP256K1_EC_COMPRESSED);
310  pubkeyChild.Set(pub, pub + publen);
311  return true;
312 }
313 
314 void CExtPubKey::Encode(uint8_t code[BIP32_EXTKEY_SIZE]) const {
315  code[0] = nDepth;
316  memcpy(code + 1, vchFingerprint, 4);
317  code[5] = (nChild >> 24) & 0xFF;
318  code[6] = (nChild >> 16) & 0xFF;
319  code[7] = (nChild >> 8) & 0xFF;
320  code[8] = (nChild >> 0) & 0xFF;
321  memcpy(code + 9, chaincode.begin(), 32);
322  assert(pubkey.size() == CPubKey::COMPRESSED_SIZE);
323  memcpy(code + 41, pubkey.begin(), CPubKey::COMPRESSED_SIZE);
324 }
325 
326 void CExtPubKey::Decode(const uint8_t code[BIP32_EXTKEY_SIZE]) {
327  nDepth = code[0];
328  memcpy(vchFingerprint, code + 1, 4);
329  nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8];
330  memcpy(chaincode.begin(), code + 9, 32);
331  pubkey.Set(code + 41, code + BIP32_EXTKEY_SIZE);
332 }
333 
334 bool CExtPubKey::Derive(CExtPubKey &out, unsigned int _nChild) const {
335  out.nDepth = nDepth + 1;
336  CKeyID id = pubkey.GetID();
337  memcpy(&out.vchFingerprint[0], &id, 4);
338  out.nChild = _nChild;
339  return pubkey.Derive(out.pubkey, out.chaincode, _nChild, chaincode);
340 }
341 
343  const boost::sliced_range<const std::vector<uint8_t>> &vchSig) {
345  assert(secp256k1_context_verify &&
346  "secp256k1_context_verify must be initialized to use CPubKey.");
347  if (!ecdsa_signature_parse_der_lax(secp256k1_context_verify, &sig,
348  &vchSig.front(), vchSig.size())) {
349  return false;
350  }
351  return (!secp256k1_ecdsa_signature_normalize(secp256k1_context_verify,
352  nullptr, &sig));
353 }
354 
355 /* static */ int ECCVerifyHandle::refcount = 0;
356 
358  if (refcount == 0) {
359  assert(secp256k1_context_verify == nullptr);
360  secp256k1_context_verify =
362  assert(secp256k1_context_verify != nullptr);
363  }
364  refcount++;
365 }
366 
368  refcount--;
369  if (refcount == 0) {
370  assert(secp256k1_context_verify != nullptr);
371  secp256k1_context_destroy(secp256k1_context_verify);
372  secp256k1_context_verify = nullptr;
373  }
374 }
SECP256K1_API int secp256k1_ecdsa_recoverable_signature_parse_compact(const secp256k1_context *ctx, secp256k1_ecdsa_recoverable_signature *sig, const unsigned char *input64, int recid) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Parse a compact ECDSA signature (64 bytes + recovery id).
Definition: main_impl.h:38
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add(const secp256k1_context *ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Tweak a public key by adding tweak times the generator to it.
Definition: secp256k1.c:665
std::array< uint8_t, 64 > sig
Definition: processor.cpp:248
static constexpr unsigned int SIZE
secp256k1:
Definition: pubkey.h:36
SECP256K1_API int secp256k1_ecdsa_signature_normalize(const secp256k1_context *ctx, secp256k1_ecdsa_signature *sigout, const secp256k1_ecdsa_signature *sigin) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3)
Convert a signature to a normalized lower-S form.
Definition: secp256k1.c:406
secp256k1_context * ctx
Opaque data structured that holds a parsed ECDSA signature, supporting pubkey recovery.
unsigned char data[64]
Definition: secp256k1.h:81
void Set(const T pbegin, const T pend)
Initialize a public key using begin/end iterators to byte data.
Definition: pubkey.h:78
static int refcount
Definition: pubkey.h:224
bool VerifyECDSA(const uint256 &hash, const std::vector< uint8_t > &vchSig) const
Verify a DER-serialized ECDSA signature (~72 bytes).
Definition: pubkey.cpp:173
bool Derive(CPubKey &pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode &cc) const
Derive BIP32 child pubkey.
Definition: pubkey.cpp:287
SECP256K1_API int secp256k1_ec_pubkey_serialize(const secp256k1_context *ctx, unsigned char *output, size_t *outputlen, const secp256k1_pubkey *pubkey, unsigned int flags) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4)
Serialize a pubkey object into a serialized byte sequence.
Definition: secp256k1.c:297
bool VerifySchnorr(const uint256 &hash, const std::array< uint8_t, SCHNORR_SIZE > &sig) const
Verify a Schnorr signature (=64 bytes).
Definition: pubkey.cpp:200
ChainCode chaincode
Definition: pubkey.h:197
static bool CheckLowS(const boost::sliced_range< const std::vector< uint8_t >> &vchSig)
Check whether a DER-serialized ECDSA signature is normalized (lower-S).
Definition: pubkey.cpp:342
unsigned int nChild
Definition: pubkey.h:196
const uint8_t * begin() const
Definition: pubkey.h:100
void Decode(const uint8_t code[BIP32_EXTKEY_SIZE])
Definition: pubkey.cpp:326
SECP256K1_API void secp256k1_context_destroy(secp256k1_context *ctx)
Destroy a secp256k1 context object (created in dynamically allocated memory).
Definition: secp256k1.c:197
#define SECP256K1_EC_UNCOMPRESSED
Definition: secp256k1.h:177
#define SECP256K1_EC_COMPRESSED
Flag to pass to secp256k1_ec_pubkey_serialize.
Definition: secp256k1.h:176
static int ecdsa_signature_parse_der_lax(const secp256k1_context *ctx, secp256k1_ecdsa_signature *sig, const uint8_t *input, size_t inputlen)
This function is taken from the libsecp256k1 distribution and implements DER parsing for ECDSA signat...
Definition: pubkey.cpp:28
static constexpr unsigned int COMPRESSED_SIZE
Definition: pubkey.h:37
bool IsFullyValid() const
fully validate whether this is a valid public key (more expensive than IsValid()) ...
Definition: pubkey.cpp:257
void BIP32Hash(const ChainCode &chainCode, uint32_t nChild, uint8_t header, const uint8_t data[32], uint8_t output[64])
Definition: hash.cpp:72
bool IsValid() const
Definition: pubkey.h:147
An encapsulated public key.
Definition: pubkey.h:31
static constexpr unsigned int SCHNORR_SIZE
Definition: pubkey.h:38
bool RecoverCompact(const uint256 &hash, const std::vector< uint8_t > &vchSig)
Recover a public key from a compact ECDSA signature.
Definition: pubkey.cpp:228
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
Definition: pubkey.h:98
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse(const secp256k1_context *ctx, secp256k1_pubkey *pubkey, const unsigned char *input, size_t inputlen) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Parse a variable-length public key into the pubkey object.
Definition: secp256k1.c:279
uint8_t * begin()
Definition: uint256.h:76
Opaque data structured that holds a parsed ECDSA signature.
Definition: secp256k1.h:80
static constexpr unsigned int COMPACT_SIGNATURE_SIZE
Definition: pubkey.h:40
uint8_t nDepth
Definition: pubkey.h:194
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorr_verify(const secp256k1_context *ctx, const unsigned char *sig64, const unsigned char *msg32, const secp256k1_pubkey *pubkey) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4)
Verify a signature created by secp256k1_schnorr_sign.
Definition: main_impl.h:13
uint8_t vchFingerprint[4]
Definition: pubkey.h:195
#define SECP256K1_CONTEXT_VERIFY
Flags to pass to secp256k1_context_create, secp256k1_context_preallocated_size, and secp256k1_context...
Definition: secp256k1.h:170
256-bit opaque blob.
Definition: uint256.h:120
bool Derive(CExtPubKey &out, unsigned int nChild) const
Definition: pubkey.cpp:334
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover(const secp256k1_context *ctx, secp256k1_pubkey *pubkey, const secp256k1_ecdsa_recoverable_signature *sig, const unsigned char *msg32) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4)
Recover an ECDSA public key from a signature.
Definition: main_impl.h:138
SECP256K1_API int secp256k1_ecdsa_signature_parse_compact(const secp256k1_context *ctx, secp256k1_ecdsa_signature *sig, const unsigned char *input64) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3)
Parse an ECDSA signature in compact (64 bytes) format.
Definition: secp256k1.c:360
const unsigned int BIP32_EXTKEY_SIZE
Definition: pubkey.h:19
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:22
uint8_t vch[SIZE]
see www.keylength.com script supports up to 75 for single byte push
Definition: pubkey.h:46
CPubKey pubkey
Definition: pubkey.h:198
void Encode(uint8_t code[BIP32_EXTKEY_SIZE]) const
Definition: pubkey.cpp:314
SECP256K1_API secp256k1_context * secp256k1_context_create(unsigned int flags) SECP256K1_WARN_UNUSED_RESULT
Create a secp256k1 context object (in dynamically allocated memory).
Definition: secp256k1.c:153
bool Decompress()
Turn this public key into an uncompressed public key.
Definition: pubkey.cpp:268
Opaque data structure that holds a parsed and valid public key.
Definition: secp256k1.h:67
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify(const secp256k1_context *ctx, const secp256k1_ecdsa_signature *sig, const unsigned char *msg32, const secp256k1_pubkey *pubkey) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4)
Verify an ECDSA signature.
Definition: secp256k1.c:425