commit
796e7b7aec
4 changed files with 67 additions and 9 deletions
23
src/key.cpp
23
src/key.cpp
|
@ -166,9 +166,12 @@ public:
|
|||
assert(nSize == nSize2);
|
||||
}
|
||||
|
||||
bool SetPrivKey(const CPrivKey &privkey) {
|
||||
bool SetPrivKey(const CPrivKey &privkey, bool fSkipCheck=false) {
|
||||
const unsigned char* pbegin = &privkey[0];
|
||||
if (d2i_ECPrivateKey(&pkey, &pbegin, privkey.size())) {
|
||||
if(fSkipCheck)
|
||||
return true;
|
||||
|
||||
// d2i_ECPrivateKey returns true if parsing succeeds.
|
||||
// This doesn't necessarily mean the key is valid.
|
||||
if (EC_KEY_check_key(pkey))
|
||||
|
@ -411,6 +414,24 @@ bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool CKey::Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck=false) {
|
||||
CECKey key;
|
||||
if (!key.SetPrivKey(privkey, fSkipCheck))
|
||||
return false;
|
||||
|
||||
key.GetSecretBytes(vch);
|
||||
fCompressed = vchPubKey.IsCompressed();
|
||||
fValid = true;
|
||||
|
||||
if (fSkipCheck)
|
||||
return true;
|
||||
|
||||
if (GetPubKey() != vchPubKey)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) const {
|
||||
if (!IsValid())
|
||||
return false;
|
||||
|
|
|
@ -261,6 +261,9 @@ public:
|
|||
|
||||
// Derive BIP32 child key.
|
||||
bool Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const;
|
||||
|
||||
// Load private key and check that public key matches.
|
||||
bool Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck);
|
||||
};
|
||||
|
||||
struct CExtPubKey {
|
||||
|
|
|
@ -306,6 +306,8 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
|||
}
|
||||
CKey key;
|
||||
CPrivKey pkey;
|
||||
uint256 hash = 0;
|
||||
|
||||
if (strType == "key")
|
||||
{
|
||||
wss.nKeys++;
|
||||
|
@ -315,16 +317,42 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
|||
ssValue >> wkey;
|
||||
pkey = wkey.vchPrivKey;
|
||||
}
|
||||
if (!key.SetPrivKey(pkey, vchPubKey.IsCompressed()))
|
||||
|
||||
// Old wallets store keys as "key" [pubkey] => [privkey]
|
||||
// ... which was slow for wallets with lots of keys, because the public key is re-derived from the private key
|
||||
// using EC operations as a checksum.
|
||||
// Newer wallets store keys as "key"[pubkey] => [privkey][hash(pubkey,privkey)], which is much faster while
|
||||
// remaining backwards-compatible.
|
||||
try
|
||||
{
|
||||
ssValue >> hash;
|
||||
}
|
||||
catch(...){}
|
||||
|
||||
bool fSkipCheck = false;
|
||||
|
||||
if (hash != 0)
|
||||
{
|
||||
// hash pubkey/privkey to accelerate wallet load
|
||||
std::vector<unsigned char> vchKey;
|
||||
vchKey.reserve(vchPubKey.size() + pkey.size());
|
||||
vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
|
||||
vchKey.insert(vchKey.end(), pkey.begin(), pkey.end());
|
||||
|
||||
if (Hash(vchKey.begin(), vchKey.end()) != hash)
|
||||
{
|
||||
strErr = "Error reading wallet database: CPubKey/CPrivKey corrupt";
|
||||
return false;
|
||||
}
|
||||
|
||||
fSkipCheck = true;
|
||||
}
|
||||
|
||||
if (!key.Load(pkey, vchPubKey, fSkipCheck))
|
||||
{
|
||||
strErr = "Error reading wallet database: CPrivKey corrupt";
|
||||
return false;
|
||||
}
|
||||
if (key.GetPubKey() != vchPubKey)
|
||||
{
|
||||
strErr = "Error reading wallet database: CPrivKey pubkey inconsistency";
|
||||
return false;
|
||||
}
|
||||
if (!pwallet->LoadKey(key, vchPubKey))
|
||||
{
|
||||
strErr = "Error reading wallet database: LoadKey failed";
|
||||
|
|
|
@ -93,8 +93,14 @@ public:
|
|||
if (!Write(std::make_pair(std::string("keymeta"), vchPubKey),
|
||||
keyMeta))
|
||||
return false;
|
||||
|
||||
return Write(std::make_pair(std::string("key"), vchPubKey), vchPrivKey, false);
|
||||
|
||||
// hash pubkey/privkey to accelerate wallet load
|
||||
std::vector<unsigned char> vchKey;
|
||||
vchKey.reserve(vchPubKey.size() + vchPrivKey.size());
|
||||
vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
|
||||
vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end());
|
||||
|
||||
return Write(std::make_pair(std::string("key"), vchPubKey), std::make_pair(vchPrivKey, Hash(vchKey.begin(), vchKey.end())), false);
|
||||
}
|
||||
|
||||
bool WriteCryptedKey(const CPubKey& vchPubKey,
|
||||
|
|
Loading…
Reference in a new issue