def _get_subnode(cls, node, i): # Child key derivation (CKD) algorithm of BIP32 i_as_bytes = struct.pack(">L", i) if cls.is_prime(i): # Prime derivation data = '\0' + node.private_key + i_as_bytes I64 = hmac.HMAC(key=node.chain_code, msg=data, digestmod=hashlib.sha512).digest() else: # 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]) secexp = (I_left_as_exponent + string_to_number(node.private_key)) % SECP256k1.order if I_left_as_exponent >= SECP256k1.order: raise Exception("Il cannot be bigger than order") if secexp == 0: raise Exception("secexp cannot be zero") node_out = types.HDNodeType() node_out.depth = node.depth + 1 node_out.child_num = i node_out.chain_code = I64[32:] node_out.private_key = number_to_string(secexp, SECP256k1.order) node_out.public_key = cls._get_pubkey(node_out.private_key) node_out.fingerprint = bip32_fingerprint(node.public_key) return node_out
def get_subnode(node, i): # Public Child key derivation (CKD) algorithm of BIP32 i_as_bytes = struct.pack(">L", i) if BIP32.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 = types.HDNodeType() node_out.depth = node.depth + 1 node_out.child_num = i node_out.chain_code = I64[32:] node_out.fingerprint = bip32_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