b7a205a0f59a1cb99a532b952314e7f0912a19a1
[novacoin.git] / src / key.cpp
1 // Copyright (c) 2009-2012 The Bitcoin developers
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5 #include <map>
6
7 #include <openssl/ecdsa.h>
8 #include <openssl/evp.h>
9
10 #include "key.h"
11 #include "base58.h"
12
13 // Generate a private key from just the secret parameter
14 int EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
15 {
16     int ok = 0;
17     BN_CTX *ctx = NULL;
18     EC_POINT *pub_key = NULL;
19
20     if (!eckey) return 0;
21
22     const EC_GROUP *group = EC_KEY_get0_group(eckey);
23
24     if ((ctx = BN_CTX_new()) == NULL)
25         goto err;
26
27     pub_key = EC_POINT_new(group);
28
29     if (pub_key == NULL)
30         goto err;
31
32     if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
33         goto err;
34
35     EC_KEY_set_private_key(eckey,priv_key);
36     EC_KEY_set_public_key(eckey,pub_key);
37
38     ok = 1;
39
40 err:
41
42     if (pub_key)
43         EC_POINT_free(pub_key);
44     if (ctx != NULL)
45         BN_CTX_free(ctx);
46
47     return(ok);
48 }
49
50 // Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields
51 // recid selects which key is recovered
52 // if check is non-zero, additional checks are performed
53 int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check)
54 {
55     if (!eckey) return 0;
56
57     int ret = 0;
58     BN_CTX *ctx = NULL;
59
60     BIGNUM *x = NULL;
61     BIGNUM *e = NULL;
62     BIGNUM *order = NULL;
63     BIGNUM *sor = NULL;
64     BIGNUM *eor = NULL;
65     BIGNUM *field = NULL;
66     EC_POINT *R = NULL;
67     EC_POINT *O = NULL;
68     EC_POINT *Q = NULL;
69     BIGNUM *rr = NULL;
70     BIGNUM *zero = NULL;
71     int n = 0;
72     int i = recid / 2;
73
74     const EC_GROUP *group = EC_KEY_get0_group(eckey);
75     if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; }
76     BN_CTX_start(ctx);
77     order = BN_CTX_get(ctx);
78     if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; }
79     x = BN_CTX_get(ctx);
80     if (!BN_copy(x, order)) { ret=-1; goto err; }
81     if (!BN_mul_word(x, i)) { ret=-1; goto err; }
82
83     // Get internal R and S pointers
84     const BIGNUM *ecsig_r, *ecsig_s;
85     ECDSA_SIG_get0(ecsig, &ecsig_r, &ecsig_s);
86
87     if (!BN_add(x, x, ecsig_r)) { ret=-1; goto err; }
88     field = BN_CTX_get(ctx);
89     if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; }
90     if (BN_cmp(x, field) >= 0) { ret=0; goto err; }
91     if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
92     if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; }
93     if (check)
94     {
95         if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
96         if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; }
97         if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; }
98     }
99     if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
100     n = EC_GROUP_get_degree(group);
101     e = BN_CTX_get(ctx);
102     if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; }
103     if (8*msglen > n) BN_rshift(e, e, 8-(n & 7));
104     zero = BN_CTX_get(ctx);
105     if (!BN_set_word(zero, 0)) { ret=-1; goto err; }
106     if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; }
107     rr = BN_CTX_get(ctx);
108     if (!BN_mod_inverse(rr, ecsig_r, order, ctx)) { ret=-1; goto err; }
109     sor = BN_CTX_get(ctx);
110     if (!BN_mod_mul(sor, ecsig_s, rr, order, ctx)) { ret=-1; goto err; }
111     eor = BN_CTX_get(ctx);
112     if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; }
113     if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; }
114     if (!EC_KEY_set_public_key(eckey, Q)) { ret=-2; goto err; }
115
116     ret = 1;
117
118 err:
119     if (ctx) {
120         BN_CTX_end(ctx);
121         BN_CTX_free(ctx);
122     }
123     if (R != NULL) EC_POINT_free(R);
124     if (O != NULL) EC_POINT_free(O);
125     if (Q != NULL) EC_POINT_free(Q);
126     return ret;
127 }
128
129 int CompareBigEndian(const unsigned char *c1, size_t c1len, const unsigned char *c2, size_t c2len) {
130     while (c1len > c2len) {
131         if (*c1)
132             return 1;
133         c1++;
134         c1len--;
135     }
136     while (c2len > c1len) {
137         if (*c2)
138             return -1;
139         c2++;
140         c2len--;
141     }
142     while (c1len > 0) {
143         if (*c1 > *c2)
144             return 1;
145         if (*c2 > *c1)
146             return -1;
147         c1++;
148         c2++;
149         c1len--;
150     }
151     return 0;
152 }
153
154 // Order of secp256k1's generator minus 1.
155 const unsigned char vchMaxModOrder[32] = {
156     0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
157     0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,
158     0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,
159     0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x40
160 };
161
162 // Half of the order of secp256k1's generator minus 1.
163 const unsigned char vchMaxModHalfOrder[32] = {
164     0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
165     0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
166     0x5D,0x57,0x6E,0x73,0x57,0xA4,0x50,0x1D,
167     0xDF,0xE9,0x2F,0x46,0x68,0x1B,0x20,0xA0
168 };
169
170 const unsigned char *vchZero = NULL;
171
172 void CKey::SetCompressedPubKey(bool fCompressed)
173 {
174     EC_KEY_set_conv_form(pkey, fCompressed ? POINT_CONVERSION_COMPRESSED : POINT_CONVERSION_UNCOMPRESSED);
175 }
176
177 void CKey::Reset()
178 {
179     fSet = false;
180     if (pkey != NULL)
181         EC_KEY_free(pkey);
182     pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
183     if (pkey == NULL)
184         throw key_error("CKey::CKey() : EC_KEY_new_by_curve_name failed");
185 }
186
187 CKey::CKey()
188 {
189     pkey = NULL;
190     Reset();
191 }
192
193 CKey::CKey(const CKey& b)
194 {
195     pkey = EC_KEY_dup(b.pkey);
196     if (pkey == NULL)
197         throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
198     fSet = b.fSet;
199 }
200
201 CKey::CKey(const CSecret& b, bool fCompressed)
202 {
203     pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
204     if (pkey == NULL)
205         throw key_error("CKey::CKey(const CKey&) : EC_KEY_dup failed");
206     SetSecret(b, fCompressed);
207 }
208
209 CKey& CKey::operator=(const CKey& b)
210 {
211     if (!EC_KEY_copy(pkey, b.pkey))
212         throw key_error("CKey::operator=(const CKey&) : EC_KEY_copy failed");
213     fSet = b.fSet;
214     return (*this);
215 }
216
217 CKey::~CKey()
218 {
219     if (pkey != NULL)
220         EC_KEY_free(pkey);
221 }
222
223 bool CKey::IsNull() const
224 {
225     return !fSet;
226 }
227
228 bool CKey::IsCompressed() const
229 {
230     return (EC_KEY_get_conv_form(pkey) == POINT_CONVERSION_COMPRESSED);
231 }
232
233 bool CKey::CheckSignatureElement(const unsigned char *vch, int len, bool half) {
234     return CompareBigEndian(vch, len, vchZero, 0) > 0 &&
235         CompareBigEndian(vch, len, half ? vchMaxModHalfOrder : vchMaxModOrder, 32) <= 0;
236 }
237
238 bool CPubKey::ReserealizeSignature(std::vector<unsigned char>& vchSig)
239 {
240     if (vchSig.empty())
241         return false;
242
243     unsigned char *pos = &vchSig[0];
244     ECDSA_SIG *sig = d2i_ECDSA_SIG(NULL, (const unsigned char **)&pos, vchSig.size());
245     if (sig == NULL)
246         return false;
247
248     bool ret = false;
249     int nSize = i2d_ECDSA_SIG(sig, NULL);
250     if (nSize > 0) {
251         vchSig.resize(nSize); // grow or shrink as needed
252
253         pos = &vchSig[0];
254         i2d_ECDSA_SIG(sig, &pos);
255
256         ret = true;
257     }
258
259     ECDSA_SIG_free(sig);
260
261     return ret;
262 }
263
264 void CKey::MakeNewKey(bool fCompressed)
265 {
266     if (!EC_KEY_generate_key(pkey))
267         throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
268     SetCompressedPubKey(fCompressed);
269     fSet = true;
270 }
271
272 bool CKey::SetPrivKey(const CPrivKey& vchPrivKey)
273 {
274     const unsigned char* pbegin = &vchPrivKey[0];
275     if (d2i_ECPrivateKey(&pkey, &pbegin, vchPrivKey.size()))
276     {
277         // In testing, d2i_ECPrivateKey can return true
278         // but fill in pkey with a key that fails
279         // EC_KEY_check_key, so:
280         if (EC_KEY_check_key(pkey))
281         {
282             fSet = true;
283             return true;
284         }
285     }
286     // If vchPrivKey data is bad d2i_ECPrivateKey() can
287     // leave pkey in a state where calling EC_KEY_free()
288     // crashes. To avoid that, set pkey to NULL and
289     // leak the memory (a leak is better than a crash)
290     pkey = NULL;
291     Reset();
292     return false;
293 }
294
295 bool CKey::SetSecret(const CSecret& vchSecret, bool fCompressed)
296 {
297     EC_KEY_free(pkey);
298     pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
299     if (pkey == NULL)
300         throw key_error("CKey::SetSecret() : EC_KEY_new_by_curve_name failed");
301
302     if (vchSecret.size() != 32)
303         throw key_error("CKey::SetSecret() : secret must be 32 bytes");
304     BIGNUM *bn = BN_bin2bn(&vchSecret[0],32,BN_new());
305     if (bn == NULL)
306         throw key_error("CKey::SetSecret() : BN_bin2bn failed");
307     if (!EC_KEY_regenerate_key(pkey,bn))
308     {
309         BN_clear_free(bn);
310         throw key_error("CKey::SetSecret() : EC_KEY_regenerate_key failed");
311     }
312     BN_clear_free(bn);
313     fSet = true;
314     SetCompressedPubKey(fCompressed);
315     return true;
316 }
317
318 CSecret CKey::GetSecret(bool &fCompressed) const
319 {
320     CSecret vchRet;
321     vchRet.resize(32);
322     const BIGNUM *bn = EC_KEY_get0_private_key(pkey);
323     int nBytes = BN_num_bytes(bn);
324     if (bn == NULL)
325         throw key_error("CKey::GetSecret() : EC_KEY_get0_private_key failed");
326     int n=BN_bn2bin(bn,&vchRet[32 - nBytes]);
327     if (n != nBytes)
328         throw key_error("CKey::GetSecret(): BN_bn2bin failed");
329     fCompressed = IsCompressed();
330     return vchRet;
331 }
332
333 CSecret CKey::GetSecret() const
334 {
335     bool fCompressed;
336     return GetSecret(fCompressed);
337 }
338
339 CPrivKey CKey::GetPrivKey() const
340 {
341     int nSize = i2d_ECPrivateKey(pkey, NULL);
342     if (!nSize)
343         throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey failed");
344     CPrivKey vchPrivKey(nSize, 0);
345     unsigned char* pbegin = &vchPrivKey[0];
346     if (i2d_ECPrivateKey(pkey, &pbegin) != nSize)
347         throw key_error("CKey::GetPrivKey() : i2d_ECPrivateKey returned unexpected size");
348     return vchPrivKey;
349 }
350
351 CPubKey CKey::GetPubKey() const
352 {
353     int nSize = i2o_ECPublicKey(pkey, NULL);
354     if (!nSize)
355         throw key_error("CKey::GetPubKey() : i2o_ECPublicKey failed");
356     std::vector<unsigned char> vchPubKey(nSize, 0);
357     unsigned char* pbegin = &vchPubKey[0];
358     if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
359         throw key_error("CKey::GetPubKey() : i2o_ECPublicKey returned unexpected size");
360     return CPubKey(vchPubKey);
361 }
362
363 bool CKey::Sign(uint256 hash, std::vector<unsigned char>& vchSig)
364 {
365     vchSig.clear();
366     ECDSA_SIG *sig = ECDSA_do_sign(hash.begin(), sizeof(hash), pkey);
367     if (sig==nullptr)
368         return false;
369     const EC_GROUP *group = EC_KEY_get0_group(pkey);
370
371     BIGNUM* order = BN_new(), *halforder = BN_new();
372     EC_GROUP_get_order(group, order, nullptr);
373     BN_rshift1(halforder, order);
374
375     // Get internal R and S pointers
376     const BIGNUM *current_s = ECDSA_SIG_get0_s(sig);
377     BIGNUM *current_r = BN_dup(ECDSA_SIG_get0_r(sig));
378
379     // enforce low S values, by negating the value (modulo the order) if above order/2.
380     if (BN_cmp(current_s, halforder) > 0) {
381         BIGNUM *updated_s = BN_new();
382         BN_copy(updated_s, current_s);
383         BN_sub(updated_s, order, updated_s);
384         ECDSA_SIG_set0(sig, current_r, updated_s);
385     }
386
387     BN_free(order);
388     BN_free(halforder);
389
390     unsigned int nSize = ECDSA_size(pkey);
391     vchSig.resize(nSize); // Make sure it is big enough
392     unsigned char *pos = &vchSig[0];
393     nSize = i2d_ECDSA_SIG(sig, &pos);
394     ECDSA_SIG_free(sig);
395     vchSig.resize(nSize); // Shrink to fit actual size
396     // Testing our new signature
397     if (ECDSA_verify(0, hash.begin(), sizeof(hash), &vchSig[0], vchSig.size(), pkey) != 1) {
398         vchSig.clear();
399         return false;
400     }
401     return true;
402 }
403
404 // create a compact signature (65 bytes), which allows reconstructing the used public key
405 // The format is one header byte, followed by two times 32 bytes for the serialized r and s values.
406 // The header byte: 0x1B = first key with even y, 0x1C = first key with odd y,
407 //                  0x1D = second key with even y, 0x1E = second key with odd y
408 bool CKey::SignCompact(uint256 hash, std::vector<unsigned char>& vchSig)
409 {
410     bool fOk = false;
411     ECDSA_SIG *sig = ECDSA_do_sign(hash.begin(), sizeof(hash), pkey);
412     if (sig==nullptr)
413         return false;
414     const EC_GROUP *group = EC_KEY_get0_group(pkey);
415     BIGNUM* order = BN_new(), *halforder = BN_new();
416     EC_GROUP_get_order(group, order, nullptr);
417     BN_rshift1(halforder, order);
418
419     // Get internal R and S pointers
420     const BIGNUM *current_s = ECDSA_SIG_get0_s(sig);
421     BIGNUM *current_r = BN_dup(ECDSA_SIG_get0_r(sig));
422
423     // enforce low S values, by negating the value (modulo the order) if above order/2.
424     if (BN_cmp(current_s, halforder) > 0) {
425         BIGNUM *updated_s = BN_new();
426         BN_copy(updated_s, current_s);
427         BN_sub(updated_s, order, updated_s);
428         ECDSA_SIG_set0(sig, current_r, updated_s);
429     }
430
431     BN_free(order);
432     BN_free(halforder);
433
434     vchSig.clear();
435     vchSig.resize(65,0);
436     int nBitsR = BN_num_bits(ECDSA_SIG_get0_r(sig));
437     int nBitsS = BN_num_bits(ECDSA_SIG_get0_s(sig));
438     bool fCompressedPubKey = IsCompressed();
439     if (nBitsR <= 256 && nBitsS <= 256)
440     {
441         int8_t nRecId = -1;
442         for (int8_t i=0; i<4; i++)
443         {
444             CKey keyRec;
445             keyRec.fSet = true;
446             keyRec.SetCompressedPubKey(fCompressedPubKey);
447             if (ECDSA_SIG_recover_key_GFp(keyRec.pkey, sig, hash.begin(), sizeof(hash), i, 1) == 1)
448                 if (keyRec.GetPubKey() == this->GetPubKey())
449                 {
450                     nRecId = i;
451                     break;
452                 }
453         }
454
455         if (nRecId == -1)
456         {
457             ECDSA_SIG_free(sig);
458             throw key_error("CKey::SignCompact() : unable to construct recoverable key");
459         }
460
461         vchSig[0] = nRecId+27+(fCompressedPubKey ? 4 : 0);
462         BN_bn2bin(ECDSA_SIG_get0_r(sig),&vchSig[33-(nBitsR+7)/8]);
463         BN_bn2bin(ECDSA_SIG_get0_s(sig),&vchSig[65-(nBitsS+7)/8]);
464         fOk = true;
465     }
466
467     ECDSA_SIG_free(sig);
468     return fOk;
469 }
470
471 // reconstruct public key from a compact signature
472 // This is only slightly more CPU intensive than just verifying it.
473 // If this function succeeds, the recovered public key is guaranteed to be valid
474 // (the signature is a valid signature of the given data for that key)
475 bool CPubKey::SetCompactSignature(uint256 hash, const std::vector<unsigned char>& vchSig)
476 {
477     if (vchSig.size() != 65)
478         return false;
479     int nV = vchSig[0];
480     if (nV<27 || nV>=35)
481         return false;
482     ECDSA_SIG *sig = ECDSA_SIG_new();
483     BIGNUM *sig_r = BN_new(), *sig_s = BN_new();
484     BN_bin2bn(&vchSig[1],32,sig_r);
485     BN_bin2bn(&vchSig[33],32,sig_s);
486     ECDSA_SIG_set0(sig, sig_r, sig_s);
487     bool fSuccessful = false;
488     EC_KEY* pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
489     if (nV >= 31)
490     {
491         nV -= 4;
492         EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED);
493     }
494     do
495     {
496         if (ECDSA_SIG_recover_key_GFp(pkey, sig, (unsigned char*)&hash, sizeof(hash), nV - 27, 0) != 1)
497             break;
498         int nSize = i2o_ECPublicKey(pkey, NULL);
499         if (!nSize)
500             break;
501         std::vector<unsigned char> vchPubKey(nSize, 0);
502         unsigned char* pbegin = &vchPubKey[0];
503         if (i2o_ECPublicKey(pkey, &pbegin) != nSize)
504             break;
505         Set(vchPubKey.begin(), vchPubKey.end());
506         fSuccessful = IsValid();
507
508     } while (false);
509     ECDSA_SIG_free(sig);
510     EC_KEY_free(pkey);
511     if (!fSuccessful)
512         Invalidate();
513     return fSuccessful;
514 }
515
516 bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) const
517 {
518     if (vchSig.empty() || !IsValid())
519         return false;
520
521     EC_KEY *pkey = EC_KEY_new_by_curve_name(NID_secp256k1);
522     ECDSA_SIG *norm_sig = ECDSA_SIG_new();
523
524     assert(norm_sig);
525     assert(pkey);
526
527     bool ret = false;
528     do
529     {
530         int derlen;
531         uint8_t *norm_der = NULL;
532         const uint8_t* pbegin = &vbytes[0];
533         const uint8_t* sigptr = &vchSig[0];
534
535         // Trying to parse public key
536         if (!o2i_ECPublicKey(&pkey, &pbegin, size()))
537             break;
538         // New versions of OpenSSL are rejecting a non-canonical DER signatures, de/re-serialize first.
539         if (d2i_ECDSA_SIG(&norm_sig, &sigptr, vchSig.size()) == NULL)
540             break;
541         if ((derlen = i2d_ECDSA_SIG(norm_sig, &norm_der)) <= 0)
542             break;
543
544         // -1 = error, 0 = bad sig, 1 = good
545         ret = ECDSA_verify(0, (const unsigned char*)&hash, sizeof(hash), norm_der, derlen, pkey) == 1;
546         OPENSSL_free(norm_der);
547     } while(false);
548
549     ECDSA_SIG_free(norm_sig);
550     EC_KEY_free(pkey);
551
552     return ret;
553 }
554
555 bool CPubKey::VerifyCompact(uint256 hash, const std::vector<unsigned char>& vchSig)
556 {
557     CPubKey key;
558     if (!key.SetCompactSignature(hash, vchSig))
559         return false;
560     return true;
561 }
562
563 bool CKey::IsValid()
564 {
565     if (!fSet)
566         return false;
567
568     if (!EC_KEY_check_key(pkey))
569         return false;
570
571     bool fCompr;
572     CSecret secret = GetSecret(fCompr);
573     CKey key2;
574     key2.SetSecret(secret, fCompr);
575
576     return GetPubKey() == key2.GetPubKey();
577 }
578
579 CPoint::CPoint()
580 {
581     std::string err;
582     group = NULL;
583     point = NULL;
584     ctx   = NULL;
585
586     group = EC_GROUP_new_by_curve_name(NID_secp256k1);
587     if (!group) {
588         err = "EC_KEY_new_by_curve_name failed.";
589         goto finish;
590     }
591
592     point = EC_POINT_new(group);
593     if (!point) {
594         err = "EC_POINT_new failed.";
595         goto finish;
596     }
597
598     ctx = BN_CTX_new();
599     if (!ctx) {
600         err = "BN_CTX_new failed.";
601         goto finish;
602     }
603
604     return;
605
606 finish:
607     if (group) EC_GROUP_free(group);
608     if (point) EC_POINT_free(point);
609     throw std::runtime_error(std::string("CPoint::CPoint() :  - ") + err);
610 }
611
612 bool CPoint::operator!=(const CPoint &a)
613 {
614     if (EC_POINT_cmp(group, point, a.point, ctx) != 0)
615         return true;
616     return false;
617 }
618 CPoint::~CPoint()
619 {
620     if (point) EC_POINT_free(point);
621     if (group) EC_GROUP_free(group);
622     if (ctx)   BN_CTX_free(ctx);
623 }
624
625 // Initialize from octets stream
626 bool CPoint::setBytes(const std::vector<unsigned char> &vchBytes)
627 {
628     if (!EC_POINT_oct2point(group, point, &vchBytes[0], vchBytes.size(), ctx)) {
629         return false;
630     }
631     return true;
632 }
633
634 // Initialize from octets stream
635 bool CPoint::setPubKey(const CPubKey &key)
636 {
637     std::vector<uint8_t> vchPubKey(key.begin(), key.end());
638     return setBytes(vchPubKey);
639 }
640
641 // Serialize to octets stream
642 bool CPoint::getBytes(std::vector<unsigned char> &vchBytes)
643 {
644     size_t nSize = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, NULL, 0, ctx);
645     vchBytes.resize(nSize);
646     if (!(nSize == EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, &vchBytes[0], nSize, ctx))) {
647         return false;
648     }
649     return true;
650 }
651
652 // ECC multiplication by specified multiplier
653 bool CPoint::ECMUL(const CBigNum &bnMultiplier)
654 {
655     BIGNUM* bnMul = bnMultiplier.get();
656     bool ok = EC_POINT_mul(group, point, NULL, point, bnMul, NULL);
657     if (!ok) printf("CPoint::ECMUL() : EC_POINT_mul failed");
658     BN_free(bnMul);
659     return ok;
660 }
661
662 // Calculate G*m + q
663 bool CPoint::ECMULGEN(const CBigNum &bnMultiplier, const CPoint &qPoint)
664 {
665     BIGNUM* bnMul = bnMultiplier.get();
666     bool ok = EC_POINT_mul(group, point, bnMul, qPoint.point, BN_value_one(), NULL);
667     if (!ok) printf("CPoint::ECMULGEN() : EC_POINT_mul failed.");
668     BN_free(bnMul);
669     return ok;
670 }
671
672 // CMalleablePubKey
673
674 void CMalleablePubKey::GetVariant(CPubKey &R, CPubKey &vchPubKeyVariant)
675 {
676     EC_KEY *eckey = NULL;
677     eckey = EC_KEY_new_by_curve_name(NID_secp256k1);
678     if (eckey == NULL) {
679         throw key_error("CMalleablePubKey::GetVariant() : EC_KEY_new_by_curve_name failed");
680     }
681
682     // Use standard key generation function to get r and R values.
683     //
684     // r will be presented by private key;
685     // R is ECDSA public key which calculated as G*r
686     if (!EC_KEY_generate_key(eckey)) {
687         throw key_error("CMalleablePubKey::GetVariant() : EC_KEY_generate_key failed");
688     }
689
690     EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
691
692     int nSize = i2o_ECPublicKey(eckey, NULL);
693     if (!nSize) {
694         throw key_error("CMalleablePubKey::GetVariant() : i2o_ECPublicKey failed");
695     }
696
697     std::vector<unsigned char> vchPubKey(nSize, 0);
698     unsigned char* pbegin_R = &vchPubKey[0];
699
700     if (i2o_ECPublicKey(eckey, &pbegin_R) != nSize) {
701         throw key_error("CMalleablePubKey::GetVariant() : i2o_ECPublicKey returned unexpected size");
702     }
703
704     // R = G*r
705     R = CPubKey(vchPubKey);
706
707     // OpenSSL BIGNUM representation of r value
708     CBigNum bnr(EC_KEY_get0_private_key(eckey));
709     EC_KEY_free(eckey);
710
711     CPoint point;
712     if (!point.setPubKey(pubKeyL)) {
713         throw key_error("CMalleablePubKey::GetVariant() : Unable to decode L value");
714     }
715
716     // Calculate L*r
717     point.ECMUL(bnr);
718
719     std::vector<unsigned char> vchLr;
720     if (!point.getBytes(vchLr)) {
721         throw key_error("CMalleablePubKey::GetVariant() : Unable to convert Lr value");
722     }
723
724     // Calculate Hash(L*r) and then get a BIGNUM representation of hash value.
725     CBigNum bnHash;
726     bnHash.setuint160(Hash160(vchLr));
727
728     CPoint pointH;
729     pointH.setPubKey(pubKeyH);
730
731     CPoint P;
732     // Calculate P = Hash(L*r)*G + H
733     P.ECMULGEN(bnHash, pointH);
734
735     if (P.IsInfinity()) {
736         throw key_error("CMalleablePubKey::GetVariant() : P is infinity");
737     }
738
739     std::vector<unsigned char> vchResult;
740     P.getBytes(vchResult);
741
742     vchPubKeyVariant = CPubKey(vchResult);
743 }
744
745 std::string CMalleablePubKey::ToString() const
746 {
747     CDataStream ssKey(SER_NETWORK, PROTOCOL_VERSION);
748     ssKey << *this;
749     std::vector<unsigned char> vch(ssKey.begin(), ssKey.end());
750
751     return EncodeBase58Check(vch);
752 }
753
754 bool CMalleablePubKey::setvch(const std::vector<unsigned char> &vchPubKeyPair)
755 {
756     CDataStream ssKey(vchPubKeyPair, SER_NETWORK, PROTOCOL_VERSION);
757     ssKey >> *this;
758
759     return IsValid();
760 }
761
762 std::vector<unsigned char> CMalleablePubKey::Raw() const
763 {
764     CDataStream ssKey(SER_NETWORK, PROTOCOL_VERSION);
765     ssKey << *this;
766     std::vector<unsigned char> vch(ssKey.begin(), ssKey.end());
767
768     return vch;
769 }
770
771 bool CMalleablePubKey::SetString(const std::string& strMalleablePubKey)
772 {
773     std::vector<unsigned char> vchTemp;
774     if (!DecodeBase58Check(strMalleablePubKey, vchTemp)) {
775         throw key_error("CMalleablePubKey::SetString() : Provided key data seems corrupted.");
776     }
777     if (vchTemp.size() != 68)
778         return false;
779
780     CDataStream ssKey(vchTemp, SER_NETWORK, PROTOCOL_VERSION);
781     ssKey >> *this;
782
783     return IsValid();
784 }
785
786 bool CMalleablePubKey::operator==(const CMalleablePubKey &b)
787 {
788     return pubKeyL == b.pubKeyL && pubKeyH == b.pubKeyH;
789 }
790
791
792 // CMalleableKey
793
794 void CMalleableKey::Reset()
795 {
796     vchSecretL.clear();
797     vchSecretH.clear();
798 }
799
800 void CMalleableKey::MakeNewKeys()
801 {
802     Reset();
803
804     CKey keyL, keyH;
805     keyL.MakeNewKey();
806     keyH.MakeNewKey();
807
808     vchSecretL = keyL.GetSecret();
809     vchSecretH = keyH.GetSecret();
810 }
811
812 CMalleableKey::CMalleableKey()
813 {
814     Reset();
815 }
816
817 CMalleableKey::CMalleableKey(const CMalleableKey &b)
818 {
819     SetSecrets(b.vchSecretL, b.vchSecretH);
820 }
821
822 CMalleableKey::CMalleableKey(const CSecret &L, const CSecret &H)
823 {
824     SetSecrets(L, H);
825 }
826
827 CMalleableKey::~CMalleableKey()
828 {
829 }
830
831 bool CMalleableKey::IsNull() const
832 {
833     return vchSecretL.size() != 32 || vchSecretH.size() != 32;
834 }
835
836 bool CMalleableKey::SetSecrets(const CSecret &pvchSecretL, const CSecret &pvchSecretH)
837 {
838     Reset();
839
840     CKey keyL(pvchSecretL);
841     CKey keyH(pvchSecretH);
842
843     if (!keyL.IsValid() || !keyH.IsValid())
844         return false;
845
846     vchSecretL = pvchSecretL;
847     vchSecretH = pvchSecretH;
848
849     return true;
850 }
851
852 CMalleablePubKey CMalleableKey::GetMalleablePubKey() const
853 {
854     CKey L(vchSecretL), H(vchSecretH);
855     return CMalleablePubKey(L.GetPubKey(), H.GetPubKey());
856 }
857
858 // Check ownership
859 bool CMalleableKey::CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant) const
860 {
861     if (IsNull()) {
862         throw key_error("CMalleableKey::CheckKeyVariant() : Attempting to run on NULL key object.");
863     }
864
865     if (!R.IsValid()) {
866         printf("CMalleableKey::CheckKeyVariant() : R is invalid");
867         return false;
868     }
869
870     if (!vchPubKeyVariant.IsValid()) {
871         printf("CMalleableKey::CheckKeyVariant() : public key variant is invalid");
872         return false;
873     }
874
875     CPoint point_R;
876     if (!point_R.setPubKey(R)) {
877         printf("CMalleableKey::CheckKeyVariant() : Unable to decode R value");
878         return false;
879     }
880
881     CKey H(vchSecretH);
882     CPubKey vchPubKeyH = H.GetPubKey();
883
884     CPoint point_H;
885     if (!point_H.setPubKey(vchPubKeyH)) {
886         printf("CMalleableKey::CheckKeyVariant() : Unable to decode H value");
887         return false;
888     }
889
890     CPoint point_P;
891     if (!point_P.setPubKey(vchPubKeyVariant)) {
892         printf("CMalleableKey::CheckKeyVariant() : Unable to decode P value");
893         return false;
894     }
895
896     // Infinity points are senseless
897     if (point_P.IsInfinity()) {
898         printf("CMalleableKey::CheckKeyVariant() : P is infinity");
899         return false;
900     }
901
902     CBigNum bnl;
903     bnl.setBytes(std::vector<unsigned char>(vchSecretL.begin(), vchSecretL.end()));
904
905     point_R.ECMUL(bnl);
906
907     std::vector<unsigned char> vchRl;
908     if (!point_R.getBytes(vchRl)) {
909         printf("CMalleableKey::CheckKeyVariant() : Unable to convert Rl value");
910         return false;
911     }
912
913     // Calculate Hash(R*l)
914     CBigNum bnHash;
915     bnHash.setuint160(Hash160(vchRl));
916
917     CPoint point_Ps;
918     // Calculate Ps = Hash(L*r)*G + H
919     point_Ps.ECMULGEN(bnHash, point_H);
920
921     // Infinity points are senseless
922     if (point_Ps.IsInfinity()) {
923         printf("CMalleableKey::CheckKeyVariant() : Ps is infinity");
924         return false;
925     }
926
927     // Check ownership
928     if (point_Ps != point_P) {
929         return false;
930     }
931
932     return true;
933 }
934
935 // Check ownership and restore private key
936 bool CMalleableKey::CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant, CKey &privKeyVariant) const
937 {
938     if (IsNull()) {
939         throw key_error("CMalleableKey::CheckKeyVariant() : Attempting to run on NULL key object.");
940     }
941
942     if (!R.IsValid()) {
943         printf("CMalleableKey::CheckKeyVariant() : R is invalid");
944         return false;
945     }
946
947     if (!vchPubKeyVariant.IsValid()) {
948         printf("CMalleableKey::CheckKeyVariant() : public key variant is invalid");
949         return false;
950     }
951
952     CPoint point_R;
953     if (!point_R.setPubKey(R)) {
954         printf("CMalleableKey::CheckKeyVariant() : Unable to decode R value");
955         return false;
956     }
957
958     CKey H(vchSecretH);
959     CPubKey vchPubKeyH = H.GetPubKey();
960
961     CPoint point_H;
962     if (!point_H.setPubKey(vchPubKeyH)) {
963         printf("CMalleableKey::CheckKeyVariant() : Unable to decode H value");
964         return false;
965     }
966
967     CPoint point_P;
968     if (!point_P.setPubKey(vchPubKeyVariant)) {
969         printf("CMalleableKey::CheckKeyVariant() : Unable to decode P value");
970         return false;
971     }
972
973     // Infinity points are senseless
974     if (point_P.IsInfinity()) {
975         printf("CMalleableKey::CheckKeyVariant() : P is infinity");
976         return false;
977     }
978
979     CBigNum bnl;
980     bnl.setBytes(std::vector<unsigned char>(vchSecretL.begin(), vchSecretL.end()));
981
982     point_R.ECMUL(bnl);
983
984     std::vector<unsigned char> vchRl;
985     if (!point_R.getBytes(vchRl)) {
986         printf("CMalleableKey::CheckKeyVariant() : Unable to convert Rl value");
987         return false;
988     }
989
990     // Calculate Hash(R*l)
991     CBigNum bnHash;
992     bnHash.setuint160(Hash160(vchRl));
993
994     CPoint point_Ps;
995     // Calculate Ps = Hash(L*r)*G + H
996     point_Ps.ECMULGEN(bnHash, point_H);
997
998     // Infinity points are senseless
999     if (point_Ps.IsInfinity()) {
1000         printf("CMalleableKey::CheckKeyVariant() : Ps is infinity");
1001         return false;
1002     }
1003
1004     // Check ownership
1005     if (point_Ps != point_P) {
1006         return false;
1007     }
1008
1009     // OpenSSL BIGNUM representation of the second private key from (l, h) pair
1010     CBigNum bnh;
1011     bnh.setBytes(std::vector<unsigned char>(vchSecretH.begin(), vchSecretH.end()));
1012
1013     // Calculate p = Hash(R*l) + h
1014     CBigNum bnp = bnHash + bnh;
1015
1016     std::vector<unsigned char> vchp = bnp.getBytes();
1017     privKeyVariant.SetSecret(CSecret(vchp.begin(), vchp.end()));
1018
1019     return true;
1020 }
1021
1022 std::string CMalleableKey::ToString() const
1023 {
1024     CDataStream ssKey(SER_NETWORK, PROTOCOL_VERSION);
1025     ssKey << *this;
1026     std::vector<unsigned char> vch(ssKey.begin(), ssKey.end());
1027
1028     return EncodeBase58Check(vch);
1029 }
1030
1031 std::vector<unsigned char> CMalleableKey::Raw() const
1032 {
1033     CDataStream ssKey(SER_NETWORK, PROTOCOL_VERSION);
1034     ssKey << *this;
1035     std::vector<unsigned char> vch(ssKey.begin(), ssKey.end());
1036
1037     return vch;
1038 }
1039
1040 bool CMalleableKey::SetString(const std::string& strMutableKey)
1041 {
1042     std::vector<unsigned char> vchTemp;
1043     if (!DecodeBase58Check(strMutableKey, vchTemp)) {
1044         throw key_error("CMalleableKey::SetString() : Provided key data seems corrupted.");
1045     }
1046     if (vchTemp.size() != 66)
1047         return false;
1048     CDataStream ssKey(vchTemp, SER_NETWORK, PROTOCOL_VERSION);
1049     ssKey >> *this;
1050
1051     return IsValid();
1052 }
1053
1054 // CMalleableKeyView
1055
1056 CMalleableKeyView::CMalleableKeyView(const std::string &strMalleableKey)
1057 {
1058     SetString(strMalleableKey);
1059 }
1060
1061 CMalleableKeyView::CMalleableKeyView(const CMalleableKey &b)
1062 {
1063     if (b.vchSecretL.size() != 32)
1064         throw key_error("CMalleableKeyView::CMalleableKeyView() : L size must be 32 bytes");
1065
1066     if (b.vchSecretH.size() != 32)
1067         throw key_error("CMalleableKeyView::CMalleableKeyView() : H size must be 32 bytes");
1068
1069     vchSecretL = b.vchSecretL;
1070
1071     CKey H(b.vchSecretH);
1072     vchPubKeyH = H.GetPubKey();
1073 }
1074
1075 CMalleableKeyView::CMalleableKeyView(const CMalleableKeyView &b)
1076 {
1077     vchSecretL = b.vchSecretL;
1078     vchPubKeyH = b.vchPubKeyH;
1079 }
1080
1081 CMalleableKeyView& CMalleableKeyView::operator=(const CMalleableKey &b)
1082 {
1083     vchSecretL = b.vchSecretL;
1084
1085     CKey H(b.vchSecretH);
1086     vchPubKeyH = H.GetPubKey();
1087
1088     return (*this);
1089 }
1090
1091 CMalleableKeyView::~CMalleableKeyView()
1092 {
1093 }
1094
1095 CMalleablePubKey CMalleableKeyView::GetMalleablePubKey() const
1096 {
1097     CKey keyL(vchSecretL);
1098     return CMalleablePubKey(keyL.GetPubKey(), vchPubKeyH);
1099 }
1100
1101 // Check ownership
1102 bool CMalleableKeyView::CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant) const
1103 {
1104     if (!IsValid()) {
1105         throw key_error("CMalleableKeyView::CheckKeyVariant() : Attempting to run on invalid view object.");
1106     }
1107
1108     if (!R.IsValid()) {
1109         printf("CMalleableKeyView::CheckKeyVariant() : R is invalid");
1110         return false;
1111     }
1112
1113     if (!vchPubKeyVariant.IsValid()) {
1114         printf("CMalleableKeyView::CheckKeyVariant() : public key variant is invalid");
1115         return false;
1116     }
1117
1118     CPoint point_R;
1119     if (!point_R.setPubKey(R)) {
1120         printf("CMalleableKeyView::CheckKeyVariant() : Unable to decode R value");
1121         return false;
1122     }
1123
1124     CPoint point_H;
1125     if (!point_H.setPubKey(vchPubKeyH)) {
1126         printf("CMalleableKeyView::CheckKeyVariant() : Unable to decode H value");
1127         return false;
1128     }
1129
1130     CPoint point_P;
1131     if (!point_P.setPubKey(vchPubKeyVariant)) {
1132         printf("CMalleableKeyView::CheckKeyVariant() : Unable to decode P value");
1133         return false;
1134     }
1135
1136     // Infinity points are senseless
1137     if (point_P.IsInfinity()) {
1138         printf("CMalleableKeyView::CheckKeyVariant() : P is infinity");
1139         return false;
1140     }
1141
1142     CBigNum bnl;
1143     bnl.setBytes(std::vector<unsigned char>(vchSecretL.begin(), vchSecretL.end()));
1144
1145     point_R.ECMUL(bnl);
1146
1147     std::vector<unsigned char> vchRl;
1148     if (!point_R.getBytes(vchRl)) {
1149         printf("CMalleableKeyView::CheckKeyVariant() : Unable to convert Rl value");
1150         return false;
1151     }
1152
1153     // Calculate Hash(R*l)
1154     CBigNum bnHash;
1155     bnHash.setuint160(Hash160(vchRl));
1156
1157     CPoint point_Ps;
1158     // Calculate Ps = Hash(L*r)*G + H
1159     point_Ps.ECMULGEN(bnHash, point_H);
1160
1161     // Infinity points are senseless
1162     if (point_Ps.IsInfinity()) {
1163         printf("CMalleableKeyView::CheckKeyVariant() : Ps is infinity");
1164         return false;
1165     }
1166
1167     // Check ownership
1168     if (point_Ps != point_P) {
1169         return false;
1170     }
1171
1172     return true;
1173 }
1174
1175 std::string CMalleableKeyView::ToString() const
1176 {
1177     CDataStream ssKey(SER_NETWORK, PROTOCOL_VERSION);
1178     ssKey << *this;
1179     std::vector<unsigned char> vch(ssKey.begin(), ssKey.end());
1180
1181     return EncodeBase58Check(vch);
1182 }
1183
1184 bool CMalleableKeyView::SetString(const std::string& strMutableKey)
1185 {
1186     std::vector<unsigned char> vchTemp;
1187     if (!DecodeBase58Check(strMutableKey, vchTemp)) {
1188         throw key_error("CMalleableKeyView::SetString() : Provided key data seems corrupted.");
1189     }
1190
1191     if (vchTemp.size() != 67)
1192         return false;
1193
1194     CDataStream ssKey(vchTemp, SER_NETWORK, PROTOCOL_VERSION);
1195     ssKey >> *this;
1196
1197     return IsValid();
1198 }
1199
1200 std::vector<unsigned char> CMalleableKeyView::Raw() const
1201 {
1202     CDataStream ssKey(SER_NETWORK, PROTOCOL_VERSION);
1203     ssKey << *this;
1204     std::vector<unsigned char> vch(ssKey.begin(), ssKey.end());
1205
1206     return vch;
1207 }
1208
1209
1210 bool CMalleableKeyView::IsValid() const
1211 {
1212     return vchSecretL.size() == 32 && GetMalleablePubKey().IsValid();
1213 }