def get_subnode(node, i): # Public Child key derivation (CKD) algorithm of BIP32 i_as_bytes = struct.pack(">L", i) if is_prime(i): raise Exception("Prime derivation not supported") # Public derivation data = node.public_key + i_as_bytes I64 = hmac.HMAC(key=node.chain_code, msg=data, digestmod=hashlib.sha512).digest() I_left_as_exponent = string_to_number(I64[:32]) node_out = proto_types.HDNodeType() node_out.depth = node.depth + 1 node_out.child_num = i node_out.chain_code = I64[32:] node_out.fingerprint = fingerprint(node.public_key) # BIP32 magic converts old public key to new public point x, y = sec_to_public_pair(node.public_key) point = I_left_as_exponent * SECP256k1.generator + \ Point(SECP256k1.curve, x, y, SECP256k1.order) if point == INFINITY: raise Exception("Point cannot be INFINITY") # Convert public point to compressed public key node_out.public_key = point_to_pubkey(point) return node_out
def public_ckd(public_node, n): if not isinstance(n, list): raise Exception('Parameter must be a list') node = proto_types.HDNodeType() node.CopyFrom(public_node) for i in n: node.CopyFrom(get_subnode(node, i)) return node
def load_device_by_xprv(self, xprv, pin, passphrase_protection, label, language): if self.features.initialized: raise Exception( "Device is initialized already. Call wipe_device() and try again." ) if xprv[0:4] not in ('xprv', 'tprv'): raise Exception("Unknown type of xprv") if len(xprv) < 100 and len(xprv) > 112: raise Exception("Invalid length of xprv") node = types.HDNodeType() data = tools.b58decode(xprv, None).encode('hex') if data[90:92] != '00': raise Exception("Contain invalid private key") checksum = hashlib.sha256( hashlib.sha256(binascii.unhexlify( data[:156])).digest()).hexdigest()[:8] if checksum != data[156:]: raise Exception("Checksum doesn't match") # version 0488ade4 # depth 00 # fingerprint 00000000 # child_num 00000000 # chaincode 873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508 # privkey 00e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35 # checksum e77e9d71 node.depth = int(data[8:10], 16) node.fingerprint = int(data[10:18], 16) node.child_num = int(data[18:26], 16) node.chain_code = data[26:90].decode('hex') node.private_key = data[92:156].decode( 'hex') # skip 0x00 indicating privkey resp = self.call( proto.LoadDevice(node=node, pin=pin, passphrase_protection=passphrase_protection, language=language, label=label)) self.init_device() return resp
def deserialize(xpub): data = tools.b58decode(xpub, None) if tools.Hash(data[:-4])[:4] != data[-4:]: raise Exception("Checksum failed") node = proto_types.HDNodeType() node.depth = struct.unpack('>B', data[4:5])[0] node.fingerprint = struct.unpack('>I', data[5:9])[0] node.child_num = struct.unpack('>I', data[9:13])[0] node.chain_code = data[13:45] key = data[45:-4] if key[0] == '\x00': node.private_key = key[1:] else: node.public_key = key return node