async def show_version(*a): # show firmware, bootload versions. from main import settings import callgate, version from ubinascii import hexlify as b2a_hex built, rel, *_ = version.get_mpy_version() bl = callgate.get_bl_version()[0] chk = str(b2a_hex(callgate.get_bl_checksum(0))[-8:], 'ascii') msg = '''\ Coldcard Firmware {rel} {built} Bootloader: {bl} {chk} Serial: {ser} ''' await ux_show_story( msg.format(rel=rel, built=built, bl=bl, chk=chk, ser=version.serial_number()))
async def view_ident(*a): # show the XPUB, and other ident on screen from main import settings, pa from version import serial_number import callgate, stash tpl = '''\ Master Key Fingerprint: {xfp:08x} USB Serial Number: {serial} Extended Master Key: {xpub} ''' msg = tpl.format(xpub=settings.get('xpub', '(none yet)'), xfp=settings.get('xfp', 0), serial=serial_number()) if pa.is_secondary: msg += '\n(Secondary wallet)\n' if stash.bip39_passphrase: msg += '\nBIP39 passphrase is in effect.\n' bn = callgate.get_bag_number() if bn: msg += '\nShipping Bag:\n %s\n' % bn await ux_show_story(msg)
def calc_hmac_key(text_password): # Calculate a 32-byte key based on user's text password, PBKDF2_ITER_COUNT, # and device serial number as salt. # - before v4, this was pbkdf2_sha256 import version salt = ngu.hash.sha256s(b'pepper' + version.serial_number().encode()) pw = ngu.hash.pbkdf2_sha512(text_password, salt, PBKDF2_ITER_COUNT) return pw[0:32]
def calc_hmac_key(text_password): # Calculate a 32-byte key based on user's text password, PBKDF2_ITER_COUNT, # and device serial number as salt. import version salt = tcc.sha256(b'pepper' + version.serial_number().encode()).digest() pw = tcc.pbkdf2('hmac-sha256', text_password, salt, PBKDF2_ITER_COUNT).key() return pw
def render_backup_contents(): # simple text format: # key = value # or #comments # but value is JSON from main import settings, pa rv = StringIO() def COMMENT(val=None): if val: rv.write('\n# %s\n' % val) else: rv.write('\n') def ADD(key, val): rv.write('%s = %s\n' % (key, ujson.dumps(val))) rv.write('# Coldcard backup file! DO NOT CHANGE.\n') chain = chains.current_chain() COMMENT('Private key details: ' + chain.name) with stash.SensitiveValues(for_backup=True) as sv: if sv.mode == 'words': ADD('mnemonic', tcc.bip39.from_data(sv.raw)) if sv.mode == 'master': ADD('bip32_master_key', b2a_hex(sv.raw)) ADD('chain', chain.ctype) ADD('xprv', chain.serialize_private(sv.node)) ADD('xpub', chain.serialize_public(sv.node)) # BTW: everything is really a duplicate of this value ADD('raw_secret', b2a_hex(sv.secret).rstrip(b'0')) if pa.has_duress_pin(): COMMENT('Duress Wallet (informational)') dpk = sv.duress_root() ADD('duress_xprv', chain.serialize_private(dpk)) ADD('duress_xpub', chain.serialize_public(dpk)) if version.has_608: # save the so-called long-secret ADD('long_secret', b2a_hex(pa.ls_fetch())) COMMENT('Firmware version (informational)') date, vers, timestamp = version.get_mpy_version()[0:3] ADD('fw_date', date) ADD('fw_version', vers) ADD('fw_timestamp', timestamp) ADD('serial', version.serial_number()) COMMENT('User preferences') # user preferences for k, v in settings.current.items(): if k[0] == '_': continue # debug stuff in simulator if k == 'xpub': continue # redundant, and wrong if bip39pw if k == 'xfp': continue # redundant, and wrong if bip39pw ADD('setting.' + k, v) if version.has_fatram: import hsm if hsm.hsm_policy_available(): ADD('hsm_policy', hsm.capture_backup()) rv.write('\n# EOF\n') return rv.getvalue()