}
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<unsigned char> &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;
+}
// will encrypt previously unencrypted keys
bool EncryptKeys(CKeyingMaterial& vMasterKeyIn);
+ bool DecryptKeys(const CKeyingMaterial& vMasterKeyIn);
bool Unlock(const CKeyingMaterial& vMasterKeyIn);
}
else
{
- QDialog::accept(); // Success
+ QMessageBox::warning(this, tr("Wallet decrypted"),
+ "<qt>" +
+ tr("NovaCoin will close now to finish the decryption process. ") +
+ "</b></qt>");
+ QApplication::quit();
}
break;
case ChangePass:
labelEncryptionIcon->setToolTip(tr("Wallet is <b>encrypted</b> and currently <b>unlocked</b>"));
encryptWalletAction->setChecked(true);
changePassphraseAction->setEnabled(true);
- encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported
+ encryptWalletAction->setEnabled(true);
lockWalletAction->setEnabled(true);
lockWalletAction->setChecked(false);
labelEncryptionIcon->setToolTip(tr("Wallet is <b>encrypted</b> and currently <b>locked</b>"));
encryptWalletAction->setChecked(true);
changePassphraseAction->setEnabled(true);
- encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported
+ encryptWalletAction->setEnabled(true);
lockWalletAction->setChecked(true);
unlockWalletAction->setChecked(false);
}
else
{
- // Decrypt -- TODO; not supported yet
- return false;
+ // Decrypt
+ return wallet->DecryptWallet(passphrase);
}
}
bool CWallet::AddKey(const CKey& key)
{
CPubKey pubkey = key.GetPubKey();
-
if (!CCryptoKeyStore::AddKey(key))
return false;
if (!fFileBacked)
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++;
bool SelectCoinsSimple(int64_t nTargetValue, int64_t nMinValue, int64_t nMaxValue, unsigned int nSpendTime, int nMinConf, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet) const;
bool SelectCoins(int64_t nTargetValue, unsigned int nSpendTime, std::set<std::pair<const CWalletTx*,unsigned int> >& 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;
fFileBacked = false;
nMasterKeyMaxID = 0;
pwalletdbEncryption = NULL;
+ pwalletdbDecryption = NULL;
nOrderPosNext = 0;
nKernelsTried = 0;
nCoinDaysTried = 0;
fFileBacked = true;
nMasterKeyMaxID = 0;
pwalletdbEncryption = NULL;
+ pwalletdbDecryption = NULL;
nOrderPosNext = 0;
nKernelsTried = 0;
nCoinDaysTried = 0;
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<CKeyID, int64_t> &mapKeyBirth) const;
ssKey >> nID;
CMasterKey kMasterKey;
ssValue >> kMasterKey;
+
if(pwallet->mapMasterKeys.count(nID) != 0)
{
strErr = strprintf("Error reading wallet database: duplicate CMasterKey id %u", nID);
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<unsigned char>& vchCryptedSecret, const CKeyMetadata &keyMeta)
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++;