During wallet creation, do not write seed on disk before it is encrypted
This commit is contained in:
@@ -903,7 +903,7 @@ class ElectrumGui:
|
||||
if action == 'create':
|
||||
wallet.init_seed(None)
|
||||
self.show_seed()
|
||||
wallet.save_seed()
|
||||
wallet.save_seed(None)
|
||||
wallet.synchronize() # generate first addresses offline
|
||||
|
||||
elif action == 'restore':
|
||||
@@ -911,7 +911,7 @@ class ElectrumGui:
|
||||
if not seed:
|
||||
exit()
|
||||
wallet.init_seed(str(seed))
|
||||
wallet.save_seed()
|
||||
wallet.save_seed(None)
|
||||
else:
|
||||
exit()
|
||||
|
||||
@@ -996,9 +996,6 @@ class ElectrumGui:
|
||||
def network_dialog(self):
|
||||
return True
|
||||
|
||||
def verify_seed(self):
|
||||
wallet.save_seed()
|
||||
return True
|
||||
|
||||
def show_seed(self):
|
||||
modal_dialog('Your seed is:', wallet.seed)
|
||||
|
||||
102
gui/gtk.py
102
gui/gtk.py
@@ -69,7 +69,7 @@ def show_seed_dialog(wallet, password, parent):
|
||||
show_message("No seed")
|
||||
return
|
||||
try:
|
||||
seed = wallet.get_seed(password)
|
||||
mnemonic = wallet.get_mnemonic(password)
|
||||
except Exception:
|
||||
show_message("Incorrect password")
|
||||
return
|
||||
@@ -77,9 +77,8 @@ def show_seed_dialog(wallet, password, parent):
|
||||
parent = parent,
|
||||
flags = gtk.DIALOG_MODAL,
|
||||
buttons = gtk.BUTTONS_OK,
|
||||
message_format = "Your wallet generation seed is:\n\n" + seed \
|
||||
+ "\n\nPlease keep it in a safe place; if you lose it, you will not be able to restore your wallet.\n\n" \
|
||||
+ "Equivalently, your wallet seed can be stored and recovered with the following mnemonic code:\n\n\"" + ' '.join(mnemonic.mn_encode(seed)) + "\"" )
|
||||
message_format = "Your wallet generation seed is:\n\n" + '"' + mnemonic + '"'\
|
||||
+ "\n\nPlease keep it in a safe place; if you lose it, you will not be able to restore your wallet.\n\n" )
|
||||
dialog.set_title("Seed")
|
||||
dialog.show()
|
||||
dialog.run()
|
||||
@@ -404,13 +403,11 @@ def password_dialog(parent):
|
||||
dialog.destroy()
|
||||
if result != gtk.RESPONSE_CANCEL: return pw
|
||||
|
||||
def change_password_dialog(wallet, parent, icon):
|
||||
if not wallet.seed:
|
||||
show_message("No seed")
|
||||
return
|
||||
|
||||
def change_password_dialog(is_encrypted, parent):
|
||||
|
||||
if parent:
|
||||
msg = 'Your wallet is encrypted. Use this dialog to change the password. To disable wallet encryption, enter an empty new password.' if wallet.use_encryption else 'Your wallet keys are not encrypted'
|
||||
msg = 'Your wallet is encrypted. Use this dialog to change the password. To disable wallet encryption, enter an empty new password.' if is_encrypted else 'Your wallet keys are not encrypted'
|
||||
else:
|
||||
msg = "Please choose a password to encrypt your wallet keys"
|
||||
|
||||
@@ -421,7 +418,7 @@ def change_password_dialog(wallet, parent, icon):
|
||||
image.show()
|
||||
dialog.set_image(image)
|
||||
|
||||
if wallet.use_encryption:
|
||||
if is_encrypted:
|
||||
current_pw, current_pw_entry = password_line('Current password:')
|
||||
dialog.vbox.pack_start(current_pw, False, True, 0)
|
||||
|
||||
@@ -432,30 +429,22 @@ def change_password_dialog(wallet, parent, icon):
|
||||
|
||||
dialog.show()
|
||||
result = dialog.run()
|
||||
password = current_pw_entry.get_text() if wallet.use_encryption else None
|
||||
password = current_pw_entry.get_text() if is_encrypted else None
|
||||
new_password = password_entry.get_text()
|
||||
new_password2 = password2_entry.get_text()
|
||||
dialog.destroy()
|
||||
if result == gtk.RESPONSE_CANCEL:
|
||||
return
|
||||
|
||||
try:
|
||||
wallet.get_seed(password)
|
||||
except Exception:
|
||||
show_message("Incorrect password")
|
||||
return
|
||||
|
||||
if new_password != new_password2:
|
||||
show_message("passwords do not match")
|
||||
return
|
||||
return change_password_dialog(is_encrypted, parent)
|
||||
|
||||
wallet.update_password(password, new_password)
|
||||
if not new_password:
|
||||
new_password = None
|
||||
|
||||
return True, password, new_password
|
||||
|
||||
if icon:
|
||||
if wallet.use_encryption:
|
||||
icon.set_tooltip_text('wallet is encrypted')
|
||||
else:
|
||||
icon.set_tooltip_text('wallet is unencrypted')
|
||||
|
||||
|
||||
def add_help_button(hbox, message):
|
||||
@@ -548,16 +537,16 @@ class ElectrumWindow:
|
||||
prefs_button.show()
|
||||
self.status_bar.pack_end(prefs_button,False,False)
|
||||
|
||||
pw_icon = gtk.Image()
|
||||
pw_icon.set_from_stock(gtk.STOCK_DIALOG_AUTHENTICATION, gtk.ICON_SIZE_MENU)
|
||||
pw_icon.set_alignment(0.5, 0.5)
|
||||
pw_icon.set_size_request(16,16 )
|
||||
pw_icon.show()
|
||||
self.pw_icon = gtk.Image()
|
||||
self.pw_icon.set_from_stock(gtk.STOCK_DIALOG_AUTHENTICATION, gtk.ICON_SIZE_MENU)
|
||||
self.pw_icon.set_alignment(0.5, 0.5)
|
||||
self.pw_icon.set_size_request(16,16 )
|
||||
self.pw_icon.show()
|
||||
|
||||
if self.wallet.seed:
|
||||
password_button = gtk.Button()
|
||||
password_button.connect("clicked", lambda x: change_password_dialog(self.wallet, self.window, pw_icon))
|
||||
password_button.add(pw_icon)
|
||||
password_button.connect("clicked", self.do_update_password)
|
||||
password_button.add(self.pw_icon)
|
||||
password_button.set_relief(gtk.RELIEF_NONE)
|
||||
password_button.show()
|
||||
self.status_bar.pack_end(password_button,False,False)
|
||||
@@ -606,6 +595,28 @@ class ElectrumWindow:
|
||||
def update_callback(self):
|
||||
self.wallet_updated = True
|
||||
|
||||
def do_update_password(self):
|
||||
if not wallet.seed:
|
||||
show_message("No seed")
|
||||
return
|
||||
|
||||
res = change_password_dialog(self.wallet.use_encryption, self.window)
|
||||
if res:
|
||||
_, password, new_password = res
|
||||
|
||||
try:
|
||||
wallet.get_seed(password)
|
||||
except Exception:
|
||||
show_message("Incorrect password")
|
||||
return
|
||||
|
||||
wallet.update_password(password, new_password)
|
||||
|
||||
if wallet.use_encryption:
|
||||
self.pw_icon.set_tooltip_text('wallet is encrypted')
|
||||
else:
|
||||
self.pw_icon.set_tooltip_text('wallet is unencrypted')
|
||||
|
||||
|
||||
def add_tab(self, page, name):
|
||||
tab_label = gtk.Label(name)
|
||||
@@ -1293,23 +1304,33 @@ class ElectrumGui():
|
||||
wallet.gap_limit = gap
|
||||
wallet.storage.put('gap_limit', gap, True)
|
||||
|
||||
self.wallet.start_threads(self.network)
|
||||
|
||||
if action == 'create':
|
||||
wallet.init_seed(None)
|
||||
wallet.save_seed()
|
||||
show_seed_dialog(wallet, None, None)
|
||||
r = change_password_dialog(False, None)
|
||||
password = r[2] if r else None
|
||||
print "password", password
|
||||
wallet.save_seed(password)
|
||||
wallet.synchronize() # generate first addresses offline
|
||||
|
||||
elif action == 'restore':
|
||||
seed = self.seed_dialog()
|
||||
wallet.init_seed(seed)
|
||||
wallet.save_seed()
|
||||
self.restore_wallet(wallet)
|
||||
r = change_password_dialog(False, None)
|
||||
password = r[2] if r else None
|
||||
wallet.save_seed(password)
|
||||
|
||||
else:
|
||||
exit()
|
||||
else:
|
||||
self.wallet = Wallet(storage)
|
||||
self.wallet.start_threads(self.network)
|
||||
action = None
|
||||
|
||||
self.wallet.start_threads(self.network)
|
||||
|
||||
if action == 'restore':
|
||||
self.restore_wallet(wallet)
|
||||
|
||||
w = ElectrumWindow(self.wallet, self.config, self.network)
|
||||
if url: w.set_url(url)
|
||||
@@ -1321,18 +1342,9 @@ class ElectrumGui():
|
||||
def seed_dialog(self):
|
||||
return run_recovery_dialog()
|
||||
|
||||
def verify_seed(self):
|
||||
self.wallet.save_seed()
|
||||
return True
|
||||
|
||||
def network_dialog(self):
|
||||
return run_network_dialog( self.network, parent=None )
|
||||
|
||||
def show_seed(self):
|
||||
show_seed_dialog(self.wallet, None, None)
|
||||
|
||||
def password_dialog(self):
|
||||
change_password_dialog(self.wallet, None, None)
|
||||
|
||||
def restore_wallet(self, wallet):
|
||||
|
||||
|
||||
@@ -247,8 +247,7 @@ class InstallWizard(QDialog):
|
||||
+_("Leave these fields empty if you want to disable encryption.")
|
||||
from password_dialog import make_password_dialog, run_password_dialog
|
||||
self.set_layout( make_password_dialog(self, wallet, msg) )
|
||||
|
||||
run_password_dialog(self, wallet, self)
|
||||
return run_password_dialog(self, wallet, self)
|
||||
|
||||
|
||||
def run(self):
|
||||
@@ -269,13 +268,14 @@ class InstallWizard(QDialog):
|
||||
return
|
||||
if not self.verify_seed(wallet):
|
||||
return
|
||||
ok, _, password = self.password_dialog(wallet)
|
||||
def create():
|
||||
wallet.save_seed()
|
||||
wallet.save_seed(password)
|
||||
wallet.synchronize() # generate first addresses offline
|
||||
self.waiting_dialog(create)
|
||||
|
||||
|
||||
elif action == 'restore':
|
||||
# ask for seed and gap.
|
||||
seed = self.seed_dialog()
|
||||
if not seed:
|
||||
return
|
||||
@@ -287,10 +287,11 @@ class InstallWizard(QDialog):
|
||||
QMessageBox.warning(None, _('Error'), _('Incorrect seed'), _('OK'))
|
||||
return
|
||||
|
||||
wallet.save_seed()
|
||||
ok, _, password = self.password_dialog(wallet)
|
||||
wallet.save_seed(password)
|
||||
|
||||
|
||||
elif action == 'watching':
|
||||
# ask for seed and gap.
|
||||
mpk = self.mpk_dialog()
|
||||
if not mpk:
|
||||
return
|
||||
@@ -318,6 +319,4 @@ class InstallWizard(QDialog):
|
||||
else:
|
||||
QMessageBox.information(None, _('Information'), _("This wallet was restored offline. It may contain more addresses than displayed."), _('OK'))
|
||||
|
||||
self.password_dialog(wallet)
|
||||
|
||||
return wallet
|
||||
|
||||
@@ -75,37 +75,24 @@ def run_password_dialog(self, wallet, parent):
|
||||
|
||||
if not wallet.seed:
|
||||
QMessageBox.information(parent, _('Error'), _('No seed'), _('OK'))
|
||||
return
|
||||
return False, None, None
|
||||
|
||||
if not self.exec_(): return
|
||||
if not self.exec_():
|
||||
return False, None, None
|
||||
|
||||
password = unicode(self.pw.text()) if wallet.use_encryption else None
|
||||
new_password = unicode(self.new_pw.text())
|
||||
new_password2 = unicode(self.conf_pw.text())
|
||||
|
||||
try:
|
||||
wallet.get_seed(password)
|
||||
except Exception:
|
||||
QMessageBox.warning(parent, _('Error'), _('Incorrect Password'), _('OK'))
|
||||
return
|
||||
|
||||
if new_password != new_password2:
|
||||
QMessageBox.warning(parent, _('Error'), _('Passwords do not match'), _('OK'))
|
||||
# Retry
|
||||
run_password_dialog(self, wallet, parent)
|
||||
return
|
||||
return run_password_dialog(self, wallet, parent)
|
||||
|
||||
try:
|
||||
wallet.update_password(password, new_password)
|
||||
except Exception:
|
||||
QMessageBox.warning(parent, _('Error'), _('Failed to update password'), _('OK'))
|
||||
return
|
||||
|
||||
if new_password:
|
||||
QMessageBox.information(parent, _('Success'), _('Password was updated successfully'), _('OK'))
|
||||
else:
|
||||
QMessageBox.information(parent, _('Success'), _('This wallet is not encrypted'), _('OK'))
|
||||
if not new_password:
|
||||
new_password = None
|
||||
|
||||
return True, password, new_password
|
||||
|
||||
|
||||
|
||||
@@ -123,7 +110,27 @@ class PasswordDialog(QDialog):
|
||||
|
||||
|
||||
def run(self):
|
||||
run_password_dialog(self, self.wallet, self.parent)
|
||||
ok, password, new_password = run_password_dialog(self, self.wallet, self.parent)
|
||||
if not ok:
|
||||
return
|
||||
|
||||
try:
|
||||
self.wallet.get_seed(password)
|
||||
except Exception:
|
||||
QMessageBox.warning(self.parent, _('Error'), _('Incorrect Password'), _('OK'))
|
||||
return False, None, None
|
||||
|
||||
try:
|
||||
self.wallet.update_password(password, new_password)
|
||||
except:
|
||||
QMessageBox.warning(self.parent, _('Error'), _('Failed to update password'), _('OK'))
|
||||
return
|
||||
|
||||
if new_password:
|
||||
QMessageBox.information(self.parent, _('Success'), _('Password was updated successfully'), _('OK'))
|
||||
else:
|
||||
QMessageBox.information(self.parent, _('Success'), _('This wallet is not encrypted'), _('OK'))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user