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