Dogecoin Core  1.14.2
P2P Digital Currency
pubkey.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2016 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 "pubkey.h"
6 
7 #include <secp256k1.h>
8 #include <secp256k1_recovery.h>
9 
10 namespace
11 {
12 /* Global secp256k1_context object used for verification. */
13 secp256k1_context* secp256k1_context_verify = NULL;
14 }
15 
26 static int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) {
27  size_t rpos, rlen, spos, slen;
28  size_t pos = 0;
29  size_t lenbyte;
30  unsigned char tmpsig[64] = {0};
31  int overflow = 0;
32 
33  /* Hack to initialize sig with a correctly-parsed but invalid signature. */
35 
36  /* Sequence tag byte */
37  if (pos == inputlen || input[pos] != 0x30) {
38  return 0;
39  }
40  pos++;
41 
42  /* Sequence length bytes */
43  if (pos == inputlen) {
44  return 0;
45  }
46  lenbyte = input[pos++];
47  if (lenbyte & 0x80) {
48  lenbyte -= 0x80;
49  if (pos + lenbyte > inputlen) {
50  return 0;
51  }
52  pos += lenbyte;
53  }
54 
55  /* Integer tag byte for R */
56  if (pos == inputlen || input[pos] != 0x02) {
57  return 0;
58  }
59  pos++;
60 
61  /* Integer length for R */
62  if (pos == inputlen) {
63  return 0;
64  }
65  lenbyte = input[pos++];
66  if (lenbyte & 0x80) {
67  lenbyte -= 0x80;
68  if (pos + lenbyte > inputlen) {
69  return 0;
70  }
71  while (lenbyte > 0 && input[pos] == 0) {
72  pos++;
73  lenbyte--;
74  }
75  if (lenbyte >= sizeof(size_t)) {
76  return 0;
77  }
78  rlen = 0;
79  while (lenbyte > 0) {
80  rlen = (rlen << 8) + input[pos];
81  pos++;
82  lenbyte--;
83  }
84  } else {
85  rlen = lenbyte;
86  }
87  if (rlen > inputlen - pos) {
88  return 0;
89  }
90  rpos = pos;
91  pos += rlen;
92 
93  /* Integer tag byte for S */
94  if (pos == inputlen || input[pos] != 0x02) {
95  return 0;
96  }
97  pos++;
98 
99  /* Integer length for S */
100  if (pos == inputlen) {
101  return 0;
102  }
103  lenbyte = input[pos++];
104  if (lenbyte & 0x80) {
105  lenbyte -= 0x80;
106  if (pos + lenbyte > inputlen) {
107  return 0;
108  }
109  while (lenbyte > 0 && input[pos] == 0) {
110  pos++;
111  lenbyte--;
112  }
113  if (lenbyte >= sizeof(size_t)) {
114  return 0;
115  }
116  slen = 0;
117  while (lenbyte > 0) {
118  slen = (slen << 8) + input[pos];
119  pos++;
120  lenbyte--;
121  }
122  } else {
123  slen = lenbyte;
124  }
125  if (slen > inputlen - pos) {
126  return 0;
127  }
128  spos = pos;
129  pos += slen;
130 
131  /* Ignore leading zeroes in R */
132  while (rlen > 0 && input[rpos] == 0) {
133  rlen--;
134  rpos++;
135  }
136  /* Copy R value */
137  if (rlen > 32) {
138  overflow = 1;
139  } else {
140  memcpy(tmpsig + 32 - rlen, input + rpos, rlen);
141  }
142 
143  /* Ignore leading zeroes in S */
144  while (slen > 0 && input[spos] == 0) {
145  slen--;
146  spos++;
147  }
148  /* Copy S value */
149  if (slen > 32) {
150  overflow = 1;
151  } else {
152  memcpy(tmpsig + 64 - slen, input + spos, slen);
153  }
154 
155  if (!overflow) {
156  overflow = !secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
157  }
158  if (overflow) {
159  /* Overwrite the result again with a correctly-parsed but invalid
160  signature if parsing failed. */
161  memset(tmpsig, 0, 64);
162  secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig);
163  }
164  return 1;
165 }
166 
167 bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) const {
168  if (!IsValid())
169  return false;
170  secp256k1_pubkey pubkey;
172  if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, &(*this)[0], size())) {
173  return false;
174  }
175  if (vchSig.size() == 0) {
176  return false;
177  }
178  if (!ecdsa_signature_parse_der_lax(secp256k1_context_verify, &sig, &vchSig[0], vchSig.size())) {
179  return false;
180  }
181  /* libsecp256k1's ECDSA verification requires lower-S signatures, which have
182  * not historically been enforced in Bitcoin, so normalize them first. */
183  secp256k1_ecdsa_signature_normalize(secp256k1_context_verify, &sig, &sig);
184  return secp256k1_ecdsa_verify(secp256k1_context_verify, &sig, hash.begin(), &pubkey);
185 }
186 
187 bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig) {
188  if (vchSig.size() != 65)
189  return false;
190  int recid = (vchSig[0] - 27) & 3;
191  bool fComp = ((vchSig[0] - 27) & 4) != 0;
192  secp256k1_pubkey pubkey;
194  if (!secp256k1_ecdsa_recoverable_signature_parse_compact(secp256k1_context_verify, &sig, &vchSig[1], recid)) {
195  return false;
196  }
197  if (!secp256k1_ecdsa_recover(secp256k1_context_verify, &pubkey, &sig, hash.begin())) {
198  return false;
199  }
200  unsigned char pub[65];
201  size_t publen = 65;
202  secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, fComp ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED);
203  Set(pub, pub + publen);
204  return true;
205 }
206 
207 bool CPubKey::IsFullyValid() const {
208  if (!IsValid())
209  return false;
210  secp256k1_pubkey pubkey;
211  return secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, &(*this)[0], size());
212 }
213 
215  if (!IsValid())
216  return false;
217  secp256k1_pubkey pubkey;
218  if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, &(*this)[0], size()))
219  return false;
220  unsigned char pub[33];
221  size_t publen = 33;
222  secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, SECP256K1_EC_COMPRESSED);
223  Set(pub, pub + publen);
224  return true;
225 }
226 
228  if (!IsValid())
229  return false;
230  secp256k1_pubkey pubkey;
231  if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, &(*this)[0], size())) {
232  return false;
233  }
234  unsigned char pub[65];
235  size_t publen = 65;
236  secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, SECP256K1_EC_UNCOMPRESSED);
237  Set(pub, pub + publen);
238  return true;
239 }
240 
241 bool CPubKey::Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const {
242  assert(IsValid());
243  assert((nChild >> 31) == 0);
244  assert(begin() + 33 == end());
245  unsigned char out[64];
246  BIP32Hash(cc, nChild, *begin(), begin()+1, out);
247  memcpy(ccChild.begin(), out+32, 32);
248  secp256k1_pubkey pubkey;
249  if (!secp256k1_ec_pubkey_parse(secp256k1_context_verify, &pubkey, &(*this)[0], size())) {
250  return false;
251  }
252  if (!secp256k1_ec_pubkey_tweak_add(secp256k1_context_verify, &pubkey, out)) {
253  return false;
254  }
255  unsigned char pub[33];
256  size_t publen = 33;
257  secp256k1_ec_pubkey_serialize(secp256k1_context_verify, pub, &publen, &pubkey, SECP256K1_EC_COMPRESSED);
258  pubkeyChild.Set(pub, pub + publen);
259  return true;
260 }
261 
262 void CExtPubKey::Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const {
263  code[0] = nDepth;
264  memcpy(code+1, vchFingerprint, 4);
265  code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF;
266  code[7] = (nChild >> 8) & 0xFF; code[8] = (nChild >> 0) & 0xFF;
267  memcpy(code+9, chaincode.begin(), 32);
268  assert(pubkey.size() == 33);
269  memcpy(code+41, pubkey.begin(), 33);
270 }
271 
272 void CExtPubKey::Decode(const unsigned char code[BIP32_EXTKEY_SIZE]) {
273  nDepth = code[0];
274  memcpy(vchFingerprint, code+1, 4);
275  nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8];
276  memcpy(chaincode.begin(), code+9, 32);
277  pubkey.Set(code+41, code+BIP32_EXTKEY_SIZE);
278 }
279 
280 bool CExtPubKey::Derive(CExtPubKey &out, unsigned int _nChild) const {
281  out.nDepth = nDepth + 1;
282  CKeyID id = pubkey.GetID();
283  memcpy(&out.vchFingerprint[0], &id, 4);
284  out.nChild = _nChild;
285  return pubkey.Derive(out.pubkey, out.chaincode, _nChild, chaincode);
286 }
287 
288 /* static */ bool CPubKey::CheckLowS(const std::vector<unsigned char>& vchSig) {
290  if (!ecdsa_signature_parse_der_lax(secp256k1_context_verify, &sig, &vchSig[0], vchSig.size())) {
291  return false;
292  }
293  return (!secp256k1_ecdsa_signature_normalize(secp256k1_context_verify, NULL, &sig));
294 }
295 
296 /* static */ int ECCVerifyHandle::refcount = 0;
297 
299 {
300  if (refcount == 0) {
301  assert(secp256k1_context_verify == NULL);
302  secp256k1_context_verify = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
303  assert(secp256k1_context_verify != NULL);
304  }
305  refcount++;
306 }
307 
309 {
310  refcount--;
311  if (refcount == 0) {
312  assert(secp256k1_context_verify != NULL);
313  secp256k1_context_destroy(secp256k1_context_verify);
314  secp256k1_context_verify = NULL;
315  }
316 }
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:30
An encapsulated public key.
Definition: pubkey.h:40
bool RecoverCompact(const uint256 &hash, const std::vector< unsigned char > &vchSig)
Recover a public key from a compact signature.
Definition: pubkey.cpp:187
const unsigned char * end() const
Definition: pubkey.h:99
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:142
static bool CheckLowS(const std::vector< unsigned char > &vchSig)
Check whether a signature is normalized (lower-S).
Definition: pubkey.cpp:288
bool IsValid() const
Definition: pubkey.h:158
bool Decompress()
Turn this public key into an uncompressed public key.
Definition: pubkey.cpp:227
bool Verify(const uint256 &hash, const std::vector< unsigned char > &vchSig) const
Verify a DER signature (~72 bytes).
Definition: pubkey.cpp:167
bool IsFullyValid() const
fully validate whether this is a valid public key (more expensive than IsValid())
Definition: pubkey.cpp:207
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
Definition: pubkey.h:97
const unsigned char * begin() const
Definition: pubkey.h:98
bool Compress()
Turn this public key into a compressed public key.
Definition: pubkey.cpp:214
bool Derive(CPubKey &pubkeyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode &cc) const
Derive BIP32 child pubkey.
Definition: pubkey.cpp:241
void Set(const T pbegin, const T pend)
Initialize a public key using begin/end iterators to byte data.
Definition: pubkey.h:74
static int refcount
Definition: pubkey.h:246
unsigned char * begin()
Definition: uint256.h:56
256-bit opaque blob.
Definition: uint256.h:123
void * memcpy(void *a, const void *b, size_t c)
void BIP32Hash(const ChainCode &chainCode, unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64])
Definition: hash.cpp:75
const unsigned int BIP32_EXTKEY_SIZE
secp256k1: const unsigned int PRIVATE_KEY_SIZE = 279; const unsigned int PUBLIC_KEY_SIZE = 65; const ...
Definition: pubkey.h:26
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:450
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:228
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:165
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:293
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:150
SECP256K1_API secp256k1_context * secp256k1_context_create(unsigned int flags) SECP256K1_WARN_UNUSED_RESULT
Create a secp256k1 context object.
Definition: secp256k1.c:58
#define SECP256K1_EC_COMPRESSED
Flag to pass to secp256k1_ec_pubkey_serialize and secp256k1_ec_privkey_export.
Definition: secp256k1.h:159
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:274
#define SECP256K1_EC_UNCOMPRESSED
Definition: secp256k1.h:160
#define SECP256K1_CONTEXT_VERIFY
Flags to pass to secp256k1_context_create.
Definition: secp256k1.h:154
SECP256K1_API void secp256k1_context_destroy(secp256k1_context *ctx)
Destroy a secp256k1 context object.
Definition: secp256k1.c:92
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_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:170
void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const
Definition: pubkey.cpp:262
ChainCode chaincode
Definition: pubkey.h:200
bool Derive(CExtPubKey &out, unsigned int nChild) const
Definition: pubkey.cpp:280
unsigned char vchFingerprint[4]
Definition: pubkey.h:198
unsigned char nDepth
Definition: pubkey.h:197
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE])
Definition: pubkey.cpp:272
CPubKey pubkey
Definition: pubkey.h:201
unsigned int nChild
Definition: pubkey.h:199
Opaque data structured that holds a parsed ECDSA signature, supporting pubkey recovery.
Opaque data structured that holds a parsed ECDSA signature.
Definition: secp256k1.h:66
Opaque data structure that holds a parsed and valid public key.
Definition: secp256k1.h:53