From b7bcaf940d27fa8cfe89422943fbeaab7a350930 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 24 Aug 2011 22:07:26 +0200 Subject: Wallet encryption part 2: ask passphrase when needed, add menu options --- src/qt/askpassphrasedialog.cpp | 186 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 src/qt/askpassphrasedialog.cpp (limited to 'src/qt/askpassphrasedialog.cpp') diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp new file mode 100644 index 0000000000..a297513a62 --- /dev/null +++ b/src/qt/askpassphrasedialog.cpp @@ -0,0 +1,186 @@ +#include "askpassphrasedialog.h" +#include "ui_askpassphrasedialog.h" + +#include "guiconstants.h" +#include "walletmodel.h" + +#include +#include + +AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) : + QDialog(parent), + ui(new Ui::AskPassphraseDialog), + mode(mode), + model(0) +{ + ui->setupUi(this); + ui->passEdit1->setMaxLength(MAX_PASSPHRASE_SIZE); + ui->passEdit2->setMaxLength(MAX_PASSPHRASE_SIZE); + ui->passEdit3->setMaxLength(MAX_PASSPHRASE_SIZE); + + switch(mode) + { + case Encrypt: // Ask passphrase x2 + ui->passLabel1->hide(); + ui->passEdit1->hide(); + ui->warningLabel->setText(tr("Enter the new passphrase to the wallet.
Please use a passphrase of 10 or more random characters, or eight or more words.")); + setWindowTitle(tr("Encrypt wallet")); + break; + case Unlock: // Ask passphrase + ui->warningLabel->setText(tr("This operation needs your wallet passphrase to unlock the wallet.")); + ui->passLabel2->hide(); + ui->passEdit2->hide(); + ui->passLabel3->hide(); + ui->passEdit3->hide(); + setWindowTitle(tr("Unlock wallet")); + break; + case Decrypt: // Ask passphrase + ui->warningLabel->setText(tr("This operation needs your wallet passphrase to decrypt the wallet.")); + ui->passLabel2->hide(); + ui->passEdit2->hide(); + ui->passLabel3->hide(); + ui->passEdit3->hide(); + setWindowTitle(tr("Decrypt wallet")); + break; + case ChangePass: // Ask old passphrase + new passphrase x2 + setWindowTitle(tr("Change passphrase")); + ui->warningLabel->setText(tr("Enter the old and new passphrase to the wallet.")); + break; + } + resize(minimumSize()); // Get rid of extra space in dialog + + textChanged(); + connect(ui->passEdit1, SIGNAL(textChanged(QString)), this, SLOT(textChanged())); + connect(ui->passEdit2, SIGNAL(textChanged(QString)), this, SLOT(textChanged())); + connect(ui->passEdit3, SIGNAL(textChanged(QString)), this, SLOT(textChanged())); +} + +AskPassphraseDialog::~AskPassphraseDialog() +{ + // Attempt to overwrite text so that they do not linger around in memory + ui->passEdit1->setText(QString(" ").repeated(ui->passEdit1->text().size())); + ui->passEdit2->setText(QString(" ").repeated(ui->passEdit2->text().size())); + ui->passEdit3->setText(QString(" ").repeated(ui->passEdit3->text().size())); + delete ui; +} + +void AskPassphraseDialog::setModel(WalletModel *model) +{ + this->model = model; +} + +void AskPassphraseDialog::accept() +{ + std::string oldpass, newpass1, newpass2; + // TODO: mlock memory / munlock on return so they will not be swapped out, really need "mlockedstring" wrapper class to do this safely + oldpass.reserve(MAX_PASSPHRASE_SIZE); + newpass1.reserve(MAX_PASSPHRASE_SIZE); + newpass2.reserve(MAX_PASSPHRASE_SIZE); + oldpass.assign(ui->passEdit1->text().toStdString()); + newpass1.assign(ui->passEdit2->text().toStdString()); + newpass2.assign(ui->passEdit3->text().toStdString()); + + switch(mode) + { + case Encrypt: { + if(newpass1.empty() || newpass2.empty()) + { + // Cannot encrypt with empty passphrase + break; + } + QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm wallet encryption"), + tr("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?"), + QMessageBox::Yes|QMessageBox::Cancel, + QMessageBox::Cancel); + if(retval == QMessageBox::Yes) + { + if(newpass1 == newpass2) + { + if(model->setWalletEncrypted(true, newpass1)) + { + QMessageBox::warning(this, tr("Wallet encrypted"), + tr("Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer.")); + } + else + { + QMessageBox::critical(this, tr("Wallet encryption failed"), + tr("Wallet encryption failed due to an internal error. Your wallet was not encrypted.")); + } + QDialog::accept(); // Success + } + else + { + QMessageBox::critical(this, tr("Wallet encryption failed"), + tr("The supplied passphrases do not match.")); + } + } + else + { + QDialog::reject(); // Cancelled + } + } break; + case Unlock: + if(!model->setWalletLocked(false, oldpass)) + { + QMessageBox::critical(this, tr("Wallet unlock failed"), + tr("The passphrase entered for the wallet decryption was incorrect.")); + } + else + { + QDialog::accept(); // Success + } + break; + case Decrypt: + if(!model->setWalletEncrypted(false, oldpass)) + { + QMessageBox::critical(this, tr("Wallet decryption failed"), + tr("The passphrase entered for the wallet decryption was incorrect.")); + } + else + { + QDialog::accept(); // Success + } + break; + case ChangePass: + if(newpass1 == newpass2) + { + if(model->changePassphrase(oldpass, newpass1)) + { + QMessageBox::information(this, tr("Wallet encrypted"), + tr("Wallet passphrase was succesfully changed.")); + QDialog::accept(); // Success + } + else + { + QMessageBox::critical(this, tr("Wallet encryption failed"), + tr("The passphrase entered for the wallet decryption was incorrect.")); + } + } + else + { + QMessageBox::critical(this, tr("Wallet encryption failed"), + tr("The supplied passphrases do not match.")); + } + break; + } +} + +void AskPassphraseDialog::textChanged() +{ + // Validate input, set Ok button to enabled when accepable + bool acceptable = false; + switch(mode) + { + case Encrypt: // New passphrase x2 + acceptable = !ui->passEdit2->text().isEmpty() && !ui->passEdit3->text().isEmpty(); + break; + case Unlock: // Old passphrase x1 + case Decrypt: + acceptable = !ui->passEdit1->text().isEmpty(); + break; + case ChangePass: // Old passphrase x1, new passphrase x2 + acceptable = !ui->passEdit1->text().isEmpty() && !ui->passEdit2->text().isEmpty() && !ui->passEdit3->text().isEmpty(); + break; + } + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(acceptable); +} -- cgit v1.2.3