48 lines
1.3 KiB
Python
48 lines
1.3 KiB
Python
import struct
|
|
import hmac
|
|
import hashlib
|
|
from ecdsa.util import string_to_number
|
|
from ecdsa.curves import SECP256k1
|
|
|
|
import messages_pb2 as proto
|
|
|
|
PRIME_DERIVATION_FLAG = 0x80000000
|
|
|
|
def is_prime(n):
|
|
return (bool)(n & PRIME_DERIVATION_FLAG)
|
|
|
|
def hash_160(public_key):
|
|
md = hashlib.new('ripemd160')
|
|
md.update(hashlib.sha256(public_key).digest())
|
|
return md.digest()
|
|
|
|
def fingerprint(pubkey):
|
|
return string_to_number(hash_160(pubkey)[:4])
|
|
|
|
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.HDNodeType()
|
|
node_out.version = node.version
|
|
node_out.depth = node.depth + 1
|
|
node_out.child_num = i
|
|
node_out.chain_code = I64[32:]
|
|
node_out.fingerprint = fingerprint(node.public_key)
|
|
|
|
# FIXME
|
|
# node_out.public_key = cls._get_pubkey(node_out.private_key)
|
|
# x, y = self.public_pair
|
|
# the_point = I_left_as_exponent * ecdsa.generator_secp256k1 + ecdsa.Point(ecdsa.generator_secp256k1.curve(), x, y, SECP256k1.generator.order())
|
|
|
|
return node_out
|