Skip to content

Commit

Permalink
Merge pull request #5224
Browse files Browse the repository at this point in the history
f321d6b Add key generation/verification to ECC sanity check (Pieter Wuille)
d0c41a7 Add sanity check after key generation (Pieter Wuille)
  • Loading branch information
laanwj committed Nov 24, 2014
2 parents dfc8e14 + f321d6b commit 6582f32
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 5 deletions.
29 changes: 24 additions & 5 deletions src/key.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 {
Expand Down Expand Up @@ -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 changes: 6 additions & 0 deletions src/key.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,12 @@ class CKey
//! 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);

Expand Down
2 changes: 2 additions & 0 deletions src/rpcdump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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());
Expand Down
20 changes: 20 additions & 0 deletions src/test/key_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()));
Expand Down
1 change: 1 addition & 0 deletions src/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down

0 comments on commit 6582f32

Please sign in to comment.