]>
Commit | Line | Data |
---|---|---|
db0e8ccd | 1 | // Copyright (c) 2009-2013 The Bitcoin developers |
93db3fce | 2 | // Distributed under the MIT/X11 software license, see the accompanying |
3a25a2b9 | 3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
93db3fce | 4 | |
51ed9ec9 BD |
5 | #include "key.h" |
6 | ||
eb2c9990 | 7 | #include <openssl/bn.h> |
93db3fce | 8 | #include <openssl/ecdsa.h> |
096e06db | 9 | #include <openssl/obj_mac.h> |
51ed9ec9 | 10 | #include <openssl/rand.h> |
dfa23b94 PW |
11 | |
12 | // anonymous namespace with local implementation code (OpenSSL interaction) | |
13 | namespace { | |
14 | ||
93db3fce PW |
15 | // Generate a private key from just the secret parameter |
16 | int EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key) | |
17 | { | |
18 | int ok = 0; | |
19 | BN_CTX *ctx = NULL; | |
20 | EC_POINT *pub_key = NULL; | |
21 | ||
22 | if (!eckey) return 0; | |
23 | ||
24 | const EC_GROUP *group = EC_KEY_get0_group(eckey); | |
25 | ||
26 | if ((ctx = BN_CTX_new()) == NULL) | |
27 | goto err; | |
28 | ||
29 | pub_key = EC_POINT_new(group); | |
30 | ||
31 | if (pub_key == NULL) | |
32 | goto err; | |
33 | ||
34 | if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)) | |
35 | goto err; | |
36 | ||
37 | EC_KEY_set_private_key(eckey,priv_key); | |
38 | EC_KEY_set_public_key(eckey,pub_key); | |
39 | ||
40 | ok = 1; | |
41 | ||
42 | err: | |
43 | ||
44 | if (pub_key) | |
45 | EC_POINT_free(pub_key); | |
46 | if (ctx != NULL) | |
47 | BN_CTX_free(ctx); | |
48 | ||
49 | return(ok); | |
50 | } | |
51 | ||
52 | // Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields | |
53 | // recid selects which key is recovered | |
814efd6f | 54 | // if check is non-zero, additional checks are performed |
93db3fce PW |
55 | int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check) |
56 | { | |
57 | if (!eckey) return 0; | |
58 | ||
59 | int ret = 0; | |
60 | BN_CTX *ctx = NULL; | |
61 | ||
62 | BIGNUM *x = NULL; | |
63 | BIGNUM *e = NULL; | |
64 | BIGNUM *order = NULL; | |
65 | BIGNUM *sor = NULL; | |
66 | BIGNUM *eor = NULL; | |
67 | BIGNUM *field = NULL; | |
68 | EC_POINT *R = NULL; | |
69 | EC_POINT *O = NULL; | |
70 | EC_POINT *Q = NULL; | |
71 | BIGNUM *rr = NULL; | |
72 | BIGNUM *zero = NULL; | |
73 | int n = 0; | |
74 | int i = recid / 2; | |
75 | ||
76 | const EC_GROUP *group = EC_KEY_get0_group(eckey); | |
77 | if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; } | |
78 | BN_CTX_start(ctx); | |
79 | order = BN_CTX_get(ctx); | |
80 | if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; } | |
81 | x = BN_CTX_get(ctx); | |
82 | if (!BN_copy(x, order)) { ret=-1; goto err; } | |
83 | if (!BN_mul_word(x, i)) { ret=-1; goto err; } | |
84 | if (!BN_add(x, x, ecsig->r)) { ret=-1; goto err; } | |
85 | field = BN_CTX_get(ctx); | |
86 | if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; } | |
87 | if (BN_cmp(x, field) >= 0) { ret=0; goto err; } | |
88 | if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; } | |
89 | if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; } | |
90 | if (check) | |
91 | { | |
92 | if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; } | |
93 | if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; } | |
94 | if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; } | |
95 | } | |
96 | if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; } | |
97 | n = EC_GROUP_get_degree(group); | |
98 | e = BN_CTX_get(ctx); | |
99 | if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; } | |
100 | if (8*msglen > n) BN_rshift(e, e, 8-(n & 7)); | |
101 | zero = BN_CTX_get(ctx); | |
102 | if (!BN_zero(zero)) { ret=-1; goto err; } | |
103 | if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; } | |
104 | rr = BN_CTX_get(ctx); | |
105 | if (!BN_mod_inverse(rr, ecsig->r, order, ctx)) { ret=-1; goto err; } | |
106 | sor = BN_CTX_get(ctx); | |
107 | if (!BN_mod_mul(sor, ecsig->s, rr, order, ctx)) { ret=-1; goto err; } | |
108 | eor = BN_CTX_get(ctx); | |
109 | if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; } | |
110 | if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; } | |
111 | if (!EC_KEY_set_public_key(eckey, Q)) { ret=-2; goto err; } | |
112 | ||
113 | ret = 1; | |
114 | ||
115 | err: | |
116 | if (ctx) { | |
117 | BN_CTX_end(ctx); | |
118 | BN_CTX_free(ctx); | |
119 | } | |
120 | if (R != NULL) EC_POINT_free(R); | |
121 | if (O != NULL) EC_POINT_free(O); | |
122 | if (Q != NULL) EC_POINT_free(Q); | |
123 | return ret; | |
124 | } | |
096e06db | 125 | |
dfa23b94 PW |
126 | // RAII Wrapper around OpenSSL's EC_KEY |
127 | class CECKey { | |
128 | private: | |
129 | EC_KEY *pkey; | |
096e06db | 130 | |
dfa23b94 PW |
131 | public: |
132 | CECKey() { | |
133 | pkey = EC_KEY_new_by_curve_name(NID_secp256k1); | |
134 | assert(pkey != NULL); | |
135 | } | |
136 | ||
137 | ~CECKey() { | |
a3d12f44 | 138 | EC_KEY_free(pkey); |
dfa23b94 | 139 | } |
096e06db | 140 | |
dfa23b94 PW |
141 | void GetSecretBytes(unsigned char vch[32]) const { |
142 | const BIGNUM *bn = EC_KEY_get0_private_key(pkey); | |
143 | assert(bn); | |
144 | int nBytes = BN_num_bytes(bn); | |
145 | int n=BN_bn2bin(bn,&vch[32 - nBytes]); | |
146 | assert(n == nBytes); | |
147 | memset(vch, 0, 32 - nBytes); | |
148 | } | |
096e06db | 149 | |
dfa23b94 | 150 | void SetSecretBytes(const unsigned char vch[32]) { |
9b59e3bd | 151 | bool ret; |
dfa23b94 PW |
152 | BIGNUM bn; |
153 | BN_init(&bn); | |
9b59e3bd GM |
154 | ret = BN_bin2bn(vch, 32, &bn); |
155 | assert(ret); | |
156 | ret = EC_KEY_regenerate_key(pkey, &bn); | |
157 | assert(ret); | |
dfa23b94 PW |
158 | BN_clear_free(&bn); |
159 | } | |
096e06db | 160 | |
fb83a79b PW |
161 | void GetPrivKey(CPrivKey &privkey, bool fCompressed) { |
162 | EC_KEY_set_conv_form(pkey, fCompressed ? POINT_CONVERSION_COMPRESSED : POINT_CONVERSION_UNCOMPRESSED); | |
dfa23b94 PW |
163 | int nSize = i2d_ECPrivateKey(pkey, NULL); |
164 | assert(nSize); | |
165 | privkey.resize(nSize); | |
166 | unsigned char* pbegin = &privkey[0]; | |
167 | int nSize2 = i2d_ECPrivateKey(pkey, &pbegin); | |
168 | assert(nSize == nSize2); | |
169 | } | |
096e06db | 170 | |
6e51b3bd | 171 | bool SetPrivKey(const CPrivKey &privkey, bool fSkipCheck=false) { |
dfa23b94 PW |
172 | const unsigned char* pbegin = &privkey[0]; |
173 | if (d2i_ECPrivateKey(&pkey, &pbegin, privkey.size())) { | |
6e51b3bd | 174 | if(fSkipCheck) |
175 | return true; | |
176 | ||
dfa23b94 PW |
177 | // d2i_ECPrivateKey returns true if parsing succeeds. |
178 | // This doesn't necessarily mean the key is valid. | |
179 | if (EC_KEY_check_key(pkey)) | |
180 | return true; | |
181 | } | |
182 | return false; | |
183 | } | |
096e06db | 184 | |
dfa23b94 PW |
185 | void GetPubKey(CPubKey &pubkey, bool fCompressed) { |
186 | EC_KEY_set_conv_form(pkey, fCompressed ? POINT_CONVERSION_COMPRESSED : POINT_CONVERSION_UNCOMPRESSED); | |
187 | int nSize = i2o_ECPublicKey(pkey, NULL); | |
188 | assert(nSize); | |
189 | assert(nSize <= 65); | |
190 | unsigned char c[65]; | |
191 | unsigned char *pbegin = c; | |
192 | int nSize2 = i2o_ECPublicKey(pkey, &pbegin); | |
193 | assert(nSize == nSize2); | |
194 | pubkey.Set(&c[0], &c[nSize]); | |
195 | } | |
096e06db | 196 | |
dfa23b94 PW |
197 | bool SetPubKey(const CPubKey &pubkey) { |
198 | const unsigned char* pbegin = pubkey.begin(); | |
199 | return o2i_ECPublicKey(&pkey, &pbegin, pubkey.size()); | |
200 | } | |
096e06db | 201 | |
dfa23b94 | 202 | bool Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) { |
a81cd968 PW |
203 | vchSig.clear(); |
204 | ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey); | |
205 | if (sig == NULL) | |
206 | return false; | |
e0e14e43 PW |
207 | BN_CTX *ctx = BN_CTX_new(); |
208 | BN_CTX_start(ctx); | |
209 | const EC_GROUP *group = EC_KEY_get0_group(pkey); | |
210 | BIGNUM *order = BN_CTX_get(ctx); | |
211 | BIGNUM *halforder = BN_CTX_get(ctx); | |
212 | EC_GROUP_get_order(group, order, ctx); | |
213 | BN_rshift1(halforder, order); | |
214 | if (BN_cmp(sig->s, halforder) > 0) { | |
215 | // enforce low S values, by negating the value (modulo the order) if above order/2. | |
a81cd968 | 216 | BN_sub(sig->s, order, sig->s); |
a81cd968 | 217 | } |
e0e14e43 PW |
218 | BN_CTX_end(ctx); |
219 | BN_CTX_free(ctx); | |
dfa23b94 PW |
220 | unsigned int nSize = ECDSA_size(pkey); |
221 | vchSig.resize(nSize); // Make sure it is big enough | |
a81cd968 PW |
222 | unsigned char *pos = &vchSig[0]; |
223 | nSize = i2d_ECDSA_SIG(sig, &pos); | |
224 | ECDSA_SIG_free(sig); | |
dfa23b94 PW |
225 | vchSig.resize(nSize); // Shrink to fit actual size |
226 | return true; | |
227 | } | |
096e06db | 228 | |
dfa23b94 PW |
229 | bool Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) { |
230 | // -1 = error, 0 = bad sig, 1 = good | |
231 | if (ECDSA_verify(0, (unsigned char*)&hash, sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1) | |
232 | return false; | |
233 | return true; | |
234 | } | |
235 | ||
236 | bool SignCompact(const uint256 &hash, unsigned char *p64, int &rec) { | |
237 | bool fOk = false; | |
238 | ECDSA_SIG *sig = ECDSA_do_sign((unsigned char*)&hash, sizeof(hash), pkey); | |
239 | if (sig==NULL) | |
240 | return false; | |
241 | memset(p64, 0, 64); | |
242 | int nBitsR = BN_num_bits(sig->r); | |
243 | int nBitsS = BN_num_bits(sig->s); | |
244 | if (nBitsR <= 256 && nBitsS <= 256) { | |
245 | CPubKey pubkey; | |
246 | GetPubKey(pubkey, true); | |
247 | for (int i=0; i<4; i++) { | |
248 | CECKey keyRec; | |
249 | if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, (unsigned char*)&hash, sizeof(hash), i, 1) == 1) { | |
250 | CPubKey pubkeyRec; | |
251 | keyRec.GetPubKey(pubkeyRec, true); | |
252 | if (pubkeyRec == pubkey) { | |
253 | rec = i; | |
254 | fOk = true; | |
255 | break; | |
256 | } | |
257 | } | |
258 | } | |
259 | assert(fOk); | |
260 | BN_bn2bin(sig->r,&p64[32-(nBitsR+7)/8]); | |
261 | BN_bn2bin(sig->s,&p64[64-(nBitsS+7)/8]); | |
eed1785f | 262 | } |
dfa23b94 PW |
263 | ECDSA_SIG_free(sig); |
264 | return fOk; | |
eed1785f | 265 | } |
096e06db | 266 | |
dfa23b94 PW |
267 | // reconstruct public key from a compact signature |
268 | // This is only slightly more CPU intensive than just verifying it. | |
269 | // If this function succeeds, the recovered public key is guaranteed to be valid | |
270 | // (the signature is a valid signature of the given data for that key) | |
271 | bool Recover(const uint256 &hash, const unsigned char *p64, int rec) | |
096e06db | 272 | { |
dfa23b94 PW |
273 | if (rec<0 || rec>=3) |
274 | return false; | |
275 | ECDSA_SIG *sig = ECDSA_SIG_new(); | |
276 | BN_bin2bn(&p64[0], 32, sig->r); | |
277 | BN_bin2bn(&p64[32], 32, sig->s); | |
278 | bool ret = ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), rec, 0) == 1; | |
279 | ECDSA_SIG_free(sig); | |
280 | return ret; | |
281 | } | |
eb2c9990 PW |
282 | |
283 | static bool TweakSecret(unsigned char vchSecretOut[32], const unsigned char vchSecretIn[32], const unsigned char vchTweak[32]) | |
284 | { | |
285 | bool ret = true; | |
286 | BN_CTX *ctx = BN_CTX_new(); | |
287 | BN_CTX_start(ctx); | |
288 | BIGNUM *bnSecret = BN_CTX_get(ctx); | |
289 | BIGNUM *bnTweak = BN_CTX_get(ctx); | |
290 | BIGNUM *bnOrder = BN_CTX_get(ctx); | |
291 | EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp256k1); | |
292 | EC_GROUP_get_order(group, bnOrder, ctx); // what a grossly inefficient way to get the (constant) group order... | |
293 | BN_bin2bn(vchTweak, 32, bnTweak); | |
294 | if (BN_cmp(bnTweak, bnOrder) >= 0) | |
295 | ret = false; // extremely unlikely | |
296 | BN_bin2bn(vchSecretIn, 32, bnSecret); | |
297 | BN_add(bnSecret, bnSecret, bnTweak); | |
298 | BN_nnmod(bnSecret, bnSecret, bnOrder, ctx); | |
299 | if (BN_is_zero(bnSecret)) | |
300 | ret = false; // ridiculously unlikely | |
301 | int nBits = BN_num_bits(bnSecret); | |
302 | memset(vchSecretOut, 0, 32); | |
303 | BN_bn2bin(bnSecret, &vchSecretOut[32-(nBits+7)/8]); | |
304 | EC_GROUP_free(group); | |
305 | BN_CTX_end(ctx); | |
306 | BN_CTX_free(ctx); | |
307 | return ret; | |
308 | } | |
309 | ||
310 | bool TweakPublic(const unsigned char vchTweak[32]) { | |
311 | bool ret = true; | |
312 | BN_CTX *ctx = BN_CTX_new(); | |
313 | BN_CTX_start(ctx); | |
314 | BIGNUM *bnTweak = BN_CTX_get(ctx); | |
315 | BIGNUM *bnOrder = BN_CTX_get(ctx); | |
316 | BIGNUM *bnOne = BN_CTX_get(ctx); | |
317 | const EC_GROUP *group = EC_KEY_get0_group(pkey); | |
318 | EC_GROUP_get_order(group, bnOrder, ctx); // what a grossly inefficient way to get the (constant) group order... | |
319 | BN_bin2bn(vchTweak, 32, bnTweak); | |
320 | if (BN_cmp(bnTweak, bnOrder) >= 0) | |
321 | ret = false; // extremely unlikely | |
322 | EC_POINT *point = EC_POINT_dup(EC_KEY_get0_public_key(pkey), group); | |
323 | BN_one(bnOne); | |
324 | EC_POINT_mul(group, point, bnTweak, point, bnOne, ctx); | |
325 | if (EC_POINT_is_at_infinity(group, point)) | |
326 | ret = false; // ridiculously unlikely | |
327 | EC_KEY_set_public_key(pkey, point); | |
328 | EC_POINT_free(point); | |
329 | BN_CTX_end(ctx); | |
330 | BN_CTX_free(ctx); | |
331 | return ret; | |
332 | } | |
dfa23b94 PW |
333 | }; |
334 | ||
6fd7ef2b PW |
335 | int CompareBigEndian(const unsigned char *c1, size_t c1len, const unsigned char *c2, size_t c2len) { |
336 | while (c1len > c2len) { | |
337 | if (*c1) | |
338 | return 1; | |
339 | c1++; | |
340 | c1len--; | |
341 | } | |
342 | while (c2len > c1len) { | |
343 | if (*c2) | |
344 | return -1; | |
345 | c2++; | |
346 | c2len--; | |
347 | } | |
348 | while (c1len > 0) { | |
349 | if (*c1 > *c2) | |
350 | return 1; | |
351 | if (*c2 > *c1) | |
352 | return -1; | |
353 | c1++; | |
354 | c2++; | |
355 | c1len--; | |
356 | } | |
357 | return 0; | |
358 | } | |
359 | ||
360 | // Order of secp256k1's generator minus 1. | |
361 | const unsigned char vchMaxModOrder[32] = { | |
362 | 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, | |
363 | 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, | |
364 | 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, | |
365 | 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x40 | |
366 | }; | |
367 | ||
368 | // Half of the order of secp256k1's generator minus 1. | |
369 | const unsigned char vchMaxModHalfOrder[32] = { | |
370 | 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, | |
371 | 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, | |
372 | 0x5D,0x57,0x6E,0x73,0x57,0xA4,0x50,0x1D, | |
373 | 0xDF,0xE9,0x2F,0x46,0x68,0x1B,0x20,0xA0 | |
374 | }; | |
375 | ||
376 | const unsigned char vchZero[0] = {}; | |
377 | ||
378 | ||
dfa23b94 PW |
379 | }; // end of anonymous namespace |
380 | ||
381 | bool CKey::Check(const unsigned char *vch) { | |
6fd7ef2b PW |
382 | return CompareBigEndian(vch, 32, vchZero, 0) > 0 && |
383 | CompareBigEndian(vch, 32, vchMaxModOrder, 32) <= 0; | |
384 | } | |
385 | ||
386 | bool CKey::CheckSignatureElement(const unsigned char *vch, int len, bool half) { | |
387 | return CompareBigEndian(vch, len, vchZero, 0) > 0 && | |
388 | CompareBigEndian(vch, len, half ? vchMaxModHalfOrder : vchMaxModOrder, 32) <= 0; | |
096e06db GA |
389 | } |
390 | ||
dfa23b94 PW |
391 | void CKey::MakeNewKey(bool fCompressedIn) { |
392 | do { | |
393 | RAND_bytes(vch, sizeof(vch)); | |
394 | } while (!Check(vch)); | |
395 | fValid = true; | |
396 | fCompressed = fCompressedIn; | |
096e06db GA |
397 | } |
398 | ||
dfa23b94 PW |
399 | bool CKey::SetPrivKey(const CPrivKey &privkey, bool fCompressedIn) { |
400 | CECKey key; | |
401 | if (!key.SetPrivKey(privkey)) | |
402 | return false; | |
403 | key.GetSecretBytes(vch); | |
404 | fCompressed = fCompressedIn; | |
405 | fValid = true; | |
406 | return true; | |
096e06db GA |
407 | } |
408 | ||
dfa23b94 PW |
409 | CPrivKey CKey::GetPrivKey() const { |
410 | assert(fValid); | |
411 | CECKey key; | |
412 | key.SetSecretBytes(vch); | |
413 | CPrivKey privkey; | |
fb83a79b | 414 | key.GetPrivKey(privkey, fCompressed); |
dfa23b94 | 415 | return privkey; |
096e06db GA |
416 | } |
417 | ||
dfa23b94 PW |
418 | CPubKey CKey::GetPubKey() const { |
419 | assert(fValid); | |
420 | CECKey key; | |
421 | key.SetSecretBytes(vch); | |
422 | CPubKey pubkey; | |
423 | key.GetPubKey(pubkey, fCompressed); | |
424 | return pubkey; | |
096e06db GA |
425 | } |
426 | ||
dfa23b94 PW |
427 | bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) const { |
428 | if (!fValid) | |
096e06db | 429 | return false; |
dfa23b94 PW |
430 | CECKey key; |
431 | key.SetSecretBytes(vch); | |
432 | return key.Sign(hash, vchSig); | |
096e06db GA |
433 | } |
434 | ||
dfa23b94 PW |
435 | bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig) const { |
436 | if (!fValid) | |
096e06db | 437 | return false; |
dfa23b94 PW |
438 | CECKey key; |
439 | key.SetSecretBytes(vch); | |
440 | vchSig.resize(65); | |
441 | int rec = -1; | |
442 | if (!key.SignCompact(hash, &vchSig[1], rec)) | |
443 | return false; | |
444 | assert(rec != -1); | |
445 | vchSig[0] = 27 + rec + (fCompressed ? 4 : 0); | |
446 | return true; | |
447 | } | |
096e06db | 448 | |
6e51b3bd | 449 | bool CKey::Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck=false) { |
450 | CECKey key; | |
451 | if (!key.SetPrivKey(privkey, fSkipCheck)) | |
452 | return false; | |
453 | ||
454 | key.GetSecretBytes(vch); | |
455 | fCompressed = vchPubKey.IsCompressed(); | |
456 | fValid = true; | |
457 | ||
a42eef6f | 458 | if (fSkipCheck) |
459 | return true; | |
460 | ||
461 | if (GetPubKey() != vchPubKey) | |
462 | return false; | |
463 | ||
6e51b3bd | 464 | return true; |
465 | } | |
466 | ||
dfa23b94 PW |
467 | bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) const { |
468 | if (!IsValid()) | |
469 | return false; | |
470 | CECKey key; | |
471 | if (!key.SetPubKey(*this)) | |
472 | return false; | |
473 | if (!key.Verify(hash, vchSig)) | |
474 | return false; | |
475 | return true; | |
096e06db GA |
476 | } |
477 | ||
dfa23b94 | 478 | bool CPubKey::RecoverCompact(const uint256 &hash, const std::vector<unsigned char>& vchSig) { |
096e06db GA |
479 | if (vchSig.size() != 65) |
480 | return false; | |
dfa23b94 PW |
481 | CECKey key; |
482 | if (!key.Recover(hash, &vchSig[1], (vchSig[0] - 27) & ~4)) | |
096e06db | 483 | return false; |
dfa23b94 PW |
484 | key.GetPubKey(*this, (vchSig[0] - 27) & 4); |
485 | return true; | |
096e06db GA |
486 | } |
487 | ||
dfa23b94 PW |
488 | bool CPubKey::IsFullyValid() const { |
489 | if (!IsValid()) | |
096e06db | 490 | return false; |
dfa23b94 PW |
491 | CECKey key; |
492 | if (!key.SetPubKey(*this)) | |
096e06db GA |
493 | return false; |
494 | return true; | |
495 | } | |
496 | ||
dfa23b94 PW |
497 | bool CPubKey::Decompress() { |
498 | if (!IsValid()) | |
096e06db | 499 | return false; |
dfa23b94 PW |
500 | CECKey key; |
501 | if (!key.SetPubKey(*this)) | |
eed1785f | 502 | return false; |
dfa23b94 PW |
503 | key.GetPubKey(*this, false); |
504 | return true; | |
096e06db | 505 | } |
eb2c9990 PW |
506 | |
507 | void static BIP32Hash(const unsigned char chainCode[32], unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64]) { | |
508 | unsigned char num[4]; | |
509 | num[0] = (nChild >> 24) & 0xFF; | |
510 | num[1] = (nChild >> 16) & 0xFF; | |
511 | num[2] = (nChild >> 8) & 0xFF; | |
512 | num[3] = (nChild >> 0) & 0xFF; | |
513 | HMAC_SHA512_CTX ctx; | |
514 | HMAC_SHA512_Init(&ctx, chainCode, 32); | |
515 | HMAC_SHA512_Update(&ctx, &header, 1); | |
516 | HMAC_SHA512_Update(&ctx, data, 32); | |
517 | HMAC_SHA512_Update(&ctx, num, 4); | |
518 | HMAC_SHA512_Final(output, &ctx); | |
519 | } | |
520 | ||
521 | bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const { | |
522 | assert(IsValid()); | |
523 | assert(IsCompressed()); | |
524 | unsigned char out[64]; | |
525 | LockObject(out); | |
526 | if ((nChild >> 31) == 0) { | |
527 | CPubKey pubkey = GetPubKey(); | |
528 | assert(pubkey.begin() + 33 == pubkey.end()); | |
529 | BIP32Hash(cc, nChild, *pubkey.begin(), pubkey.begin()+1, out); | |
530 | } else { | |
531 | assert(begin() + 32 == end()); | |
532 | BIP32Hash(cc, nChild, 0, begin(), out); | |
533 | } | |
534 | memcpy(ccChild, out+32, 32); | |
535 | bool ret = CECKey::TweakSecret((unsigned char*)keyChild.begin(), begin(), out); | |
536 | UnlockObject(out); | |
537 | keyChild.fCompressed = true; | |
538 | keyChild.fValid = ret; | |
539 | return ret; | |
540 | } | |
541 | ||
542 | bool CPubKey::Derive(CPubKey& pubkeyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const { | |
543 | assert(IsValid()); | |
544 | assert((nChild >> 31) == 0); | |
545 | assert(begin() + 33 == end()); | |
546 | unsigned char out[64]; | |
547 | BIP32Hash(cc, nChild, *begin(), begin()+1, out); | |
548 | memcpy(ccChild, out+32, 32); | |
549 | CECKey key; | |
550 | bool ret = key.SetPubKey(*this); | |
551 | ret &= key.TweakPublic(out); | |
552 | key.GetPubKey(pubkeyChild, true); | |
553 | return ret; | |
554 | } | |
555 | ||
556 | bool CExtKey::Derive(CExtKey &out, unsigned int nChild) const { | |
557 | out.nDepth = nDepth + 1; | |
558 | CKeyID id = key.GetPubKey().GetID(); | |
559 | memcpy(&out.vchFingerprint[0], &id, 4); | |
560 | out.nChild = nChild; | |
561 | return key.Derive(out.key, out.vchChainCode, nChild, vchChainCode); | |
562 | } | |
563 | ||
564 | void CExtKey::SetMaster(const unsigned char *seed, unsigned int nSeedLen) { | |
565 | static const char hashkey[] = {'B','i','t','c','o','i','n',' ','s','e','e','d'}; | |
566 | HMAC_SHA512_CTX ctx; | |
567 | HMAC_SHA512_Init(&ctx, hashkey, sizeof(hashkey)); | |
568 | HMAC_SHA512_Update(&ctx, seed, nSeedLen); | |
569 | unsigned char out[64]; | |
570 | LockObject(out); | |
571 | HMAC_SHA512_Final(out, &ctx); | |
572 | key.Set(&out[0], &out[32], true); | |
573 | memcpy(vchChainCode, &out[32], 32); | |
574 | UnlockObject(out); | |
575 | nDepth = 0; | |
576 | nChild = 0; | |
577 | memset(vchFingerprint, 0, sizeof(vchFingerprint)); | |
578 | } | |
579 | ||
580 | CExtPubKey CExtKey::Neuter() const { | |
581 | CExtPubKey ret; | |
582 | ret.nDepth = nDepth; | |
583 | memcpy(&ret.vchFingerprint[0], &vchFingerprint[0], 4); | |
584 | ret.nChild = nChild; | |
585 | ret.pubkey = key.GetPubKey(); | |
586 | memcpy(&ret.vchChainCode[0], &vchChainCode[0], 32); | |
587 | return ret; | |
588 | } | |
589 | ||
590 | void CExtKey::Encode(unsigned char code[74]) const { | |
591 | code[0] = nDepth; | |
592 | memcpy(code+1, vchFingerprint, 4); | |
593 | code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF; | |
594 | code[7] = (nChild >> 8) & 0xFF; code[8] = (nChild >> 0) & 0xFF; | |
595 | memcpy(code+9, vchChainCode, 32); | |
596 | code[41] = 0; | |
597 | assert(key.size() == 32); | |
598 | memcpy(code+42, key.begin(), 32); | |
599 | } | |
600 | ||
601 | void CExtKey::Decode(const unsigned char code[74]) { | |
602 | nDepth = code[0]; | |
603 | memcpy(vchFingerprint, code+1, 4); | |
604 | nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8]; | |
605 | memcpy(vchChainCode, code+9, 32); | |
606 | key.Set(code+42, code+74, true); | |
607 | } | |
608 | ||
609 | void CExtPubKey::Encode(unsigned char code[74]) const { | |
610 | code[0] = nDepth; | |
611 | memcpy(code+1, vchFingerprint, 4); | |
612 | code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF; | |
613 | code[7] = (nChild >> 8) & 0xFF; code[8] = (nChild >> 0) & 0xFF; | |
614 | memcpy(code+9, vchChainCode, 32); | |
615 | assert(pubkey.size() == 33); | |
616 | memcpy(code+41, pubkey.begin(), 33); | |
617 | } | |
618 | ||
619 | void CExtPubKey::Decode(const unsigned char code[74]) { | |
620 | nDepth = code[0]; | |
621 | memcpy(vchFingerprint, code+1, 4); | |
622 | nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8]; | |
623 | memcpy(vchChainCode, code+9, 32); | |
624 | pubkey.Set(code+41, code+74); | |
625 | } | |
626 | ||
627 | bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const { | |
628 | out.nDepth = nDepth + 1; | |
629 | CKeyID id = pubkey.GetID(); | |
630 | memcpy(&out.vchFingerprint[0], &id, 4); | |
631 | out.nChild = nChild; | |
632 | return pubkey.Derive(out.pubkey, out.vchChainCode, nChild, vchChainCode); | |
633 | } |