def set_seed_value(words=None, encoded=None): # Save the seed words into secure element, and reboot. BIP-39 password # is not set at this point (empty string) if words: bip39.a2b_words(words) # checksum check # map words to bip39 wordlist indices data = [bip39.wordlist_en.index(w) for w in words] # map to packed binary representation. val = 0 for v in data: val <<= 11 val |= v # remove the checksum part vlen = (len(words) * 4) // 3 val >>= (len(words) // 3) # convert to bytes seed = val.to_bytes(vlen, 'big') assert len(seed) == vlen # encode it for our limited secret space nv = SecretStash.encode(seed_phrase=seed) else: nv = encoded from glob import dis dis.fullscreen('Applying...') pa.change(new_secret=nv) # re-read settings since key is now different # - also captures xfp, xpub at this point pa.new_main_secret(nv) # check and reload secret pa.reset() pa.login()
async def remember_bip39_passphrase(): # Compute current xprv and switch to using that as root secret. import stash from glob import dis dis.fullscreen('Check...') with stash.SensitiveValues() as sv: nv = SecretStash.encode(xprv=sv.node) # Important: won't write new XFP to nvram if pw still set stash.bip39_passphrase = '' dis.fullscreen('Saving...') pa.change(new_secret=nv) # re-read settings since key is now different # - also captures xfp, xpub at this point pa.new_main_secret(nv) # check and reload secret pa.reset() pa.login()
def clear_seed(): from glob import dis import utime, version dis.fullscreen('Clearing...') # clear settings associated with this key, since it will be no more settings.blank() # save a blank secret (all zeros is a special case, detected by bootloader) nv = bytes(AE_SECRET_LEN) pa.change(new_secret=nv) if version.has_608: # wipe the long secret too nv = bytes(AE_LONG_SECRET_LEN) pa.ls_change(nv) dis.fullscreen('Reboot...') utime.sleep(1) # security: need to reboot to really be sure to clear the secrets from main memory. from machine import reset reset()
# (c) Copyright 2020 by Coinkite Inc. This file is covered by license found in COPYING-CC. # # load up the simulator w/ indicated encoded secret. could be xprv/words/etc. from sim_settings import sim_defaults import stash, chains from h import b2a_hex from pincodes import pa from nvstore import settings from stash import SecretStash, SensitiveValues from utils import xfp2str settings.current = dict(sim_defaults) settings.overrides.clear() import main raw = main.ENCODED_SECRET pa.change(new_secret=raw) pa.new_main_secret(raw) print("New key in effect: %s" % settings.get('xpub', 'MISSING')) print("Fingerprint: %s" % xfp2str(settings.get('xfp', 0)))
# (c) Copyright 2020 by Coinkite Inc. This file is covered by license found in COPYING-CC. # # load up the simulator w/ indicated test master key from sim_settings import sim_defaults import stash, chains from h import b2a_hex from pincodes import pa from nvstore import settings from stash import SecretStash, SensitiveValues from utils import xfp2str import main rs = main.RAW_SECRET print("New raw secret: %s" % b2a_hex(rs)) if 1: settings.current = dict(sim_defaults) settings.overrides.clear() settings.set('chain', 'XTN') pa.change(new_secret=rs) pa.new_main_secret(rs) print("New key in effect: %s" % settings.get('xpub', 'MISSING')) print("Fingerprint: %s" % xfp2str(settings.get('xfp', 0)))
async def restore_from_dict(vals): # Restore from a dict of values. Already JSON decoded. # Reboot on success, return string on failure from glob import dis #print("Restoring from: %r" % vals) # step1: the private key # - prefer raw_secret over other values # - TODO: fail back to other values try: chain = chains.get_chain(vals.get('chain', 'BTC')) assert 'raw_secret' in vals raw = bytearray(AE_SECRET_LEN) rs = vals.pop('raw_secret') if len(rs) % 2: rs += '0' x = a2b_hex(rs) raw[0:len(x)] = x # check we can decode this right (might be different firmare) opmode, bits, node = stash.SecretStash.decode(raw) assert node # verify against xprv value (if we have it) if 'xprv' in vals: check_xprv = chain.serialize_private(node) assert check_xprv == vals['xprv'], 'xprv mismatch' except Exception as e: return ('Unable to decode raw_secret and ' 'restore the seed value!\n\n\n' + str(e)) ls = None if ('long_secret' in vals) and version.has_608: try: ls = a2b_hex(vals.pop('long_secret')) except Exception as exc: sys.print_exception(exc) # but keep going. dis.fullscreen("Saving...") dis.progress_bar_show(.25) # clear (in-memory) settings and change also nvram key # - also captures xfp, xpub at this point pa.change(new_secret=raw) # force the right chain pa.new_main_secret(raw, chain) # updates xfp/xpub # NOTE: don't fail after this point... they can muddle thru w/ just right seed if ls is not None: try: pa.ls_change(ls) except Exception as exc: sys.print_exception(exc) # but keep going # restore settings from backup file for idx, k in enumerate(vals): dis.progress_bar_show(idx / len(vals)) if not k.startswith('setting.'): continue if k == 'xfp' or k == 'xpub': continue settings.set(k[8:], vals[k]) # write out settings.save() if version.has_fatram and ('hsm_policy' in vals): import hsm hsm.restore_backup(vals['hsm_policy']) await ux_show_story( 'Everything has been successfully restored. ' 'We must now reboot to install the ' 'updated settings and seed.', title='Success!') from machine import reset reset()
# (c) Copyright 2020 by Coinkite Inc. This file is covered by license found in COPYING-CC. # # quickly main wipe seed; don't install anything new from glob import numpad, dis from pincodes import pa from nvstore import settings from pincodes import AE_SECRET_LEN, PA_IS_BLANK if not pa.is_secret_blank(): # clear settings associated with this key, since it will be no more settings.blank() # save a blank secret (all zeros is a special case, detected by bootloader) dis.fullscreen('Wipe Seed!') nv = bytes(AE_SECRET_LEN) pa.change(new_secret=nv) rv = pa.setup(pa.pin) pa.login() assert pa.is_secret_blank() # reset top menu and go there from actions import goto_top_menu goto_top_menu() numpad.abort_ux()