Esempio n. 1
0
    def handle_crypto_setup(self, version, his_pubkey):
        # pick a one-time key pair for myself, and return the pubkey for that
        # determine what the session key will be for this connection
        assert version == 0x1
        assert len(his_pubkey) == 64

        # pick a random key pair, just for this session
        pair = ngu.secp256k1.keypair()
        my_pubkey = pair.pubkey().to_bytes(True)  # un-compressed

        #print('my pubkey = ' + str(b2a_hex(my_pubkey)))
        #print('his pubkey = ' + str(b2a_hex(his_pubkey)))

        self.session_key = pair.ecdh_multiply(b'\x04' + his_pubkey)
        del pair

        #print("session = " + str(b2a_hex(self.session_key)))

        # Would be nice to have nonce in addition to the counter, but
        # harder on the desktop side.
        ctr = aes256ctr.new(self.session_key)
        self.encrypt = ctr.cipher
        self.decrypt = ctr.copy().cipher

        xfp = settings.get('xfp', 0)
        xpub = settings.get('xpub', '')

        #assert my_pubkey[0] == 0x04
        return b'mypb' + my_pubkey[1:] + pack('<II', xfp, len(xpub)) + xpub
Esempio n. 2
0
def generate_generic_export(account_num=0):
    # Generate data that other programers will use to import Coldcard (single-signer)
    from public_constants import AF_CLASSIC, AF_P2WPKH, AF_P2WPKH_P2SH

    chain = chains.current_chain()

    rv = dict(chain=chain.ctype,
                xpub = settings.get('xpub'),
                xfp = xfp2str(settings.get('xfp')),
                account = account_num,
            )

    with stash.SensitiveValues() as sv:
        # each of these paths would have /{change}/{idx} in usage (not hardened)
        for name, deriv, fmt, atype in [
            ( 'bip44', "m/44'/{ct}'/{acc}'", AF_CLASSIC, 'p2pkh' ),
            ( 'bip49', "m/49'/{ct}'/{acc}'", AF_P2WPKH_P2SH, 'p2sh-p2wpkh' ),   # was "p2wpkh-p2sh"
            ( 'bip84', "m/84'/{ct}'/{acc}'", AF_P2WPKH, 'p2wpkh' ),
        ]:
            dd = deriv.format(ct=chain.b44_cointype, acc=account_num)
            node = sv.derive_path(dd)
            xfp = xfp2str(swab32(node.my_fp()))
            xp = chain.serialize_public(node, AF_CLASSIC)
            zp = chain.serialize_public(node, fmt) if fmt != AF_CLASSIC else None

            # bonus/check: first non-change address: 0/0
            node.derive(0, False).derive(0, False)

            rv[name] = dict(deriv=dd, xpub=xp, xfp=xfp, first=chain.address(node, fmt), name=atype)
            if zp:
                rv[name]['_pub'] = zp

    return rv
Esempio n. 3
0
    def handle_bag_number(self, bag_num):
        import version, callgate
        from glob import dis
        from pincodes import pa

        if version.is_factory_mode and bag_num:
            # check state first
            assert settings.get('tested', False)
            assert pa.is_blank()
            assert 8 <= len(bag_num) < 32

            # do the change
            failed = callgate.set_bag_number(bag_num)
            assert not failed

            callgate.set_rdp_level(2 if not is_devmode else 0)
            pa.greenlight_firmware()
            dis.fullscreen(bytes(bag_num).decode())

            self.call_after(callgate.show_logout, 1)

        # always report the existing/new value
        val = callgate.get_bag_number() or b''

        return b'asci' + val
Esempio n. 4
0
def chain_chooser():
    # Pick Bitcoin or Testnet3 blockchains
    from chains import AllChains

    chain = settings.get('chain', 'BTC')

    ch = [(i.ctype, i.menu_name or i.name) for i in AllChains]

    # find index of current choice
    try:
        which = [n for n, (k, v) in enumerate(ch) if k == chain][0]
    except IndexError:
        which = 0

    def set_chain(idx, text):
        val = ch[idx][0]
        assert ch[idx][1] == text
        settings.set('chain', val)

        try:
            # update xpub stored in settings
            import stash
            with stash.SensitiveValues() as sv:
                sv.capture_xpub()
        except ValueError:
            # no secrets yet, not an error
            pass

    return which, [t for _, t in ch], set_chain
