Browse Source

Merge pull request #5224

f321d6b Add key generation/verification to ECC sanity check (Pieter Wuille)
d0c41a7 Add sanity check after key generation (Pieter Wuille)
0.10
Wladimir J. van der Laan 10 years ago
parent
commit
6582f323f0
No known key found for this signature in database
GPG Key ID: 74810B012346C9A6
  1. 29
      src/key.cpp
  2. 6
      src/key.h
  3. 2
      src/rpcdump.cpp
  4. 20
      src/test/key_tests.cpp
  5. 1
      src/wallet.cpp

29
src/key.cpp

@ -86,6 +86,20 @@ bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) const { @@ -86,6 +86,20 @@ bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) const {
return true;
}
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((unsigned char*)&hash);
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 {
if (!fValid)
return false;
@ -111,10 +125,7 @@ bool CKey::Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck=false) { @@ -111,10 +125,7 @@ bool CKey::Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck=false) {
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 {
@ -190,5 +201,13 @@ void CExtKey::Decode(const unsigned char code[74]) { @@ -190,5 +201,13 @@ void CExtKey::Decode(const unsigned char code[74]) {
}
bool ECC_InitSanityCheck() {
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);
}

6
src/key.h

@ -137,6 +137,12 @@ public: @@ -137,6 +137,12 @@ public:
//! Derive BIP32 child key.
bool Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const;
/**
* Verify thoroughly whether a private key and a public key match.
* This is done using a different mechanism than just regenerating it.
*/
bool VerifyPubKey(const CPubKey& vchPubKey) const;
//! Load private key and check that public key matches.
bool Load(CPrivKey& privkey, CPubKey& vchPubKey, bool fSkipCheck);

2
src/rpcdump.cpp

@ -112,6 +112,7 @@ Value importprivkey(const Array& params, bool fHelp) @@ -112,6 +112,7 @@ Value importprivkey(const Array& params, bool fHelp)
if (!key.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
CPubKey pubkey = key.GetPubKey();
assert(key.VerifyPubKey(pubkey));
CKeyID vchAddress = pubkey.GetID();
{
pwalletMain->MarkDirty();
@ -253,6 +254,7 @@ Value importwallet(const Array& params, bool fHelp) @@ -253,6 +254,7 @@ Value importwallet(const Array& params, bool fHelp)
continue;
CKey key = vchSecret.GetKey();
CPubKey pubkey = key.GetPubKey();
assert(key.VerifyPubKey(pubkey));
CKeyID keyid = pubkey.GetID();
if (pwalletMain->HaveKey(keyid)) {
LogPrintf("Skipping import of %s (key already present)\n", CBitcoinAddress(keyid).ToString());

20
src/test/key_tests.cpp

@ -82,6 +82,26 @@ BOOST_AUTO_TEST_CASE(key_test1) @@ -82,6 +82,26 @@ BOOST_AUTO_TEST_CASE(key_test1)
CPubKey pubkey1C = key1C.GetPubKey();
CPubKey pubkey2C = key2C.GetPubKey();
BOOST_CHECK(key1.VerifyPubKey(pubkey1));
BOOST_CHECK(!key1.VerifyPubKey(pubkey1C));
BOOST_CHECK(!key1.VerifyPubKey(pubkey2));
BOOST_CHECK(!key1.VerifyPubKey(pubkey2C));
BOOST_CHECK(!key1C.VerifyPubKey(pubkey1));
BOOST_CHECK(key1C.VerifyPubKey(pubkey1C));
BOOST_CHECK(!key1C.VerifyPubKey(pubkey2));
BOOST_CHECK(!key1C.VerifyPubKey(pubkey2C));
BOOST_CHECK(!key2.VerifyPubKey(pubkey1));
BOOST_CHECK(!key2.VerifyPubKey(pubkey1C));
BOOST_CHECK(key2.VerifyPubKey(pubkey2));
BOOST_CHECK(!key2.VerifyPubKey(pubkey2C));
BOOST_CHECK(!key2C.VerifyPubKey(pubkey1));
BOOST_CHECK(!key2C.VerifyPubKey(pubkey1C));
BOOST_CHECK(!key2C.VerifyPubKey(pubkey2));
BOOST_CHECK(key2C.VerifyPubKey(pubkey2C));
BOOST_CHECK(addr1.Get() == CTxDestination(pubkey1.GetID()));
BOOST_CHECK(addr2.Get() == CTxDestination(pubkey2.GetID()));
BOOST_CHECK(addr1C.Get() == CTxDestination(pubkey1C.GetID()));

1
src/wallet.cpp

@ -79,6 +79,7 @@ CPubKey CWallet::GenerateNewKey() @@ -79,6 +79,7 @@ CPubKey CWallet::GenerateNewKey()
SetMinVersion(FEATURE_COMPRPUBKEY);
CPubKey pubkey = secret.GetPubKey();
assert(secret.VerifyPubKey(pubkey));
// Create new metadata
int64_t nCreationTime = GetTime();

Loading…
Cancel
Save