def test_verify_signature(): p = "eb696a065ef48a2192da5b28b694f87544b30fae8327c4510137a922f32c6dcf" p2 = "eb296a065ef48a2192da5b28b694f87544b30fae8327c4510137a922f32c6dcf" s = "3044022047ac8e878352d3ebbde1c94ce3a10d057c24175747116f8288e5d794" \ "d12d482f0220217f36a485cae903c713331d877c1f64677e3622ad4010726870540656fe9dcb" msg = "64f3b0f4dd2bb3aa1ce8566d220cc74dda9df97d8490cc81d89d735c92e59fb6" assert verify_signature(s, private_to_public_key(p), msg) assert verify_signature(s, private_to_public_key(p2), msg) == False
def test_public_key_recovery(): s = "3044022047ac8e878352d3ebbde1c94ce3a10d057c24175747116f8288e5d794" \ "d12d482f0220217f36a485cae903c713331d877c1f64677e3622ad4010726870540656fe9dcb" p = "eb696a065ef48a2192da5b28b694f87544b30fae8327c4510137a922f32c6dcf" msg = "64f3b0f4dd2bb3aa1ce8566d220cc74dda9df97d8490cc81d89d735c92e59fb6" assert public_key_recovery(s, msg, 0) == private_to_public_key(p, hex=True) assert public_key_recovery(s, msg, 1) != private_to_public_key(p, hex=True) assert public_key_recovery(s, msg, 2) != private_to_public_key(p, hex=True) assert public_key_recovery(s, msg, 3) is None s = "1044022047ac8e878252d3ebbde1c94ce3a10d057c24175747116f8288e5d794" \ "d12d482f0220217f36a485cae903c713331d877c1f64677e3622ad4010726870540656fe9dcb" with pytest.raises(RuntimeError): assert public_key_recovery(s, msg, 3) is None
def __init__(self, key, compressed=True, testnet=False): if isinstance(key, str): try: key = bytes_from_hex(key) except: if is_wif_valid(key): key = PrivateKey(key) if isinstance(key, bytes): if len(key) == 32: key = PrivateKey(key, compressed=compressed, testnet=testnet) elif is_public_key_valid(key): public_key = key self.testnet = testnet self.compressed = True if len(key) == 33 else False else: raise TypeError("key invalid") if isinstance(key, PrivateKey): #: flag for testnet network private key (boolean) self.testnet = key.testnet #: flag for compressed type of corresponding public key (boolean) self.compressed = key.compressed public_key = private_to_public_key(key.key, compressed=key.compressed, hex=False) #: public key in bytes (bytes) self.key = public_key #: public key in HEX (string) self.hex = self.key.hex()
def test_public_key_to_address(): pc = "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" assert public_key_to_address( pc) == "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4" assert public_key_to_address( pc) == "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4" assert public_key_to_address( pc, testnet=True) == "tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx" pc = "03b635dbdc16dbdf4bb9cf5b55e7d03e514fb04dcef34208155c7d3ec88e9045f4" assert public_key_to_address( pc, witness_version=None, testnet=False) == "1Fs2Xqrk4P2XADaJeZWykaGXJ4HEb6RyT1" assert public_key_to_address( pc, witness_version=None, testnet=True) == "mvNyptwisQTmwL3vN8VMaVUrA3swVCX83c" p = "L32a8Mo1LgvjrVDbzcc3NkuUfkpoLsf2Y2oEWkV4t1KpQdFzuyff" pk = private_to_public_key(p) assert public_key_to_address( pk, witness_version=None, p2sh_p2wpkh=True) == "33am12q3Bncnn3BfvLYHczyv23Sq2Wbwjw" with pytest.raises(ValueError): public_key_to_address(pc + "33", p2sh_p2wpkh=True) with pytest.raises(ValueError): public_key_to_address(pc + "33", witness_version=0)
def multisig(cls, n, m, public_key_list, testnet=False, witness_version=0): """ The class method for creating a multisig address. :param n: count of required signatures (max 15). :param m: count of total addresses of participants (max 15). :param list address_list: addresses list, allowed types: - bytes or HEX encoded private key - private key in WIF format - PrivateKey instance, - bytes or HEX encoded public key - PublicKey instance """ if n > 15 or m > 15 or n > m or n < 1 or m < 1: raise TypeError("invalid n of m maximum 15 of 15 multisig allowed") if len(public_key_list) != m: raise TypeError("invalid address list count") script = bytes([0x50 + n]) for a in list(public_key_list): if isinstance(a, str): try: a = bytes.fromhex(a) except: if is_wif_valid(a): a = private_to_public_key(a, hex=False) pass if isinstance(a, Address): a = a.public_key.key elif isinstance(a, PublicKey): a = a.key elif isinstance(a, PrivateKey): a = private_to_public_key(a.key) if not isinstance(a, bytes): raise TypeError("invalid public key list element") if len(a) == 32: a = private_to_public_key(a) if len(a) != 33: raise TypeError("invalid public key list element size") script += b"%s%s" % (int_to_var_int(len(a)), a) script += b"%s%s" % (bytes([0x50 + m]), OP_CHECKMULTISIG) return cls(script, testnet=testnet, witness_version=witness_version)
def private_to_public_key(private_key, compressed=True, hex=True): """ Get public key from private key using ECDSA secp256k1 :param private_key: private key in WIF, HEX or bytes. :param compressed: (optional) flag of public key compressed format, by default set to True. In case private_key in WIF format, this flag is set in accordance with the key format specified in WIF string. :param hex: (optional) if set to True return key in HEX format, by default is True. :return: 33/65 bytes public key in HEX or bytes string. """ return __parent__.private_to_public_key(private_key, compressed=compressed, hex=hex)
def xprivate_to_xpublic_key(xprivate_key, base58=True, hex=False): """ Get extended public key from extended private key using ECDSA secp256k1 :param str,bytes key: extended private key in base58, 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 public key in base58, HEX or bytes string format. """ if isinstance(xprivate_key, str): try: if len(xprivate_key) == 156: xprivate_key = bytes.fromhex(xprivate_key) else: xprivate_key = decode_base58(xprivate_key, checksum=True) except: raise ValueError("invalid extended private key") if not isinstance(xprivate_key, bytes): raise TypeError( "extended private key should be base58 string or bytes") if xprivate_key[:4] == TESTNET_XPRIVATE_KEY_PREFIX: prefix = TESTNET_XPUBLIC_KEY_PREFIX elif xprivate_key[:4] == MAINNET_XPRIVATE_KEY_PREFIX: prefix = MAINNET_XPUBLIC_KEY_PREFIX elif xprivate_key[:4] == MAINNET_M49_XPRIVATE_KEY_PREFIX: prefix = MAINNET_M49_XPUBLIC_KEY_PREFIX elif xprivate_key[:4] == TESTNET_M49_XPRIVATE_KEY_PREFIX: prefix = TESTNET_M49_XPUBLIC_KEY_PREFIX elif xprivate_key[:4] == MAINNET_M84_XPRIVATE_KEY_PREFIX: prefix = MAINNET_M84_XPUBLIC_KEY_PREFIX elif xprivate_key[:4] == TESTNET_M84_XPRIVATE_KEY_PREFIX: prefix = TESTNET_M84_XPUBLIC_KEY_PREFIX else: raise ValueError("invalid extended private key") key = b"".join([ prefix, xprivate_key[4:45], private_to_public_key(xprivate_key[46:], hex=False) ]) if hex: return key.hex() elif base58: key = b"".join([key, double_sha256(key)[:4]]) return encode_base58(key) else: return key
def test_hash_to_address(): pc = "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" h = hash160(pc) s = bytes([len(bytes_from_hex(pc)) ]) + bytes_from_hex(pc) + BYTE_OPCODE["OP_CHECKSIG"] assert hash_to_address(h) == "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4" assert hash_to_address( h, testnet=True) == "tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx" h = script_to_hash(s, witness=True, hex=hex) assert hash_to_address( h) == "bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3" assert hash_to_address( h, testnet=True ) == "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7" pk = "03b635dbdc16dbdf4bb9cf5b55e7d03e514fb04dcef34208155c7d3ec88e9045f4" h = hash160(pk) assert hash_to_address( h, witness_version=None) == "1Fs2Xqrk4P2XADaJeZWykaGXJ4HEb6RyT1" assert hash_to_address( h, witness_version=None, testnet=True) == "mvNyptwisQTmwL3vN8VMaVUrA3swVCX83c" # p2wpkh inside p2sh p = "L32a8Mo1LgvjrVDbzcc3NkuUfkpoLsf2Y2oEWkV4t1KpQdFzuyff" pk = private_to_public_key(p) script = b'\x00\x14' + hash160(pk) script_hash = hash160(script) assert hash_to_address( script_hash, script_hash=1, witness_version=None) == "33am12q3Bncnn3BfvLYHczyv23Sq2Wbwjw" assert hash_to_address(script_hash, script_hash=1, witness_version=None, testnet=1) == "2Mu8y4mm4oF88yppDbUAAEwyBEPezrx7CLh" with pytest.raises(ValueError): hash_to_address(29023) with pytest.raises(ValueError): hash_to_address(h + b"33", witness_version=None) with pytest.raises(ValueError): hash_to_address(h + b"33", witness_version=0)
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 ])
def test_private_to_public_key(): priv = "ceda1ae4286015d45ec5147fe3f63e9377ccd6d4e98bcf0847df9937da1944a4" pu = "04b635dbdc16dbdf4bb9cf5b55e7d03e514fb04dcef34208155c7d3ec88e9045f4" \ "c8cbe28702911260f2a1da099a338bed4ee98f66bb8dba8031a76ab537ff6663" pk = "03b635dbdc16dbdf4bb9cf5b55e7d03e514fb04dcef34208155c7d3ec88e9045f4" assert private_to_public_key(priv) == pk assert private_to_public_key(bytes_from_hex(priv)) == pk assert private_to_public_key(bytearray(bytes_from_hex(priv))) == pk assert private_to_public_key(priv) == pk assert private_to_public_key(priv, hex=True) == pk assert private_to_public_key(priv, hex=False).hex() == pk assert private_to_public_key(priv, compressed=False) == pu assert private_to_public_key( "L49obCXV7fGz2YRzLCSJgeZBYmGeBbKPT7xiehUeYX2S4URkPFZX", pk) assert private_to_public_key( "5KPPLXhtga99qqMceRo4Z6LXV3Kx6a9hRx3ez2U7EwP5KZfy2Wf", pu) assert private_to_public_key( "93A1vGXSGoDHotruGmgyRgtV8hgfFjgtmtuc4epcag886W9d44L", pu) with pytest.raises(ValueError): assert private_to_public_key( "ceda1ae4286015d45ec5147fe3f63e9377ccd6d4e98bcf0847df9937da1944a411", pu) with pytest.raises(ValueError): private_to_public_key(3738) with pytest.raises(Exception): private_to_public_key( "L49obCXV7fGz2YRzLCSJgeZBYmGeBbKPT7xiehUeYX2S4URkPFZQ")