Esempio n. 5
0
def generate_unchained_export(acct_num=0):
    # They used to rely on our airgapped export file, so this is same style
    # - for multisig purposes
    # - BIP-45 style paths for now
    # - no account numbers (at this level)
    from public_constants import AF_P2SH, AF_P2WSH_P2SH, AF_P2WSH

    chain = chains.current_chain()
    todo = [
        ("m/45'", 'p2sh', AF_P2SH),  # iff acct_num == 0
        ("m/48'/{coin}'/{acct_num}'/1'", 'p2sh_p2wsh', AF_P2WSH_P2SH),
        ("m/48'/{coin}'/{acct_num}'/2'", 'p2wsh', AF_P2WSH),
    ]

    xfp = xfp2str(settings.get('xfp', 0))
    rv = dict(account=acct_num, xfp=xfp)

    with stash.SensitiveValues() as sv:
        for deriv, name, fmt in todo:
            if fmt == AF_P2SH and acct_num:
                continue
            dd = deriv.format(coin=chain.b44_cointype, acct_num=acct_num)
            node = sv.derive_path(dd)
            xp = chain.serialize_public(node, fmt)

            rv['%s_deriv' % name] = dd
            rv[name] = xp

    return rv
Esempio n. 6
0
async def address_explore(*a):
    # explore addresses based on derivation path chosen
    # by proxy external index=0 address

    while not settings.get('axskip', False):
        ch = await ux_show_story('''\
The following menu lists the first payment address \
produced by various common wallet systems.

Choose the address that your desktop or mobile wallet \
has shown you as the first receive address.

WARNING: Please understand that exceeding the gap limit \
of your wallet, or choosing the wrong address on the next screen \
may make it very difficult to recover your funds.

Press 4 to start or 6 to hide this message forever.''', escape='46')

        if ch == '4': break
        if ch == '6':
            settings.set('axskip', True)
            break
        if ch == 'x': return

    m = AddressListMenu()
    await m.render()        # slow

    the_ux.push(m)
Esempio n. 7
0
def current_chain():
    # return chain matching current setting
    from nvstore import settings

    chain = settings.get('chain', 'BTC')

    return get_chain(chain)
Esempio n. 8
0
async def xor_restore_start(*a):
    # shown on import menu when no seed of any kind yet
    # - or operational system
    ch = await ux_show_story('''\
To import a seed split using XOR, you must import all the parts.
It does not matter the order (A/B/C or C/A/B) and the Coldcard
cannot determine when you have all the parts. You may stop at
any time and you will have a valid wallet.''')
    if ch == 'x': return

    global import_xor_parts
    import_xor_parts.clear()

    from pincodes import pa

    if not pa.is_secret_blank():
        msg = "Since you have a seed already on this Coldcard, the reconstructed XOR seed will be temporary and not saved. Wipe the seed first if you want to commit the new value into the secure element."
        if settings.get('words', True):
            msg += '''\n
Press (1) to include this Coldcard's seed words into the XOR seed set, or OK to continue without.'''

        ch = await ux_show_story(msg, escape='1')

        if ch == 'x':
            return
        elif ch == '1':
            with stash.SensitiveValues() as sv:
                if sv.mode == 'words':
                    words = bip39.b2a_words(sv.raw).split(' ')
                    import_xor_parts.append(words)

    return XORWordNestMenu(num_words=24)
