2018-07-27 00:36:45 +02:00
// Copyright (c) 2011-2018 The Bitcoin Core developers
2014-12-13 05:09:33 +01:00
// Distributed under the MIT software license, see the accompanying
2013-11-04 16:20:43 +01:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2015-12-09 11:53:12 +01:00
# if defined(HAVE_CONFIG_H)
2017-11-10 01:57:53 +01:00
# include <config/bitcoin-config.h>
2015-12-09 11:53:12 +01:00
# endif
2017-11-10 01:57:53 +01:00
# include <qt/askpassphrasedialog.h>
2017-08-15 17:31:26 +02:00
# include <qt/forms/ui_askpassphrasedialog.h>
2011-08-24 22:07:26 +02:00
2017-11-10 01:57:53 +01:00
# include <qt/guiconstants.h>
# include <qt/walletmodel.h>
2011-08-24 22:07:26 +02:00
2017-11-10 01:57:53 +01:00
# include <support/allocators/secure.h>
2013-04-13 07:13:08 +02:00
# include <QKeyEvent>
2011-08-24 22:07:26 +02:00
# include <QMessageBox>
# include <QPushButton>
2016-09-09 13:43:29 +02:00
AskPassphraseDialog : : AskPassphraseDialog ( Mode _mode , QWidget * parent ) :
2011-08-24 22:07:26 +02:00
QDialog ( parent ) ,
ui ( new Ui : : AskPassphraseDialog ) ,
2016-09-09 13:43:29 +02:00
mode ( _mode ) ,
2011-10-15 20:56:06 +02:00
model ( 0 ) ,
fCapsLock ( false )
2011-08-24 22:07:26 +02:00
{
ui - > setupUi ( this ) ;
2013-08-31 01:11:12 +02:00
2014-11-20 12:28:34 +01:00
ui - > passEdit1 - > setMinimumSize ( ui - > passEdit1 - > sizeHint ( ) ) ;
ui - > passEdit2 - > setMinimumSize ( ui - > passEdit2 - > sizeHint ( ) ) ;
ui - > passEdit3 - > setMinimumSize ( ui - > passEdit3 - > sizeHint ( ) ) ;
2011-08-24 22:07:26 +02:00
ui - > passEdit1 - > setMaxLength ( MAX_PASSPHRASE_SIZE ) ;
ui - > passEdit2 - > setMaxLength ( MAX_PASSPHRASE_SIZE ) ;
ui - > passEdit3 - > setMaxLength ( MAX_PASSPHRASE_SIZE ) ;
2012-10-25 11:52:34 +02:00
2011-10-15 20:56:06 +02:00
// Setup Caps Lock detection.
ui - > passEdit1 - > installEventFilter ( this ) ;
ui - > passEdit2 - > installEventFilter ( this ) ;
ui - > passEdit3 - > installEventFilter ( this ) ;
2011-08-24 22:07:26 +02:00
switch ( mode )
{
case Encrypt : // Ask passphrase x2
2014-11-20 12:28:34 +01:00
ui - > warningLabel - > setText ( tr ( " Enter the new passphrase to the wallet.<br/>Please use a passphrase of <b>ten or more random characters</b>, or <b>eight or more words</b>. " ) ) ;
2011-08-24 22:07:26 +02:00
ui - > passLabel1 - > hide ( ) ;
ui - > passEdit1 - > hide ( ) ;
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 " ) ) ;
2015-04-28 16:48:28 +02:00
ui - > warningLabel - > setText ( tr ( " Enter the old passphrase and new passphrase to the wallet. " ) ) ;
2011-08-24 22:07:26 +02:00
break ;
}
textChanged ( ) ;
2017-10-11 06:50:01 +02:00
connect ( ui - > toggleShowPasswordButton , SIGNAL ( toggled ( bool ) ) , this , SLOT ( toggleShowPassword ( bool ) ) ) ;
2011-08-24 22:07:26 +02:00
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 ( )
{
2015-08-03 02:03:14 +02:00
secureClearPassFields ( ) ;
2011-08-24 22:07:26 +02:00
delete ui ;
}
2016-09-09 13:43:29 +02:00
void AskPassphraseDialog : : setModel ( WalletModel * _model )
2011-08-24 22:07:26 +02:00
{
2016-09-09 13:43:29 +02:00
this - > model = _model ;
2011-08-24 22:07:26 +02:00
}
void AskPassphraseDialog : : accept ( )
{
2011-11-26 07:02:04 +01:00
SecureString oldpass , newpass1 , newpass2 ;
2011-11-08 21:18:36 +01:00
if ( ! model )
return ;
2011-08-24 22:07:26 +02:00
oldpass . reserve ( MAX_PASSPHRASE_SIZE ) ;
newpass1 . reserve ( MAX_PASSPHRASE_SIZE ) ;
newpass2 . reserve ( MAX_PASSPHRASE_SIZE ) ;
2011-11-26 07:02:04 +01:00
// TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
// Alternately, find a way to make this input mlock()'d to begin with.
oldpass . assign ( ui - > passEdit1 - > text ( ) . toStdString ( ) . c_str ( ) ) ;
newpass1 . assign ( ui - > passEdit2 - > text ( ) . toStdString ( ) . c_str ( ) ) ;
newpass2 . assign ( ui - > passEdit3 - > text ( ) . toStdString ( ) . c_str ( ) ) ;
2011-08-24 22:07:26 +02:00
2015-08-03 02:03:14 +02:00
secureClearPassFields ( ) ;
2011-08-24 22:07:26 +02:00
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 " ) ,
2012-07-27 08:36:43 +02:00
tr ( " Warning: If you encrypt your wallet and lose your passphrase, you will <b>LOSE ALL OF YOUR BITCOINS</b>! " ) + " <br><br> " + tr ( " Are you sure you wish to encrypt your wallet? " ) ,
2011-08-24 22:07:26 +02:00
QMessageBox : : Yes | QMessageBox : : Cancel ,
QMessageBox : : Cancel ) ;
if ( retval = = QMessageBox : : Yes )
{
if ( newpass1 = = newpass2 )
{
if ( model - > setWalletEncrypted ( true , newpass1 ) )
{
QMessageBox : : warning ( this , tr ( " Wallet encrypted " ) ,
2012-10-25 11:52:34 +02:00
" <qt> " +
2015-12-09 11:53:12 +01:00
tr ( " %1 will close now to finish the encryption process. "
2012-09-30 11:37:45 +02:00
" Remember that encrypting your wallet cannot fully protect "
2015-12-09 11:53:12 +01:00
" your bitcoins from being stolen by malware infecting your computer. " ) . arg ( tr ( PACKAGE_NAME ) ) +
2012-10-25 11:52:34 +02:00
" <br><br><b> " +
2012-09-30 11:37:45 +02:00
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 "
2012-10-25 11:52:34 +02:00
" will become useless as soon as you start using the new, encrypted wallet. " ) +
2012-09-30 11:37:45 +02:00
" </b></qt> " ) ;
2011-11-11 22:20:57 +01:00
QApplication : : quit ( ) ;
2011-08-24 22:07:26 +02:00
}
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 " ) ,
2012-07-24 10:20:25 +02:00
tr ( " Wallet passphrase was successfully changed. " ) ) ;
2011-08-24 22:07:26 +02:00
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 ( )
{
2012-07-26 02:48:39 +02:00
// Validate input, set Ok button to enabled when acceptable
2011-08-24 22:07:26 +02:00
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 ) ;
}
2011-10-15 20:56:06 +02:00
bool AskPassphraseDialog : : event ( QEvent * event )
{
// Detect Caps Lock key press.
if ( event - > type ( ) = = QEvent : : KeyPress ) {
QKeyEvent * ke = static_cast < QKeyEvent * > ( event ) ;
if ( ke - > key ( ) = = Qt : : Key_CapsLock ) {
fCapsLock = ! fCapsLock ;
}
if ( fCapsLock ) {
2012-07-27 08:36:43 +02:00
ui - > capsLabel - > setText ( tr ( " Warning: The Caps Lock key is on! " ) ) ;
2011-10-15 20:56:06 +02:00
} else {
ui - > capsLabel - > clear ( ) ;
}
}
return QWidget : : event ( event ) ;
}
2017-10-11 06:50:01 +02:00
void AskPassphraseDialog : : toggleShowPassword ( bool show )
{
ui - > toggleShowPasswordButton - > setDown ( show ) ;
const auto mode = show ? QLineEdit : : Normal : QLineEdit : : Password ;
ui - > passEdit1 - > setEchoMode ( mode ) ;
ui - > passEdit2 - > setEchoMode ( mode ) ;
ui - > passEdit3 - > setEchoMode ( mode ) ;
}
2012-10-25 11:52:34 +02:00
bool AskPassphraseDialog : : eventFilter ( QObject * object , QEvent * event )
2011-10-15 20:56:06 +02:00
{
2012-05-05 18:24:23 +02:00
/* Detect Caps Lock.
2011-10-15 20:56:06 +02:00
* 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 < QKeyEvent * > ( event ) ;
QString str = ke - > text ( ) ;
if ( str . length ( ) ! = 0 ) {
const QChar * psz = str . unicode ( ) ;
bool fShift = ( ke - > modifiers ( ) & Qt : : ShiftModifier ) ! = 0 ;
2013-03-29 10:52:24 +01:00
if ( ( fShift & & * psz > = ' a ' & & * psz < = ' z ' ) | | ( ! fShift & & * psz > = ' A ' & & * psz < = ' Z ' ) ) {
2011-10-15 20:56:06 +02:00
fCapsLock = true ;
2012-07-27 08:36:43 +02:00
ui - > capsLabel - > setText ( tr ( " Warning: The Caps Lock key is on! " ) ) ;
2011-10-15 20:56:06 +02:00
} else if ( psz - > isLetter ( ) ) {
fCapsLock = false ;
ui - > capsLabel - > clear ( ) ;
}
}
}
2012-10-25 11:52:34 +02:00
return QDialog : : eventFilter ( object , event ) ;
2011-10-15 20:56:06 +02:00
}
2015-08-03 02:03:14 +02:00
static void SecureClearQLineEdit ( QLineEdit * edit )
{
// Attempt to overwrite text so that they do not linger around in memory
edit - > setText ( QString ( " " ) . repeated ( edit - > text ( ) . size ( ) ) ) ;
edit - > clear ( ) ;
}
void AskPassphraseDialog : : secureClearPassFields ( )
{
SecureClearQLineEdit ( ui - > passEdit1 ) ;
SecureClearQLineEdit ( ui - > passEdit2 ) ;
SecureClearQLineEdit ( ui - > passEdit3 ) ;
}