Use any QR as BIP-39 passphrase
This commit is contained in:
parent
138cbad573
commit
cd00c626c7
@ -68,8 +68,10 @@ def decode_secret(got):
|
||||
|
||||
raise ValueError('no idea')
|
||||
|
||||
def decode_qr_result(got, expect_secret=False):
|
||||
def decode_qr_result(got, expect_secret=False, expect_text=False):
|
||||
# Could be BBQr or text
|
||||
# - if expect_text, just give us unparsed text back; after BBQr decode
|
||||
# - otherwise, returns a tuple: (type, (*parsed_data))
|
||||
|
||||
if hasattr(got, 'storage'):
|
||||
# BBQr object
|
||||
@ -82,6 +84,11 @@ def decode_qr_result(got, expect_secret=False):
|
||||
if expect_secret and ty in 'PT':
|
||||
raise QRDecodeExplained('Expected secrets not PSBT/TXN')
|
||||
|
||||
if expect_text:
|
||||
if ty != 'U':
|
||||
raise QRDecodeExplained('Expected text?')
|
||||
return got.decode()
|
||||
|
||||
if ty == 'P':
|
||||
# may already be in PSRAM, avoid a copy here
|
||||
from glob import PSRAM
|
||||
@ -102,6 +109,11 @@ def decode_qr_result(got, expect_secret=False):
|
||||
msg = TYPE_LABELS.get(ty, 'Unknown FileType')
|
||||
raise QRDecodeExplained("Sorry, %s not useful." % msg)
|
||||
|
||||
elif expect_text:
|
||||
# caller just wants text anyway, so we are done
|
||||
#assert isinstance(got, str)
|
||||
return got
|
||||
|
||||
# First can we decode a master secret of some type?
|
||||
|
||||
try:
|
||||
@ -117,6 +129,7 @@ def decode_qr_result(got, expect_secret=False):
|
||||
if expect_secret:
|
||||
raise QRDecodeExplained("Not a secret?")
|
||||
|
||||
# try to recognize various bitcoin-related text strings...
|
||||
return decode_qr_text(got)
|
||||
|
||||
def decode_qr_text(got):
|
||||
|
||||
@ -24,7 +24,7 @@ from glob import settings, dis
|
||||
from pincodes import pa
|
||||
from nvstore import SettingsObject
|
||||
from files import CardMissingError, needs_microsd, CardSlot
|
||||
from charcodes import KEY_QR, KEY_ENTER, KEY_CANCEL
|
||||
from charcodes import KEY_QR, KEY_ENTER, KEY_CANCEL, KEY_CLEAR
|
||||
|
||||
|
||||
# seed words lengths we support: 24=>256 bits, and recommended
|
||||
@ -287,7 +287,7 @@ async def show_words(words, prompt=None, escape=None, extra='', ephemeral=False)
|
||||
extra += 'Press (1) to view as QR Code. '
|
||||
else:
|
||||
escape = (escape or '') + KEY_QR
|
||||
extra += 'Press QR button to view as QR Code. '
|
||||
extra += 'Press '+ KEY_QR + ' to view as QR Code. '
|
||||
|
||||
if extra:
|
||||
msg += '\n\n'
|
||||
@ -1089,8 +1089,8 @@ class PassphraseMenu(MenuSystem):
|
||||
|
||||
if version.has_qwerty:
|
||||
items = [
|
||||
MenuItem('Edit Phrase', f=self.view_edit_phrase),
|
||||
MenuItem('Clear Phrase', f=self.empty_phrase),
|
||||
MenuItem('Edit Phrase', f=self.view_edit_phrase, shortcut=KEY_QR),
|
||||
MenuItem('Clear Phrase', f=self.empty_phrase, shortcut=KEY_CLEAR),
|
||||
MenuItem('APPLY', f=self.done_apply),
|
||||
MenuItem('CANCEL', f=self.done_cancel),
|
||||
]
|
||||
@ -1104,8 +1104,8 @@ class PassphraseMenu(MenuSystem):
|
||||
MenuItem('APPLY', f=self.done_apply),
|
||||
MenuItem('CANCEL', f=self.done_cancel),
|
||||
]
|
||||
# quick SD card check
|
||||
# TODO this needs to handle 2 SD cards now ?
|
||||
|
||||
# quick SD card check: will use A if both slots are stuffed
|
||||
if pyb.SDCard().present():
|
||||
try:
|
||||
with CardSlot() as card:
|
||||
@ -1154,7 +1154,7 @@ class PassphraseMenu(MenuSystem):
|
||||
global pp_sofar
|
||||
|
||||
if len(pp_sofar) >= 3:
|
||||
if not await ux_confirm("Press OK to clear passphrase. X to cancel."):
|
||||
if not await ux_confirm("Press OK to clear passphrase."):
|
||||
return
|
||||
|
||||
pp_sofar = ''
|
||||
|
||||
@ -183,6 +183,7 @@ async def ux_input_text(value, confirm_exit=True, hex_only=False, max_len=100,
|
||||
# no key-repeat on certain keys
|
||||
err_msg = last_err = None
|
||||
press = PressRelease()
|
||||
exit_armed = False
|
||||
while 1:
|
||||
dis.clear_box(x, y, line_len, num_lines)
|
||||
|
||||
@ -214,6 +215,9 @@ async def ux_input_text(value, confirm_exit=True, hex_only=False, max_len=100,
|
||||
|
||||
ch = await press.wait()
|
||||
|
||||
if ch != KEY_CANCEL:
|
||||
exit_armed = False
|
||||
|
||||
if ch == KEY_ENTER:
|
||||
if len(value) >= min_len:
|
||||
break
|
||||
@ -227,12 +231,25 @@ async def ux_input_text(value, confirm_exit=True, hex_only=False, max_len=100,
|
||||
value = ''
|
||||
elif ch == KEY_CANCEL:
|
||||
if confirm_exit:
|
||||
pp = await ux_show_story(
|
||||
"OK to leave without any changes? Or CANCEL to avoid leaving.")
|
||||
if pp == KEY_CANCEL:
|
||||
continue
|
||||
value = None
|
||||
break
|
||||
if exit_armed:
|
||||
value = None
|
||||
break
|
||||
err_msg = 'Confirm exit w/o change?'
|
||||
exit_armed = True
|
||||
continue
|
||||
else:
|
||||
value = None
|
||||
break
|
||||
|
||||
elif ch == KEY_QR:
|
||||
# Insert or replace? I think replace
|
||||
ss = dis.save_state()
|
||||
zz = QRScannerInteraction()
|
||||
got = await zz.scan_text('Scan any QR or Barcode for text.')
|
||||
if got: # handle cancel, etc
|
||||
value = got
|
||||
err_msg = 'Replace w/ data from scan.'
|
||||
dis.restore_state(ss)
|
||||
|
||||
elif b39_complete and ch == KEY_TAB:
|
||||
# match case and auto-complete BIP-39 word if we can
|
||||
@ -643,6 +660,27 @@ class QRScannerInteraction:
|
||||
|
||||
return data
|
||||
|
||||
async def scan_text(self, prompt):
|
||||
# Scan and return a text string. For things like BIP-39 passphrase
|
||||
# and perhaps they are re-using a QR from something else. Don't act on contents.
|
||||
problem = None
|
||||
|
||||
while 1:
|
||||
try:
|
||||
got = await self.scan(prompt, line2=problem)
|
||||
if got is None:
|
||||
return None
|
||||
|
||||
# Decode BBQr but not anything more complex
|
||||
return decode_qr_result(got, expect_text=True)
|
||||
except QRDecodeExplained as exc:
|
||||
problem = str(exc)
|
||||
continue
|
||||
except Exception as exc:
|
||||
#import sys; sys.print_exception(exc)
|
||||
problem = "Unable to decode QR"
|
||||
continue
|
||||
|
||||
|
||||
async def scan_anything(self, expect_secret=False):
|
||||
# start a QR scan, and act on what we find, whatever it may be.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user