kivy: save pin code in memory

This commit is contained in:
ThomasV 2020-02-14 16:08:54 +01:00
parent 2dad87cbb4
commit d5dc8d1ab2
3 changed files with 41 additions and 28 deletions

View file

@ -326,6 +326,7 @@ class ElectrumWindow(App):
self.wallet = None # type: Optional[Abstract_Wallet] self.wallet = None # type: Optional[Abstract_Wallet]
self.pause_time = 0 self.pause_time = 0
self.asyncio_loop = asyncio.get_event_loop() self.asyncio_loop = asyncio.get_event_loop()
self.pin_code = None
App.__init__(self)#, **kwargs) App.__init__(self)#, **kwargs)
@ -619,9 +620,13 @@ class ElectrumWindow(App):
return return
wallet = self.daemon.load_wallet(path, None) wallet = self.daemon.load_wallet(path, None)
if wallet: if wallet:
if platform == 'android' and wallet.has_password(): if wallet.has_password():
def on_success(x):
# save pin_code so that we can create backups
self.pin_code = x
self.load_wallet(wallet)
self.password_dialog(wallet=wallet, msg=_('Enter PIN code'), self.password_dialog(wallet=wallet, msg=_('Enter PIN code'),
on_success=lambda x: self.load_wallet(wallet), on_failure=self.stop) on_success=on_success, on_failure=self.stop)
else: else:
self.load_wallet(wallet) self.load_wallet(wallet)
else: else:
@ -637,6 +642,7 @@ class ElectrumWindow(App):
if not storage.is_encrypted_with_user_pw(): if not storage.is_encrypted_with_user_pw():
raise Exception("Kivy GUI does not support this type of encrypted wallet files.") raise Exception("Kivy GUI does not support this type of encrypted wallet files.")
def on_password(pw): def on_password(pw):
self.pin_code = pw
storage.decrypt(pw) storage.decrypt(pw)
self._on_decrypted_storage(storage) self._on_decrypted_storage(storage)
self.password_dialog(wallet=storage, msg=_('Enter PIN code'), self.password_dialog(wallet=storage, msg=_('Enter PIN code'),
@ -1196,7 +1202,7 @@ class ElectrumWindow(App):
self.show_info(_("Your PIN code was updated")) self.show_info(_("Your PIN code was updated"))
on_failure = lambda: self.show_error(_("PIN codes do not match")) on_failure = lambda: self.show_error(_("PIN codes do not match"))
self._password_dialog.init(self, wallet=self.wallet, msg=message, self._password_dialog.init(self, wallet=self.wallet, msg=message,
on_success=on_success, on_failure=on_failure, is_change=1) on_success=on_success, on_failure=on_failure, is_change=True)
self._password_dialog.open() self._password_dialog.open()
def change_backup_password(self): def change_backup_password(self):
@ -1209,16 +1215,15 @@ class ElectrumWindow(App):
def on_success(old_password, new_password): def on_success(old_password, new_password):
backup_pubkey = WalletStorage.get_eckey_from_password(new_password).get_public_key_hex() backup_pubkey = WalletStorage.get_eckey_from_password(new_password).get_public_key_hex()
# TODO: use a unique PIN for all wallets # TODO: use a unique PIN for all wallets
self.electrum_config.set_key('pin_code', old_password)
self.electrum_config.set_key('backup_pubkey', backup_pubkey) self.electrum_config.set_key('backup_pubkey', backup_pubkey)
self.show_info(_("Backup password set")) self.show_info(_("Backup password set"))
on_failure = lambda: self.show_error(_("Passwords do not match")) on_failure = lambda: self.show_error(_("Passwords do not match"))
self._password_dialog.init(self, wallet=self.wallet, msg=message, self._password_dialog.init(self, wallet=self.wallet, msg=message,
on_success=on_success, on_failure=on_failure, is_change=1, is_backup=True) on_success=on_success, on_failure=on_failure, is_change=True, is_backup=True)
self._password_dialog.open() self._password_dialog.open()
def save_backup(self): def save_backup(self):
new_path = self.wallet.save_backup() new_path = self.wallet.save_backup(pin_code=self.pin_code)
if new_path: if new_path:
self.show_info(_("Backup saved:") + f"\n{new_path}") self.show_info(_("Backup saved:") + f"\n{new_path}")
else: else:

View file

@ -114,24 +114,34 @@ class PasswordDialog(Factory.Popup):
def init(self, app: 'ElectrumWindow', *, def init(self, app: 'ElectrumWindow', *,
wallet: Union['Abstract_Wallet', 'WalletStorage'] = None, wallet: Union['Abstract_Wallet', 'WalletStorage'] = None,
msg: str, on_success: Callable = None, on_failure: Callable = None, msg: str, on_success: Callable = None, on_failure: Callable = None,
is_change: int = 0, is_backup: bool = False): is_change: bool = False, is_backup: bool = False):
self.app = app self.app = app
self.is_backup = is_backup self.is_backup = is_backup
self.wallet = wallet self.wallet = wallet
self.message = msg self.message = msg
self.on_success = on_success self.on_success = on_success
self.on_failure = on_failure self.on_failure = on_failure
self.ids.kb.password = ''
self.ids.textinput_generic_password.text = ''
self.success = False self.success = False
self.is_change = is_change self.is_change = is_change
self.pw = None self.pw = None
self.new_password = None self.new_password = None
self.title = 'Electrum' + (' - ' + self.wallet.basename() if self.wallet else '') self.title = 'Electrum' + (' - ' + self.wallet.basename() if self.wallet else '')
#self.ids.cb_generic_password.active = False self.level = 1 if is_backup else 0
self.is_generic = self.is_backup
self.update_screen()
def update_screen(self):
self.ids.kb.password = ''
self.ids.textinput_generic_password.text = ''
if self.level == 0:
self.message = _('Enter your PIN')
elif self.level == 1:
self.message = _('Enter a strong password for your backup') if self.is_backup else _('Enter new PIN')
elif self.level == 2:
self.message = _('Confirm backup password') if self.is_backup else _('Confirm new PIN')
def check_password(self, password): def check_password(self, password):
if self.is_change > 1: if self.level > 0:
return True return True
try: try:
self.wallet.check_password(password) self.wallet.check_password(password)
@ -162,6 +172,7 @@ class PasswordDialog(Factory.Popup):
text += c text += c
kb.password = text kb.password = text
def on_password(self, pw: str): def on_password(self, pw: str):
if self.is_generic: if self.is_generic:
if len(pw) < 6: if len(pw) < 6:
@ -169,25 +180,20 @@ class PasswordDialog(Factory.Popup):
return return
if len(pw) >= 6: if len(pw) >= 6:
if self.check_password(pw): if self.check_password(pw):
if self.is_change == 0: if self.is_change is False:
self.success = True self.success = True
self.pw = pw self.pw = pw
self.message = _('Please wait...') self.message = _('Please wait...')
self.dismiss() self.dismiss()
elif self.is_change == 1: elif self.level == 0:
self.level = 1
self.pw = pw self.pw = pw
self.message = _('Enter a strong password for your backup') if self.is_backup else _('Enter new PIN') self.update_screen()
self.ids.kb.password = '' elif self.level == 1:
self.ids.textinput_generic_password.text = '' self.level = 2
self.is_change = 2
self.is_generic = self.is_backup
elif self.is_change == 2:
self.new_password = pw self.new_password = pw
self.message = _('Confirm backup password') if self.is_backup else _('Confirm new PIN') self.update_screen()
self.ids.kb.password = '' elif self.level == 2:
self.ids.textinput_generic_password.text = ''
self.is_change = 3
elif self.is_change == 3:
self.success = pw == self.new_password self.success = pw == self.new_password
self.is_generic = False self.is_generic = False
self.dismiss() self.dismiss()

View file

@ -263,19 +263,21 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
if self.storage: if self.storage:
self.db.write(self.storage) self.db.write(self.storage)
def save_backup(self): def save_backup(self, pin_code=None):
new_db = WalletDB(self.db.dump(), manual_upgrades=False) new_db = WalletDB(self.db.dump(), manual_upgrades=False)
new_db.put('is_backup', True) new_db.put('is_backup', True)
new_path = os.path.join(get_backup_dir(self.config), self.basename() + '.backup') new_path = os.path.join(get_backup_dir(self.config), self.basename() + '.backup')
if new_path is None: if new_path is None:
return return
new_storage = WalletStorage(new_path) new_storage = WalletStorage(new_path)
if 'ANDROID_DATA' in os.environ: if pin_code:
pin_code = self.config.get('pin_code') backup_pubkey = self.config.get('backup_pubkey')
if backup_pubkey is None:
return
w2 = Wallet(new_db, None, config=self.config) w2 = Wallet(new_db, None, config=self.config)
w2.update_password(pin_code, None) w2.update_password(pin_code, None)
new_storage._encryption_version = StorageEncryptionVersion.USER_PASSWORD new_storage._encryption_version = StorageEncryptionVersion.USER_PASSWORD
new_storage.pubkey = self.config.get('backup_pubkey') new_storage.pubkey = backup_pubkey
else: else:
new_storage._encryption_version = self.storage._encryption_version new_storage._encryption_version = self.storage._encryption_version
new_storage.pubkey = self.storage.pubkey new_storage.pubkey = self.storage.pubkey