diff options
author | Jeff Garzik <jgarzik@exmulti.com> | 2011-07-12 19:10:12 -0700 |
---|---|---|
committer | Jeff Garzik <jgarzik@exmulti.com> | 2011-07-12 19:10:12 -0700 |
commit | 0bad8e423754cae582ceb99389709953f56947bc (patch) | |
tree | c27d3fa0eda767de7f6bd7acfcde4e05fc083b18 /src/ui.cpp | |
parent | 354f2dd09487c865f8f0d0d40f66573f764e5a96 (diff) | |
parent | 7414733beac92ce8ba365def592d0363fb24872c (diff) |
Merge pull request #352 from TheBlueMatt/newenc
Wallet Private Key Encryption (on CWallet)
Diffstat (limited to 'src/ui.cpp')
-rw-r--r-- | src/ui.cpp | 273 |
1 files changed, 261 insertions, 12 deletions
diff --git a/src/ui.cpp b/src/ui.cpp index ff0b4afb55..eae0a4f4c8 100644 --- a/src/ui.cpp +++ b/src/ui.cpp @@ -245,6 +245,41 @@ void SetDefaultReceivingAddress(const string& strAddress) } } +bool GetWalletPassphrase() +{ + if (pwalletMain->IsLocked()) + { + string strWalletPass; + strWalletPass.reserve(100); + mlock(&strWalletPass[0], strWalletPass.capacity()); + + // obtain current wallet encrypt/decrypt key, from passphrase + // Note that the passphrase is not mlock()d during this entry and could potentially + // be obtained from disk long after bitcoin has run. + strWalletPass = wxGetPasswordFromUser(_("Enter the current passphrase to the wallet."), + _("Passphrase")).ToStdString(); + + if (!strWalletPass.size()) + { + fill(strWalletPass.begin(), strWalletPass.end(), '\0'); + munlock(&strWalletPass[0], strWalletPass.capacity()); + wxMessageBox(_("Please supply the current wallet decryption passphrase."), "Bitcoin"); + return false; + } + + if (!pwalletMain->Unlock(strWalletPass)) + { + fill(strWalletPass.begin(), strWalletPass.end(), '\0'); + munlock(&strWalletPass[0], strWalletPass.capacity()); + wxMessageBox(_("The passphrase entered for the wallet decryption was incorrect."), "Bitcoin"); + return false; + } + fill(strWalletPass.begin(), strWalletPass.end(), '\0'); + munlock(&strWalletPass[0], strWalletPass.capacity()); + } + return true; +} + @@ -333,6 +368,11 @@ CMainFrame::CMainFrame(wxWindow* parent) : CMainFrameBase(parent) if (CWalletDB(pwalletMain->strWalletFile,"r").ReadDefaultKey(vchPubKey)) m_textCtrlAddress->SetValue(PubKeyToAddress(vchPubKey)); + if (pwalletMain->IsCrypted()) + m_menuOptions->Remove(m_menuOptionsEncryptWallet); + else + m_menuOptions->Remove(m_menuOptionsChangeWalletPassphrase); + // Fill listctrl with wallet transactions RefreshListCtrl(); } @@ -1122,6 +1162,169 @@ void CMainFrame::OnMenuOptionsChangeYourAddress(wxCommandEvent& event) return; } +void CMainFrame::OnMenuOptionsEncryptWallet(wxCommandEvent& event) +{ + // Options->Encrypt Wallet + if (pwalletMain->IsCrypted()) + { + wxMessageBox(_("Wallet already encrypted."), "Bitcoin", wxOK | wxICON_ERROR); + return; + } + + string strWalletPass; + strWalletPass.reserve(100); + mlock(&strWalletPass[0], strWalletPass.capacity()); + + // obtain current wallet encrypt/decrypt key, from passphrase + // Note that the passphrase is not mlock()d during this entry and could potentially + // be obtained from disk long after bitcoin has run. + strWalletPass = wxGetPasswordFromUser(_("Enter the new passphrase to the wallet.\nPlease use a passphrase of 10 or more random characters, or eight or more words."), + _("Passphrase")).ToStdString(); + + if (!strWalletPass.size()) + { + fill(strWalletPass.begin(), strWalletPass.end(), '\0'); + munlock(&strWalletPass[0], strWalletPass.capacity()); + wxMessageBox(_("Error: The supplied passphrase was too short."), "Bitcoin", wxOK | wxICON_ERROR); + return; + } + + if(wxMessageBox(_("WARNING: If you encrypt your wallet and lose your passphrase, you will LOSE ALL OF YOUR BITCOINS!\nAre you sure you wish to encrypt your wallet?"), "Bitcoin", wxYES_NO) != wxYES) + return; + + string strWalletPassTest; + strWalletPassTest.reserve(100); + mlock(&strWalletPassTest[0], strWalletPassTest.capacity()); + strWalletPassTest = wxGetPasswordFromUser(_("Please re-enter your new wallet passphrase."), + _("Passphrase")).ToStdString(); + + if (strWalletPassTest != strWalletPass) + { + fill(strWalletPass.begin(), strWalletPass.end(), '\0'); + fill(strWalletPassTest.begin(), strWalletPassTest.end(), '\0'); + munlock(&strWalletPass[0], strWalletPass.capacity()); + munlock(&strWalletPassTest[0], strWalletPassTest.capacity()); + wxMessageBox(_("Error: the supplied passphrases didn't match."), "Bitcoin", wxOK | wxICON_ERROR); + return; + } + + if (!pwalletMain->EncryptWallet(strWalletPass)) + { + fill(strWalletPass.begin(), strWalletPass.end(), '\0'); + fill(strWalletPassTest.begin(), strWalletPassTest.end(), '\0'); + munlock(&strWalletPass[0], strWalletPass.capacity()); + munlock(&strWalletPassTest[0], strWalletPassTest.capacity()); + wxMessageBox(_("Wallet encryption failed."), "Bitcoin", wxOK | wxICON_ERROR); + return; + } + fill(strWalletPass.begin(), strWalletPass.end(), '\0'); + fill(strWalletPassTest.begin(), strWalletPassTest.end(), '\0'); + munlock(&strWalletPass[0], strWalletPass.capacity()); + munlock(&strWalletPassTest[0], strWalletPassTest.capacity()); + wxMessageBox(_("Wallet Encrypted.\nRemember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer."), "Bitcoin"); + + m_menuOptions->Remove(m_menuOptionsEncryptWallet); + m_menuOptions->Insert(m_menuOptions->GetMenuItemCount() - 1, m_menuOptionsChangeWalletPassphrase); +} + +void CMainFrame::OnMenuOptionsChangeWalletPassphrase(wxCommandEvent& event) +{ + // Options->Change Wallet Encryption Passphrase + if (!pwalletMain->IsCrypted()) + { + wxMessageBox(_("Wallet is unencrypted, please encrypt it first."), "Bitcoin", wxOK | wxICON_ERROR); + return; + } + + string strOldWalletPass; + strOldWalletPass.reserve(100); + mlock(&strOldWalletPass[0], strOldWalletPass.capacity()); + + // obtain current wallet encrypt/decrypt key, from passphrase + // Note that the passphrase is not mlock()d during this entry and could potentially + // be obtained from disk long after bitcoin has run. + strOldWalletPass = wxGetPasswordFromUser(_("Enter the current passphrase to the wallet."), + _("Passphrase")).ToStdString(); + + CRITICAL_BLOCK(pwalletMain->cs_vMasterKey) + { + bool fWasLocked = pwalletMain->IsLocked(); + pwalletMain->Lock(); + + if (!strOldWalletPass.size() || !pwalletMain->Unlock(strOldWalletPass)) + { + fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0'); + munlock(&strOldWalletPass[0], strOldWalletPass.capacity()); + wxMessageBox(_("The passphrase entered for the wallet decryption was incorrect."), "Bitcoin", wxOK | wxICON_ERROR); + return; + } + + if (fWasLocked) + pwalletMain->Lock(); + + string strNewWalletPass; + strNewWalletPass.reserve(100); + mlock(&strNewWalletPass[0], strNewWalletPass.capacity()); + + // obtain new wallet encrypt/decrypt key, from passphrase + // Note that the passphrase is not mlock()d during this entry and could potentially + // be obtained from disk long after bitcoin has run. + strNewWalletPass = wxGetPasswordFromUser(_("Enter the new passphrase for the wallet."), + _("Passphrase")).ToStdString(); + + if (!strNewWalletPass.size()) + { + fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0'); + fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0'); + munlock(&strOldWalletPass[0], strOldWalletPass.capacity()); + munlock(&strNewWalletPass[0], strNewWalletPass.capacity()); + wxMessageBox(_("Error: The supplied passphrase was too short."), "Bitcoin", wxOK | wxICON_ERROR); + return; + } + + string strNewWalletPassTest; + strNewWalletPassTest.reserve(100); + mlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity()); + + // obtain new wallet encrypt/decrypt key, from passphrase + // Note that the passphrase is not mlock()d during this entry and could potentially + // be obtained from disk long after bitcoin has run. + strNewWalletPassTest = wxGetPasswordFromUser(_("Re-enter the new passphrase for the wallet."), + _("Passphrase")).ToStdString(); + + if (strNewWalletPassTest != strNewWalletPass) + { + fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0'); + fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0'); + fill(strNewWalletPassTest.begin(), strNewWalletPassTest.end(), '\0'); + munlock(&strOldWalletPass[0], strOldWalletPass.capacity()); + munlock(&strNewWalletPass[0], strNewWalletPass.capacity()); + munlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity()); + wxMessageBox(_("Error: the supplied passphrases didn't match."), "Bitcoin", wxOK | wxICON_ERROR); + return; + } + + if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass)) + { + fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0'); + fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0'); + fill(strNewWalletPassTest.begin(), strNewWalletPassTest.end(), '\0'); + munlock(&strOldWalletPass[0], strOldWalletPass.capacity()); + munlock(&strNewWalletPass[0], strNewWalletPass.capacity()); + munlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity()); + wxMessageBox(_("The passphrase entered for the wallet decryption was incorrect."), "Bitcoin", wxOK | wxICON_ERROR); + return; + } + fill(strOldWalletPass.begin(), strOldWalletPass.end(), '\0'); + fill(strNewWalletPass.begin(), strNewWalletPass.end(), '\0'); + fill(strNewWalletPassTest.begin(), strNewWalletPassTest.end(), '\0'); + munlock(&strOldWalletPass[0], strOldWalletPass.capacity()); + munlock(&strNewWalletPass[0], strNewWalletPass.capacity()); + munlock(&strNewWalletPassTest[0], strNewWalletPassTest.capacity()); + wxMessageBox(_("Wallet Passphrase Changed."), "Bitcoin"); + } +} + void CMainFrame::OnMenuOptionsOptions(wxCommandEvent& event) { // Options->Options @@ -1182,8 +1385,19 @@ void CMainFrame::OnButtonNew(wxCommandEvent& event) return; string strName = dialog.GetValue(); - // Generate new key - string strAddress = PubKeyToAddress(pwalletMain->GetKeyFromKeyPool()); + string strAddress; + CRITICAL_BLOCK(pwalletMain->cs_vMasterKey) + { + bool fWasLocked = pwalletMain->IsLocked(); + if (!GetWalletPassphrase()) + return; + + // Generate new key + strAddress = PubKeyToAddress(pwalletMain->GetOrReuseKeyFromPool()); + + if (fWasLocked) + pwalletMain->Lock(); + } // Save CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook) @@ -1947,7 +2161,12 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event) if (fBitcoinAddress) { CRITICAL_BLOCK(cs_main) + CRITICAL_BLOCK(pwalletMain->cs_vMasterKey) { + bool fWasLocked = pwalletMain->IsLocked(); + if (!GetWalletPassphrase()) + return; + // Send to bitcoin address CScript scriptPubKey; scriptPubKey << OP_DUP << OP_HASH160 << hash160 << OP_EQUALVERIFY << OP_CHECKSIG; @@ -1956,13 +2175,22 @@ void CSendDialog::OnButtonSend(wxCommandEvent& event) if (strError == "") wxMessageBox(_("Payment sent "), _("Sending...")); else if (strError == "ABORTED") + { + if (fWasLocked) + pwalletMain->Lock(); return; // leave send dialog open + } else { wxMessageBox(strError + " ", _("Sending...")); EndModal(false); + if (fWasLocked) + pwalletMain->Lock(); return; } + + if (fWasLocked) + pwalletMain->Lock(); } } else @@ -2246,16 +2474,27 @@ void CSendingDialog::OnReply2(CDataStream& vRecv) Error(_("Insufficient funds")); return; } + CReserveKey reservekey(pwalletMain); int64 nFeeRequired; - if (!pwalletMain->CreateTransaction(scriptPubKey, nPrice, wtx, reservekey, nFeeRequired)) + CRITICAL_BLOCK(pwalletMain->cs_vMasterKey) { - if (nPrice + nFeeRequired > pwalletMain->GetBalance()) - Error(strprintf(_("This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds"), FormatMoney(nFeeRequired).c_str())); - else - Error(_("Transaction creation failed")); - return; - } + bool fWasLocked = pwalletMain->IsLocked(); + if (!GetWalletPassphrase()) + return; + + if (!pwalletMain->CreateTransaction(scriptPubKey, nPrice, wtx, reservekey, nFeeRequired)) + { + if (nPrice + nFeeRequired > pwalletMain->GetBalance()) + Error(strprintf(_("This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds"), FormatMoney(nFeeRequired).c_str())); + else + Error(_("Transaction creation failed")); + return; + } + + if (fWasLocked) + pwalletMain->Lock(); + } // Transaction fee if (!ThreadSafeAskFee(nFeeRequired, _("Sending..."), this)) @@ -2382,7 +2621,7 @@ CAddressBookDialog::CAddressBookDialog(wxWindow* parent, const wxString& strInit m_listCtrlReceiving->SetFocus(); // Fill listctrl with address book data - CRITICAL_BLOCK(pwalletMain->cs_mapKeys) + CRITICAL_BLOCK(pwalletMain->cs_KeyStore) CRITICAL_BLOCK(pwalletMain->cs_mapAddressBook) { string strDefaultReceiving = (string)pframeMain->m_textCtrlAddress->GetValue(); @@ -2581,8 +2820,18 @@ void CAddressBookDialog::OnButtonNew(wxCommandEvent& event) return; strName = dialog.GetValue(); - // Generate new key - strAddress = PubKeyToAddress(pwalletMain->GetKeyFromKeyPool()); + CRITICAL_BLOCK(pwalletMain->cs_vMasterKey) + { + bool fWasLocked = pwalletMain->IsLocked(); + if (!GetWalletPassphrase()) + return; + + // Generate new key + strAddress = PubKeyToAddress(pwalletMain->GetOrReuseKeyFromPool()); + + if (fWasLocked) + pwalletMain->Lock(); + } } // Add to list and select it |