def create_master_xprivate_key(seed, testnet=False, base58=True, hex=False): """ Create extended private key from seed :param str,bytes key: seed HEX or bytes string. :param boolean base58: (optional) return result as base58 encoded string, by default True. :param boolean hex: (optional) return result as HEX encoded string, by default False. In case True base58 flag value will be ignored. :return: extended private key in base58, HEX or bytes string format. """ if isinstance(seed, str): seed = bytes.fromhex(seed) if not isinstance(seed, bytes): raise TypeError("seed should be bytes or hex encoded string") i = hmac_sha512(b"Bitcoin seed", seed) m, c = i[:32], i[32:] m_int = int.from_bytes(m, byteorder="big") if m_int <= 0 or m_int > ECDSA_SEC256K1_ORDER: return None prefix = TESTNET_XPRIVATE_KEY_PREFIX if testnet else MAINNET_XPRIVATE_KEY_PREFIX key = b''.join( [prefix, b'\x00\x00\x00\x00\x00\x00\x00\x00\x00', c, b'\x00', m]) if base58: key = b"".join([key, double_sha256(key)[:4]]) return encode_base58(key) else: return key
def derive_child_xpublic_key(xpublic_key, i): c = xpublic_key[13:45] k = xpublic_key[45:] fingerprint = hash160(k)[:4] depth = xpublic_key[4] + 1 if depth > 255: raise ValueError("path depth should be <= 255") if i >= HARDENED_KEY: raise ValueError("derivation from extended public key impossible") s = hmac_sha512(c, k + pack(">L", i)) if int.from_bytes(s[:32], byteorder='big') >= ECDSA_SEC256K1_ORDER: return None pubkey_ptr = ffi.new('secp256k1_pubkey *') if not lib.secp256k1_ec_pubkey_parse(ECDSA_CONTEXT_VERIFY, pubkey_ptr, k, len(k)): raise RuntimeError("secp256k1 parse public key operation failed") if not lib.secp256k1_ec_pubkey_tweak_add(ECDSA_CONTEXT_ALL, pubkey_ptr, s[:32]): raise RuntimeError("secp256k1 parse tweak addition operation failed") pubkey = ffi.new('char [%d]' % 33) outlen = ffi.new('size_t *', 33) if not lib.secp256k1_ec_pubkey_serialize( ECDSA_CONTEXT_VERIFY, pubkey, outlen, pubkey_ptr, EC_COMPRESSED): raise RuntimeError("secp256k1 serialize public key operation failed") pk = bytes(ffi.buffer(pubkey, 33)) print(len(pk)) return b"".join([ xpublic_key[:4], bytes([depth]), fingerprint, pack(">L", i), s[32:], pk ])
def create_master_xprivate_key(seed, testnet=False, base58=None, hex=None): """ Create extended private key from seed :param str,bytes key: seed HEX or bytes string. :param boolean base58: (optional) return result as base58 encoded string, by default True. :param boolean hex: (optional) return result as HEX encoded string, by default False. In case True base58 flag value will be ignored. :return: extended private key in base58, HEX or bytes string format. """ seed = get_bytes(seed) i = hmac_sha512(b"Bitcoin seed", seed) m, c = i[:32], i[32:] m_int = int.from_bytes(m, byteorder="big") if m_int <= 0 or m_int > ECDSA_SEC256K1_ORDER: # pragma: no cover return None prefix = TESTNET_XPRIVATE_KEY_PREFIX if testnet else MAINNET_XPRIVATE_KEY_PREFIX key = b''.join( [prefix, b'\x00\x00\x00\x00\x00\x00\x00\x00\x00', c, b'\x00', m]) if base58 is None and hex is None: base58 = True if base58: key = b"".join([key, double_sha256(key)[:4]]) return encode_base58(key) else: if hex is None: hex = False return key if not hex else key.hex()
def derive_child_xpublic_key(xpublic_key, i): c = xpublic_key[13:45] k = xpublic_key[45:] fingerprint = hash160(k)[:4] depth = xpublic_key[4] + 1 if depth > 255: raise ValueError("path depth should be <= 255") if i >= HARDENED_KEY: raise ValueError("derivation from extended public key impossible") s = hmac_sha512(c, k + pack(">L", i)) if int.from_bytes(s[:32], byteorder='big') >= ECDSA_SEC256K1_ORDER: return None pk = __secp256k1_ec_pubkey_tweak_add__(k, s[:32]) if isinstance(pk, int): raise RuntimeError("pubkey_tweak_add error %s" % pk) return b"".join([ xpublic_key[:4], bytes([depth]), fingerprint, pack(">L", i), s[32:], pk ])
def derive_child_xprivate_key(xprivate_key, i): c = xprivate_key[13:45] k = xprivate_key[45:] depth = xprivate_key[4] + 1 if depth > 255: raise ValueError("path depth should be <= 255") pub = private_to_public_key(k[1:], hex=False) fingerprint = hash160(pub)[:4] s = hmac_sha512(c, b"%s%s" % (k if i >= HARDENED_KEY else pub, pack(">L", i))) p_int = int.from_bytes(s[:32], byteorder='big') if p_int >= ECDSA_SEC256K1_ORDER: return None k_int = (int.from_bytes(k[1:], byteorder='big') + p_int) % ECDSA_SEC256K1_ORDER if not k_int: return None key = int.to_bytes(k_int, byteorder="big", length=32) return b"".join([ xprivate_key[:4], bytes([depth]), fingerprint, pack(">L", i), s[32:], b'\x00', key ])