Esempio n. 9
0
    def render_value(cls, val, unpad=False):
        # convert nValue from a transaction into human form.
        # - always be precise
        # - return (string, units label)
        from nvstore import settings
        rz = settings.get('rz', 8)

        if rz == 8:
            # full Bitcoins, for OG's
            unit = cls.ctype
            div = 100000000  # caution: don't use 1E8 here, that's a float
            fmt = '%08d'
        elif rz == 5:
            unit = 'm' + cls.ctype  # includes mXTN
            div = 100000
            fmt = '%05d'
        elif rz == 2:
            unit = 'bits'
            div = 100
            fmt = '%02d'
        elif rz == 0:
            return str(val), 'sats'

        if unpad:
            # show precise value, but no trailing zeros
            if (val % div):
                txt = (('%d.' + fmt) % (val // div, val % div)).rstrip('0')
            else:
                # round amount, omit decimal point
                txt = '%d' % (val // div)
        else:
            # all the zeros & fixed with result
            txt = ('%d.' + fmt) % (val // div, val % div)

        return txt, unit
Esempio n. 10
0
def generate_electrum_wallet(addr_type, account_num=0):
    # Generate line-by-line JSON details about wallet.
    #
    # Much reverse enginerring of Electrum here. It's a complex
    # legacy file format.
    from public_constants import AF_CLASSIC, AF_P2WPKH, AF_P2WPKH_P2SH

    chain = chains.current_chain()

    xfp = settings.get('xfp')

    # Must get the derivation path, and the SLIP32 version bytes right!
    if addr_type == AF_CLASSIC:
        mode = 44
    elif addr_type == AF_P2WPKH:
        mode = 84
    elif addr_type == AF_P2WPKH_P2SH:
        mode = 49
    else:
        raise ValueError(addr_type)

    derive = "m/{mode}'/{coin_type}'/{account}'".format(
        mode=mode, account=account_num, coin_type=chain.b44_cointype)

    with stash.SensitiveValues() as sv:
        top = chain.serialize_public(sv.derive_path(derive), addr_type)

    # most values are nicely defaulted, and for max forward compat, don't want to set
    # anything more than I need to

    rv = dict(seed_version=17, use_encryption=False, wallet_type='standard')

    lab = 'Coldcard Import %s' % xfp2str(xfp)
    if account_num:
        lab += ' Acct#%d' % account_num

    # the important stuff.
    rv['keystore'] = dict(ckcc_xfp=xfp,
                          ckcc_xpub=settings.get('xpub'),
                          hw_type='coldcard',
                          type='hardware',
                          label=lab,
                          derivation=derive,
                          xpub=top)

    return rv
Esempio n. 11
0
    async def interact(self):
        # prompt them
        from nvstore import settings

        showit = False
        while 1:
            if showit:
                ch = await ux_show_story('''Given:\n\n%s\n\nShould we switch to that wallet now?

OK to continue, X to cancel.''' % self._pw, title="Passphrase")
            else:
                ch = await ux_show_story('''BIP-39 passphrase (%d chars long) has been provided over USB connection. Should we switch to that wallet now?

Press 2 to view the provided passphrase.\n\nOK to continue, X to cancel.''' % len(self._pw), title="Passphrase", escape='2')

            if ch == '2':
                showit = True
                continue
            break

        try:
            if ch != 'y':
                # they don't want to!
                self.refused = True
                await ux_dramatic_pause("Refused.", 1)
            else:
                from seed import set_bip39_passphrase

                # full screen message shown: "Working..."
                set_bip39_passphrase(self._pw)

                self.result = settings.get('xpub')


        except BaseException as exc:
            self.failed = "Exception"
            sys.print_exception(exc)
        finally:
            self.done()

        if self.result:
            new_xfp = settings.get('xfp')
            await ux_show_story('''Above is the master key fingerprint of the current wallet.''',
                            title="[%s]" % xfp2str(new_xfp))
Esempio n. 12
0
def delete_inputs_chooser():
    #   del = (int) 0=normal 1=overwrite+delete input PSBT's, rename outputs
    del_psbt = settings.get('del', 0)

    ch = ['Normal', 'Delete PSBTs']

    def set_del_psbt(idx, text):
        settings.set('del', idx)

    return del_psbt, ch, set_del_psbt
Esempio n. 13
0
async def make_bitcoin_core_wallet(account_num=0,
                                   fname_pattern='bitcoin-core.txt'):
    from glob import dis
    import ustruct
    xfp = xfp2str(settings.get('xfp'))

    dis.fullscreen('Generating...')

    # make the data
    examples = []
    imp_multi = []
    imp_desc = []
    for a, b in generate_bitcoin_core_wallet(account_num, examples):
        imp_multi.append(a)
        imp_desc.append(b)

    imp_multi = ujson.dumps(imp_multi)
    imp_desc = ujson.dumps(imp_desc)

    body = '''\
# Bitcoin Core Wallet Import File

https://github.com/Coldcard/firmware/blob/master/docs/bitcoin-core-usage.md

## For wallet with master key fingerprint: {xfp}

Wallet operates on blockchain: {nb}

## Bitcoin Core RPC

The following command can be entered after opening Window -> Console
in Bitcoin Core, or using bitcoin-cli:

importdescriptors '{imp_desc}'

### Bitcoin Core before v0.21.0 

This command can be used on older versions, but it is not as robust
and "importdescriptors" should be prefered if possible:

importmulti '{imp_multi}'

## Resulting Addresses (first 3)

'''.format(imp_multi=imp_multi,
           imp_desc=imp_desc,
           xfp=xfp,
           nb=chains.current_chain().name)

    body += '\n'.join('%s => %s' % t for t in examples)

    body += '\n'

    await write_text_file(fname_pattern, body, 'Bitcoin Core')
Esempio n. 14
0
        async def doit(menu, idx, item):
            # apply the password immediately and drop them at top menu
            set_bip39_passphrase(data[idx]['pw'])

            from nvstore import settings
            from utils import xfp2str
            xfp = settings.get('xfp')

            # verification step; I don't see any way for this to go wrong
            assert xfp == data[idx]['xfp']

            # feedback that it worked
            await ux_show_story("Passphrase restored.", title="[%s]" % xfp2str(xfp))

            goto_top_menu()
Esempio n. 15
0
def max_fee_chooser():
    from psbt import DEFAULT_MAX_FEE_PERCENTAGE
    limit = settings.get('fee_limit', DEFAULT_MAX_FEE_PERCENTAGE)

    ch = ['10% (default)', '25%', '50%', 'no limit']
    va = [10, 25, 50, -1]

    try:
        which = va.index(limit)
    except ValueError:
        which = 0

    def set(idx, text):
        settings.set('fee_limit', va[idx])

    return which, ch, set
Esempio n. 16
0
def value_resolution_chooser():
    # how to render Bitcoin values
    ch = ['BTC', 'mBTC', 'bits', 'sats']
    va = [8, 5, 2, 0]

    rz = settings.get('rz', 8)

    try:
        which = va.index(rz)
    except ValueError:
        which = 0

    def doit(idx, text):
        settings.set('rz', va[idx])

    return which, ch, doit
Esempio n. 17
0
def generate_bitcoin_core_wallet(example_addrs, account_num):
    # Generate the data for an RPC command to import keys into Bitcoin Core
    # - yields dicts for json purposes
    from descriptor import append_checksum
    import ustruct

    from public_constants import AF_P2WPKH

    chain = chains.current_chain()

    derive = "84'/{coin_type}'/{account}'".format(account=account_num,
                                                  coin_type=chain.b44_cointype)

    with stash.SensitiveValues() as sv:
        prefix = sv.derive_path(derive)
        xpub = chain.serialize_public(prefix)

        for i in range(3):
            sp = '0/%d' % i
            node = sv.derive_path(sp, master=prefix)
            a = chain.address(node, AF_P2WPKH)
            example_addrs.append(('m/%s/%s' % (derive, sp), a))

    xfp = settings.get('xfp')
    txt_xfp = xfp2str(xfp).lower()

    chain = chains.current_chain()

    _, vers, _ = version.get_mpy_version()

    for internal in [False, True]:
        desc = "wpkh([{fingerprint}/{derive}]{xpub}/{change}/*)".format(
            derive=derive.replace("'", "h"),
            fingerprint=txt_xfp,
            coin_type=chain.b44_cointype,
            account=0,
            xpub=xpub,
            change=(1 if internal else 0))

        yield {
            'desc': append_checksum(desc),
            'range': [0, 1000],
            'timestamp': 'now',
            'internal': internal,
            'keypool': True,
            'watchonly': True
        }
Esempio n. 18
0
    async def render(self):
        # Choose from a truncated list of index 0 common addresses, remember
        # the last address the user selected and use it as the default
        from glob import dis
        chain = chains.current_chain()

        dis.fullscreen('Wait...')

        with stash.SensitiveValues() as sv:

            # Create list of choices (address_index_0, path, addr_fmt)
            choices = []
            for name, path, addr_fmt in chains.CommonDerivations:
                if '{coin_type}' in path:
                    path = path.replace('{coin_type}', str(chain.b44_cointype))

                if self.account_num != 0 and '{account}' not in path:
                    # skip derivations that are not affected by account number
                    continue

                deriv = path.format(account=self.account_num, change=0, idx=0)
                node = sv.derive_path(deriv, register=False)
                address = chain.address(node, addr_fmt)
                choices.append( (truncate_address(address), path, addr_fmt) )

                dis.progress_bar_show(len(choices) / len(chains.CommonDerivations))

            stash.blank_object(node)

        items = [MenuItem(address, f=self.pick_single, arg=(path, addr_fmt)) 
                        for i, (address, path, addr_fmt) in enumerate(choices)]

        # some other choices
        if self.account_num == 0:
            items.append(MenuItem("Account Number", f=self.change_account))
            items.append(MenuItem("Custom Path", menu=self.make_custom))

            # if they have MS wallets, add those next
            for ms in MultisigWallet.iter_wallets():
                if not ms.addr_fmt: continue
                items.append(MenuItem(ms.name, f=self.pick_multisig, arg=ms))
        else:
            items.append(MenuItem("Account: %d" % self.account_num, f=self.change_account))

        self.goto_idx(settings.get('axi', 0))      # weak

        self.replace_items(items)
Esempio n. 19
0
async def more_setup():
    # Boot up code; splash screen is being shown

    # MAYBE: check if we're a brick and die again? Or show msg?

    try:
        # Some background "tasks"
        #
        from dev_helper import monitor_usb
        IMPT.start_task('vcp', monitor_usb())

        from files import CardSlot
        CardSlot.setup()

        # This "pa" object holds some state shared w/ bootloader about the PIN
        try:
            from pincodes import pa
            pa.setup(b'')  # just to see where we stand.
        except RuntimeError as e:
            print("Problem: %r" % e)

        if version.is_factory_mode:
            # in factory mode, turn on USB early to allow debug/setup
            from usb import enable_usb
            enable_usb()

            # always start the self test.
            if not settings.get('tested', False):
                from actions import start_selftest
                await start_selftest()

        else:
            # force them to accept terms (unless marked as already done)
            from actions import accept_terms
            await accept_terms()

        # Prompt for PIN and then pick appropriate top-level menu,
        # based on contents of secure chip (ie. is there
        # a wallet defined)
        from actions import start_login_sequence
        await start_login_sequence()
    except BaseException as exc:
        die_with_debug(exc)

    IMPT.start_task('mainline', mainline())
Esempio n. 20
0
def disable_usb_chooser():
    value = settings.get('du', 0)
    ch = ['Normal', 'Disable USB']

    def set_it(idx, text):
        settings.set('du', idx)

        import pyb
        from usb import enable_usb, disable_usb
        cur = pyb.usb_mode()
        if cur and idx:
            # usb enabled, but should not be now
            disable_usb()
        elif not cur and not idx:
            # USB disabled, but now should be
            enable_usb()

    return value, ch, set_it
Esempio n. 21
0
def idle_timeout_chooser():
    from ux import DEFAULT_IDLE_TIMEOUT

    timeout = settings.get('idle_to', DEFAULT_IDLE_TIMEOUT)  # in seconds

    ch = [
        ' 2 minutes', ' 5 minutes', '15 minutes', ' 1 hour', ' 4 hours',
        ' 8 hours', ' Never'
    ]
    va = [2 * 60, 5 * 60, 15 * 60, 3600, 4 * 3600, 8 * 3600, 0]

    try:
        which = va.index(timeout)
    except ValueError:
        which = 0

    def set_idle_timeout(idx, text):
        settings.set('idle_to', va[idx])

    return which, ch, set_idle_timeout
Esempio n. 22
0
async def make_bitcoin_core_wallet(account_num=0,
                                   fname_pattern='bitcoin-core.txt'):
    from glob import dis
    import ustruct
    xfp = xfp2str(settings.get('xfp'))

    dis.fullscreen('Generating...')

    # make the data
    examples = []
    payload = ujson.dumps(
        list(generate_bitcoin_core_wallet(examples, account_num)))

    body = '''\
# Bitcoin Core Wallet Import File

https://github.com/Coldcard/firmware/blob/master/docs/bitcoin-core-usage.md

## For wallet with master key fingerprint: {xfp}

Wallet operates on blockchain: {nb}

## Bitcoin Core RPC

The following command can be entered after opening Window -> Console
in Bitcoin Core, or using bitcoin-cli:

importmulti '{payload}'

## Resulting Addresses (first 3)

'''.format(payload=payload, xfp=xfp, nb=chains.current_chain().name)

    body += '\n'.join('%s => %s' % t for t in examples)

    body += '\n'

    await write_text_file(fname_pattern, body, 'Bitcoin Core')
Esempio n. 23
0
def generate_wasabi_wallet():
    # Generate the data for a JSON file which Wasabi can open directly as a new wallet.
    import ustruct, version

    # bitcoin (xpub) is used, even for testnet case (ie. no tpub)
    # - altho, doesn't matter; the wallet operates based on it's own settings for test/mainnet
    #   regardless of the contents of the wallet file
    btc = chains.BitcoinMain

    with stash.SensitiveValues() as sv:
        xpub = btc.serialize_public(sv.derive_path("84'/0'/0'"))

    xfp = settings.get('xfp')
    txt_xfp = xfp2str(xfp)

    chain = chains.current_chain()
    assert chain.ctype in {'BTC', 'XTN'}, "Only Bitcoin supported"

    _,vers,_ = version.get_mpy_version()

    return dict(MasterFingerprint=txt_xfp,
                ColdCardFirmwareVersion=vers,
                ExtPubKey=xpub)
Esempio n. 24
0
async def idle_logout():
    import glob
    from nvstore import settings

    while not glob.hsm_active:
        await sleep_ms(250)

        # they may have changed setting recently
        timeout = settings.get('idle_to', DEFAULT_IDLE_TIMEOUT) * 1000  # ms
        if timeout == 0:
            continue

        now = utime.ticks_ms()

        if not glob.numpad.last_event_time:
            continue

        if now > glob.numpad.last_event_time + timeout:
            # do a logout now.
            print("Idle!")

            from actions import logout_now
            await logout_now()
            return  # not reached
Esempio n. 25
0
    async def done_apply(self, *a):
        # apply the passphrase.
        # - important to work on empty string here too.
        from stash import bip39_passphrase
        old_pw = str(bip39_passphrase)

        set_bip39_passphrase(pp_sofar)

        xfp = settings.get('xfp')

        msg = '''Above is the master key fingerprint of the new wallet.

Press X to abort and keep editing passphrase, OK to use the new wallet, or 1 to use and save to MicroSD'''

        ch = await ux_show_story(msg, title="[%s]" % xfp2str(xfp), escape='1')
        if ch == 'x':
            # go back!
            set_bip39_passphrase(old_pw)
            return

        if ch == '1':
            await PassphraseSaver().append(xfp, pp_sofar)

        goto_top_menu()
Esempio n. 26
0
async def test_7z():
    # test full 7z round-trip
    # Altho cleartext mode is not for real, if the code is written, I must test it.
    from backups import write_complete_backup, restore_complete_doit
    from sffile import SFFile
    import ngu, version, uos
    from glob import numpad
    from pincodes import pa
    from nvstore import settings

    if version.has_fatram:
        import hsm
        had_policy = hsm.hsm_policy_available()
    else:
        had_policy = False

    today = ngu.random.uniform(1000000)

    import machine
    machine.reset = lambda: None

    for chain in ['BTC', 'XTN']:
        for words in ([], ['abc', 'def']):
            settings.set('check', today)
            settings.set('chain', chain)

            if version.has_608:
                ls = b'%416d' % today
                pa.ls_change(ls)

            ll, sha = await write_complete_backup(words, None, True)

            result = SFFile(0, ll).read()

            if words:
                #open('debug.7z', 'wb').write(result)
                assert ll > 800
                assert len(sha) == 32
                assert result[0:6] == b"7z\xbc\xaf'\x1c"
                assert ngu.hash.sha256s(result) == sha
                assert len(set(result)) >= 240  # encrypted
            else:
                sr = str(result, 'ascii')
                print("Backup contents:\n" + sr)
                assert sr[0] == '#', result
                assert 'Coldcard' in sr
                assert len(set(sr)) < 100  # cleartext, english
                assert ('chain = "%s"' % chain) in result

            # test restore
            # - cant wipe flash, since the backup file is there
            # - cant wipe all settings becuase PIN and stuff is simulated there
            del settings.current['check']

            if had_policy:
                from hsm import POLICY_FNAME
                uos.unlink(POLICY_FNAME)
                assert not hsm.hsm_policy_available()

            with SFFile(0, ll) as fd:
                numpad.inject('y')  # for 'success' message
                await restore_complete_doit(fd, words)

                assert settings.get('check') == today, \
                            (settings.get('check'), '!=',  today)
                assert settings.get('chain') == chain, \
                            (settings.get('chain'), '!=',  chain)

                if version.has_608:
                    assert pa.ls_fetch() == ls

            if had_policy:
                assert had_policy == hsm.hsm_policy_available()

            today += 3

            import ux
            ux.restore_menu()
Esempio n. 27
0
# (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)))

Esempio n. 28
0
# (c) Copyright 2020 by Coinkite Inc. This file is covered by license found in COPYING-CC.
#
# quickly clear all multisig wallets installed
from nvstore import settings
from ux import restore_menu

if settings.get('multisig'):
    del settings.current['multisig']
    settings.save()

    print("cleared multisigs")

restore_menu()
Esempio n. 29
0
EmptyWallet = [
    #         xxxxxxxxxxxxxxxx
    MenuItem('New Wallet', f=pick_new_wallet),
    MenuItem('Import Existing', menu=ImportWallet),
    MenuItem('Help', f=virgin_help),
    MenuItem('Advanced', menu=AdvancedPinnedVirginMenu),
    MenuItem('Settings', menu=SettingsMenu),
]

# In operation, normal system, after a good PIN received.
NormalSystem = [
    #         xxxxxxxxxxxxxxxx
    MenuItem('Ready To Sign', f=ready2sign),
    MenuItem('Passphrase',
             f=start_b39_pw,
             predicate=lambda: settings.get('words', True)),
    MenuItem('Start HSM Mode',
             f=start_hsm_menu_item,
             predicate=hsm_policy_available),
    MenuItem("Address Explorer", f=address_explore),
    MenuItem('Secure Logout', f=logout_now),
    MenuItem('Advanced', menu=AdvancedNormalMenu),
    MenuItem('Settings', menu=SettingsMenu),
]

# Shown until unit is put into a numbered bag
FactoryMenu = [
    MenuItem('Bag Me Now'),  # nice to have NOP at top of menu
    MenuItem('DFU Upgrade', f=start_dfu),
    MenuItem('Show Version', f=show_version),
    MenuItem('Ship W/O Bag', f=ship_wo_bag),
Esempio n. 30
0
if '--seed' in sys.argv:
    # --seed "word1 word2 ... word24" => import that seed phrase at start
    from ustruct import unpack
    from utils import xfp2str
    from seed import set_seed_value
    from main import pa
    from nvstore import settings

    words = sys.argv[sys.argv.index('--seed') + 1].split(' ')
    assert len(words) in {12, 18, 24}, "Expected space-separated words: add some quotes"
    pa.pin = b'12-12'
    set_seed_value(words)
    settings.set('terms_ok', 1)
    settings.set('_skip_pin', '12-12')
    settings.set('chain', 'XTN')
    print("Seed phrase set, resulting XFP: " + xfp2str(settings.get('xfp')))

if '--secret' in sys.argv:
    # --secret 01a1a1a....   Set SE master secret directly. See SecretStash.encode
    from ubinascii import unhexlify as a2b_hex
    from ubinascii import hexlify as b2a_hex

    val = sys.argv[sys.argv.index('--secret') + 1]
    val = a2b_hex(val)
    assert val[0] in { 0x01, 0x80, 0x81, 0x82} or 16 <= val[0] <= 64, "bad first byte"
    val += bytes(72 - len(val))

    SECRETS.update({
        '_pin1_secret': b2a_hex(val),
    })