async def add_text(_1, _2, item): global pp_sofar pp_sofar += item.label PassphraseMenu.check_length() while not isinstance(the_ux.top_of_stack(), PassphraseMenu): the_ux.pop()
def picked(menu, picked, xx_self): menu.chosen = picked menu.show() await sleep_ms(100) # visual feedback that we changed it setter(picked, choices[picked]) the_ux.pop()
async def delete_user(menu, label, item): if not await ux_confirm('Delete user:\n %s\n' % item.arg): return Users.delete(item.arg) await ux_dramatic_pause('Deleted.', 3) from ux import the_ux the_ux.pop() m = the_ux.top_of_stack() m.update_contents()
def on_cancel(self): # user pressed cancel on a menu (so he's going upwards) # - if it's a step where we added to the word list, undo that. # - but keep them in our system until: # - when the word list is empty and they cancel, stop words = WordNestMenu.words if self.is_commit and words: words.pop() # replace the menu we are show w/ top-level (a-) menu the_ux.pop() nxt = WordNestMenu(is_commit=True) the_ux.push(nxt) else: the_ux.pop()
def done(self, _1, menu_idx, item): final_path = item.arg or item.label self.chosen = menu_idx self.show() await sleep_ms(100) # visual feedback that we changed it # pop entire stack of path choosing while 1: top = the_ux.top_of_stack() if isinstance(top, KeypathMenu): the_ux.pop() continue assert isinstance(top, AddressListMenu) break return PickAddrFmtMenu(final_path, top)
async def ms_wallet_delete(menu, label, item): ms = item.arg # delete if not await ux_confirm("Delete this multisig wallet (%s)?\n\nFunds may be impacted." % ms.name): return ms.delete() await ux_dramatic_pause('Deleted.', 3) # update/hide from menu # menu.update_contents() from ux import the_ux # pop stack the_ux.pop() m = the_ux.top_of_stack() m.update_contents()
def pop_menu(self): # drop them back into menu system, but try not to affect # menu position. self.ux_done = True from actions import goto_top_menu from ux import the_ux, restore_menu if the_ux.top_of_stack() == self: empty = the_ux.pop() if empty: goto_top_menu() restore_menu()
def on_cancel(self): # override me if the_ux.pop(): # top of stack (main top-level menu) self.top()
def pop_all(cls): while isinstance(the_ux.top_of_stack(), cls): the_ux.pop()
def drv_entro_step2(_1, picked, _2): from main import dis from files import CardSlot, CardMissingError the_ux.pop() index = await ux_enter_number("Index Number?", 9999) if picked in (0,1,2): # BIP39 seed phrases (we only support English) num_words = (12, 18, 24)[picked] width = (16, 24, 32)[picked] # of bytes path = "m/83696968'/39'/0'/{num_words}'/{index}'".format(num_words=num_words, index=index) s_mode = 'words' elif picked == 3: # HDSeed for Bitcoin Core: but really a WIF of a private key, can be used anywhere s_mode = 'wif' path = "m/83696968'/2'/{index}'".format(index=index) width = 32 elif picked == 4: # New XPRV path = "m/83696968'/32'/{index}'".format(index=index) s_mode = 'xprv' width = 64 elif picked in (5, 6): width = 32 if picked == 5 else 64 path = "m/83696968'/128169'/{width}'/{index}'".format(width=width, index=index) s_mode = 'hex' else: raise ValueError(picked) dis.fullscreen("Working...") encoded = None with stash.SensitiveValues() as sv: node = sv.derive_path(path) entropy = hmac.HMAC(b'bip-entropy-from-k', node.private_key(), tcc.sha512).digest() sv.register(entropy) # truncate for this application new_secret = entropy[0:width] # only "new_secret" is interesting past here (node already blanked at this point) del node # Reveal to user! chain = chains.current_chain() if s_mode == 'words': # BIP39 seed phrase, various lengths words = tcc.bip39.from_data(new_secret).split(' ') msg = 'Seed words (%d):\n' % len(words) msg += '\n'.join('%2d: %s' % (i+1, w) for i,w in enumerate(words)) encoded = stash.SecretStash.encode(seed_phrase=new_secret) elif s_mode == 'wif': # for Bitcoin Core: a 32-byte of secret exponent, base58 w/ prefix 0x80 # - always "compressed", so has suffix of 0x01 (inside base58) # - we're not checking it's on curve # - we have no way to represent this internally, since we rely on bip32 # append 0x01 to indicate it's a compressed private key pk = new_secret + b'\x01' msg = 'WIF (privkey):\n' + tcc.codecs.b58_encode(chain.b58_privkey + pk) elif s_mode == 'xprv': # Raw XPRV value. ch, pk = new_secret[0:32], new_secret[32:64] master_node = tcc.bip32.HDNode(chain_code=ch, private_key=pk, child_num=0, depth=0, fingerprint=0) encoded = stash.SecretStash.encode(xprv=master_node) msg = 'Derived XPRV:\n' + chain.serialize_private(master_node) elif s_mode == 'hex': # Random hex number for whatever purpose msg = ('Hex (%d bytes):\n' % width) + str(b2a_hex(new_secret), 'ascii') stash.blank_object(new_secret) new_secret = None # no need to print it again else: raise ValueError(s_mode) msg += '\n\nPath Used (index=%d):\n %s' % (index, path) if new_secret: msg += '\n\nRaw Entropy:\n' + str(b2a_hex(new_secret), 'ascii') print(msg) # XXX debug prompt = '\n\nPress 1 to save to MicroSD card' if encoded is not None: prompt += ', 2 to switch to derived secret.' while 1: ch = await ux_show_story(msg+prompt, sensitive=True, escape='12') if ch == '1': # write to SD card: simple text file try: with CardSlot() as card: fname, out_fn = card.pick_filename('drv-%s-idx%d.txt' % (s_mode, index)) with open(fname, 'wt') as fp: fp.write(msg) fp.write('\n') except CardMissingError: await needs_microsd() continue except Exception as e: await ux_show_story('Failed to write!\n\n\n'+str(e)) continue await ux_show_story("Filename is:\n\n%s" % out_fn, title='Saved') else: break if new_secret is not None: stash.blank_object(new_secret) stash.blank_object(msg) if ch == '2' and (encoded is not None): from main import pa, settings, dis from pincodes import AE_SECRET_LEN # switch over to new secret! dis.fullscreen("Applying...") stash.bip39_passphrase = '' tmp_secret = encoded + bytes(AE_SECRET_LEN - len(encoded)) # monkey-patch to block SE access, and just use new secret pa.fetch = lambda *a, **k: bytearray(tmp_secret) pa.change = lambda *a, **k: None pa.ls_fetch = pa.change pa.ls_change = pa.change # copies system settings to new encrypted-key value, calculates # XFP, XPUB and saves into that, and starts using them. pa.new_main_secret(pa.fetch()) await ux_show_story("New master key in effect until next power down.") if encoded is not None: stash.blank_object(encoded)
async def clicked(_1, _2, item): if picked is None: picked = item.arg the_ux.pop()
async def clicked(_1, _2, item): picked.append('/'.join(item.arg)) the_ux.pop()
def done(self, _1, _2, item): the_ux.pop() await self.parent.got_custom_path(*item.arg)
def drv_entro_step2(_1, picked, _2): from glob import dis from files import CardSlot, CardMissingError the_ux.pop() index = await ux_enter_number("Index Number?", 9999) if picked in (0,1,2): # BIP-39 seed phrases (we only support English) num_words = (12, 18, 24)[picked] width = (16, 24, 32)[picked] # of bytes path = "m/83696968'/39'/0'/{num_words}'/{index}'".format(num_words=num_words, index=index) s_mode = 'words' elif picked == 3: # HDSeed for Bitcoin Core: but really a WIF of a private key, can be used anywhere s_mode = 'wif' path = "m/83696968'/2'/{index}'".format(index=index) width = 32 elif picked == 4: # New XPRV path = "m/83696968'/32'/{index}'".format(index=index) s_mode = 'xprv' width = 64 elif picked in (5, 6): width = 32 if picked == 5 else 64 path = "m/83696968'/128169'/{width}'/{index}'".format(width=width, index=index) s_mode = 'hex' else: raise ValueError(picked) dis.fullscreen("Working...") encoded = None with stash.SensitiveValues() as sv: node = sv.derive_path(path) entropy = ngu.hmac.hmac_sha512(b'bip-entropy-from-k', node.privkey()) sv.register(entropy) # truncate for this application new_secret = entropy[0:width] # only "new_secret" is interesting past here (node already blanked at this point) del node # Reveal to user! chain = chains.current_chain() qr = None qr_alnum = False if s_mode == 'words': # BIP-39 seed phrase, various lengths words = bip39.b2a_words(new_secret).split(' ') # encode more tightly for QR qr = ' '.join(w[0:4] for w in words) qr_alnum = True msg = 'Seed words (%d):\n' % len(words) msg += '\n'.join('%2d: %s' % (i+1, w) for i,w in enumerate(words)) encoded = stash.SecretStash.encode(seed_phrase=new_secret) elif s_mode == 'wif': # for Bitcoin Core: a 32-byte of secret exponent, base58 w/ prefix 0x80 # - always "compressed", so has suffix of 0x01 (inside base58) # - we're not checking it's on curve # - we have no way to represent this internally, since we rely on bip32 # append 0x01 to indicate it's a compressed private key pk = new_secret + b'\x01' qr = ngu.codecs.b58_encode(chain.b58_privkey + pk) msg = 'WIF (privkey):\n' + qr elif s_mode == 'xprv': # Raw XPRV value. ch, pk = new_secret[0:32], new_secret[32:64] master_node = ngu.hdnode.HDNode().from_chaincode_privkey(ch, pk) encoded = stash.SecretStash.encode(xprv=master_node) qr = chain.serialize_private(master_node) msg = 'Derived XPRV:\n' + qr elif s_mode == 'hex': # Random hex number for whatever purpose qr = str(b2a_hex(new_secret), 'ascii') msg = ('Hex (%d bytes):\n' % width) + qr qr_alnum = True stash.blank_object(new_secret) new_secret = None # no need to print it again else: raise ValueError(s_mode) msg += '\n\nPath Used (index=%d):\n %s' % (index, path) if new_secret: msg += '\n\nRaw Entropy:\n' + str(b2a_hex(new_secret), 'ascii') prompt = '\n\nPress 1 to save to MicroSD card' if encoded is not None: prompt += ', 2 to switch to derived secret' if (qr is not None) and version.has_fatram: prompt += ', 3 to view as QR code.' while 1: ch = await ux_show_story(msg+prompt, sensitive=True, escape='123') if ch == '1': # write to SD card: simple text file try: with CardSlot() as card: fname, out_fn = card.pick_filename('drv-%s-idx%d.txt' % (s_mode, index)) with open(fname, 'wt') as fp: fp.write(msg) fp.write('\n') except CardMissingError: await needs_microsd() continue except Exception as e: await ux_show_story('Failed to write!\n\n\n'+str(e)) continue await ux_show_story("Filename is:\n\n%s" % out_fn, title='Saved') elif ch == '3' and version.has_fatram: from ux import show_qr_code await show_qr_code(qr, qr_alnum) continue else: break if new_secret is not None: stash.blank_object(new_secret) stash.blank_object(msg) if ch == '2' and (encoded is not None): from glob import dis from pincodes import pa # switch over to new secret! dis.fullscreen("Applying...") pa.tmp_secret(encoded) await ux_show_story("New master key in effect until next power down.") if encoded is not None: stash.blank_object(encoded)