LCOV - code coverage report
Current view: top level - src - key.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 134 140 95.7 %
Date: 2015-10-12 22:39:14 Functions: 19 20 95.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2009-2014 The Bitcoin Core developers
       2             : // Distributed under the MIT software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #include "key.h"
       6             : 
       7             : #include "arith_uint256.h"
       8             : #include "crypto/common.h"
       9             : #include "crypto/hmac_sha512.h"
      10             : #include "eccryptoverify.h"
      11             : #include "pubkey.h"
      12             : #include "random.h"
      13             : 
      14             : #include <secp256k1.h>
      15             : #include "ecwrapper.h"
      16             : 
      17             : static secp256k1_context_t* secp256k1_context = NULL;
      18             : 
      19         594 : bool CKey::Check(const unsigned char *vch) {
      20        1812 :     return eccrypto::Check(vch);
      21             : }
      22             : 
      23        1204 : void CKey::MakeNewKey(bool fCompressedIn) {
      24        1204 :     RandAddSeedPerfmon();
      25        1204 :     do {
      26        1204 :         GetRandBytes(vch, sizeof(vch));
      27        1204 :     } while (!Check(vch));
      28        1204 :     fValid = true;
      29        1204 :     fCompressed = fCompressedIn;
      30        1204 : }
      31             : 
      32           0 : bool CKey::SetPrivKey(const CPrivKey &privkey, bool fCompressedIn) {
      33           0 :     if (!secp256k1_ec_privkey_import(secp256k1_context, (unsigned char*)begin(), &privkey[0], privkey.size()))
      34             :         return false;
      35           0 :     fCompressed = fCompressedIn;
      36           0 :     fValid = true;
      37           0 :     return true;
      38             : }
      39             : 
      40        1349 : CPrivKey CKey::GetPrivKey() const {
      41        1349 :     assert(fValid);
      42             :     CPrivKey privkey;
      43             :     int privkeylen, ret;
      44        1349 :     privkey.resize(279);
      45        1349 :     privkeylen = 279;
      46        2698 :     ret = secp256k1_ec_privkey_export(secp256k1_context, begin(), (unsigned char*)&privkey[0], &privkeylen, fCompressed);
      47        1349 :     assert(ret);
      48        1349 :     privkey.resize(privkeylen);
      49        1349 :     return privkey;
      50             : }
      51             : 
      52        2158 : CPubKey CKey::GetPubKey() const {
      53        2158 :     assert(fValid);
      54             :     CPubKey result;
      55        2158 :     int clen = 65;
      56        4316 :     int ret = secp256k1_ec_pubkey_create(secp256k1_context, (unsigned char*)result.begin(), &clen, begin(), fCompressed);
      57        4316 :     assert((int)result.size() == clen);
      58        2158 :     assert(ret);
      59        2158 :     assert(result.IsValid());
      60        2158 :     return result;
      61             : }
      62             : 
      63        3804 : bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig, uint32_t test_case) const {
      64        3804 :     if (!fValid)
      65             :         return false;
      66        3804 :     vchSig.resize(72);
      67        3804 :     int nSigLen = 72;
      68        3804 :     unsigned char extra_entropy[32] = {0};
      69             :     WriteLE32(extra_entropy, test_case);
      70       11412 :     int ret = secp256k1_ecdsa_sign(secp256k1_context, hash.begin(), (unsigned char*)&vchSig[0], &nSigLen, begin(), secp256k1_nonce_function_rfc6979, test_case ? extra_entropy : NULL);
      71        3804 :     assert(ret);
      72        3804 :     vchSig.resize(nSigLen);
      73             :     return true;
      74             : }
      75             : 
      76        1697 : bool CKey::VerifyPubKey(const CPubKey& pubkey) const {
      77        1697 :     if (pubkey.IsCompressed() != fCompressed) {
      78             :         return false;
      79             :     }
      80             :     unsigned char rnd[8];
      81        3378 :     std::string str = "Bitcoin key verification\n";
      82        1689 :     GetRandBytes(rnd, sizeof(rnd));
      83             :     uint256 hash;
      84        5067 :     CHash256().Write((unsigned char*)str.data(), str.size()).Write(rnd, sizeof(rnd)).Finalize(hash.begin());
      85             :     std::vector<unsigned char> vchSig;
      86        1689 :     Sign(hash, vchSig);
      87        1689 :     return pubkey.Verify(hash, vchSig);
      88             : }
      89             : 
      90          69 : bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig) const {
      91          69 :     if (!fValid)
      92             :         return false;
      93          69 :     vchSig.resize(65);
      94          69 :     int rec = -1;
      95         276 :     int ret = secp256k1_ecdsa_sign_compact(secp256k1_context, hash.begin(), &vchSig[1], begin(), secp256k1_nonce_function_rfc6979, NULL, &rec);
      96          69 :     assert(ret);
      97          69 :     assert(rec != -1);
      98          69 :     vchSig[0] = 27 + rec + (fCompressed ? 4 : 0);
      99          69 :     return true;
     100             : }
     101             : 
     102        2598 : bool CKey::Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck=false) {
     103        7794 :     if (!secp256k1_ec_privkey_import(secp256k1_context, (unsigned char*)begin(), &privkey[0], privkey.size()))
     104             :         return false;
     105        2598 :     fCompressed = vchPubKey.IsCompressed();
     106        2598 :     fValid = true;
     107             : 
     108        2598 :     if (fSkipCheck)
     109             :         return true;
     110             : 
     111           0 :     return VerifyPubKey(vchPubKey);
     112             : }
     113             : 
     114          12 : bool CKey::Derive(CKey& keyChild, ChainCode &ccChild, unsigned int nChild, const ChainCode& cc) const {
     115          12 :     assert(IsValid());
     116          12 :     assert(IsCompressed());
     117             :     unsigned char out[64];
     118          12 :     LockObject(out);
     119          12 :     if ((nChild >> 31) == 0) {
     120           8 :         CPubKey pubkey = GetPubKey();
     121          16 :         assert(pubkey.begin() + 33 == pubkey.end());
     122           8 :         BIP32Hash(cc, nChild, *pubkey.begin(), pubkey.begin()+1, out);
     123             :     } else {
     124           8 :         assert(begin() + 32 == end());
     125           4 :         BIP32Hash(cc, nChild, 0, begin(), out);
     126             :     }
     127          24 :     memcpy(ccChild.begin(), out+32, 32);
     128          24 :     memcpy((unsigned char*)keyChild.begin(), begin(), 32);
     129          12 :     bool ret = secp256k1_ec_privkey_tweak_add(secp256k1_context, (unsigned char*)keyChild.begin(), out);
     130          12 :     UnlockObject(out);
     131          12 :     keyChild.fCompressed = true;
     132          12 :     keyChild.fValid = ret;
     133          12 :     return ret;
     134             : }
     135             : 
     136          12 : bool CExtKey::Derive(CExtKey &out, unsigned int nChild) const {
     137          12 :     out.nDepth = nDepth + 1;
     138          12 :     CKeyID id = key.GetPubKey().GetID();
     139          12 :     memcpy(&out.vchFingerprint[0], &id, 4);
     140          12 :     out.nChild = nChild;
     141          12 :     return key.Derive(out.key, out.chaincode, nChild, chaincode);
     142             : }
     143             : 
     144           2 : void CExtKey::SetMaster(const unsigned char *seed, unsigned int nSeedLen) {
     145             :     static const unsigned char hashkey[] = {'B','i','t','c','o','i','n',' ','s','e','e','d'};
     146             :     unsigned char out[64];
     147           2 :     LockObject(out);
     148           4 :     CHMAC_SHA512(hashkey, sizeof(hashkey)).Write(seed, nSeedLen).Finalize(out);
     149           2 :     key.Set(&out[0], &out[32], true);
     150           4 :     memcpy(chaincode.begin(), &out[32], 32);
     151           2 :     UnlockObject(out);
     152           2 :     nDepth = 0;
     153           2 :     nChild = 0;
     154           2 :     memset(vchFingerprint, 0, sizeof(vchFingerprint));
     155           2 : }
     156             : 
     157          14 : CExtPubKey CExtKey::Neuter() const {
     158             :     CExtPubKey ret;
     159          14 :     ret.nDepth = nDepth;
     160          14 :     memcpy(&ret.vchFingerprint[0], &vchFingerprint[0], 4);
     161          14 :     ret.nChild = nChild;
     162          14 :     ret.pubkey = key.GetPubKey();
     163          14 :     ret.chaincode = chaincode;
     164          14 :     return ret;
     165             : }
     166             : 
     167          24 : void CExtKey::Encode(unsigned char code[74]) const {
     168          24 :     code[0] = nDepth;
     169          24 :     memcpy(code+1, vchFingerprint, 4);
     170          24 :     code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF;
     171          24 :     code[7] = (nChild >>  8) & 0xFF; code[8] = (nChild >>  0) & 0xFF;
     172          48 :     memcpy(code+9, chaincode.begin(), 32);
     173          24 :     code[41] = 0;
     174          48 :     assert(key.size() == 32);
     175          48 :     memcpy(code+42, key.begin(), 32);
     176          24 : }
     177             : 
     178          12 : void CExtKey::Decode(const unsigned char code[74]) {
     179          12 :     nDepth = code[0];
     180          12 :     memcpy(vchFingerprint, code+1, 4);
     181          12 :     nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8];
     182          24 :     memcpy(chaincode.begin(), code+9, 32);
     183          12 :     key.Set(code+42, code+74, true);
     184          12 : }
     185             : 
     186          95 : bool ECC_InitSanityCheck() {
     187          95 :     if (!CECKey::SanityCheck()) {
     188             :         return false;
     189             :     }
     190             :     CKey key;
     191          95 :     key.MakeNewKey(true);
     192          95 :     CPubKey pubkey = key.GetPubKey();
     193          95 :     return key.VerifyPubKey(pubkey);
     194             : }
     195             : 
     196             : 
     197         270 : void ECC_Start() {
     198         270 :     assert(secp256k1_context == NULL);
     199             : 
     200         270 :     secp256k1_context_t *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
     201         270 :     assert(ctx != NULL);
     202             : 
     203             :     {
     204             :         // Pass in a random blinding seed to the secp256k1 context.
     205             :         unsigned char seed[32];
     206         270 :         LockObject(seed);
     207         270 :         GetRandBytes(seed, 32);
     208         270 :         bool ret = secp256k1_context_randomize(ctx, seed);
     209         270 :         assert(ret);
     210         270 :         UnlockObject(seed);
     211             :     }
     212             : 
     213         270 :     secp256k1_context = ctx;
     214         270 : }
     215             : 
     216         270 : void ECC_Stop() {
     217         270 :     secp256k1_context_t *ctx = secp256k1_context;
     218         270 :     secp256k1_context = NULL;
     219             : 
     220         270 :     if (ctx) {
     221         270 :         secp256k1_context_destroy(ctx);
     222             :     }
     223         600 : }

Generated by: LCOV version 1.11