diff --git a/jmclient/jmclient/__init__.py b/jmclient/jmclient/__init__.py index 0a48658..8edcc29 100644 --- a/jmclient/jmclient/__init__.py +++ b/jmclient/jmclient/__init__.py @@ -50,7 +50,8 @@ from .cli_options import (add_base_options, add_common_options, from .wallet_utils import ( wallet_tool_main, wallet_generate_recover_bip39, open_wallet, open_test_wallet_maybe, create_wallet, get_wallet_cls, get_wallet_path, - wallet_display, get_utxos_enabled_disabled, wallet_gettimelockaddress) + wallet_display, get_utxos_enabled_disabled, wallet_gettimelockaddress, + wallet_change_passphrase) from .wallet_service import WalletService from .maker import Maker, P2EPMaker from .yieldgenerator import YieldGenerator, YieldGeneratorBasic, ygmain diff --git a/jmclient/jmclient/wallet_utils.py b/jmclient/jmclient/wallet_utils.py index 2635326..537f876 100644 --- a/jmclient/jmclient/wallet_utils.py +++ b/jmclient/jmclient/wallet_utils.py @@ -555,10 +555,9 @@ def wallet_display(wallet_service, showprivkey, displayall=False, else: return walletview -def cli_get_wallet_passphrase_check(changing_passphrase=False): - new_string = "new " if changing_passphrase else "" - password = get_password("Enter " + new_string + "passphrase to encrypt wallet: ") - password2 = get_password("Reenter " + new_string + "passphrase to encrypt wallet: ") +def cli_get_wallet_passphrase_check(): + password = get_password("Enter new passphrase to encrypt wallet: ") + password2 = get_password("Reenter new passphrase to encrypt wallet: ") if password != password2: jmprint('ERROR. Passwords did not match', "error") return False @@ -698,9 +697,10 @@ def wallet_generate_recover(method, walletspath, def wallet_change_passphrase(walletservice, enter_wallet_passphrase_callback=cli_get_wallet_passphrase_check): - passphrase = enter_wallet_passphrase_callback(changing_passphrase=True) - walletservice.change_wallet_passphrase(passphrase) - return True + passphrase = enter_wallet_passphrase_callback() + if passphrase: + walletservice.change_wallet_passphrase(passphrase) + return True def dict_factory(cursor, row): diff --git a/scripts/joinmarket-qt.py b/scripts/joinmarket-qt.py index 6e5a453..4e9f922 100755 --- a/scripts/joinmarket-qt.py +++ b/scripts/joinmarket-qt.py @@ -76,7 +76,7 @@ from jmclient import load_program_config, get_network, update_persist_config,\ wallet_generate_recover_bip39, wallet_display, get_utxos_enabled_disabled,\ NO_ROUNDING, get_max_cj_fee_values, get_default_max_absolute_fee, \ get_default_max_relative_fee, RetryableStorageError, add_base_options, \ - BTCEngine, BTC_P2SH_P2WPKH, FidelityBondMixin + BTCEngine, BTC_P2SH_P2WPKH, FidelityBondMixin, wallet_change_passphrase from qtsupport import ScheduleWizard, TumbleRestartWizard, config_tips,\ config_types, QtHandler, XStream, Buttons, OkButton, CancelButton,\ PasswordDialog, MyTreeWidget, JMQtMessageBox, BLUE_FG,\ @@ -1434,6 +1434,9 @@ class JMMainWindow(QMainWindow): exportPrivAction = QAction('&Export keys', self) exportPrivAction.setStatusTip('Export all private keys to a file') exportPrivAction.triggered.connect(self.exportPrivkeysJson) + changePassAction = QAction('&Change passphrase...', self) + changePassAction.setStatusTip('Change wallet encryption passphrase') + changePassAction.triggered.connect(self.changePassphrase) quitAction = QAction(QIcon('exit.png'), '&Quit', self) quitAction.setShortcut('Ctrl+Q') quitAction.setStatusTip('Quit application') @@ -1449,6 +1452,7 @@ class JMMainWindow(QMainWindow): walletMenu.addAction(recoverAction) walletMenu.addAction(showSeedAction) walletMenu.addAction(exportPrivAction) + walletMenu.addAction(changePassAction) walletMenu.addAction(quitAction) aboutMenu = menubar.addMenu('&About') aboutMenu.addAction(aboutAction) @@ -1813,6 +1817,18 @@ class JMMainWindow(QMainWindow): else: self.initWallet() + def changePassphrase(self): + if not self.wallet_service: + JMQtMessageBox(self, "Cannot change passphrase without loaded wallet.", + mbtype="crit", title="Error") + return + if not wallet_change_passphrase(self.wallet_service, self.getPassword): + JMQtMessageBox(self, "Failed to change passphrase.", + title="Error", mbtype="warn") + return + JMQtMessageBox(self, "Passphrase changed successfully.", + title="Passphrase changed") + def getTestnetSeed(self): text, ok = QInputDialog.getText( self, 'Testnet seed', 'Enter a 32 char hex string as seed:') @@ -1842,18 +1858,21 @@ class JMMainWindow(QMainWindow): def getPassword(self): pd = PasswordDialog() while True: + for child in pd.findChildren(QLineEdit): + child.clear() + pd.findChild(QLineEdit).setFocus() pd_return = pd.exec_() if pd_return == QDialog.Rejected: return None elif pd.new_pw.text() != pd.conf_pw.text(): JMQtMessageBox(self, - "Passwords don't match.", + "Passphrases don't match.", mbtype='warn', title="Error") continue elif pd.new_pw.text() == "": JMQtMessageBox(self, - "Password must not be empty.", + "Passphrase must not be empty.", mbtype='warn', title="Error") continue diff --git a/scripts/qtsupport.py b/scripts/qtsupport.py index 9317d6a..1ce7a81 100644 --- a/scripts/qtsupport.py +++ b/scripts/qtsupport.py @@ -315,7 +315,7 @@ def update_password_strength(pw_strength_label, password): pw_strength_label.setText(label) -def make_password_dialog(self, msg, new_pass=True): +def make_password_dialog(self, msg): self.new_pw = QLineEdit() self.new_pw.setEchoMode(QLineEdit.EchoMode(2)) @@ -345,10 +345,10 @@ def make_password_dialog(self, msg, new_pass=True): grid.setColumnMinimumWidth(0, 250) grid.setColumnStretch(1, 1) - grid.addWidget(QLabel('New Password' if new_pass else 'Password'), 1, 0) + grid.addWidget(QLabel('New Passphrase'), 1, 0) grid.addWidget(self.new_pw, 1, 1) - grid.addWidget(QLabel('Confirm Password'), 2, 0) + grid.addWidget(QLabel('Confirm Passphrase'), 2, 0) grid.addWidget(self.conf_pw, 2, 1) vbox.addLayout(grid) @@ -370,8 +370,8 @@ class PasswordDialog(QDialog): self.initUI() def initUI(self): - self.setWindowTitle('Create a new password') - msg = "Enter a new password" + self.setWindowTitle('Create a new passphrase') + msg = "Enter a new passphrase" self.setLayout(make_password_dialog(self, msg)) self.show()