#include "askpassphrasedialog.h" #include "ui_askpassphrasedialog.h" #include "dialog_move_handler.h" #include "guiconstants.h" #include "walletmodel.h" #include #include #include extern bool fWalletUnlockStakingOnly; AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) : QDialog(parent), ui(new Ui::AskPassphraseDialog), mode(mode), model(0), fCapsLock(false) { ui->setupUi(this); setWindowFlags(Qt::CustomizeWindowHint | Qt::FramelessWindowHint | Qt::Window); ui->wCaption->installEventFilter(new DialogMoveHandler(this)); ui->passEdit1->setMaxLength(MAX_PASSPHRASE_SIZE); ui->passEdit2->setMaxLength(MAX_PASSPHRASE_SIZE); ui->passEdit3->setMaxLength(MAX_PASSPHRASE_SIZE); // Setup Caps Lock detection. ui->passEdit1->installEventFilter(this); ui->passEdit2->installEventFilter(this); ui->passEdit3->installEventFilter(this); ui->stakingCheckBox->hide(); switch(mode) { case Encrypt: // Ask passphrase x2 ui->lbTitleIcon_Passphrase->hide(); ui->lbTitleIcon_Unlock->hide(); 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.")); ui->lbTitle->setText(tr("Encrypt wallet")); break; case UnlockStaking: ui->stakingCheckBox->setChecked(false); ui->stakingCheckBox->show(); // fallthru case Unlock: // Ask passphrase ui->lbTitleIcon_Lock->hide(); ui->lbTitleIcon_Passphrase->hide(); 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(); ui->lbTitle->setText(tr("Unlock wallet")); break; case Decrypt: // Ask passphrase ui->lbTitleIcon_Lock->hide(); ui->lbTitleIcon_Passphrase->hide(); 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(); ui->lbTitle->setText(tr("Decrypt wallet")); break; case ChangePass: // Ask old passphrase + new passphrase x2 ui->lbTitleIcon_Lock->hide(); ui->lbTitleIcon_Unlock->hide(); ui->lbTitle->setText(tr("Change passphrase")); ui->warningLabel->setText(tr("Enter the old and new passphrase to the wallet.")); break; } 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() { secureClearPassFields(); delete ui; } void AskPassphraseDialog::setModel(WalletModel *model) { this->model = model; } void AskPassphraseDialog::accept() { SecureString oldpass, newpass1, newpass2; if(!model) return; oldpass.reserve(MAX_PASSPHRASE_SIZE); newpass1.reserve(MAX_PASSPHRASE_SIZE); newpass2.reserve(MAX_PASSPHRASE_SIZE); oldpass = MakeSecureString(ui->passEdit1->text().toStdString()); newpass1 = MakeSecureString(ui->passEdit2->text().toStdString()); newpass2 = MakeSecureString(ui->passEdit3->text().toStdString()); switch(mode) { case Encrypt: { if(newpass1.empty() || newpass2.empty()) { // Cannot encrypt with empty passphrase break; } QMessageBox* msgBox = new QMessageBox(QMessageBox::Question, tr("Confirm wallet encryption"), tr("Warning: If you encrypt your wallet and lose your passphrase, you will LOSE ALL OF YOUR COINS!") + "

