5
5
#include " key.h"
6
6
7
7
#include " crypto/sha2.h"
8
+ #include < openssl/rand.h>
8
9
10
+ #ifdef USE_SECP256K1
11
+ #include < secp256k1.h>
12
+ #else
9
13
#include < openssl/bn.h>
10
14
#include < openssl/ecdsa.h>
11
15
#include < openssl/obj_mac.h>
12
- #include < openssl/rand.h >
16
+ #endif
13
17
14
18
// anonymous namespace with local implementation code (OpenSSL interaction)
15
19
namespace {
16
20
21
+ #ifdef USE_SECP256K1
22
+ #include < secp256k1.h>
23
+ class CSecp256k1Init {
24
+ public:
25
+ CSecp256k1Init () {
26
+ secp256k1_start ();
27
+ }
28
+ ~CSecp256k1Init () {
29
+ secp256k1_stop ();
30
+ }
31
+ };
32
+ static CSecp256k1Init instance_of_csecp256k1;
33
+
34
+ #else
35
+
17
36
// Generate a private key from just the secret parameter
18
37
int EC_KEY_regenerate_key (EC_KEY *eckey, BIGNUM *priv_key)
19
38
{
@@ -334,6 +353,8 @@ class CECKey {
334
353
}
335
354
};
336
355
356
+ #endif
357
+
337
358
int CompareBigEndian (const unsigned char *c1, size_t c1len, const unsigned char *c2, size_t c2len) {
338
359
while (c1len > c2len) {
339
360
if (*c1)
@@ -398,110 +419,183 @@ void CKey::MakeNewKey(bool fCompressedIn) {
398
419
}
399
420
400
421
bool CKey::SetPrivKey (const CPrivKey &privkey, bool fCompressedIn ) {
422
+ #ifdef USE_SECP256K1
423
+ if (!secp256k1_ecdsa_privkey_import ((unsigned char *)begin (), &privkey[0 ], privkey.size ()))
424
+ return false ;
425
+ #else
401
426
CECKey key;
402
427
if (!key.SetPrivKey (privkey))
403
428
return false ;
404
429
key.GetSecretBytes (vch);
430
+ #endif
405
431
fCompressed = fCompressedIn ;
406
432
fValid = true ;
407
433
return true ;
408
434
}
409
435
410
436
CPrivKey CKey::GetPrivKey () const {
411
437
assert (fValid );
438
+ CPrivKey privkey;
439
+ #ifdef USE_SECP256K1
440
+ privkey.resize (279 );
441
+ int privkeylen = 279 ;
442
+ int ret = secp256k1_ecdsa_privkey_export (begin (), (unsigned char *)&privkey[0 ], &privkeylen, fCompressed );
443
+ assert (ret);
444
+ privkey.resize (privkeylen);
445
+ #else
412
446
CECKey key;
413
447
key.SetSecretBytes (vch);
414
- CPrivKey privkey;
415
448
key.GetPrivKey (privkey, fCompressed );
449
+ #endif
416
450
return privkey;
417
451
}
418
452
419
453
CPubKey CKey::GetPubKey () const {
420
454
assert (fValid );
455
+ CPubKey pubkey;
456
+ #ifdef USE_SECP256K1
457
+ int clen = 65 ;
458
+ int ret = secp256k1_ecdsa_pubkey_create ((unsigned char *)pubkey.begin (), &clen, begin (), fCompressed );
459
+ assert (ret);
460
+ assert (pubkey.IsValid ());
461
+ assert ((int )pubkey.size () == clen);
462
+ #else
421
463
CECKey key;
422
464
key.SetSecretBytes (vch);
423
- CPubKey pubkey;
424
465
key.GetPubKey (pubkey, fCompressed );
466
+ #endif
425
467
return pubkey;
426
468
}
427
469
428
470
bool CKey::Sign (const uint256 &hash, std::vector<unsigned char >& vchSig) const {
429
471
if (!fValid )
430
472
return false ;
473
+ #ifdef USE_SECP256K1
474
+ vchSig.resize (72 );
475
+ int nSigLen = 72 ;
476
+ CKey nonce;
477
+ do {
478
+ nonce.MakeNewKey (true );
479
+ if (secp256k1_ecdsa_sign ((const unsigned char *)&hash, 32 , (unsigned char *)&vchSig[0 ], &nSigLen, begin (), nonce.begin ()))
480
+ break ;
481
+ } while (true );
482
+ vchSig.resize (nSigLen);
483
+ return true ;
484
+ #else
431
485
CECKey key;
432
486
key.SetSecretBytes (vch);
433
487
return key.Sign (hash, vchSig);
488
+ #endif
434
489
}
435
490
436
491
bool CKey::SignCompact (const uint256 &hash, std::vector<unsigned char >& vchSig) const {
437
492
if (!fValid )
438
493
return false ;
439
- CECKey key;
440
- key.SetSecretBytes (vch);
441
494
vchSig.resize (65 );
442
495
int rec = -1 ;
496
+ #ifdef USE_SECP256K1
497
+ CKey nonce;
498
+ do {
499
+ nonce.MakeNewKey (true );
500
+ if (secp256k1_ecdsa_sign_compact ((const unsigned char *)&hash, 32 , &vchSig[1 ], begin (), nonce.begin (), &rec))
501
+ break ;
502
+ } while (true );
503
+ #else
504
+ CECKey key;
505
+ key.SetSecretBytes (vch);
443
506
if (!key.SignCompact (hash, &vchSig[1 ], rec))
444
507
return false ;
508
+ #endif
445
509
assert (rec != -1 );
446
510
vchSig[0 ] = 27 + rec + (fCompressed ? 4 : 0 );
447
511
return true ;
448
512
}
449
513
450
514
bool CKey::Load (CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck =false ) {
515
+ #ifdef USE_SECP256K1
516
+ if (!secp256k1_ecdsa_privkey_import ((unsigned char *)begin (), &privkey[0 ], privkey.size ()))
517
+ return false ;
518
+ #else
451
519
CECKey key;
452
520
if (!key.SetPrivKey (privkey, fSkipCheck ))
453
521
return false ;
454
-
455
522
key.GetSecretBytes (vch);
523
+ #endif
456
524
fCompressed = vchPubKey.IsCompressed ();
457
525
fValid = true ;
458
-
526
+
459
527
if (fSkipCheck )
460
528
return true ;
461
-
529
+
462
530
if (GetPubKey () != vchPubKey)
463
531
return false ;
464
-
532
+
465
533
return true ;
466
534
}
467
535
468
536
bool CPubKey::Verify (const uint256 &hash, const std::vector<unsigned char >& vchSig) const {
469
537
if (!IsValid ())
470
538
return false ;
539
+ #ifdef USE_SECP256K1
540
+ if (secp256k1_ecdsa_verify ((const unsigned char *)&hash, 32 , &vchSig[0 ], vchSig.size (), begin (), size ()) != 1 )
541
+ return false ;
542
+ #else
471
543
CECKey key;
472
544
if (!key.SetPubKey (*this ))
473
545
return false ;
474
546
if (!key.Verify (hash, vchSig))
475
547
return false ;
548
+ #endif
476
549
return true ;
477
550
}
478
551
479
552
bool CPubKey::RecoverCompact (const uint256 &hash, const std::vector<unsigned char >& vchSig) {
480
553
if (vchSig.size () != 65 )
481
554
return false ;
555
+ int recid = (vchSig[0 ] - 27 ) & 3 ;
556
+ bool fComp = (vchSig[0 ] - 27 ) & 4 ;
557
+ #ifdef USE_SECP256K1
558
+ int pubkeylen = 65 ;
559
+ if (!secp256k1_ecdsa_recover_compact ((const unsigned char *)&hash, 32 , &vchSig[1 ], (unsigned char *)begin (), &pubkeylen, fComp , recid))
560
+ return false ;
561
+ assert ((int )size () == pubkeylen);
562
+ #else
482
563
CECKey key;
483
- if (!key.Recover (hash, &vchSig[1 ], (vchSig[ 0 ] - 27 ) & ~ 4 ))
564
+ if (!key.Recover (hash, &vchSig[1 ], recid ))
484
565
return false ;
485
- key.GetPubKey (*this , (vchSig[0 ] - 27 ) & 4 );
566
+ key.GetPubKey (*this , fComp );
567
+ #endif
486
568
return true ;
487
569
}
488
570
489
571
bool CPubKey::IsFullyValid () const {
490
572
if (!IsValid ())
491
573
return false ;
574
+ #ifdef USE_SECP256K1
575
+ if (!secp256k1_ecdsa_pubkey_verify (begin (), size ()))
576
+ return false ;
577
+ #else
492
578
CECKey key;
493
579
if (!key.SetPubKey (*this ))
494
580
return false ;
581
+ #endif
495
582
return true ;
496
583
}
497
584
498
585
bool CPubKey::Decompress () {
499
586
if (!IsValid ())
500
587
return false ;
588
+ #ifdef USE_SECP256K1
589
+ int clen = size ();
590
+ int ret = secp256k1_ecdsa_pubkey_decompress ((unsigned char *)begin (), &clen);
591
+ assert (ret);
592
+ assert (clen == (int )size ());
593
+ #else
501
594
CECKey key;
502
595
if (!key.SetPubKey (*this ))
503
596
return false ;
504
597
key.GetPubKey (*this , false );
598
+ #endif
505
599
return true ;
506
600
}
507
601
@@ -531,7 +625,12 @@ bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild
531
625
BIP32Hash (cc, nChild, 0 , begin (), out);
532
626
}
533
627
memcpy (ccChild, out+32 , 32 );
628
+ #ifdef USE_SECP256K1
629
+ memcpy ((unsigned char *)keyChild.begin (), begin (), 32 );
630
+ bool ret = secp256k1_ecdsa_privkey_tweak_add ((unsigned char *)keyChild.begin (), out);
631
+ #else
534
632
bool ret = CECKey::TweakSecret ((unsigned char *)keyChild.begin (), begin (), out);
633
+ #endif
535
634
UnlockObject (out);
536
635
keyChild.fCompressed = true ;
537
636
keyChild.fValid = ret;
@@ -545,10 +644,15 @@ bool CPubKey::Derive(CPubKey& pubkeyChild, unsigned char ccChild[32], unsigned i
545
644
unsigned char out[64 ];
546
645
BIP32Hash (cc, nChild, *begin (), begin ()+1 , out);
547
646
memcpy (ccChild, out+32 , 32 );
647
+ #ifdef USE_SECP256K1
648
+ pubkeyChild = *this ;
649
+ bool ret = secp256k1_ecdsa_pubkey_tweak_add ((unsigned char *)pubkeyChild.begin (), pubkeyChild.size (), out);
650
+ #else
548
651
CECKey key;
549
652
bool ret = key.SetPubKey (*this );
550
653
ret &= key.TweakPublic (out);
551
654
key.GetPubKey (pubkeyChild, true );
655
+ #endif
552
656
return ret;
553
657
}
554
658
@@ -629,13 +733,17 @@ bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const {
629
733
}
630
734
631
735
bool ECC_InitSanityCheck () {
736
+ #ifdef USE_SECP256K1
737
+ return true ;
738
+ #else
632
739
EC_KEY *pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
633
740
if (pkey == NULL )
634
741
return false ;
635
742
EC_KEY_free (pkey);
636
743
637
744
// TODO Is there more EC functionality that could be missing?
638
745
return true ;
746
+ #endif
639
747
}
640
748
641
749
0 commit comments