postpone Restore Saved MicroSD card reading

(cherry picked from commit 56e26d051e)
This commit is contained in:
scgbckbone 2023-10-31 20:25:40 +01:00 committed by doc-hex
parent 422a3a2834
commit 80106f300e
3 changed files with 47 additions and 36 deletions

View File

@ -4,6 +4,9 @@
- Enhancement: Add current temporary seed to Seed Vault from within Seed Vault menu.
If current active temporary seed is not saved yet, `Add current tmp` menu item is
present in Seed Vault menu.
- Enhancement: `Restore Saved` passphrases: MicroSD card data reading postponed after
user chooses the menu option, not on access to `Passphrase` menu as before.
This speeds up opening `Passphrase` menu when MicroSD card is available.
- Reorg: `12 Words` menu option preferred on the top of the menu in all the seed menus
## 5.2.0 - 2023-10-10

View File

@ -2,7 +2,7 @@
#
# pwsave.py - Save bip39 passphrases into encrypted file on MicroSD (if desired)
#
import sys, stash, ujson, os, ngu, pyb
import stash, ujson, ngu, pyb
from files import CardSlot, CardMissingError, needs_microsd
from ux import ux_dramatic_pause, ux_confirm, ux_show_story
from utils import xfp2str
@ -13,6 +13,8 @@ class PassphraseSaver:
# to a file on MicroSD card. Order is preserved.
# AES-256 CTR with key=SHA256(SHA256(salt + derived key off master + salt))
# where: salt=sha256(microSD serial # details)
def __init__(self):
self.key = None
def filename(self, card):
# Construct actual filename to use.
@ -21,17 +23,14 @@ class PassphraseSaver:
def _calc_key(self, card, force=False):
# calculate the key to be used.
if not force and getattr(self, 'key', None):
if not force and self.key:
return
try:
salt = card.get_id_hash()
salt = card.get_id_hash()
with stash.SensitiveValues(bypass_tmp=True) as sv:
self.key = bytearray(sv.encryption_key(salt))
with stash.SensitiveValues(bypass_tmp=True) as sv:
self.key = bytearray(sv.encryption_key(salt))
except:
self.key = None
def _read(self, card):
# Return a list of saved passphrases, or empty list if fail.
@ -44,9 +43,6 @@ class PassphraseSaver:
txt = decrypt.cipher(msg)
return ujson.loads(txt)
except OSError:
#print('missing? ' + fname)
return []
except:
return []
@ -88,25 +84,16 @@ class PassphraseSaver:
from ux import ux_show_story
from seed import set_bip39_passphrase
# Very quick check for card not present case.
if not pyb.SDCard().present():
return None
# Read file, decrypt and make a menu to show; OR return None
# if any error hit.
try:
with CardSlot() as card:
with CardSlot() as card:
self._calc_key(card)
if not self.key: return None
self._calc_key(card)
if not self.key: return None
data = self._read(card)
data = self._read(card)
if not data: return None
except CardMissingError:
# not an error: they just aren't using feature
return None
if not data: return None
# We have a list of xfp+pw fields. Make a menu.

View File

@ -10,20 +10,21 @@
# - 'abandon' * 17 + 'agent'
# - 'abandon' * 11 + 'about'
#
import ngu, uctypes, bip39, random, stash, pyb
from menu import MenuItem, MenuSystem
from utils import xfp2str, parse_extended_key, swab32, pad_raw_secret
import ngu, uctypes, bip39, random, version, stash, chains
from utils import xfp2str, parse_extended_key, swab32, pad_raw_secret, problem_file_line
from uhashlib import sha256
from ux import ux_show_story, the_ux, ux_dramatic_pause, ux_confirm
from ux import PressRelease, ux_input_numbers, ux_input_text, show_qr_code
from actions import goto_top_menu
from stash import SecretStash
from ubinascii import hexlify as b2a_hex
from ubinascii import unhexlify as a2b_hex
from pwsave import PassphraseSaver
from glob import settings, dis
from pincodes import pa
from nvstore import SettingsObject
from files import CardMissingError, needs_microsd, CardSlot
# seed words lengths we support: 24=>256 bits, and recommended
VALID_LENGTHS = (24, 18, 12)
@ -1069,7 +1070,7 @@ class PassphraseMenu(MenuSystem):
# singleton (cls level) vars
done_cb = None
def __init__(self, done_cb=None, items=None):
def __init__(self):
global pp_sofar
pp_sofar = ''
@ -1082,17 +1083,37 @@ class PassphraseMenu(MenuSystem):
MenuItem('APPLY', f=self.done_apply),
MenuItem('CANCEL', f=self.done_cancel),
]
# quick SD card check
if pyb.SDCard().present():
try:
with CardSlot() as card:
# check if passphrases file exists on SD
# if yes add menu item
if card.exists(PassphraseSaver().filename(card)):
items.insert(0, MenuItem('Restore Saved', menu=self.restore_saved))
try:
saved = PassphraseSaver().make_menu()
if saved:
items.insert(0, MenuItem('Restore Saved', menu=saved))
except:
# don't want bugs/corrupt files to make rest of menu inaccessible
pass
except: pass
super(PassphraseMenu, self).__init__(items)
@staticmethod
async def restore_saved(*a):
dis.fullscreen("Decrypting...")
try:
menu = PassphraseSaver().make_menu()
except CardMissingError:
await needs_microsd()
return
except Exception as e:
await ux_show_story(title="Failure", msg=str(e) + problem_file_line(e))
return
if not menu:
await ux_show_story("Nothing found")
return
return menu
def on_cancel(self):
# zip to cancel item when they fail to exit via X button
self.goto_idx(self.count - 1)