" + tr("Are you sure you wish to encrypt your wallet?"), QMessageBox::Yes|QMessageBox::Cancel, this, Qt::FramelessWindowHint); msgBox->setIconPixmap(QPixmap(":/msgbox/question")); msgBox->setStyleSheet("QMessageBox { border: 2px solid #e22104;}"); msgBox->button(QMessageBox::Yes)->setStyleSheet("\ QMessageBox QPushButton {background-color: #000;color: #e32105;border: 1px solid #e32105;\ min-width: 120px;max-width: 120px;max-height: 20px;min-height: 20px;}\ QMessageBox QPushButton:hover {background-color: #3d0e04;}\ QMessageBox QPushButton:pressed:flat {color: #000;background-color: #e32105;}\ "); msgBox->button(QMessageBox::Cancel)->setStyleSheet("\ QMessageBox QPushButton {background-color: #000;color: #e32105;border: 1px solid #e32105;\ min-width: 120px;max-width: 120px;max-height: 20px;min-height: 20px;}\ QMessageBox QPushButton:hover {background-color: #3d0e04;}\ QMessageBox QPushButton:pressed:flat {color: #000;background-color: #e32105;}\ "); int retval = msgBox->exec(); if(retval == QMessageBox::Yes) { if(newpass1 == newpass2) { if(model->setWalletEncrypted(true, newpass1)) { QMessageBox* msgBox = new QMessageBox(QMessageBox::Warning, tr("Wallet encrypted"), "" + tr("Triangles will close now to finish the encryption process. " "Remember that encrypting your wallet cannot fully protect " "your coins from being stolen by malware infecting your computer.") + "

" + tr("IMPORTANT: Any previous backups you have made of your wallet file " "should be replaced with the newly generated, encrypted wallet file. " "For security reasons, previous backups of the unencrypted wallet file " "will become useless as soon as you start using the new, encrypted wallet.") + "
", QMessageBox::Ok, this, Qt::FramelessWindowHint); msgBox->setIconPixmap(QPixmap(":/msgbox/warning")); msgBox->setStyleSheet("QMessageBox { border: 2px solid #e22104;}"); msgBox->button(QMessageBox::Ok)->setStyleSheet("\ QMessageBox QPushButton {background-color: #000;color: #e32105;border: 1px solid #e32105;\ min-width: 120px;max-width: 120px;max-height: 20px;min-height: 20px;}\ QMessageBox QPushButton:hover {background-color: #3d0e04;}\ QMessageBox QPushButton:pressed:flat {color: #000;background-color: #e32105;}\ "); msgBox->exec(); QApplication::quit(); } else { QMessageBox* msgBox = new QMessageBox(QMessageBox::Critical, tr("Wallet encryption failed"), tr("Wallet encryption failed due to an internal error. Your wallet was not encrypted."), QMessageBox::Ok, this, Qt::FramelessWindowHint); msgBox->setIconPixmap(QPixmap(":/msgbox/critical")); msgBox->setStyleSheet("QMessageBox { border: 2px solid #e22104;}"); msgBox->button(QMessageBox::Ok)->setStyleSheet("\ QMessageBox QPushButton {background-color: #000;color: #e32105;border: 1px solid #e32105;\ min-width: 120px;max-width: 120px;max-height: 20px;min-height: 20px;}\ QMessageBox QPushButton:hover {background-color: #3d0e04;}\ QMessageBox QPushButton:pressed:flat {color: #000;background-color: #e32105;}\ "); msgBox->exec(); } QDialog::accept(); // Success } else { QMessageBox* msgBox = new QMessageBox(QMessageBox::Critical, tr("Wallet encryption failed"), tr("The supplied passphrases do not match."), QMessageBox::Ok, this, Qt::FramelessWindowHint); msgBox->setIconPixmap(QPixmap(":/msgbox/critical")); msgBox->setStyleSheet("QMessageBox { border: 2px solid #e22104;}"); msgBox->button(QMessageBox::Ok)->setStyleSheet("\ QMessageBox QPushButton {background-color: #000;color: #e32105;border: 1px solid #e32105;\ min-width: 120px;max-width: 120px;max-height: 20px;min-height: 20px;}\ QMessageBox QPushButton:hover {background-color: #3d0e04;}\ QMessageBox QPushButton:pressed:flat {color: #000;background-color: #e32105;}\ "); msgBox->exec(); } } else { QDialog::reject(); // Cancelled } } break; case UnlockStaking: case Unlock: if(!model->setWalletLocked(false, oldpass)) { QMessageBox* msgBox = new QMessageBox(QMessageBox::Critical, tr("Wallet unlock failed"), tr("The passphrase entered for the wallet decryption was incorrect!"), QMessageBox::Ok, this, Qt::FramelessWindowHint); msgBox->setIconPixmap(QPixmap(":/msgbox/critical")); msgBox->setStyleSheet("QMessageBox { border: 2px solid #e22104;}"); msgBox->button(QMessageBox::Ok)->setStyleSheet("\ QMessageBox QPushButton {background-color: #000;color: #e32105;border: 1px solid #e32105;\ min-width: 120px;max-width: 120px;max-height: 20px;min-height: 20px;}\ QMessageBox QPushButton:hover {background-color: #3d0e04;}\ QMessageBox QPushButton:pressed:flat {color: #000;background-color: #e32105;}\ "); msgBox->exec(); } else { fWalletUnlockStakingOnly = ui->stakingCheckBox->isChecked(); QDialog::accept(); // Success } break; case Decrypt: if(!model->setWalletEncrypted(false, oldpass)) { QMessageBox* msgBox = new QMessageBox(QMessageBox::Critical, tr("Wallet decryption failed"), tr("The passphrase entered for the wallet decryption was incorrect!"), QMessageBox::Ok, this, Qt::FramelessWindowHint); msgBox->setIconPixmap(QPixmap(":/msgbox/critical")); msgBox->setStyleSheet("QMessageBox { border: 2px solid #e22104;}"); msgBox->button(QMessageBox::Ok)->setStyleSheet("\ QMessageBox QPushButton {background-color: #000;color: #e32105;border: 1px solid #e32105;\ min-width: 120px;max-width: 120px;max-height: 20px;min-height: 20px;}\ QMessageBox QPushButton:hover {background-color: #3d0e04;}\ QMessageBox QPushButton:pressed:flat {color: #000;background-color: #e32105;}\ "); msgBox->exec(); } else { QDialog::accept(); // Success } break; case ChangePass: if(newpass1 == newpass2) { if(model->changePassphrase(oldpass, newpass1)) { QMessageBox* msgBox = new QMessageBox(QMessageBox::Information, tr("Wallet encrypted"), tr("Wallet passphrase was successfully changed."), QMessageBox::Ok, this, Qt::FramelessWindowHint); msgBox->setIconPixmap(QPixmap(":/msgbox/information")); msgBox->setStyleSheet("QMessageBox { border: 2px solid #e22104;}"); msgBox->button(QMessageBox::Ok)->setStyleSheet("\ QMessageBox QPushButton {background-color: #000;color: #e32105;border: 1px solid #e32105;\ min-width: 120px;max-width: 120px;max-height: 20px;min-height: 20px;}\ QMessageBox QPushButton:hover {background-color: #3d0e04;}\ QMessageBox QPushButton:pressed:flat {color: #000;background-color: #e32105;}\ "); msgBox->exec(); QDialog::accept(); // Success } else { QMessageBox* msgBox = new QMessageBox(QMessageBox::Critical, tr("Wallet encryption failed"), tr("The passphrase entered for the wallet decryption was incorrect!"), QMessageBox::Ok, this, Qt::FramelessWindowHint); msgBox->setIconPixmap(QPixmap(":/msgbox/critical")); msgBox->setStyleSheet("QMessageBox { border: 2px solid #e22104;}"); msgBox->button(QMessageBox::Ok)->setStyleSheet("\ QMessageBox QPushButton {background-color: #000;color: #e32105;border: 1px solid #e32105;\ min-width: 120px;max-width: 120px;max-height: 20px;min-height: 20px;}\ QMessageBox QPushButton:hover {background-color: #3d0e04;}\ QMessageBox QPushButton:pressed:flat {color: #000;background-color: #e32105;}\ "); msgBox->exec(); } } else { QMessageBox* msgBox = new QMessageBox(QMessageBox::Critical, tr("Wallet encryption failed"), tr("The supplied passphrases do not match."), QMessageBox::Ok, this, Qt::FramelessWindowHint); msgBox->setIconPixmap(QPixmap(":/msgbox/critical")); msgBox->setStyleSheet("QMessageBox { border: 2px solid #e22104;}"); msgBox->button(QMessageBox::Ok)->setStyleSheet("\ QMessageBox QPushButton {background-color: #000;color: #e32105;border: 1px solid #e32105;\ min-width: 120px;max-width: 120px;max-height: 20px;min-height: 20px;}\ QMessageBox QPushButton:hover {background-color: #3d0e04;}\ QMessageBox QPushButton:pressed:flat {color: #000;background-color: #e32105;}\ "); msgBox->exec(); } break; } } void AskPassphraseDialog::textChanged() { // Validate input, set Ok button to enabled when acceptable bool acceptable = false; switch(mode) { case Encrypt: // New passphrase x2 acceptable = !ui->passEdit2->text().isEmpty() && !ui->passEdit3->text().isEmpty(); break; case UnlockStaking: 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); } bool AskPassphraseDialog::event(QEvent *event) { // Detect Caps Lock key press. if (event->type() == QEvent::KeyPress) { QKeyEvent *ke = static_cast(event); if (ke->key() == Qt::Key_CapsLock) { fCapsLock = !fCapsLock; } if (fCapsLock) { ui->capsLabel->setText(tr("Warning: The Caps Lock key is on!")); } else { ui->capsLabel->clear(); } } return QWidget::event(event); } bool AskPassphraseDialog::eventFilter(QObject *object, QEvent *event) { /* Detect Caps Lock. * There is no good OS-independent way to check a key state in Qt, but we * can detect Caps Lock by checking for the following condition: * Shift key is down and the result is a lower case character, or * Shift key is not down and the result is an upper case character. */ if (event->type() == QEvent::KeyPress) { QKeyEvent *ke = static_cast(event); QString str = ke->text(); if (str.length() != 0) { const QChar *psz = str.unicode(); bool fShift = (ke->modifiers() & Qt::ShiftModifier) != 0; if ((fShift && psz->isLower()) || (!fShift && psz->isUpper())) { fCapsLock = true; ui->capsLabel->setText(tr("Warning: The Caps Lock key is on!")); } else if (psz->isLetter()) { fCapsLock = false; ui->capsLabel->clear(); } } } return QDialog::eventFilter(object, event); } void AskPassphraseDialog::secureClearPassFields() { // 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())); ui->passEdit1->clear(); ui->passEdit2->clear(); ui->passEdit3->clear(); }