def test_crack() -> None: parent_xpub = "xpub6BabMgRo8rKHfpAb8waRM5vj2AneD4kDMsJhm7jpBDHSJvrFAjHJHU5hM43YgsuJVUVHWacAcTsgnyRptfMdMP8b28LYfqGocGdKCFjhQMV" child_xprv = "xprv9xkG88dGyiurKbVbPH1kjdYrA8poBBBXa53RKuRGJXyruuoJUDd8e4m6poiz7rV8Z4NoM5AJNcPHN6aj8wRFt5CWvF8VPfQCrDUcLU5tcTm" parent_xprv = crack_prvkey(parent_xpub, child_xprv) assert xpub_from_xprv(parent_xprv).decode("ascii") == parent_xpub # same check with XKeyDict parent_xprv = crack_prvkey(BIP32KeyData.deserialize(parent_xpub), BIP32KeyData.deserialize(child_xprv)) assert xpub_from_xprv(parent_xprv).decode("ascii") == parent_xpub err_msg = "extended parent key is not a public key: " with pytest.raises(BTClibValueError, match=err_msg): crack_prvkey(parent_xprv, child_xprv) err_msg = "extended child key is not a private key: " with pytest.raises(BTClibValueError, match=err_msg): crack_prvkey(parent_xpub, parent_xpub) child_xpub = xpub_from_xprv(child_xprv) with pytest.raises(BTClibValueError, match="not a parent's child: wrong depths"): crack_prvkey(child_xpub, child_xprv) child0_xprv = derive(parent_xprv, 0) grandchild_xprv = derive(child0_xprv, 0) err_msg = "not a parent's child: wrong parent fingerprint" with pytest.raises(BTClibValueError, match=err_msg): crack_prvkey(child_xpub, grandchild_xprv) hardened_child_xprv = derive(parent_xprv, 0x80000000) with pytest.raises(BTClibValueError, match="hardened child derivation"): crack_prvkey(parent_xpub, hardened_child_xprv)
def test_invalid_bip32_xkeys() -> None: filename = path.join(data_folder, "bip32_invalid_keys.json") with open(filename, "r") as file_: test_vectors = json.load(file_) for xkey, err_msg in test_vectors: with pytest.raises(BTClibValueError, match=re.escape(err_msg)): BIP32KeyData.deserialize(xkey)
def test_point_from_bip340pubkey() -> None: q, x_Q = ssa.gen_keys() Q = mult(q) # Integer (int) assert ssa.point_from_bip340pubkey(x_Q) == Q # Integer (bytes) assert ssa.point_from_bip340pubkey(x_Q.to_bytes(32, byteorder="big")) == Q # Integer (hex-str) assert ssa.point_from_bip340pubkey( x_Q.to_bytes(32, byteorder="big").hex()) == Q # tuple Point assert ssa.point_from_bip340pubkey(Q) == Q # 33 bytes assert ssa.point_from_bip340pubkey(bytes_from_point(Q)) == Q # 33 bytes hex-string assert ssa.point_from_bip340pubkey(bytes_from_point(Q).hex()) == Q # 65 bytes assert ssa.point_from_bip340pubkey(bytes_from_point(Q, compressed=False)) == Q # 65 bytes hex-string assert ssa.point_from_bip340pubkey( bytes_from_point(Q, compressed=False).hex()) == Q xpub_data = BIP32KeyData.deserialize( "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy" ) xpub_data.key = bytes_from_point(Q) # BIP32KeyData assert ssa.point_from_bip340pubkey(xpub_data) == Q # BIP32Key encoded str xpub = xpub_data.serialize() assert ssa.point_from_bip340pubkey(xpub) == Q # BIP32Key str assert ssa.point_from_bip340pubkey(xpub.decode("ascii")) == Q
def test_fingerprint() -> None: seed = "bfc4cbaad0ff131aa97fa30a48d09ae7df914bcc083af1e07793cd0a7c61a03f65d622848209ad3366a419f4718a80ec9037df107d8d12c19b83202de00a40ad" xprv = rootxprv_from_seed(seed) pf = fingerprint(xprv) # xprv is automatically converted to xpub child_key = derive(xprv, 0x80000000) pf2 = BIP32KeyData.deserialize(child_key).parent_fingerprint assert pf == pf2
def test_dataclasses_json_dict() -> None: xkey = derive( "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", "m/0h", ) # dataclass xkey_data = BIP32KeyData.deserialize(xkey) assert isinstance(xkey_data, BIP32KeyData) # str xkey_json_str = xkey_data.to_json() assert isinstance(xkey_json_str, str) assert xkey_data == BIP32KeyData.from_json(xkey_json_str) # dict xkey_dict = xkey_data.to_dict() assert isinstance(xkey_dict, dict) assert xkey_data == BIP32KeyData.from_dict(xkey_dict) datadir = path.join(path.dirname(__file__), "generated_files") filename = path.join(datadir, "xkey.json") with open(filename, "w") as file_: json.dump(xkey_dict, file_, indent=4)
def test_serialization() -> None: xkey = "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi" xkey_data = BIP32KeyData.deserialize(xkey) decoded_key = b58decode(xkey, 78) assert xkey_data.version == decoded_key[:4] assert xkey_data.depth == decoded_key[4] assert xkey_data.parent_fingerprint == decoded_key[5:9] assert xkey_data.index == int.from_bytes(decoded_key[9:13], "big") assert xkey_data.chain_code == decoded_key[13:45] assert xkey_data.key == decoded_key[45:] assert xkey_data.serialize().decode("ascii") == xkey xpub = xpub_from_xprv(xkey) xpub2 = xpub_from_xprv(xkey_data) assert xpub == xpub2
plain_prv_keys: List[Union[bytes, str]] = [ q_hexstring, q_hexstring2, ] wif_compressed = b58encode(b"\x80" + q_bytes + b"\x01") wif_compressed_string = wif_compressed.decode("ascii") wif_compressed_string2 = " " + wif_compressed_string + " " wif_uncompressed = b58encode(b"\x80" + q_bytes) wif_uncompressed_string = wif_uncompressed.decode("ascii") wif_uncompressed_string2 = " " + wif_uncompressed_string + " " xprv_data = BIP32KeyData( version=bytes.fromhex("04 88 ad e4"), depth=0, parent_fingerprint=bytes.fromhex("00000000"), index=0, chain_code=32 * b"\x00", key=b"\x00" + q_bytes, ) xprv = xprv_data.serialize(False) xprv_string = xprv.decode("ascii") xprv_string2 = " " + xprv_string + " " net_aware_compressed_prv_keys: List[Union[bytes, str]] = [ wif_compressed_string, wif_compressed_string2, xprv_string, xprv_string2, ] net_aware_uncompressed_prv_keys: List[Union[bytes, str]] = [ wif_uncompressed_string,
def test_assert_valid() -> None: xkey = "xprv9s21ZrQH143K2ZP8tyNiUtgoezZosUkw9hhir2JFzDhcUWKz8qFYk3cxdgSFoCMzt8E2Ubi1nXw71TLhwgCfzqFHfM5Snv4zboSebePRmLS" xkey_data = BIP32KeyData.deserialize(xkey) xkey_data.version = (xkey_data.version)[:-1] with pytest.raises(BTClibValueError, match="invalid version length: "): xkey_data.assert_valid() xkey_data = BIP32KeyData.deserialize(xkey) xkey_data.version = "1234" # type: ignore with pytest.raises(BTClibValueError, match="version is not an instance of bytes"): xkey_data.assert_valid() xkey_data = BIP32KeyData.deserialize(xkey) xkey_data.depth = -1 with pytest.raises(BTClibValueError, match="invalid depth: "): xkey_data.assert_valid() xkey_data = BIP32KeyData.deserialize(xkey) xkey_data.depth = 256 with pytest.raises(BTClibValueError, match="invalid depth: "): xkey_data.assert_valid() xkey_data = BIP32KeyData.deserialize(xkey) xkey_data.depth = "1" # type: ignore with pytest.raises(BTClibValueError, match="depth is not an instance of int"): xkey_data.assert_valid() xkey_data = BIP32KeyData.deserialize(xkey) xkey_data.parent_fingerprint = (xkey_data.parent_fingerprint)[:-1] with pytest.raises(BTClibValueError, match="invalid parent fingerprint length: "): xkey_data.assert_valid() xkey_data = BIP32KeyData.deserialize(xkey) xkey_data.parent_fingerprint = "1234" # type: ignore with pytest.raises(BTClibValueError, match="parent fingerprint is not an instance of bytes"): xkey_data.assert_valid() xkey_data = BIP32KeyData.deserialize(xkey) xkey_data.index = -1 with pytest.raises(BTClibValueError, match="invalid index: "): xkey_data.assert_valid() xkey_data = BIP32KeyData.deserialize(xkey) xkey_data.index = 0xFFFFFFFF + 1 with pytest.raises(BTClibValueError, match="invalid index: "): xkey_data.assert_valid() xkey_data = BIP32KeyData.deserialize(xkey) xkey_data.index = "1234" # type: ignore with pytest.raises(BTClibValueError, match="index is not an instance of bytes"): xkey_data.assert_valid() xkey_data = BIP32KeyData.deserialize(xkey) xkey_data.chain_code = (xkey_data.chain_code)[:-1] with pytest.raises(BTClibValueError, match="invalid chain code length: "): xkey_data.assert_valid() xkey_data = BIP32KeyData.deserialize(xkey) xkey_data.chain_code = "length is 32 but not a chaincode" # type: ignore with pytest.raises(BTClibValueError, match="chain code is not an instance of bytes"): xkey_data.assert_valid() xkey_data = BIP32KeyData.deserialize(xkey) xkey_data.key = (xkey_data.key)[:-1] with pytest.raises(BTClibValueError, match="invalid key length: "): xkey_data.assert_valid() xkey_data = BIP32KeyData.deserialize(xkey) xkey_data.key = "length is 33, but not a key" # type: ignore with pytest.raises(BTClibValueError, match="key is not an instance of bytes"): xkey_data.assert_valid() xkey_data = BIP32KeyData.deserialize(xkey) xkey_data.parent_fingerprint = bytes.fromhex("deadbeef") err_msg = "zero depth with non-zero parent fingerprint: " with pytest.raises(BTClibValueError, match=err_msg): xkey_data.serialize() xkey_data = BIP32KeyData.deserialize(xkey) xkey_data.index = 1 with pytest.raises(BTClibValueError, match="zero depth with non-zero index: "): xkey_data.serialize()