Skip to content

Commit 6582f32

Browse files
committed
Merge pull request #5224
f321d6b Add key generation/verification to ECC sanity check (Pieter Wuille) d0c41a7 Add sanity check after key generation (Pieter Wuille)
2 parents dfc8e14 + f321d6b commit 6582f32

File tree

5 files changed

+53
-5
lines changed

5 files changed

+53
-5
lines changed

src/key.cpp

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,20 @@ bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) const {
8686
return true;
8787
}
8888

89+
bool CKey::VerifyPubKey(const CPubKey& pubkey) const {
90+
if (pubkey.IsCompressed() != fCompressed) {
91+
return false;
92+
}
93+
unsigned char rnd[8];
94+
std::string str = "Bitcoin key verification\n";
95+
GetRandBytes(rnd, sizeof(rnd));
96+
uint256 hash;
97+
CHash256().Write((unsigned char*)str.data(), str.size()).Write(rnd, sizeof(rnd)).Finalize((unsigned char*)&hash);
98+
std::vector<unsigned char> vchSig;
99+
Sign(hash, vchSig);
100+
return pubkey.Verify(hash, vchSig);
101+
}
102+
89103
bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig) const {
90104
if (!fValid)
91105
return false;
@@ -111,10 +125,7 @@ bool CKey::Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck=false) {
111125
if (fSkipCheck)
112126
return true;
113127

114-
if (GetPubKey() != vchPubKey)
115-
return false;
116-
117-
return true;
128+
return VerifyPubKey(vchPubKey);
118129
}
119130

120131
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]) {
190201
}
191202

192203
bool ECC_InitSanityCheck() {
193-
return CECKey::SanityCheck();
204+
#if !defined(USE_SECP256K1)
205+
if (!CECKey::SanityCheck()) {
206+
return false;
207+
}
208+
#endif
209+
CKey key;
210+
key.MakeNewKey(true);
211+
CPubKey pubkey = key.GetPubKey();
212+
return key.VerifyPubKey(pubkey);
194213
}

src/key.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,12 @@ class CKey
137137
//! Derive BIP32 child key.
138138
bool Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const;
139139

140+
/**
141+
* Verify thoroughly whether a private key and a public key match.
142+
* This is done using a different mechanism than just regenerating it.
143+
*/
144+
bool VerifyPubKey(const CPubKey& vchPubKey) const;
145+
140146
//! Load private key and check that public key matches.
141147
bool Load(CPrivKey& privkey, CPubKey& vchPubKey, bool fSkipCheck);
142148

src/rpcdump.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ Value importprivkey(const Array& params, bool fHelp)
112112
if (!key.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
113113

114114
CPubKey pubkey = key.GetPubKey();
115+
assert(key.VerifyPubKey(pubkey));
115116
CKeyID vchAddress = pubkey.GetID();
116117
{
117118
pwalletMain->MarkDirty();
@@ -253,6 +254,7 @@ Value importwallet(const Array& params, bool fHelp)
253254
continue;
254255
CKey key = vchSecret.GetKey();
255256
CPubKey pubkey = key.GetPubKey();
257+
assert(key.VerifyPubKey(pubkey));
256258
CKeyID keyid = pubkey.GetID();
257259
if (pwalletMain->HaveKey(keyid)) {
258260
LogPrintf("Skipping import of %s (key already present)\n", CBitcoinAddress(keyid).ToString());

src/test/key_tests.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,26 @@ BOOST_AUTO_TEST_CASE(key_test1)
8282
CPubKey pubkey1C = key1C.GetPubKey();
8383
CPubKey pubkey2C = key2C.GetPubKey();
8484

85+
BOOST_CHECK(key1.VerifyPubKey(pubkey1));
86+
BOOST_CHECK(!key1.VerifyPubKey(pubkey1C));
87+
BOOST_CHECK(!key1.VerifyPubKey(pubkey2));
88+
BOOST_CHECK(!key1.VerifyPubKey(pubkey2C));
89+
90+
BOOST_CHECK(!key1C.VerifyPubKey(pubkey1));
91+
BOOST_CHECK(key1C.VerifyPubKey(pubkey1C));
92+
BOOST_CHECK(!key1C.VerifyPubKey(pubkey2));
93+
BOOST_CHECK(!key1C.VerifyPubKey(pubkey2C));
94+
95+
BOOST_CHECK(!key2.VerifyPubKey(pubkey1));
96+
BOOST_CHECK(!key2.VerifyPubKey(pubkey1C));
97+
BOOST_CHECK(key2.VerifyPubKey(pubkey2));
98+
BOOST_CHECK(!key2.VerifyPubKey(pubkey2C));
99+
100+
BOOST_CHECK(!key2C.VerifyPubKey(pubkey1));
101+
BOOST_CHECK(!key2C.VerifyPubKey(pubkey1C));
102+
BOOST_CHECK(!key2C.VerifyPubKey(pubkey2));
103+
BOOST_CHECK(key2C.VerifyPubKey(pubkey2C));
104+
85105
BOOST_CHECK(addr1.Get() == CTxDestination(pubkey1.GetID()));
86106
BOOST_CHECK(addr2.Get() == CTxDestination(pubkey2.GetID()));
87107
BOOST_CHECK(addr1C.Get() == CTxDestination(pubkey1C.GetID()));

src/wallet.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ CPubKey CWallet::GenerateNewKey()
7979
SetMinVersion(FEATURE_COMPRPUBKEY);
8080

8181
CPubKey pubkey = secret.GetPubKey();
82+
assert(secret.VerifyPubKey(pubkey));
8283

8384
// Create new metadata
8485
int64_t nCreationTime = GetTime();

0 commit comments

Comments
 (0)