def setUp(self): transport = config.TRANSPORT(*config.TRANSPORT_ARGS, **config.TRANSPORT_KWARGS) if hasattr(config, 'DEBUG_TRANSPORT'): debug_transport = config.DEBUG_TRANSPORT( *config.DEBUG_TRANSPORT_ARGS, **config.DEBUG_TRANSPORT_KWARGS) self.client = KeepKeyDebugClient(transport) self.client.set_debuglink(debug_transport) else: self.client = KeepKeyClient(transport) self.client.set_tx_api(tx_api.TxApiBitcoin) # self.client.set_buttonwait(3) # 1 2 3 4 5 6 7 8 9 10 11 12 self.mnemonic12 = 'alcohol woman abuse must during monitor noble actual mixed trade anger aisle' self.mnemonic18 = 'owner little vague addict embark decide pink prosper true fork panda embody mixture exchange choose canoe electric jewel' self.mnemonic24 = 'dignity pass list indicate nasty swamp pool script soccer toe leaf photo multiply desk host tomato cradle drill spread actor shine dismiss champion exotic' self.mnemonic_all = ' '.join(['all'] * 12) self.pin4 = '1234' self.pin6 = '789456' self.pin8 = '45678978' self.client.wipe_device() print("Setup finished") print("--------------")
def main(): # List all connected KeepKeys on USB devices = HidTransport.enumerate() # Check whether we found any if len(devices) == 0: print('No KeepKey found') return # Use first connected device transport = HidTransport(devices[0]) # Creates object for manipulating KeepKey client = KeepKeyClient(transport) # Print out KeepKey's features and settings print(client.features) # Get the first address of first BIP44 account # (should be the same address as shown in KeepKey wallet Chrome extension) bip32_path = client.expand_path("44'/0'/0'/0/0") address = client.get_address('Bitcoin', bip32_path) print('Bitcoin address:', address) client.close()
def main(): # List all connected KeepKeys on USB devices = HidTransport.enumerate() # Check whether we found any if len(devices) == 0: print('No KeepKey found') return # Use first connected device transport = HidTransport(devices[0]) # Creates object for manipulating KeepKey client = KeepKeyClient(transport) # Print out KeepKey's features and settings print(client.features) # Get the first address of first BIP44 account # (should be the same address as shown in KeepKey wallet Chrome extension) mpath = "44'/0'/0'/0" bip32_path = client.expand_path(mpath) print bip32.serialize(client.get_public_node(bip32_path).node, 0x043587CF) for i in range(11): child_path = '%s%s' % ("44'/0'/0'/0/", str(i)) address = client.get_address('tDash', client.expand_path(child_path)) print 'tDASH address:', child_path, address client.close()
def main(): args = parse_args(Commands) if args.cmd == 'list': devices = list_usb() if args.json: print(json.dumps(devices)) else: for dev in devices: if dev[1] != None: print("%s - debuglink enabled" % dev[0]) else: print(dev[0]) return transport = get_transport(args.transport, args.path) if args.verbose: client = KeepKeyClientDebug(transport) else: client = KeepKeyClient(transport) cmds = Commands(client) res = args.func(cmds, args) if args.json: print(json.dumps(res, sort_keys=True, indent=4)) else: print(res)
class KeepKeyClient(HardwareWalletClient): # device is an HID device that has already been opened. def __init__(self, device, path): super(KeepKeyClient, self).__init__(device) device.close() devices = HidTransport.enumerate() self.client = None for d in devices: if d[0] == path: transport = HidTransport(d) self.client = KeepKey(transport) break # if it wasn't able to find a client, throw an error if not self.client: raise IOError("no Device") # Must return a dict with the xpub # Retrieves the public key at the specified BIP 32 derivation path def get_pubkey_at_path(self, path): expanded_path = self.client.expand_path(path) output = self.client.get_public_node(expanded_path) print({'xpub':output.xpub}) return # Must return a hex string with the signed transaction # The tx must be in the combined unsigned transaction format def sign_tx(self, tx): raise NotImplementedError('The HardwareWalletClient base class does not ' 'implement this method') # Must return a base64 encoded string with the signed message # The message can be any string def sign_message(self, message): raise NotImplementedError('The HardwareWalletClient base class does not ' 'implement this method') # Setup a new device def setup_device(self): raise NotImplementedError('The HardwareWalletClient base class does not ' 'implement this method') # Wipe this device def wipe_device(self): raise NotImplementedError('The HardwareWalletClient base class does not ' 'implement this method')
def main(): devices = wait_for_devices() transport = choose_device(devices) client = KeepKeyClient(transport) rootdir = os.environ['encfs_root'] # Read "man encfs" for more passw_file = os.path.join(rootdir, 'password.dat') if not os.path.exists(passw_file): # New encfs drive, let's generate password sys.stderr.write('Please provide label for new drive: ') label = input() sys.stderr.write('Computer asked KeepKey for new strong password.\n') sys.stderr.write('Please confirm action on your device.\n') # 32 bytes, good for AES keepkey_entropy = client.get_entropy(32) urandom_entropy = os.urandom(32) passw = hashlib.sha256(keepkey_entropy + urandom_entropy).digest() if len(passw) != 32: raise Exception("32 bytes password expected") bip32_path = [10, 0] passw_encrypted = client.encrypt_keyvalue(bip32_path, label, passw, False, True) data = {'label': label, 'bip32_path': bip32_path, 'password_encrypted_hex': binascii.hexlify(passw_encrypted)} json.dump(data, open(passw_file, 'wb')) # Let's load password data = json.load(open(passw_file, 'r')) sys.stderr.write('Please confirm action on your device.\n') passw = client.decrypt_keyvalue(data['bip32_path'], data['label'], binascii.unhexlify(data['password_encrypted_hex']), False, True) print(passw)
def __init__(self, path, password=''): super(KeepkeyClient, self).__init__(path, password) devices = HidTransport.enumerate() transport = HidTransport((path.encode(), None)) self.client = KeepKey(transport) # if it wasn't able to find a client, throw an error if not self.client: raise IOError("no Device") self.password = password os.environ['PASSPHRASE'] = password
def main(): # List all connected KeepKeys on USB devices = HidTransport.enumerate() # Check whether we found any if len(devices) == 0: print('No KeepKey found') return # Use first connected device transport = HidTransport(devices[0]) # Creates object for manipulating KeepKey client = KeepKeyClient(transport) # Print out KeepKey's features and settings print(client.features) # Get the first address of first BIP44 account # (should be the same address as shown in KeepKey wallet Chrome extension) bip32_path = client.expand_path("44'/0'/0'/0/0") address = client.get_address('morningstar', bip32_path) print('morningstar address:', address) client.close()
def __init__(self, device, path): super(KeepKeyClient, self).__init__(device) device.close() devices = HidTransport.enumerate() self.client = None for d in devices: if d[0] == path: transport = HidTransport(d) self.client = KeepKey(transport) break # if it wasn't able to find a client, throw an error if not self.client: raise IOError("no Device")
def choose_device(devices): if not len(devices): raise Exception("No KeepKey connected!") if len(devices) == 1: try: return HidTransport(devices[0]) except IOError: raise Exception("Device is currently in use") i = 0 sys.stderr.write("----------------------------\n") sys.stderr.write("Available devices:\n") for d in devices: try: t = HidTransport(d) except IOError: sys.stderr.write("[-] <device is currently in use>\n") continue client = KeepKeyClient(t) if client.features.label: sys.stderr.write("[%d] %s\n" % (i, client.features.label)) else: sys.stderr.write("[%d] <no label>\n" % i) t.close() i += 1 sys.stderr.write("----------------------------\n") sys.stderr.write("Please choose device to use: ") try: device_id = int(input()) return HidTransport(devices[device_id]) except: raise Exception("Invalid choice, exiting...")
time.sleep(0.5) if enumerateCount == 3: break enumerateCount += 1 continue if enumerateStatus is False: print("Enumerate hard failed, power cycling") continue print("Fetching path...") for d in HidTransport.enumerate(): if path in d: transport = HidTransport(d) break print("Transport locked, continuing...") phy.set_capture_size(256) client = KeepKeyClient(transport) print("KeepKeyClient OK, arming glitcher...") phy.arm() print("Arm OK") try: signal.alarm(10) client.reset_device(True, 256, False, False, "", 'english', safety=False) data = "No exception" signal.alarm(0) except keepkeylib.client.CallException as e:
class KeepkeyClient(HardwareWalletClient): def __init__(self, path, password=''): super(KeepkeyClient, self).__init__(path, password) devices = HidTransport.enumerate() transport = HidTransport((path.encode(), None)) self.client = KeepKey(transport) # if it wasn't able to find a client, throw an error if not self.client: raise IOError("no Device") self.password = password os.environ['PASSPHRASE'] = password # Must return a dict with the xpub # Retrieves the public key at the specified BIP 32 derivation path def get_pubkey_at_path(self, path): path = path.replace('h', '\'') path = path.replace('H', '\'') expanded_path = self.client.expand_path(path) output = self.client.get_public_node(expanded_path) if self.is_testnet: return {'xpub': xpub_main_2_test(output.xpub)} else: return {'xpub': output.xpub} # Must return a hex string with the signed transaction # The tx must be in the combined unsigned transaction format def sign_tx(self, tx): # Get this devices master key fingerprint master_key = self.client.get_public_node([0]) master_fp = get_xpub_fingerprint(master_key.xpub) # Prepare inputs inputs = [] for psbt_in, txin in zip(tx.inputs, tx.tx.vin): txinputtype = proto.TxInputType() # Set the input stuff txinputtype.prev_hash = ser_uint256(txin.prevout.hash)[::-1] txinputtype.prev_index = txin.prevout.n txinputtype.sequence = txin.nSequence # Detrermine spend type if psbt_in.non_witness_utxo: txinputtype.script_type = 0 elif psbt_in.witness_utxo: # Check if the output is p2sh if psbt_in.witness_utxo.is_p2sh(): txinputtype.script_type = 3 else: txinputtype.script_type = 4 # Check for 1 key if len(psbt_in.hd_keypaths) == 1: # Is this key ours pubkey = list(psbt_in.hd_keypaths.keys())[0] fp = psbt_in.hd_keypaths[pubkey][0] keypath = psbt_in.hd_keypaths[pubkey][1:] if fp == master_fp: # Set the keypath txinputtype.address_n.extend(keypath) # Check for multisig (more than 1 key) elif len(psbt_in.hd_keypaths) > 1: raise TypeError("Cannot sign multisig yet") else: raise TypeError("All inputs must have a key for this device") # Set the amount if psbt_in.non_witness_utxo: txinputtype.amount = psbt_in.non_witness_utxo.vout[ txin.prevout.n].nValue elif psbt_in.witness_utxo: txinputtype.amount = psbt_in.witness_utxo.nValue # append to inputs inputs.append(txinputtype) # address version byte if self.is_testnet: p2pkh_version = b'\x6f' p2sh_version = b'\xc4' else: p2pkh_version = b'\x00' p2sh_version = b'\x05' # prepare outputs outputs = [] for out in tx.tx.vout: txoutput = proto.TxOutputType() txoutput.amount = out.nValue if out.is_p2pkh(): txoutput.address = to_address(out.scriptPubKey[3:23], p2pkh_version) txoutput.script_type = 0 elif out.is_p2sh(): txoutput.address = to_address(out.scriptPubKey[2:22], p2sh_version) txoutput.script_type = 1 else: # TODO: Figure out what to do here. for now, just break break # append to outputs outputs.append(txoutput) logging.debug(txoutput) # Sign the transaction self.client.set_tx_api(TxAPIPSBT(tx)) if self.is_testnet: signed_tx = self.client.sign_tx("Testnet", inputs, outputs, tx.tx.nVersion, tx.tx.nLockTime) else: signed_tx = self.client.sign_tx("Bitcoin", inputs, outputs, tx.tx.nVersion, tx.tx.nLockTime) signatures = signed_tx[0] logging.debug(binascii.hexlify(signed_tx[1])) for psbt_in in tx.inputs: for pubkey, sig in zip(psbt_in.hd_keypaths.keys(), signatures): fp = psbt_in.hd_keypaths[pubkey][0] keypath = psbt_in.hd_keypaths[pubkey][1:] if fp == master_fp: psbt_in.partial_sigs[pubkey] = sig + b'\x01' return {'psbt': tx.serialize()} # Must return a base64 encoded string with the signed message # The message can be any string def sign_message(self, message, keypath): raise NotImplementedError( 'The KeepKey does not currently implement signmessage') # Display address of specified type on the device. Only supports single-key based addresses. def display_address(self, keypath, p2sh_p2wpkh, bech32): raise NotImplementedError( 'The KeepKey does not currently implement displayaddress') # Setup a new device def setup_device(self, label='', passphrase=''): if self.client.features.initialized: raise DeviceAlreadyInitError( 'Device is already initialized. Use wipe first and try again') self.client.reset_device(False, 256, bool(self.password), True, label, 'english') return {'success': True} # Wipe this device def wipe_device(self): self.client.wipe_device() return {'success': True} # Restore device from mnemonic or xprv def restore_device(self, label=''): self.client.recovery_device(False, 24, bool(self.password), True, label, 'english') return {'success': True} # Begin backup process def backup_device(self, label='', passphrase=''): raise UnavailableActionError( 'The Keepkey does not support creating a backup via software') # Close the device def close(self): self.client.close()
time.sleep(0.5) if enumerateCount == 3: break enumerateCount += 1 continue if enumerateStatus is False: print("Enumerate hard failed, power cycling") continue print("Fetching path...") for d in HidTransport.enumerate(): if path in d: transport = HidTransport(d) break print("Transport locked, continuing...") phy.set_capture_size(1025) client = KeepKeyClient(transport) print("KeepKeyClient OK, arming glitcher...") scope.arm() phy.arm() print("Arm OK") if oneshot: input("Hit enter to fire glitch event...") try: signal.alarm(10) data = client.ping("HelloHelloHelloHelloHello") print(data) if data != "HelloHelloHelloHelloHello": sys.exit(0) data = base64.b64encode(data.encode("utf-8")) except: data = ""
from keepkeylib.transport_hid import HidTransport import keepkeylib.types_pb2 as proto_types from keepkeylib import tx_api from keepkeylib.tx_api import TXAPIDashTestnet tx_api.rpcuser = '******' tx_api.rpcpassword = '******' devices = HidTransport.enumerate() if len(devices) == 0: print('No KeepKey found') sys.exit() transport = HidTransport(devices[0]) client = KeepKeyClient(transport) client.set_tx_api(TXAPIDashTestnet()) inp1 = proto_types.TxInputType( address_n=[44 | 0x80000000, 165 | 0x80000000, 0 | 0x80000000, 0, 0], # yjJUQ42u8Z86s9LiUmNgvS9dSzhunWbuQR # amount=500000000 prev_hash=binascii.unhexlify( '4a1f3f89d95dd162e30399386dd7748c7fa02ec958320f4542923cf3a63fde48'), prev_index=1, ) out1 = proto_types.TxOutputType( address='yV7G6wcfkqfjw3SyykJzYnsL3fqJByqXYG', amount=500000000 - 10000, script_type=proto_types.PAYTOADDRESS,
def check_hw_wallet(): printdbg('checking hw wallet') #client = None client = None signing = False if TYPE_HW_WALLET.lower().startswith("keepkey"): from keepkeylib.client import KeepKeyClient from keepkeylib.transport_hid import HidTransport import keepkeylib.ckd_public as bip32 try: devices = HidTransport.enumerate() except Exception as e: err_msg = str(e.args) print_err_exit(get_caller_name(), get_function_name(), err_msg) if len(devices) == 0: print('===> No HW Wallet found') signing = False else: try: print('===> keepkey HW Wallet found') transport = HidTransport(devices[0]) client = KeepKeyClient(transport) signing = True except Exception as e: err_msg = str(e.args) print_err_exit(get_caller_name(), get_function_name(), err_msg) elif TYPE_HW_WALLET.lower().startswith("trezor"): from trezorlib.client import TrezorClient from trezorlib.transport_hid import HidTransport import trezorlib.ckd_public as bip32 try: devices = HidTransport.enumerate() except Exception as e: err_msg = str(e.args) print_err_exit(get_caller_name(), get_function_name(), err_msg) if len(devices) == 0: print('===> No HW Wallet found') signing = False else: try: print('===> trezor HW Wallet found') transport = HidTransport(devices[0]) client = TrezorClient(transport) signing = True except Exception as e: err_msg = str(e.args) print_err_exit(get_caller_name(), get_function_name(), err_msg) elif TYPE_HW_WALLET.lower().startswith("ledgernanos"): #from btchip.btchip import * #from btchip.btchipUtils import * try: devices = getDongle(False) except Exception as e: err_msg = str(e.args) print_err_exit(get_caller_name(), get_function_name(), err_msg) if not devices: print('===> No HW Wallet found') signing = False else: try: print('===> Ledger nano s HW Wallet found') client = btchip(devices) signing = True except Exception as e: err_msg = str(e.args) print_err_exit(get_caller_name(), get_function_name(), err_msg) if client is not None: if TYPE_HW_WALLET.lower().startswith("ledgernanos"): pass else: try: wallet_supported_coins = list_coins(client) except Exception as e: err_msg = str(e.args) print_err_exit(get_caller_name(), get_function_name(), err_msg) if coin_name not in wallet_supported_coins: err_msg = 'only following coins supported by wallet\n\t' + \ str(wallet_supported_coins) print_err_exit(get_caller_name(), get_function_name(), err_msg) else: err_msg = "Can't run florijncoinmnb without hw wallet" print_err_exit(get_caller_name(), get_function_name(), err_msg) if TYPE_HW_WALLET.lower().startswith("ledgernanos"): mpath = get_mpath() return client, signing, mpath else: try: mpath = get_mpath() bip32_path = client.expand_path(mpath) xpub = bip32.serialize( client.get_public_node(bip32_path).node, (0x0488B21E if MAINNET else 0x043587CF)) except AssertionError as e: err_msg = str(e.args) print_err_exit(get_caller_name(), get_function_name(), err_msg) except Exception as e: err_msg = str(e.args) print_err_exit(get_caller_name(), get_function_name(), err_msg) except KeyboardInterrupt: print_err_exit(get_caller_name(), get_function_name(), "KeyboardInterrupt") printdbg('check_hw_wallet : signing : %s' % signing) printdbg('check_hw_wallet : xpub[:7] : %s' % xpub[:7]) printdbg('check_hw_wallet : xpub[-7:] : %s' % xpub[-7:]) printdbg('check_hw_wallet : mpath : %s' % mpath) return client, signing, bip32, mpath, xpub
class KeepKeyTest(unittest.TestCase): def setUp(self): transport = config.TRANSPORT(*config.TRANSPORT_ARGS, **config.TRANSPORT_KWARGS) if hasattr(config, 'DEBUG_TRANSPORT'): debug_transport = config.DEBUG_TRANSPORT( *config.DEBUG_TRANSPORT_ARGS, **config.DEBUG_TRANSPORT_KWARGS) self.client = KeepKeyDebugClient(transport) self.client.set_debuglink(debug_transport) else: self.client = KeepKeyClient(transport) self.client.set_tx_api(tx_api.TxApiBitcoin) # self.client.set_buttonwait(3) # 1 2 3 4 5 6 7 8 9 10 11 12 self.mnemonic12 = 'alcohol woman abuse must during monitor noble actual mixed trade anger aisle' self.mnemonic18 = 'owner little vague addict embark decide pink prosper true fork panda embody mixture exchange choose canoe electric jewel' self.mnemonic24 = 'dignity pass list indicate nasty swamp pool script soccer toe leaf photo multiply desk host tomato cradle drill spread actor shine dismiss champion exotic' self.mnemonic_all = ' '.join(['all'] * 12) self.mnemonic_abandon = ' '.join(['abandon'] * 11) + ' about' self.pin4 = '1234' self.pin6 = '789456' self.pin8 = '45678978' self.client.wipe_device() print("Setup finished") print("--------------") def setup_mnemonic_allallall(self): self.client.load_device_by_mnemonic(mnemonic=self.mnemonic_all, pin='', passphrase_protection=False, label='test', language='english') def setup_mnemonic_abandon(self): self.client.load_device_by_mnemonic(mnemonic=self.mnemonic_abandon, pin='', passphrase_protection=False, label='test', language='english') def setup_mnemonic_nopin_nopassphrase(self): self.client.load_device_by_mnemonic(mnemonic=self.mnemonic12, pin='', passphrase_protection=False, label='test', language='english') def setup_mnemonic_pin_nopassphrase(self): self.client.load_device_by_mnemonic(mnemonic=self.mnemonic12, pin=self.pin4, passphrase_protection=False, label='test', language='english') def setup_mnemonic_pin_passphrase(self): self.client.load_device_by_mnemonic(mnemonic=self.mnemonic12, pin=self.pin4, passphrase_protection=True, label='test', language='english') def tearDown(self): self.client.close() def assertEndsWith(self, s, suffix): self.assertTrue(s.endswith(suffix), "'{}'.endswith('{}')".format(s, suffix))
class KeepKeyTest(unittest.TestCase): def setUp(self): transport = config.TRANSPORT(*config.TRANSPORT_ARGS, **config.TRANSPORT_KWARGS) if hasattr(config, 'DEBUG_TRANSPORT'): debug_transport = config.DEBUG_TRANSPORT( *config.DEBUG_TRANSPORT_ARGS, **config.DEBUG_TRANSPORT_KWARGS) if VERBOSE: self.client = KeepKeyDebuglinkClientVerbose(transport) else: self.client = KeepKeyDebuglinkClient(transport) self.client.set_debuglink(debug_transport) else: self.client = KeepKeyClient(transport) self.client.set_tx_api(tx_api.TxApiBitcoin) # self.client.set_buttonwait(3) # 1 2 3 4 5 6 7 8 9 10 11 12 self.mnemonic12 = 'alcohol woman abuse must during monitor noble actual mixed trade anger aisle' self.mnemonic18 = 'owner little vague addict embark decide pink prosper true fork panda embody mixture exchange choose canoe electric jewel' self.mnemonic24 = 'dignity pass list indicate nasty swamp pool script soccer toe leaf photo multiply desk host tomato cradle drill spread actor shine dismiss champion exotic' self.mnemonic20007 = 'fix spot clown mobile oven eagle pond arrest opera buyer muffin myself' self.mnemonic_all = ' '.join(['all'] * 12) self.mnemonic_abandon = ' '.join(['abandon'] * 11) + ' about' self.pin4 = '1234' self.pin6 = '789456' self.pin8 = '45678978' self.client.wipe_device() if VERBOSE: print("Setup finished") print("--------------") def setup_mnemonic_allallall(self): self.client.load_device_by_mnemonic(mnemonic=self.mnemonic_all, pin='', passphrase_protection=False, label='test', language='english') def setup_mnemonic_abandon(self): self.client.load_device_by_mnemonic(mnemonic=self.mnemonic_abandon, pin='', passphrase_protection=False, label='test', language='english') def setup_mnemonic_nopin_nopassphrase(self): self.client.load_device_by_mnemonic(mnemonic=self.mnemonic12, pin='', passphrase_protection=False, label='test', language='english') def setup_mnemonic_vuln20007(self): self.client.load_device_by_mnemonic(mnemonic=self.mnemonic20007, pin='', passphrase_protection=False, label='test', language='english') def setup_mnemonic_pin_nopassphrase(self): self.client.load_device_by_mnemonic(mnemonic=self.mnemonic12, pin=self.pin4, passphrase_protection=False, label='test', language='english') def setup_mnemonic_pin_passphrase(self): self.client.load_device_by_mnemonic(mnemonic=self.mnemonic12, pin=self.pin4, passphrase_protection=True, label='test', language='english') def tearDown(self): self.client.close() def assertEqual(self, lhs, rhs): if type(lhs) == type(b'') and type(rhs) == type(''): super(KeepKeyTest, self).assertEqual(lhs, rhs.encode('utf-8')) else: super(KeepKeyTest, self).assertEqual(lhs, rhs) def assertEndsWith(self, s, suffix): self.assertTrue(s.endswith(suffix), "'{}'.endswith('{}')".format(s, suffix)) def requires_firmware(self, ver_required): self.client.init_device() features = self.client.features version = "%s.%s.%s" % (features.major_version, features.minor_version, features.patch_version) if semver.compare(version, ver_required) < 0: self.skipTest("Firmware version " + ver_required + " or higher is required to run this test")