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