From: MASM fan Date: Wed, 11 Feb 2015 21:10:59 +0000 (-0800) Subject: Wallet decryption support X-Git-Tag: nvc-v0.5.3~102 X-Git-Url: https://git.novaco.in/?p=novacoin.git;a=commitdiff_plain;h=b032c4a33e27deebe9210347048998ecc4624ee4 Wallet decryption support --- diff --git a/src/keystore.cpp b/src/keystore.cpp index fb85da1..ef61748 100644 --- a/src/keystore.cpp +++ b/src/keystore.cpp @@ -269,3 +269,33 @@ bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn) } return true; } + +bool CCryptoKeyStore::DecryptKeys(const CKeyingMaterial& vMasterKeyIn) +{ + { + LOCK(cs_KeyStore); + if (!IsCrypted()) + return false; + + CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin(); + for (; mi != mapCryptedKeys.end(); ++mi) + { + const CPubKey &vchPubKey = (*mi).second.first; + const std::vector &vchCryptedSecret = (*mi).second.second; + CSecret vchSecret; + if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, vchPubKey.GetHash(), vchSecret)) + return false; + if (vchSecret.size() != 32) + return false; + CKey key; + key.SetPubKey(vchPubKey); + key.SetSecret(vchSecret); + if (!CBasicKeyStore::AddKey(key)) + return false; + } + + mapCryptedKeys.clear(); + } + + return true; +} diff --git a/src/keystore.h b/src/keystore.h index 9573e3f..32d7783 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -147,6 +147,7 @@ protected: // will encrypt previously unencrypted keys bool EncryptKeys(CKeyingMaterial& vMasterKeyIn); + bool DecryptKeys(const CKeyingMaterial& vMasterKeyIn); bool Unlock(const CKeyingMaterial& vMasterKeyIn); diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp index 34f451e..9e91cb1 100644 --- a/src/qt/askpassphrasedialog.cpp +++ b/src/qt/askpassphrasedialog.cpp @@ -173,7 +173,11 @@ void AskPassphraseDialog::accept() } else { - QDialog::accept(); // Success + QMessageBox::warning(this, tr("Wallet decrypted"), + "" + + tr("NovaCoin will close now to finish the decryption process. ") + + ""); + QApplication::quit(); } break; case ChangePass: diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index b6d73ad..3171647 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -1023,7 +1023,7 @@ void BitcoinGUI::setEncryptionStatus(int status) labelEncryptionIcon->setToolTip(tr("Wallet is encrypted and currently unlocked")); encryptWalletAction->setChecked(true); changePassphraseAction->setEnabled(true); - encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported + encryptWalletAction->setEnabled(true); lockWalletAction->setEnabled(true); lockWalletAction->setChecked(false); @@ -1042,7 +1042,7 @@ void BitcoinGUI::setEncryptionStatus(int status) labelEncryptionIcon->setToolTip(tr("Wallet is encrypted and currently locked")); encryptWalletAction->setChecked(true); changePassphraseAction->setEnabled(true); - encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported + encryptWalletAction->setEnabled(true); lockWalletAction->setChecked(true); unlockWalletAction->setChecked(false); diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 2f2ccab..f7658b0 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -302,8 +302,8 @@ bool WalletModel::setWalletEncrypted(bool encrypted, const SecureString &passphr } else { - // Decrypt -- TODO; not supported yet - return false; + // Decrypt + return wallet->DecryptWallet(passphrase); } } diff --git a/src/wallet.cpp b/src/wallet.cpp index e77fe80..89fad8f 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -62,7 +62,6 @@ CPubKey CWallet::GenerateNewKey() bool CWallet::AddKey(const CKey& key) { CPubKey pubkey = key.GetPubKey(); - if (!CCryptoKeyStore::AddKey(key)) return false; if (!fFileBacked) @@ -376,6 +375,77 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) return true; } +bool CWallet::DecryptWallet(const SecureString& strWalletPassphrase) +{ + if (!IsCrypted()) + return false; + + CCrypter crypter; + CKeyingMaterial vMasterKey; + + { + LOCK(cs_wallet); + BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys) + { + if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod)) + return false; + if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey)) + return false; + if (!CCryptoKeyStore::Unlock(vMasterKey)) + return false; + } + + if (fFileBacked) + { + pwalletdbDecryption = new CWalletDB(strWalletFile); + if (!pwalletdbDecryption->TxnBegin()) + return false; + } + + if (!DecryptKeys(vMasterKey)) + { + if (fFileBacked) + pwalletdbDecryption->TxnAbort(); + exit(1); //We now probably have half of our keys decrypted in memory, and half not...die and let the user reload their encrypted wallet. + } + + if (fFileBacked) + { + // Overwrite crypted keys + KeyMap::const_iterator mi = mapKeys.begin(); + while (mi != mapKeys.end()) + { + CKey key; + key.SetSecret((*mi).second.first, (*mi).second.second); + pwalletdbDecryption->EraseCryptedKey(key.GetPubKey()); + pwalletdbDecryption->WriteKey(key.GetPubKey(), key.GetPrivKey(), mapKeyMetadata[(*mi).first]); + mi++; + } + + // Erase master keys + MasterKeyMap::const_iterator mk = mapMasterKeys.begin(); + while (mk != mapMasterKeys.end()) + { + pwalletdbDecryption->EraseMasterKey((*mk).first); + mk++; + } + + if (!pwalletdbDecryption->TxnCommit()) + exit(1); //We now have keys decrypted in memory, but no on disk...die to avoid confusion and let the user reload their encrypted wallet. + + delete pwalletdbDecryption; + pwalletdbDecryption = NULL; + } + + // Need to completely rewrite the wallet file; if we don't, bdb might keep + // encrypted private keys in the database file which can be a reason of consistency issues. + CDB::Rewrite(strWalletFile); + } + NotifyStatusChanged(this); + + return true; +} + int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb) { int64_t nRet = nOrderPosNext++; diff --git a/src/wallet.h b/src/wallet.h index ec937ec..803c273 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -81,7 +81,7 @@ private: bool SelectCoinsSimple(int64_t nTargetValue, int64_t nMinValue, int64_t nMaxValue, unsigned int nSpendTime, int nMinConf, std::set >& setCoinsRet, int64_t& nValueRet) const; bool SelectCoins(int64_t nTargetValue, unsigned int nSpendTime, std::set >& setCoinsRet, int64_t& nValueRet, const CCoinControl *coinControl=NULL) const; - CWalletDB *pwalletdbEncryption; + CWalletDB *pwalletdbEncryption, *pwalletdbDecryption; // the current wallet version: clients below this version are not able to load the wallet int nWalletVersion; @@ -117,6 +117,7 @@ public: fFileBacked = false; nMasterKeyMaxID = 0; pwalletdbEncryption = NULL; + pwalletdbDecryption = NULL; nOrderPosNext = 0; nKernelsTried = 0; nCoinDaysTried = 0; @@ -129,6 +130,7 @@ public: fFileBacked = true; nMasterKeyMaxID = 0; pwalletdbEncryption = NULL; + pwalletdbDecryption = NULL; nOrderPosNext = 0; nKernelsTried = 0; nCoinDaysTried = 0; @@ -178,6 +180,7 @@ public: bool Unlock(const SecureString& strWalletPassphrase); bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase); bool EncryptWallet(const SecureString& strWalletPassphrase); + bool DecryptWallet(const SecureString& strWalletPassphrase); void GetKeyBirthTimes(std::map &mapKeyBirth) const; diff --git a/src/walletdb.cpp b/src/walletdb.cpp index a35b091..ebe2003 100644 --- a/src/walletdb.cpp +++ b/src/walletdb.cpp @@ -360,6 +360,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, ssKey >> nID; CMasterKey kMasterKey; ssValue >> kMasterKey; + if(pwallet->mapMasterKeys.count(nID) != 0) { strErr = strprintf("Error reading wallet database: duplicate CMasterKey id %u", nID); diff --git a/src/walletdb.h b/src/walletdb.h index 0766aa8..1739693 100644 --- a/src/walletdb.h +++ b/src/walletdb.h @@ -86,11 +86,13 @@ public: bool WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata &keyMeta) { nWalletDBUpdated++; - if(!Write(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta)) return false; - return Write(std::make_pair(std::string("key"), vchPubKey.Raw()), vchPrivKey, false); + if(!Write(std::make_pair(std::string("key"), vchPubKey.Raw()), vchPrivKey, false)) + return false; + + return true; } bool WriteCryptedKey(const CPubKey& vchPubKey, const std::vector& vchCryptedSecret, const CKeyMetadata &keyMeta) @@ -117,6 +119,17 @@ public: return Write(std::make_pair(std::string("mkey"), nID), kMasterKey, true); } + bool EraseMasterKey(unsigned int nID) + { + nWalletDBUpdated++; + return Erase(std::make_pair(std::string("mkey"), nID)); + } + + bool EraseCryptedKey(const CPubKey& vchPubKey) + { + return Erase(std::make_pair(std::string("ckey"), vchPubKey.Raw())); + } + bool WriteCScript(const uint160& hash, const CScript& redeemScript) { nWalletDBUpdated++;