コード例 #1
0
async def remember_bip39_passphrase():
    # Compute current xprv and switch to using that as root secret.
    import stash
    from main import dis, pa

    if not stash.bip39_passphrase:
        if not await ux_confirm(
                '''You do not have a BIP39 passphrase set right now, so this command does little except forget the seed words. It does not enhance security.'''
        ):
            return

    dis.fullscreen('Check...')

    with stash.SensitiveValues() as sv:
        if sv.mode != 'words':
            # not a BIP39 derived secret, so cannot work.
            await ux_show_story(
                '''The wallet secret was not based on a seed phrase, so we cannot add a BIP39 passphrase at this time.''',
                title='Failed')
            return

        nv = SecretStash.encode(xprv=sv.node)

    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()
コード例 #2
0
async def remember_bip39_passphrase():
    # Compute current xprv and switch to using that as root secret.
    import stash
    from main import dis, pa

    dis.fullscreen('Check...')

    with stash.SensitiveValues() as sv:
        if sv.mode != 'words':
            # not a BIP39 derived secret, so cannot work.
            await ux_show_story('''The wallet secret was not based on a seed phrase, so we cannot add a BIP39 passphrase at this time.''', title='Failed')
            return

        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()
コード例 #3
0
def set_seed_value(words):
    # Save the seed words into secure element, and reboot. BIP39 password
    # is not set at this point (empty string)
    ok = tcc.bip39.check(' '.join(words))
    assert ok, "seed check: %r" % words

    # map words to bip39 wordlist indices
    data = [tcc.bip39.lookup_word(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
    
    from main import dis, pa, settings

    # encode it for our limited secret space
    nv = SecretStash.encode(seed_phrase=seed)

    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()
コード例 #4
0
ファイル: seed.py プロジェクト: twetch-inc/cold-firmware
async def remember_bip39_passphrase():
    # Compute current xprv and switch to using that as root secret.
    import stash
    from main import dis, pa

    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()
コード例 #5
0
async def restore_from_dict(vals):
    # Restore from a dict of values. Already JSON decoded.
    # Reboot on success, return string on failure
    from main import pa, dis, settings
    from pincodes import AE_SECRET_LEN

    #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/or seed.',
        title='Success!')

    from machine import reset
    reset()
コード例 #6
0
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)
コード例 #7
0
# load up the simulator w/ indicated encoded secret. could be xprv/words/etc.
import tcc, main
from sim_settings import sim_defaults
import stash, chains
from h import b2a_hex
from main import settings, pa
from stash import SecretStash, SensitiveValues
from utils import xfp2str

settings.current = sim_defaults
settings.overrides.clear()

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)))

コード例 #8
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
import tcc, main
from sim_settings import sim_defaults
import stash, chains
from h import b2a_hex
from main import settings, pa
from stash import SecretStash, SensitiveValues
from utils import xfp2str

rs = main.RAW_SECRET
print("New raw secret: %s" % b2a_hex(rs))

if 1:
    settings.current = 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)))