aboutsummaryrefslogtreecommitdiff
path: root/src/key.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/key.cpp')
-rw-r--r--src/key.cpp135
1 files changed, 51 insertions, 84 deletions
diff --git a/src/key.cpp b/src/key.cpp
index 0ca9a681a..d8319db1a 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -1,29 +1,25 @@
-// Copyright (c) 2009-2014 The Bitcoin developers
+// Copyright (c) 2009-2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "key.h"
-#include "crypto/sha2.h"
+#include "arith_uint256.h"
+#include "crypto/hmac_sha512.h"
#include "eccryptoverify.h"
#include "pubkey.h"
#include "random.h"
-#ifdef USE_SECP256K1
#include <secp256k1.h>
-#else
#include "ecwrapper.h"
-#endif
//! anonymous namespace
namespace {
-#ifdef USE_SECP256K1
-#include <secp256k1.h>
class CSecp256k1Init {
public:
CSecp256k1Init() {
- secp256k1_start();
+ secp256k1_start(SECP256K1_START_SIGN);
}
~CSecp256k1Init() {
secp256k1_stop();
@@ -31,7 +27,6 @@ public:
};
static CSecp256k1Init instance_of_csecp256k1;
-#endif
} // anon namespace
bool CKey::Check(const unsigned char *vch) {
@@ -39,6 +34,7 @@ bool CKey::Check(const unsigned char *vch) {
}
void CKey::MakeNewKey(bool fCompressedIn) {
+ RandAddSeedPerfmon();
do {
GetRandBytes(vch, sizeof(vch));
} while (!Check(vch));
@@ -47,15 +43,8 @@ void CKey::MakeNewKey(bool fCompressedIn) {
}
bool CKey::SetPrivKey(const CPrivKey &privkey, bool fCompressedIn) {
-#ifdef USE_SECP256K1
- if (!secp256k1_ecdsa_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size()))
- return false;
-#else
- CECKey key;
- if (!key.SetPrivKey(&privkey[0], privkey.size()))
+ if (!secp256k1_ec_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size()))
return false;
- key.GetSecretBytes(vch);
-#endif
fCompressed = fCompressedIn;
fValid = true;
return true;
@@ -65,62 +54,61 @@ CPrivKey CKey::GetPrivKey() const {
assert(fValid);
CPrivKey privkey;
int privkeylen, ret;
-#ifdef USE_SECP256K1
privkey.resize(279);
privkeylen = 279;
- ret = secp256k1_ecdsa_privkey_export(begin(), (unsigned char*)&privkey[0], &privkeylen, fCompressed);
+ ret = secp256k1_ec_privkey_export(begin(), (unsigned char*)&privkey[0], &privkeylen, fCompressed);
assert(ret);
privkey.resize(privkeylen);
-#else
- CECKey key;
- key.SetSecretBytes(vch);
- privkeylen = key.GetPrivKeySize(fCompressed);
- assert(privkeylen);
- privkey.resize(privkeylen);
- ret = key.GetPrivKey(&privkey[0], fCompressed);
- assert(ret == (int)privkey.size());
-#endif
return privkey;
}
CPubKey CKey::GetPubKey() const {
assert(fValid);
CPubKey result;
-#ifdef USE_SECP256K1
int clen = 65;
- int ret = secp256k1_ecdsa_pubkey_create((unsigned char*)result.begin(), &clen, begin(), fCompressed);
+ int ret = secp256k1_ec_pubkey_create((unsigned char*)result.begin(), &clen, begin(), fCompressed);
assert((int)result.size() == clen);
assert(ret);
-#else
- std::vector<unsigned char> pubkey;
- CECKey key;
- key.SetSecretBytes(vch);
- key.GetPubKey(pubkey, fCompressed);
- result.Set(pubkey.begin(), pubkey.end());
-#endif
assert(result.IsValid());
return result;
}
-bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) const {
+extern "C"
+{
+static int secp256k1_nonce_function_test_case(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, unsigned int attempt, const void *data)
+{
+ const uint32_t *test_case = static_cast<const uint32_t*>(data);
+ uint256 nonce;
+ secp256k1_nonce_function_rfc6979(nonce.begin(), msg32, key32, attempt, NULL);
+ nonce = ArithToUint256(UintToArith256(nonce) + *test_case);
+ memcpy(nonce32, nonce.begin(), 32);
+ return 1;
+}
+}
+
+bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig, uint32_t test_case) const {
if (!fValid)
return false;
-#ifdef USE_SECP256K1
vchSig.resize(72);
int nSigLen = 72;
- CKey nonce;
- do {
- nonce.MakeNewKey(true);
- if (secp256k1_ecdsa_sign((const unsigned char*)&hash, 32, (unsigned char*)&vchSig[0], &nSigLen, begin(), nonce.begin()))
- break;
- } while(true);
+ int ret = secp256k1_ecdsa_sign(hash.begin(), (unsigned char*)&vchSig[0], &nSigLen, begin(), test_case == 0 ? secp256k1_nonce_function_rfc6979 : secp256k1_nonce_function_test_case, test_case == 0 ? NULL : &test_case);
+ assert(ret);
vchSig.resize(nSigLen);
return true;
-#else
- CECKey key;
- key.SetSecretBytes(vch);
- return key.Sign(hash, vchSig);
-#endif
+}
+
+bool CKey::VerifyPubKey(const CPubKey& pubkey) const {
+ if (pubkey.IsCompressed() != fCompressed) {
+ return false;
+ }
+ unsigned char rnd[8];
+ std::string str = "Bitcoin key verification\n";
+ GetRandBytes(rnd, sizeof(rnd));
+ uint256 hash;
+ CHash256().Write((unsigned char*)str.data(), str.size()).Write(rnd, sizeof(rnd)).Finalize(hash.begin());
+ std::vector<unsigned char> vchSig;
+ Sign(hash, vchSig);
+ return pubkey.Verify(hash, vchSig);
}
bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig) const {
@@ -128,44 +116,23 @@ bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig)
return false;
vchSig.resize(65);
int rec = -1;
-#ifdef USE_SECP256K1
- CKey nonce;
- do {
- nonce.MakeNewKey(true);
- if (secp256k1_ecdsa_sign_compact((const unsigned char*)&hash, 32, &vchSig[1], begin(), nonce.begin(), &rec))
- break;
- } while(true);
-#else
- CECKey key;
- key.SetSecretBytes(vch);
- if (!key.SignCompact(hash, &vchSig[1], rec))
- return false;
-#endif
+ int ret = secp256k1_ecdsa_sign_compact(hash.begin(), &vchSig[1], begin(), secp256k1_nonce_function_rfc6979, NULL, &rec);
+ assert(ret);
assert(rec != -1);
vchSig[0] = 27 + rec + (fCompressed ? 4 : 0);
return true;
}
bool CKey::Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck=false) {
-#ifdef USE_SECP256K1
- if (!secp256k1_ecdsa_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size()))
+ if (!secp256k1_ec_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size()))
return false;
-#else
- CECKey key;
- if (!key.SetPrivKey(&privkey[0], privkey.size(), fSkipCheck))
- return false;
- key.GetSecretBytes(vch);
-#endif
fCompressed = vchPubKey.IsCompressed();
fValid = true;
if (fSkipCheck)
return true;
- if (GetPubKey() != vchPubKey)
- return false;
-
- return true;
+ return VerifyPubKey(vchPubKey);
}
bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const {
@@ -182,12 +149,8 @@ bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild
BIP32Hash(cc, nChild, 0, begin(), out);
}
memcpy(ccChild, out+32, 32);
-#ifdef USE_SECP256K1
memcpy((unsigned char*)keyChild.begin(), begin(), 32);
- bool ret = secp256k1_ecdsa_privkey_tweak_add((unsigned char*)keyChild.begin(), out);
-#else
- bool ret = CECKey::TweakSecret((unsigned char*)keyChild.begin(), begin(), out);
-#endif
+ bool ret = secp256k1_ec_privkey_tweak_add((unsigned char*)keyChild.begin(), out);
UnlockObject(out);
keyChild.fCompressed = true;
keyChild.fValid = ret;
@@ -245,9 +208,13 @@ void CExtKey::Decode(const unsigned char code[74]) {
}
bool ECC_InitSanityCheck() {
-#ifdef USE_SECP256K1
- return true;
-#else
- return CECKey::SanityCheck();
+#if !defined(USE_SECP256K1)
+ if (!CECKey::SanityCheck()) {
+ return false;
+ }
#endif
+ CKey key;
+ key.MakeNewKey(true);
+ CPubKey pubkey = key.GetPubKey();
+ return key.VerifyPubKey(pubkey);
}