diff --git a/src/wallet/scriptpubkeyman.h b/src/wallet/scriptpubkeyman.h --- a/src/wallet/scriptpubkeyman.h +++ b/src/wallet/scriptpubkeyman.h @@ -314,7 +314,7 @@ public FillableSigningProvider { private: //! keeps track of whether Unlock has run a thorough check before - bool fDecryptionThoroughlyChecked = false; + bool fDecryptionThoroughlyChecked = true; using WatchOnlySet = std::set; using WatchKeyMap = std::map; @@ -490,7 +490,8 @@ //! Adds an encrypted key to the store, without saving it to disk (used by //! LoadWallet) bool LoadCryptedKey(const CPubKey &vchPubKey, - const std::vector &vchCryptedSecret); + const std::vector &vchCryptedSecret, + bool checksum_valid); void UpdateTimeFirstKey(int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_KeyStore); //! Adds a CScript to the store diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp --- a/src/wallet/scriptpubkeyman.cpp +++ b/src/wallet/scriptpubkeyman.cpp @@ -173,6 +173,7 @@ bool keyPass = mapCryptedKeys.empty(); bool keyFail = false; CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin(); + WalletBatch batch(m_storage.GetDatabase()); for (; mi != mapCryptedKeys.end(); ++mi) { const CPubKey &vchPubKey = (*mi).second.first; const std::vector &vchCryptedSecret = (*mi).second.second; @@ -184,6 +185,10 @@ keyPass = true; if (fDecryptionThoroughlyChecked) { break; + } else { + // Rewrite these encrypted keys with checksums + batch.WriteCryptedKey(vchPubKey, vchCryptedSecret, + mapKeyMetadata[vchPubKey.GetID()]); } } if (keyPass && keyFail) { @@ -687,7 +692,13 @@ } bool LegacyScriptPubKeyMan::LoadCryptedKey( - const CPubKey &vchPubKey, const std::vector &vchCryptedSecret) { + const CPubKey &vchPubKey, const std::vector &vchCryptedSecret, + bool checksum_valid) { + // Set fDecryptionThoroughlyChecked to false when the checksum is invalid + if (!checksum_valid) { + fDecryptionThoroughlyChecked = false; + } + return AddCryptedKeyInner(vchPubKey, vchCryptedSecret); } diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -131,9 +131,19 @@ return false; } - if (!WriteIC(std::make_pair(DBKeys::CRYPTED_KEY, vchPubKey), - vchCryptedSecret, false)) { - return false; + // Compute a checksum of the encrypted key + uint256 checksum = Hash(vchCryptedSecret.begin(), vchCryptedSecret.end()); + + const auto key = std::make_pair(DBKeys::CRYPTED_KEY, vchPubKey); + if (!WriteIC(key, std::make_pair(vchCryptedSecret, checksum), false)) { + // It may already exist, so try writing just the checksum + std::vector val; + if (!m_batch.Read(key, val)) { + return false; + } + if (!WriteIC(key, std::make_pair(val, checksum), true)) { + return false; + } } EraseIC(std::make_pair(DBKeys::KEY, vchPubKey)); return true; @@ -438,10 +448,24 @@ } std::vector vchPrivKey; ssValue >> vchPrivKey; + + // Get the checksum and check it + bool checksum_valid = false; + if (!ssValue.eof()) { + uint256 checksum; + ssValue >> checksum; + if ((checksum_valid = Hash(vchPrivKey.begin(), + vchPrivKey.end()) != checksum)) { + strErr = + "Error reading wallet database: Crypted key corrupt"; + return false; + } + } + wss.nCKeys++; if (!pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadCryptedKey( - vchPubKey, vchPrivKey)) { + vchPubKey, vchPrivKey, checksum_valid)) { strErr = "Error reading wallet database: " "LegacyScriptPubKeyMan::LoadCryptedKey failed"; return false;