def test_wif_from_prv_key() -> None: prv_key = "0C28FCA386C7A227600B2FE50B7CAE11EC86D3BF1FBE471BE89827E19D72AA1D" test_vectors: List[Tuple[str, str, bool]] = [ ("KwdMAjGmerYanjeui5SHS7JkmpZvVipYvB2LJGU1ZxJwYvP98617", "mainnet", True), ("cMzLdeGd5vEqxB8B6VFQoRopQ3sLAAvEzDAoQgvX54xwofSWj1fx", "testnet", True), ("5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ", "mainnet", False), ("91gGn1HgSap6CbU12F6z3pJri26xzp7Ay1VW6NHCoEayNXwRpu2", "testnet", False), (" KwdMAjGmerYanjeui5SHS7JkmpZvVipYvB2LJGU1ZxJwYvP98617", "mainnet", True), ("KwdMAjGmerYanjeui5SHS7JkmpZvVipYvB2LJGU1ZxJwYvP98617 ", "mainnet", True), ] for v in test_vectors: assert v[0].strip() == b58.wif_from_prv_key(prv_key, v[1], v[2]) q, network, compressed = prv_keyinfo_from_prv_key(v[0]) assert q == int(prv_key, 16) assert network == v[1] assert compressed == v[2] bad_q = ec.n.to_bytes(ec.n_size, byteorder="big", signed=False) with pytest.raises(BTClibValueError, match="private key not in 1..n-1: "): b58.wif_from_prv_key(bad_q, "mainnet", True) payload = b"\x80" + bad_q badwif = b58encode(payload) with pytest.raises(BTClibValueError, match="not a private key: "): prv_keyinfo_from_prv_key(badwif) # not a private key: 33 bytes bad_q = 33 * b"\x02" with pytest.raises(BTClibValueError, match="not a private key: "): b58.wif_from_prv_key(bad_q, "mainnet", True) payload = b"\x80" + bad_q badwif = b58encode(payload) with pytest.raises(BTClibValueError, match="not a private key: "): prv_keyinfo_from_prv_key(badwif) # Not a WIF: missing leading 0x80 good_q = 32 * b"\x02" payload = b"\x81" + good_q badwif = b58encode(payload) with pytest.raises(BTClibValueError, match="not a private key: "): prv_keyinfo_from_prv_key(badwif) # Not a compressed WIF: missing trailing 0x01 payload = b"\x80" + good_q + b"\x00" badwif = b58encode(payload) with pytest.raises(BTClibValueError, match="not a private key: "): prv_keyinfo_from_prv_key(badwif) # Not a WIF: wrong size (35) payload = b"\x80" + good_q + b"\x01\x00" badwif = b58encode(payload) with pytest.raises(BTClibValueError, match="not a private key: "): prv_keyinfo_from_prv_key(badwif)
def test_derive_exceptions() -> None: # root key, zero depth rootmxprv = "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi" xprv = bip32.derive(rootmxprv, b"\x80\x00\x00\x00") xprv = bip32.derive(xprv, ".") # FIXME: this failure shoud be required # errmsg = "public derivation at depth one level" # with pytest.raises(UserWarning, match=errmsg): # bip32.deserialize(bip32.derive(rootmxprv, 0)) for der_path in ("", "/1"): with pytest.raises(ValueError, match="empty derivation path root: must be m or ."): bip32.derive(xprv, der_path) for der_path in (";/0", "invalid index", "800000"): with pytest.raises(ValueError, match="invalid derivation path root: "): bip32.derive(xprv, der_path) with pytest.raises(ValueError, match="derivation path depth greater than 255: "): bip32.derive(xprv, "." + 256 * "/0") errmsg = "absolute derivation path for non-root master key" with pytest.raises(ValueError, match=errmsg): bip32.derive(xprv, "m / 44 h/0h/1h/0/10") with pytest.raises(ValueError, match="index must be 4-bytes, not "): bip32.derive(xprv, b"\x00" * 5) errmsg = "int too big to convert" for index in (256**4, 0x8000000000): with pytest.raises(OverflowError, match=errmsg): bip32.derive(xprv, index) errmsg = "derivation path final depth greater than 255: " with pytest.raises(ValueError, match=errmsg): bip32.derive(xprv, "." + 255 * "/0") rootxprv = "xprv9s21ZrQH143K2ZP8tyNiUtgoezZosUkw9hhir2JFzDhcUWKz8qFYk3cxdgSFoCMzt8E2Ubi1nXw71TLhwgCfzqFHfM5Snv4zboSebePRmLS" temp = b58decode(rootxprv) bad_xprv = b58encode(temp[0:45] + b"\x02" + temp[46:], 78) errmsg = "invalid private key prefix: " with pytest.raises(ValueError, match=errmsg): bip32.derive(bad_xprv, 0x80000000) xpub = bip32.xpub_from_xprv(rootxprv) temp = b58decode(xpub) bad_xpub = b58encode(temp[0:45] + b"\x00" + temp[46:], 78) errmsg = "invalid public key prefix: " with pytest.raises(ValueError, match=errmsg): bip32.derive(bad_xpub, 0x80000000) errmsg = "hardened derivation from public key" with pytest.raises(ValueError, match=errmsg): bip32.derive(xpub, 0x80000000)
def test_b58_trailing_zeros(self): self.assertEqual(b58encode(b'\x00\x00hello world'), b'11StV1DL6CwTryKyV') self.assertEqual(b58decode(b'11StV1DL6CwTryKyV'), b'\x00\x00hello world') self.assertEqual(b58decode(b58encode(b'\0\0hello world')), b'\x00\x00hello world') self.assertEqual(b58encode(b58decode(b'11StV1DL6CwTryKyV')), b'11StV1DL6CwTryKyV')
def test_derive_exceptions() -> None: # root key, zero depth rootmxprv = "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi" xprv = BIP32KeyData.b58decode(rootmxprv) # FIXME # assert xprv == _derive(xprv, "m") assert rootmxprv == derive(xprv, "m") assert rootmxprv == derive(xprv, "") fingerprint = hashes.hash160(pub_keyinfo_from_key(xprv)[0])[:4] assert fingerprint == _derive(xprv, bytes.fromhex("80000000")).parent_fingerprint for der_path in ("/1", "800000", "80000000"): xkey = _derive(xprv, der_path) assert fingerprint == xkey.parent_fingerprint err_msg = "invalid literal for int" for der_path in (";/0", "invalid index"): with pytest.raises(ValueError, match=err_msg): derive(xprv, der_path) with pytest.raises(BTClibValueError, match="depth greater than 255: "): derive(xprv, "m" + 256 * "/0") with pytest.raises(BTClibValueError, match="index are not a multiple of 4-bytes: "): derive(xprv, b"\x00" * 5) for index in (2**32, 0x8000000000): with pytest.raises(OverflowError, match="int too big to convert"): derive(xprv, index) xprv = _derive(xprv, "1") err_msg = "final depth greater than 255: " with pytest.raises(BTClibValueError, match=err_msg): derive(xprv, "m" + 255 * "/0") rootxprv = "xprv9s21ZrQH143K2ZP8tyNiUtgoezZosUkw9hhir2JFzDhcUWKz8qFYk3cxdgSFoCMzt8E2Ubi1nXw71TLhwgCfzqFHfM5Snv4zboSebePRmLS" temp = base58.b58decode(rootxprv) bad_xprv = base58.b58encode(temp[:45] + b"\x02" + temp[46:], 78) err_msg = "invalid private key prefix: " with pytest.raises(BTClibValueError, match=err_msg): derive(bad_xprv, 0x80000000) xpub = xpub_from_xprv(rootxprv) temp = base58.b58decode(xpub) bad_xpub = base58.b58encode(temp[:45] + b"\x00" + temp[46:], 78) err_msg = r"invalid public key prefix not in \(0x02, 0x03\): " with pytest.raises(BTClibValueError, match=err_msg): derive(bad_xpub, 0x80000000) err_msg = "hardened derivation from public key" with pytest.raises(BTClibValueError, match=err_msg): derive(xpub, 0x80000000)
def test_wif_from_prvkey(): prvkey = "0C28FCA386C7A227600B2FE50B7CAE11EC86D3BF1FBE471BE89827E19D72AA1D" test_vectors = [ ["KwdMAjGmerYanjeui5SHS7JkmpZvVipYvB2LJGU1ZxJwYvP98617", "mainnet", True], ["cMzLdeGd5vEqxB8B6VFQoRopQ3sLAAvEzDAoQgvX54xwofSWj1fx", "testnet", True], ["5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ", "mainnet", False], ["91gGn1HgSap6CbU12F6z3pJri26xzp7Ay1VW6NHCoEayNXwRpu2", "testnet", False], [" KwdMAjGmerYanjeui5SHS7JkmpZvVipYvB2LJGU1ZxJwYvP98617", "mainnet", True], ["KwdMAjGmerYanjeui5SHS7JkmpZvVipYvB2LJGU1ZxJwYvP98617 ", "mainnet", True], ] for v in test_vectors: wif = wif_from_prvkey(prvkey, v[1], v[2]) # FIXME clarify decode("ascii") and encode("ascii") everywhere assert v[0].strip() == wif.decode("ascii") q, network, compressed = prvkeyinfo_from_prvkey(v[0]) assert q == int(prvkey, 16) assert network == v[1] assert compressed == v[2] bad_q = ec.n with pytest.raises(ValueError, match="private key not in 1..n-1: "): wif_from_prvkey(bad_q, "mainnet", True) payload = b"\x80" + bad_q.to_bytes(ec.nsize, "big") badwif = b58encode(payload) with pytest.raises(ValueError, match="not a private key: "): prvkeyinfo_from_prvkey(badwif) # not a private key: 33 bytes bad_q = 33 * b"\x02" with pytest.raises(ValueError, match="not a private key: "): wif_from_prvkey(bad_q, "mainnet", True) payload = b"\x80" + bad_q badwif = b58encode(payload) with pytest.raises(ValueError, match="not a private key: "): prvkeyinfo_from_prvkey(badwif) # Not a WIF: missing leading 0x80 good_q = 32 * b"\x02" payload = b"\x81" + good_q badwif = b58encode(payload) with pytest.raises(ValueError, match="not a private key: "): prvkeyinfo_from_prvkey(badwif) # Not a compressed WIF: missing trailing 0x01 payload = b"\x80" + good_q + b"\x00" badwif = b58encode(payload) with pytest.raises(ValueError, match="not a private key: "): prvkeyinfo_from_prvkey(badwif) # Not a WIF: wrong size (35) payload = b"\x80" + good_q + b"\x01\x00" badwif = b58encode(payload) with pytest.raises(ValueError, match="not a private key: "): prvkeyinfo_from_prvkey(badwif)
def test_utils(self): # root key, zero depth xprv = b"xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi" xdict = deserialize(xprv) decoded_key = b58decode(xprv, 78) self.assertEqual(xdict["version"], decoded_key[:4]) self.assertEqual(xdict["depth"], decoded_key[4]) self.assertEqual(xdict["parent_fingerprint"], decoded_key[5:9]) self.assertEqual(xdict["index"], decoded_key[9:13]) self.assertEqual(xdict["chain_code"], decoded_key[13:45]) self.assertEqual(xdict["key"], decoded_key[45:]) # zero depth with non-zero parent_fingerprint f2 = b'\x01\x01\x01\x01' invalid_key = b58encode(xprv[:5] + f2 + xprv[9:]) self.assertRaises(ValueError, deserialize, invalid_key) # deserialize(invalid_key) # zero depth with non-zero index i2 = b'\x01\x01\x01\x01' invalid_key = b58encode(xprv[:9] + i2 + xprv[13:]) self.assertRaises(ValueError, deserialize, invalid_key) # deserialize(invalid_key) # non-zero depth (255) with zero parent_fingerprint d2 = b'ff' invalid_key = b58encode(xprv[:4] + d2 + xprv[5:]) self.assertRaises(ValueError, deserialize, invalid_key) # deserialize(invalid_key) child_key = derive(xprv, 0) # Derivation path final depth 256>255 self.assertRaises(ValueError, derive, child_key, "." + 255 * "/0") #derive(child_key, "."+255*"/0") # Empty derivation path self.assertRaises(ValueError, derive, child_key, "") #derive(child_key, "") # Invalid derivation path root: ";" self.assertRaises(ValueError, derive, child_key, ";/0") #derive(child_key, ";/0") # Derivation path depth 256>255 self.assertRaises(ValueError, derive, child_key, "." + 256 * "/0") #derive(child_key, "." + 256*"/0") # xkey is not a public one self.assertRaises(ValueError, p2pkh_from_xpub, xprv)
def test_trailing_zeros() -> None: assert _b58encode(b"\x00\x00hello world") == b"11StV1DL6CwTryKyV" assert _b58decode(b"11StV1DL6CwTryKyV") == b"\x00\x00hello world" assert _b58decode(_b58encode(b"\x00\x00hello world")) == b"\x00\x00hello world" assert _b58encode(_b58decode(b"11StV1DL6CwTryKyV")) == b"11StV1DL6CwTryKyV" assert b58decode(b58encode(b"\x00\x00hello world"), 13) == b"\x00\x00hello world"
def test_hello_world() -> None: assert _b58encode(b"hello world") == b"StV1DL6CwTryKyV" assert _b58decode(b"StV1DL6CwTryKyV") == b"hello world" assert _b58decode(_b58encode(b"hello world")) == b"hello world" assert _b58encode(_b58decode(b"StV1DL6CwTryKyV")) == b"StV1DL6CwTryKyV" assert b58decode(b58encode(b"hello world"), 11) == b"hello world"
def test_derive_exceptions() -> None: # root key, zero depth rootmxprv = "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi" xprv = derive(rootmxprv, bytes.fromhex("80000000")) xprv = derive(xprv, "m") for der_path in ("", "/1", "800000"): derive(xprv, der_path) err_msg = "invalid literal for int" for der_path in (";/0", "invalid index"): with pytest.raises(ValueError, match=err_msg): derive(xprv, der_path) with pytest.raises(BTClibValueError, match="depth greater than 255: "): derive(xprv, "m" + 256 * "/0") with pytest.raises(BTClibValueError, match="index is not a multiple of 4-bytes: "): derive(xprv, b"\x00" * 5) for index in (256**4, 0x8000000000): with pytest.raises(BTClibValueError, match="invalid index: "): derive(xprv, index) err_msg = "final depth greater than 255: " with pytest.raises(BTClibValueError, match=err_msg): derive(xprv, "m" + 255 * "/0") rootxprv = "xprv9s21ZrQH143K2ZP8tyNiUtgoezZosUkw9hhir2JFzDhcUWKz8qFYk3cxdgSFoCMzt8E2Ubi1nXw71TLhwgCfzqFHfM5Snv4zboSebePRmLS" temp = b58decode(rootxprv) bad_xprv = b58encode(temp[0:45] + b"\x02" + temp[46:], 78) err_msg = "invalid private key prefix: " with pytest.raises(BTClibValueError, match=err_msg): derive(bad_xprv, 0x80000000) xpub = xpub_from_xprv(rootxprv) temp = b58decode(xpub) bad_xpub = b58encode(temp[0:45] + b"\x00" + temp[46:], 78) err_msg = r"invalid public key prefix not in \(0x02, 0x03\): " with pytest.raises(BTClibValueError, match=err_msg): derive(bad_xpub, 0x80000000) err_msg = "hardened derivation from public key" with pytest.raises(BTClibValueError, match=err_msg): derive(xpub, 0x80000000)
def test_exceptions(): with pytest.raises(TypeError, match="object supporting the buffer API required"): b58encode(3) encoded = b58encode(b"test") wrong_length = len(encoded) - 1 with pytest.raises(ValueError, match="Invalid base58 decoded size: "): b58decode(encoded, wrong_length) invalidChecksum = encoded[:-4] + b"1111" with pytest.raises(ValueError, match="invalid checksum: "): b58decode(invalidChecksum, 4) with pytest.raises(ValueError, match="'ascii' codec can't encode character "): b58decode("hèllo world")
def _serialize(d: BIP32KeyDict) -> bytes: t = d["version"] t += d["depth"].to_bytes(1, "big") t += d["parent_fingerprint"] t += d["index"] t += d["chain_code"] t += d["key"] return b58encode(t, 78)
def test_exceptions(self): # valid xprv xprv = b'xprv9s21ZrQH143K2oxHiQ5f7D7WYgXD9h6HAXDBuMoozDGGiYHWsq7TLBj2yvGuHTLSPCaFmUyN1v3fJRiY2A4YuNSrqQMPVLZKt76goL6LP7L' # invalid index self.assertRaises(ValueError, derive, xprv, 'invalid index') #derive(xprv, 'invalid index') # a 4 bytes int is required, not 3 self.assertRaises(ValueError, derive, xprv, "800000") #derive(xprv, "800000") # Invalid derivation path root: "" self.assertRaises(ValueError, derive, xprv, '/1') #derive(xprv, '/1') # invalid checksum xprv = b'xppp9s21ZrQH143K2oxHiQ5f7D7WYgXD9h6HAXDBuMoozDGGiYHWsq7TLBj2yvGuHTLSPCaFmUyN1v3fJRiY2A4YuNSrqQMPVLZKt76goL6LP7L' self.assertRaises(ValueError, derive, xprv, 0x80000000) #derive(xprv, 0x80000000) # invalid extended key version version = b'\x04\x88\xAD\xE5' xkey = version + b'\x00' * 74 xkey = b58encode(xkey) self.assertRaises(ValueError, derive, xkey, 0x80000000) #derive(xkey, 0x80000000) # unknown extended key version version = b'\x04\x88\xAD\xE5' seed = "5b56c417303faa3fcba7e57400e120a0ca83ec5a4fc9ffba757fbe63fbd77a89a1a3be4c67196f57c39a88b76373733891bfaba16ed27a813ceed498804c0570" self.assertRaises(ValueError, rootxprv_from_seed, seed, version) #rootxprv_from_seed(seed, version) # extended key is not a private one xpub = b'xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy' self.assertRaises(ValueError, xpub_from_xprv, xpub) # xpub_from_xprv(xpub) # Absolute derivation path for non-master key self.assertRaises(ValueError, derive, xpub, "m/44'/0'/1'/0/10") #derive(xpub, "m/0/1") # empty derivation path self.assertRaises(ValueError, derive, xpub, "") #derive(xpub, "") # extended key is not a public one self.assertRaises(ValueError, p2pkh_from_xpub, xprv) # p2pkh_from_xpub(xprv) # xkey is not a public one xprv = b'xprv9s21ZrQH143K2ZP8tyNiUtgoezZosUkw9hhir2JFzDhcUWKz8qFYk3cxdgSFoCMzt8E2Ubi1nXw71TLhwgCfzqFHfM5Snv4zboSebePRmLS' self.assertRaises(ValueError, slip32.address_from_xpub, xprv) # slip32.address_from_xpub(xprv) self.assertRaises(ValueError, p2wpkh_from_xpub, xprv) # p2wpkh_from_xpub(xprv) self.assertRaises(ValueError, p2wpkh_p2sh_from_xpub, xprv)
def test_exceptions() -> None: pubkey = "02 50863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352" payload = b"\xf5" + hash160(pubkey) invalid_address = b58encode(payload) with pytest.raises(ValueError, match="invalid base58 address prefix: "): h160_from_b58address(invalid_address) with pytest.raises(ValueError, match="not a private or public key: "): p2pkh(pubkey + "00")
def test_exceptions(self): # Invalid base58 address prefix b'\xf5' payload = b'\xf5' pubkey = "02 50863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352" payload += hash160(pubkey) invalid_address = b58encode(payload) self.assertRaises(ValueError, h160_from_b58address, invalid_address) # _h160_from_b58address(invalid_address) # Invalid SEC pubkey length: 34-bytes self.assertRaises(ValueError, p2pkh, pubkey + '00', True)
def test_wif(): # https://en.bitcoin.it/wiki/Wallet_import_format prv = 0xC28FCA386C7A227600B2FE50B7CAE11EC86D3BF1FBE471BE89827E19D72AA1D uncompressedKey = b"\x80" + prv.to_bytes(32, byteorder="big") uncomprWIF = b"5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ" wif = b58encode(uncompressedKey) assert wif == uncomprWIF key = b58decode(uncomprWIF) assert key == uncompressedKey compressedKey = b"\x80" + prv.to_bytes(32, byteorder="big") + b"\x01" compressedWIF = b"KwdMAjGmerYanjeui5SHS7JkmpZvVipYvB2LJGU1ZxJwYvP98617" wif = b58encode(compressedKey) assert wif == compressedWIF key = b58decode(compressedWIF) assert key == compressedKey # string compressedWIF = b"KwdMAjGmerYanjeui5SHS7JkmpZvVipYvB2LJGU1ZxJwYvP98617" key = b58decode(compressedWIF) assert key == compressedKey
def test_wif(self): # https://en.bitcoin.it/wiki/Wallet_import_format prvkey = 0xC28FCA386C7A227600B2FE50B7CAE11EC86D3BF1FBE471BE89827E19D72AA1D uncompressedKey = b'\x80' + prvkey.to_bytes(32, byteorder='big') uncompressedWIF = b'5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ' wif = b58encode(uncompressedKey) self.assertEqual(wif, uncompressedWIF) key = b58decode(uncompressedWIF) self.assertEqual(key, uncompressedKey) compressedKey = b'\x80' + \ prvkey.to_bytes(32, byteorder='big') + b'\x01' compressedWIF = b'KwdMAjGmerYanjeui5SHS7JkmpZvVipYvB2LJGU1ZxJwYvP98617' wif = b58encode(compressedKey) self.assertEqual(wif, compressedWIF) key = b58decode(compressedWIF) self.assertEqual(key, compressedKey) # string compressedWIF = b'KwdMAjGmerYanjeui5SHS7JkmpZvVipYvB2LJGU1ZxJwYvP98617' key = b58decode(compressedWIF) self.assertEqual(key, compressedKey)
def wif_from_prv_key(prv_key: PrvKey, network: Optional[str] = None, compressed: Optional[bool] = None) -> str: "Return the WIF encoding of a private key." q, net, compr = prv_keyinfo_from_prv_key(prv_key, network, compressed) ec = NETWORKS[net].curve payload = b"".join([ NETWORKS[net].wif, q.to_bytes(ec.n_size, byteorder="big", signed=False), b"\x01" if compr else b"", ]) return b58encode(payload).decode("ascii")
def address_from_h160(script_type: str, h160: Octets, network: str = "mainnet") -> str: "Return a base58 address from the payload." if script_type == "p2sh": prefix = NETWORKS[network].p2sh elif script_type == "p2pkh": prefix = NETWORKS[network].p2pkh else: raise BTClibValueError(f"invalid script type: {script_type}") payload = prefix + bytes_from_octets(h160, 20) return b58encode(payload).decode("ascii")
def test_exceptions(self): # valid xprv xprv = "xprv9s21ZrQH143K2oxHiQ5f7D7WYgXD9h6HAXDBuMoozDGGiYHWsq7TLBj2yvGuHTLSPCaFmUyN1v3fJRiY2A4YuNSrqQMPVLZKt76goL6LP7L" # invalid index self.assertRaises(ValueError, derive, xprv, "invalid index") # derive(xprv, "invalid index") # a 4 bytes int is required, not 3 self.assertRaises(ValueError, derive, xprv, "800000") # derive(xprv, "800000") # Invalid derivation path root: "" self.assertRaises(ValueError, derive, xprv, "/1") # derive(xprv, "/1") # invalid checksum xprv = "xppp9s21ZrQH143K2oxHiQ5f7D7WYgXD9h6HAXDBuMoozDGGiYHWsq7TLBj2yvGuHTLSPCaFmUyN1v3fJRiY2A4YuNSrqQMPVLZKt76goL6LP7L" self.assertRaises(ValueError, derive, xprv, 0x80000000) # derive(xprv, 0x80000000) # invalid extended key version version = b"\x04\x88\xAD\xE5" xkey = version + b"\x00" * 74 xkey = b58encode(xkey, 78) self.assertRaises(ValueError, derive, xkey, 0x80000000) # derive(xkey, 0x80000000) # unknown extended key version version = b"\x04\x88\xAD\xE5" seed = "5b56c417303faa3fcba7e57400e120a0ca83ec5a4fc9ffba757fbe63fbd77a89a1a3be4c67196f57c39a88b76373733891bfaba16ed27a813ceed498804c0570" self.assertRaises(ValueError, rootxprv_from_seed, seed, version) # rootxprv_from_seed(seed, version) # extended key is not a private one xpub = "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy" self.assertRaises(ValueError, xpub_from_xprv, xpub) # xpub_from_xprv(xpub) # Absolute derivation path for non-master key self.assertRaises(ValueError, derive, xpub, "m/44h/0h/1h/0/10") # derive(xpub, "m/0/1") # empty derivation path self.assertRaises(ValueError, derive, xpub, "") # derive(xpub, "") # extended key is not a public one self.assertRaises(ValueError, p2pkh, xprv)
def test_exceptions() -> None: with pytest.raises(TypeError, match="object supporting the buffer API required"): b58encode(3) # type: ignore encoded = b58encode(b"hello world") b58decode(encoded, 11) wrong_length = len(encoded) - 1 with pytest.raises(BTClibValueError, match="invalid decoded size: "): b58decode(encoded, wrong_length) invalid_checksum = encoded[:-4] + b"1111" with pytest.raises(BTClibValueError, match="invalid checksum: "): b58decode(invalid_checksum, 4) err_msg = "'ascii' codec can't encode character " with pytest.raises(UnicodeEncodeError, match=err_msg): b58decode("hèllo world") err_msg = "not enough bytes for checksum, invalid base58 decoded size: " with pytest.raises(BTClibValueError, match=err_msg): b58decode(_b58encode(b"123"))
def test_b58_empty(self): self.assertEqual(b58encode(b''), b'') self.assertEqual(b58decode(b''), b'') self.assertEqual(b58decode(b58encode(b'')), b'') self.assertEqual(b58encode(b58decode(b'')), b'') self.assertEqual(b58encode(''), b'') self.assertEqual(b58decode(''), b'') self.assertEqual(b58decode(b58encode('')), b'') self.assertEqual(b58encode(b58decode('')), b'')
def test_serialize(self): xprv = b"xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi" xprv_dict = deserialize(xprv) xpr2 = serialize(xprv_dict) self.assertEqual(xpr2, xprv) # private key not in [1, n-1] inv_key = (ec.n).to_bytes(ec.nsize, 'big') decoded_key = b58decode(xprv, 78) xkey = b58encode(decoded_key[:46] + inv_key) self.assertRaises(ValueError, deserialize, xkey) # deserialize(xkey) xpub = xpub_from_xprv(xprv) xpub2 = xpub_from_xprv(deserialize(xprv)) self.assertEqual(xpub, xpub2)
def test_exceptions(self): # int is not hex-string or bytes self.assertRaises(TypeError, b58encode, 3) encoded = b58encode(b"test") # unexpected decoded length wrong_length = len(encoded) - 1 self.assertRaises(ValueError, b58decode, encoded, wrong_length) # checksum is invalid invalidChecksum = encoded[:-4] + b'1111' self.assertRaises(ValueError, b58decode, invalidChecksum, 4) # non-ascii character self.assertRaises(ValueError, b58decode, "hèllo world")
def test_b58_hello_world(self): self.assertEqual(b58encode(b'hello world'), b'StV1DL6CwTryKyV') self.assertEqual(b58decode(b'StV1DL6CwTryKyV'), b'hello world') self.assertEqual(b58decode(b58encode(b'hello world')), b'hello world') self.assertEqual(b58encode(b58decode(b'StV1DL6CwTryKyV')), b'StV1DL6CwTryKyV') self.assertEqual(b58encode("hello world"), b'StV1DL6CwTryKyV') self.assertEqual(b58decode("StV1DL6CwTryKyV"), b'hello world') self.assertEqual(b58decode(b58encode("hello world")), b'hello world') self.assertEqual(b58encode(b58decode("StV1DL6CwTryKyV")), b'StV1DL6CwTryKyV')
def wif_from_prv_key(prv_key: PrvKey, network: Optional[str] = None, compressed: Optional[bool] = None) -> str: "Return the WIF encoding of a private key." q, net, compr = prv_keyinfo_from_prv_key(prv_key) # the private key might provide network and compressed informations # e.g., wif or xprv network = net if network is None else network compressed = compr if compressed is None else compressed ec = NETWORKS[network].curve payload = b"".join([ NETWORKS[network].wif, q.to_bytes(ec.n_size, byteorder="big", signed=False), b"\x01" if compressed else b"", ]) return b58encode(payload).decode("ascii")
def test_mainnet(self): # bitcoin core derivation style rootxprv = "xprv9s21ZrQH143K2ZP8tyNiUtgoezZosUkw9hhir2JFzDhcUWKz8qFYk3cxdgSFoCMzt8E2Ubi1nXw71TLhwgCfzqFHfM5Snv4zboSebePRmLS" # m / 0h / 0h / 463h addr1 = b"1DyfBWxhVLmrJ7keyiHeMbt7N3UdeGU4G5" indexes = [0x80000000, 0x80000000, 0x800001CF] addr = p2pkh(xpub_from_xprv(derive(rootxprv, indexes))) self.assertEqual(addr, addr1) path = "m / 0h / 0h / 463h" addr = p2pkh(xpub_from_xprv(derive(rootxprv, path))) self.assertEqual(addr, addr1) # m / 0h / 0h / 267h addr2 = b"11x2mn59Qy43DjisZWQGRResjyQmgthki" indexes = [0x80000000, 0x80000000, 0x8000010B] addr = p2pkh(xpub_from_xprv(derive(rootxprv, indexes))) self.assertEqual(addr, addr2) path = "M / 0H / 0h // 267' / " addr = p2pkh(xpub_from_xprv(derive(rootxprv, path))) self.assertEqual(addr, addr2) seed = "bfc4cbaad0ff131aa97fa30a48d09ae7df914bcc083af1e07793cd0a7c61a03f65d622848209ad3366a419f4718a80ec9037df107d8d12c19b83202de00a40ad" xprv = rootxprv_from_seed(seed) xpub = "xpub661MyMwAqRbcFMYjmw8C6dJV97a4oLss6hb3v9wTQn2X48msQB61RCaLGtNhzgPCWPaJu7SvuB9EBSFCL43kTaFJC3owdaMka85uS154cEh" self.assertEqual(xpub_from_xprv(xprv).decode(), xpub) ind = "./0/0" addr = p2pkh(xpub_from_xprv(derive(xprv, ind))) self.assertEqual(addr, b"1FcfDbWwGs1PmyhMVpCAhoTfMnmSuptH6g") ind = "./0/1" addr = p2pkh(xpub_from_xprv(derive(xprv, ind))) self.assertEqual(addr, b"1K5GjYkZnPFvMDTGaQHTrVnd8wjmrtfR5x") ind = "./0/2" addr = p2pkh(xpub_from_xprv(derive(xprv, ind))) self.assertEqual(addr, b"1PQYX2uN7NYFd7Hq22ECMzfDcKhtrHmkfi") ind = "./1/0" addr = p2pkh(xpub_from_xprv(derive(xprv, ind))) self.assertEqual(addr, b"1BvSYpojWoWUeaMLnzbkK55v42DbizCoyq") ind = "./1/1" addr = p2pkh(xpub_from_xprv(derive(xprv, ind))) self.assertEqual(addr, b"1NXB59hF4QzYpFrB7o6usLBjbk2D3ZqxAL") ind = "./1/2" addr = p2pkh(xpub_from_xprv(derive(xprv, ind))) self.assertEqual(addr, b"16NLYkKtvYhW1Jp86tbocku3gxWcvitY1w") # version/key mismatch in extended parent key temp = b58decode(rootxprv) bad_xprv = b58encode(temp[0:45] + b"\x01" + temp[46:], 78) self.assertRaises(ValueError, derive, bad_xprv, 1) # derive(bad_xprv, 1) # version/key mismatch in extended parent key xpub = xpub_from_xprv(rootxprv) temp = b58decode(xpub) bad_xpub = b58encode(temp[0:45] + b"\x00" + temp[46:], 78) self.assertRaises(ValueError, derive, bad_xpub, 1) # derive(bad_xpub, 1) # no private/hardened derivation from pubkey self.assertRaises(ValueError, derive, xpub, 0x80000000)
def test_point_from_key(self): # prvkeys xprv = b"xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi" xprv_str = xprv.decode('ascii') xprv_dict = bip32.deserialize(xprv) q, network, _ = _prvkey_info_from_xprv(xprv) ec = curve_from_network(network) q_bytes = q.to_bytes(ec.psize, 'big') wif1 = wif_from_prvkey(q, network, True) wif2 = wif_from_prvkey(q, network, False) # pubkeys Q = mult(q, ec.G, ec) xpub = bip32.xpub_from_xprv(xprv) xpub_str = xpub.decode('ascii') xpub_dict = bip32.deserialize(xpub) Q_compr = xpub_dict['key'] Q_compr_hexstr = Q_compr.hex() Q_uncompr = bytes_from_point(Q, ec, False) Q_uncompr_hexstr = Q_uncompr.hex() # int prvkey self.assertEqual(point_from_key(q, ec), Q) self.assertEqual(point_from_key(q_bytes, ec), Q) # wif prvkey self.assertEqual(point_from_key(wif1, ec), Q) self.assertEqual(point_from_key(wif2, ec), Q) # BIP32 prvkey self.assertEqual(point_from_key(xprv, ec), Q) self.assertEqual(point_from_key(xprv_str, ec), Q) self.assertEqual(point_from_key(' ' + xprv_str + ' ', ec), Q) self.assertEqual(point_from_key(xprv_dict, ec), Q) # BIP32 pubkey self.assertEqual(point_from_key(xpub, ec), Q) self.assertEqual(point_from_key(xpub_str, ec), Q) self.assertEqual(point_from_key(' ' + xpub_str + ' ', ec), Q) self.assertEqual(point_from_key(xpub_dict, ec), Q) # compressed SEC Octets (bytes or hex-string, with 02 or 03 prefix) self.assertEqual(point_from_key(Q_compr, ec), Q) self.assertRaises(ValueError, point_from_key, b'\x00' + Q_compr, ec) self.assertEqual(point_from_key(Q_compr_hexstr, ec), Q) self.assertEqual(point_from_key(' ' + Q_compr_hexstr + ' ', ec), Q) self.assertRaises(ValueError, point_from_key, Q_compr_hexstr + '00', ec) # uncompressed SEC Octets (bytes or hex-string, with 04 prefix) self.assertEqual(point_from_key(Q_uncompr, ec), Q) self.assertRaises(ValueError, point_from_key, b'\x00' + Q_uncompr, ec) self.assertEqual(point_from_key(Q_uncompr_hexstr, ec), Q) self.assertEqual(point_from_key( ' ' + Q_uncompr_hexstr + ' ', ec), Q) self.assertRaises(ValueError, point_from_key, Q_uncompr_hexstr + '00', ec) # native tuple self.assertEqual(point_from_key(Q, ec), Q) # Invalid point: 7 is not a field element Q = INF self.assertRaises(ValueError, point_from_key, Q, ec) Q_compr = b'\x02' + Q[0].to_bytes(ec.psize, 'big') self.assertRaises(ValueError, point_from_key, Q_compr, ec) Q_uncompr = b'\x04' + \ Q[0].to_bytes(ec.psize, 'big') + Q[1].to_bytes(ec.psize, 'big') self.assertRaises(ValueError, point_from_key, Q_uncompr, ec) Q_compr_hexstr = Q_compr.hex() self.assertRaises(ValueError, point_from_key, Q_compr_hexstr, ec) Q_uncompr_hexstr = Q_uncompr.hex() self.assertRaises(ValueError, point_from_key, Q_uncompr_hexstr, ec) t = xpub_dict['version'] t += xpub_dict['depth'].to_bytes(1, 'big') t += xpub_dict['parent_fingerprint'] t += xpub_dict['index'] t += xpub_dict['chain_code'] t += Q_compr xpub = b58encode(t) self.assertRaises(ValueError, point_from_key, xpub, ec) xpub_str = xpub.decode('ascii') self.assertRaises(ValueError, point_from_key, xpub_str, ec) # pubkey input self.assertRaises(ValueError, point_from_pubkey, xprv, ec) self.assertRaises(ValueError, point_from_pubkey, xprv_dict, ec)
def test_bytes_from_key(self): # prvkeys xprv = b"xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi" xprv_str = xprv.decode('ascii') xprv_dict = bip32.deserialize(xprv) q, network, _ = _prvkey_info_from_xprv(xprv) ec = curve_from_network(network) q_bytes = q.to_bytes(ec.psize, 'big') wif1 = wif_from_prvkey(q, network, True) wif2 = wif_from_prvkey(q, network, False) # pubkeys Q = mult(q, ec.G, ec) xpub = bip32.xpub_from_xprv(xprv) xpub_str = xpub.decode('ascii') xpub_dict = bip32.deserialize(xpub) Q_compr = xpub_dict['key'] Q_compr_hexstr = Q_compr.hex() Q_uncompr = bytes_from_point(Q, ec, False) Q_uncompr_hexstr = Q_uncompr.hex() # int prvkey, compressed result self.assertEqual(bytes_from_key(q)[0], Q_compr) self.assertEqual(bytes_from_key(q_bytes)[0], Q_compr) # int prvkey, uncompressed result self.assertEqual(bytes_from_key(q, compressed=False)[0], Q_uncompr) self.assertEqual(bytes_from_key( q_bytes, compressed=False)[0], Q_uncompr) # compressed wif prvkey, both results self.assertEqual(bytes_from_key(wif1)[0], Q_compr) self.assertRaises(ValueError, bytes_from_key, wif1, compressed=False) # uncompressed wif prvkey, both results self.assertRaises(ValueError, bytes_from_key, wif2, compressed=True) self.assertEqual(bytes_from_key(wif2)[0], Q_uncompr) # (compressed) BIP32 prvkey, compressed results self.assertEqual(bytes_from_key(xprv)[0], Q_compr) self.assertEqual(bytes_from_key(xprv_str)[0], Q_compr) self.assertEqual(bytes_from_key(' ' + xprv_str + ' ')[0], Q_compr) self.assertEqual(bytes_from_key(xprv_dict)[0], Q_compr) # (compressed) BIP32 prvkey, uncompressed result self.assertRaises(ValueError, bytes_from_key, xprv, compressed=False) self.assertRaises(ValueError, bytes_from_key, xprv_str, compressed=False) self.assertRaises(ValueError, bytes_from_key, ' ' + xprv_str + ' ', compressed=False) self.assertRaises(ValueError, bytes_from_key, xprv_dict, compressed=False) # (compressed) BIP32 pubkey, compressed results self.assertEqual(bytes_from_key(xpub)[0], Q_compr) self.assertEqual(bytes_from_key(xpub_str)[0], Q_compr) self.assertEqual(bytes_from_key(' ' + xpub_str + ' ')[0], Q_compr) self.assertEqual(bytes_from_key(xpub_dict)[0], Q_compr) # (compressed) BIP32 pubkey, uncompressed result self.assertRaises(ValueError, bytes_from_key, xpub, compressed=False) self.assertRaises(ValueError, bytes_from_key, xpub_str, compressed=False) self.assertRaises(ValueError, bytes_from_key, ' ' + xpub_str + ' ', compressed=False) self.assertRaises(ValueError, bytes_from_key, xpub_dict, compressed=False) # compressed SEC Octets (pubkey), compressed results self.assertEqual(bytes_from_key(Q_compr)[0], Q_compr) self.assertEqual(bytes_from_key(Q_compr_hexstr)[0], Q_compr) self.assertEqual(bytes_from_key( ' ' + Q_compr_hexstr + ' ')[0], Q_compr) # compressed SEC Octets (pubkey), uncompressed results self.assertRaises(ValueError, bytes_from_key, Q_compr, compressed=False) self.assertRaises(ValueError, bytes_from_key, Q_compr_hexstr, compressed=False) self.assertRaises(ValueError, bytes_from_key, ' ' + Q_compr_hexstr + ' ', compressed=False) self.assertRaises(ValueError, bytes_from_key, b'\x00' + Q_compr) self.assertRaises(ValueError, bytes_from_key, Q_compr_hexstr + '00') # uncompressed SEC Octets (pubkey), uncompressed results self.assertEqual(bytes_from_key(Q_uncompr)[0], Q_uncompr) self.assertEqual(bytes_from_key(Q_uncompr_hexstr)[0], Q_uncompr) self.assertEqual(bytes_from_key( ' ' + Q_uncompr_hexstr + ' ')[0], Q_uncompr) # uncompressed SEC Octets (pubkey), compressed results self.assertRaises(ValueError, bytes_from_key, Q_uncompr, compressed=True) self.assertRaises(ValueError, bytes_from_key, Q_uncompr_hexstr, compressed=True) self.assertRaises(ValueError, bytes_from_key, ' ' + Q_uncompr_hexstr + ' ', compressed=True) self.assertRaises(ValueError, bytes_from_key, b'\x00' + Q_uncompr) self.assertRaises(ValueError, bytes_from_key, Q_uncompr_hexstr + '00') # native tuple input, both results self.assertEqual(bytes_from_key(Q)[0], Q_compr) self.assertEqual(bytes_from_key(Q, compressed=False)[0], Q_uncompr) # bytes_from_pubkey does not accept prvkey inputs self.assertRaises(TypeError, bytes_from_pubkey, q) self.assertRaises(ValueError, bytes_from_pubkey, q_bytes) self.assertRaises(ValueError, bytes_from_pubkey, xprv) self.assertRaises(ValueError, bytes_from_pubkey, xprv_str) self.assertRaises(ValueError, bytes_from_pubkey, xprv_dict) self.assertRaises(ValueError, bytes_from_pubkey, wif1) self.assertRaises(ValueError, bytes_from_pubkey, wif2) # Not a public key: xpub_dict_bad = copy.copy(xpub_dict) xpub_dict_bad['key'] = b'\x00' + xpub_dict['key'][1:] self.assertRaises(ValueError, _bytes_from_xpub, xpub_dict_bad) # _bytes_from_xpub(xpub_dict_bad) # Invalid point: 7 is not a field element Q = INF self.assertRaises(ValueError, bytes_from_key, Q) Q_compr = b'\x02' + Q[0].to_bytes(ec.psize, 'big') self.assertRaises(ValueError, bytes_from_key, Q_compr) Q_uncompr = b'\x04' + \ Q[0].to_bytes(ec.psize, 'big') + Q[1].to_bytes(ec.psize, 'big') self.assertRaises(ValueError, bytes_from_key, Q_uncompr) Q_compr_hexstr = Q_compr.hex() self.assertRaises(ValueError, bytes_from_key, Q_compr_hexstr) Q_uncompr_hexstr = Q_uncompr.hex() self.assertRaises(ValueError, bytes_from_key, Q_uncompr_hexstr) t = xpub_dict['version'] t += xpub_dict['depth'].to_bytes(1, 'big') t += xpub_dict['parent_fingerprint'] t += xpub_dict['index'] t += xpub_dict['chain_code'] t += Q_compr xpub = b58encode(t) self.assertRaises(ValueError, bytes_from_key, xpub) xpub_str = xpub.decode('ascii') self.assertRaises(ValueError, bytes_from_key, xpub_str)
print("\n*** [4] SHA-256 hashing of the SHA-256:") h2 = sha256(h1).digest() print(h2.hex()) print("\n*** [5] First 4 bytes of the double SHA-256 used as checksum:") print(h2[:4].hex()) print("\n*** [6] checksum added at the end of the payload:") checksummed_payload = payload + h2[:4] print(checksummed_payload.hex()) print("\n*** [7] Base58 encoding") wif = base58._b58encode(checksummed_payload) print(wif) assert wif == b"5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ" wif = base58.b58encode(payload) assert wif == b"5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ" print("\n****** WIF to private key ******") print("\n*** [1] Base58 WIF") print(wif) compressed = len(wif) - 51 print("compressed" if (compressed == 1) else "uncompressed") print("\n*** [2] Base58 decoding") checksummed_payload = base58._b58decode(wif) print(checksummed_payload.hex()) print("\n*** [3] payload (checksum verified)") payload, checksum = checksummed_payload[:-4], checksummed_payload[-4:]
def test_to_pub_bytes(self): xpub = b'xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8' xpub_str = xpub.decode('ascii') xpub_dict = bip32.deserialize(xpub) P_compr = xpub_dict['key'] P_compr_hexstr = P_compr.hex() P = xpub_dict['Q'] P_uncompr = bytes_from_point(P, False, ec) P_uncompr_hexstr = P_uncompr.hex() # BIP32 input, compressed result self.assertEqual(to_pubkey_bytes(xpub, True, ec), P_compr) self.assertEqual(to_pubkey_bytes(xpub_str, True, ec), P_compr) self.assertEqual(to_pubkey_bytes(' ' + xpub_str + ' ', True, ec), P_compr) self.assertEqual(to_pubkey_bytes(xpub_dict, True, ec), P_compr) # compressed SEC Octets input, compressed result self.assertEqual(to_pubkey_bytes(P_compr, True, ec), P_compr) self.assertRaises(ValueError, to_pubkey_bytes, b'\x00' + P_compr, True, ec) self.assertEqual(to_pubkey_bytes(P_compr_hexstr, True, ec), P_compr) self.assertEqual(to_pubkey_bytes(' ' + P_compr_hexstr + ' ', True, ec), P_compr) self.assertRaises(ValueError, to_pubkey_bytes, P_compr_hexstr + '00', True, ec) # uncompressed SEC Octets input, compressed result self.assertRaises(ValueError, to_pubkey_bytes, P_uncompr, True, ec) self.assertRaises(ValueError, to_pubkey_bytes, P_uncompr_hexstr, True, ec) self.assertRaises(ValueError, to_pubkey_bytes, ' ' + P_uncompr_hexstr + ' ', True, ec) # native tuple input, compressed result self.assertEqual(to_pubkey_bytes(P, True, ec), P_compr) # BIP32 input, uncompressed result self.assertRaises(ValueError, to_pubkey_bytes, xpub, False, ec) self.assertRaises(ValueError, to_pubkey_bytes, xpub_str, False, ec) self.assertRaises(ValueError, to_pubkey_bytes, ' ' + xpub_str + ' ', False, ec) self.assertRaises(ValueError, to_pubkey_bytes, xpub_dict, False, ec) # compressed SEC Octets input, uncompressed result self.assertRaises(ValueError, to_pubkey_bytes, P_compr, False, ec) self.assertRaises(ValueError, to_pubkey_bytes, P_compr_hexstr, False, ec) self.assertRaises(ValueError, to_pubkey_bytes, ' ' + P_compr_hexstr + ' ', False, ec) # uncompressed SEC Octets input, uncompressed result self.assertEqual(to_pubkey_bytes(P_uncompr, False, ec), P_uncompr) self.assertRaises(ValueError, to_pubkey_bytes, b'\x00' + P_uncompr, False, ec) self.assertEqual(to_pubkey_bytes(P_uncompr_hexstr, False, ec), P_uncompr) self.assertEqual(to_pubkey_bytes(' ' + P_uncompr_hexstr + ' ', False, ec), P_uncompr) self.assertRaises(ValueError, to_pubkey_bytes, P_uncompr_hexstr + '00', False, ec) # native tuple input, uncompressed result self.assertEqual(to_pubkey_bytes(P, False, ec), P_uncompr) # pubkey input xprv = b"xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi" self.assertRaises(ValueError, to_pubkey_bytes, xprv, True, ec) xprv_dict = bip32.deserialize(xprv) self.assertRaises(ValueError, to_pubkey_bytes, xprv_dict, True, ec) # Invalid point: 7 is not a field element P = INF self.assertRaises(ValueError, to_pubkey_bytes, P, True, ec) P_compr = b'\x02' + P[0].to_bytes(ec.psize, 'big') self.assertRaises(ValueError, to_pubkey_bytes, P_compr, True, ec) P_uncompr = b'\x04' + P[0].to_bytes(ec.psize, 'big') + P[1].to_bytes(ec.psize, 'big') self.assertRaises(ValueError, to_pubkey_bytes, P_uncompr, True, ec) P_compr_hexstr = P_compr.hex() self.assertRaises(ValueError, to_pubkey_bytes, P_compr_hexstr, True, ec) P_uncompr_hexstr = P_uncompr.hex() self.assertRaises(ValueError, to_pubkey_bytes, P_uncompr_hexstr, True, ec) t = xpub_dict['version'] t += xpub_dict['depth'].to_bytes(1, 'big') t += xpub_dict['parent_fingerprint'] t += xpub_dict['index'] t += xpub_dict['chain_code'] t += P_compr xpub = b58encode(t) self.assertRaises(ValueError, to_pubkey_bytes, xpub, True, ec) xpub_str = xpub.decode('ascii') self.assertRaises(ValueError, to_pubkey_bytes, xpub_str, True, ec)