55#include " key.h"
66
77#include " crypto/sha2.h"
8+ #include < openssl/rand.h>
89
10+ #ifdef USE_SECP256K1
11+ #include < secp256k1.h>
12+ #else
913#include < openssl/bn.h>
1014#include < openssl/ecdsa.h>
1115#include < openssl/obj_mac.h>
12- #include < openssl/rand.h >
16+ #endif
1317
1418// anonymous namespace with local implementation code (OpenSSL interaction)
1519namespace {
1620
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+
1736// Generate a private key from just the secret parameter
1837int EC_KEY_regenerate_key (EC_KEY *eckey, BIGNUM *priv_key)
1938{
@@ -334,6 +353,8 @@ class CECKey {
334353 }
335354};
336355
356+ #endif
357+
337358int CompareBigEndian (const unsigned char *c1, size_t c1len, const unsigned char *c2, size_t c2len) {
338359 while (c1len > c2len) {
339360 if (*c1)
@@ -398,110 +419,183 @@ void CKey::MakeNewKey(bool fCompressedIn) {
398419}
399420
400421bool 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
401426 CECKey key;
402427 if (!key.SetPrivKey (privkey))
403428 return false ;
404429 key.GetSecretBytes (vch);
430+ #endif
405431 fCompressed = fCompressedIn ;
406432 fValid = true ;
407433 return true ;
408434}
409435
410436CPrivKey CKey::GetPrivKey () const {
411437 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
412446 CECKey key;
413447 key.SetSecretBytes (vch);
414- CPrivKey privkey;
415448 key.GetPrivKey (privkey, fCompressed );
449+ #endif
416450 return privkey;
417451}
418452
419453CPubKey CKey::GetPubKey () const {
420454 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
421463 CECKey key;
422464 key.SetSecretBytes (vch);
423- CPubKey pubkey;
424465 key.GetPubKey (pubkey, fCompressed );
466+ #endif
425467 return pubkey;
426468}
427469
428470bool CKey::Sign (const uint256 &hash, std::vector<unsigned char >& vchSig) const {
429471 if (!fValid )
430472 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
431485 CECKey key;
432486 key.SetSecretBytes (vch);
433487 return key.Sign (hash, vchSig);
488+ #endif
434489}
435490
436491bool CKey::SignCompact (const uint256 &hash, std::vector<unsigned char >& vchSig) const {
437492 if (!fValid )
438493 return false ;
439- CECKey key;
440- key.SetSecretBytes (vch);
441494 vchSig.resize (65 );
442495 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);
443506 if (!key.SignCompact (hash, &vchSig[1 ], rec))
444507 return false ;
508+ #endif
445509 assert (rec != -1 );
446510 vchSig[0 ] = 27 + rec + (fCompressed ? 4 : 0 );
447511 return true ;
448512}
449513
450514bool 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
451519 CECKey key;
452520 if (!key.SetPrivKey (privkey, fSkipCheck ))
453521 return false ;
454-
455522 key.GetSecretBytes (vch);
523+ #endif
456524 fCompressed = vchPubKey.IsCompressed ();
457525 fValid = true ;
458-
526+
459527 if (fSkipCheck )
460528 return true ;
461-
529+
462530 if (GetPubKey () != vchPubKey)
463531 return false ;
464-
532+
465533 return true ;
466534}
467535
468536bool CPubKey::Verify (const uint256 &hash, const std::vector<unsigned char >& vchSig) const {
469537 if (!IsValid ())
470538 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
471543 CECKey key;
472544 if (!key.SetPubKey (*this ))
473545 return false ;
474546 if (!key.Verify (hash, vchSig))
475547 return false ;
548+ #endif
476549 return true ;
477550}
478551
479552bool CPubKey::RecoverCompact (const uint256 &hash, const std::vector<unsigned char >& vchSig) {
480553 if (vchSig.size () != 65 )
481554 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
482563 CECKey key;
483- if (!key.Recover (hash, &vchSig[1 ], (vchSig[ 0 ] - 27 ) & ~ 4 ))
564+ if (!key.Recover (hash, &vchSig[1 ], recid ))
484565 return false ;
485- key.GetPubKey (*this , (vchSig[0 ] - 27 ) & 4 );
566+ key.GetPubKey (*this , fComp );
567+ #endif
486568 return true ;
487569}
488570
489571bool CPubKey::IsFullyValid () const {
490572 if (!IsValid ())
491573 return false ;
574+ #ifdef USE_SECP256K1
575+ if (!secp256k1_ecdsa_pubkey_verify (begin (), size ()))
576+ return false ;
577+ #else
492578 CECKey key;
493579 if (!key.SetPubKey (*this ))
494580 return false ;
581+ #endif
495582 return true ;
496583}
497584
498585bool CPubKey::Decompress () {
499586 if (!IsValid ())
500587 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
501594 CECKey key;
502595 if (!key.SetPubKey (*this ))
503596 return false ;
504597 key.GetPubKey (*this , false );
598+ #endif
505599 return true ;
506600}
507601
@@ -531,7 +625,12 @@ bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild
531625 BIP32Hash (cc, nChild, 0 , begin (), out);
532626 }
533627 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
534632 bool ret = CECKey::TweakSecret ((unsigned char *)keyChild.begin (), begin (), out);
633+ #endif
535634 UnlockObject (out);
536635 keyChild.fCompressed = true ;
537636 keyChild.fValid = ret;
@@ -545,10 +644,15 @@ bool CPubKey::Derive(CPubKey& pubkeyChild, unsigned char ccChild[32], unsigned i
545644 unsigned char out[64 ];
546645 BIP32Hash (cc, nChild, *begin (), begin ()+1 , out);
547646 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
548651 CECKey key;
549652 bool ret = key.SetPubKey (*this );
550653 ret &= key.TweakPublic (out);
551654 key.GetPubKey (pubkeyChild, true );
655+ #endif
552656 return ret;
553657}
554658
@@ -629,13 +733,17 @@ bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const {
629733}
630734
631735bool ECC_InitSanityCheck () {
736+ #ifdef USE_SECP256K1
737+ return true ;
738+ #else
632739 EC_KEY *pkey = EC_KEY_new_by_curve_name (NID_secp256k1);
633740 if (pkey == NULL )
634741 return false ;
635742 EC_KEY_free (pkey);
636743
637744 // TODO Is there more EC functionality that could be missing?
638745 return true ;
746+ #endif
639747}
640748
641749
0 commit comments