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_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 b58decode( cls: Type["BIP32KeyData"], address: String, check_validity: bool = True ) -> "BIP32KeyData": if isinstance(address, str): address = address.strip() xkey_bin = base58.b58decode(address) # pylance cannot grok the following line return cls.parse(xkey_bin, check_validity) # type: ignore
def test_exceptions() -> None: 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_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_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_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 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(ValueError, match="invalid 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") err_msg = "not enough bytes for checksum, invalid base58 decoded size: " with pytest.raises(ValueError, 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_serialization() -> None: xkey = "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi" xkey_data = BIP32KeyData.b58decode(xkey) decoded_key = base58.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", signed=False) assert xkey_data.chain_code == decoded_key[13:45] assert xkey_data.key == decoded_key[45:] assert xkey_data.b58encode() == xkey xpub = xpub_from_xprv(xkey) xpub2 = xpub_from_xprv(xkey_data) assert xpub == xpub2
def h160_from_address(b58addr: String) -> Tuple[str, bytes, str]: "Return the payload from a base58 address." if isinstance(b58addr, str): b58addr = b58addr.strip() payload = b58decode(b58addr, 21) prefix = payload[:1] for script_type in ("p2pkh", "p2sh"): # with pytohn>=3.8 use walrus operator # if network := network_from_key_value(script_type, prefix): network = network_from_key_value(script_type, prefix) if network: return script_type, payload[1:], network err_msg = f"invalid base58 address prefix: 0x{prefix.hex()}" raise BTClibValueError(err_msg)
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 _prv_keyinfo_from_wif(wif: String, network: Optional[str] = None, compressed: Optional[bool] = None) -> PrvkeyInfo: """Return private key tuple(int, compressed, network) from a WIF. WIF is always compressed and includes network information: here the 'network, compressed' input parameters are passed only to allow consistency checks. """ if isinstance(wif, str): wif = wif.strip() payload = b58decode(wif) net = network_from_key_value("wif", payload[:1]) if net is None: raise BTClibValueError(f"invalid wif prefix: {payload[:1]!r}") if network is not None and net != network: raise BTClibValueError(f"not a {network} wif: {wif!r}") ec = NETWORKS[net].curve if len(payload) == ec.n_size + 2: # compressed WIF compr = True if payload[-1] != 0x01: # must have a trailing 0x01 raise BTClibValueError( "not a compressed WIF: missing trailing 0x01") prv_key = payload[1:-1] elif len(payload) == ec.n_size + 1: # uncompressed WIF compr = False prv_key = payload[1:] else: raise BTClibValueError(f"wrong WIF size: {len(payload)}") if compressed is not None and compr != compressed: raise BTClibValueError("compression requirement mismatch") q = int.from_bytes(prv_key, byteorder="big") if not 0 < q < ec.n: raise BTClibValueError(f"private key {hex(q)} not in [1, n-1]") return q, net, compr
def test_deserialize(): xprv = "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi" xprv_dict = deserialize(xprv) decoded_key = b58decode(xprv, 78) assert xprv_dict["version"] == decoded_key[:4] assert xprv_dict["depth"] == decoded_key[4] assert xprv_dict["parent_fingerprint"] == decoded_key[5:9] assert xprv_dict["index"] == decoded_key[9:13] assert xprv_dict["chain_code"] == decoded_key[13:45] assert xprv_dict["key"] == decoded_key[45:] # no harm in deserializing again an already deserialized key xprv_dict = deserialize(xprv_dict) xpr2 = serialize(xprv_dict) assert xpr2.decode(), xprv xpub = xpub_from_xprv(xprv) xpub2 = xpub_from_xprv(deserialize(xprv)) assert xpub == xpub2
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 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)
print("\n*** [7] Base58 encoding") wif = b58encode(addr) print(wif) assert wif == b'KwdMAjGmerYanjeui5SHS7JkmpZvVipYvB2LJGU1ZxJwYvP98617', "failure" assert b58encode_check( ExtKey ) == b'KwdMAjGmerYanjeui5SHS7JkmpZvVipYvB2LJGU1ZxJwYvP98617', "failure" 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") addr = b58decode(wif) print(addr.hex()) print("\n*** [3] Extended key (checksum verified)") ExtKey, checksum = addr[:-4], addr[-4:] verified = (sha256(sha256(ExtKey).digest()).digest()[:4] == checksum) print(ExtKey.hex() + " (" + ("true" if verified else "false") + ")") print(b58decode_check(wif).hex()) print("\n*** [4] Private key") p2 = ExtKey[1:-1].hex() if compressed else ExtKey[1:].hex() assert int(p2, 16) == p, "failure" print(p2)
def hash_160_from_address(addr): return base58.b58decode(addr)[1:21]
def test_empty() -> None: assert _b58encode(b"") == b"" assert _b58decode(_b58encode(b"")) == b"" assert b58decode(b58encode(b""), 0) == b""
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:] verified = sha256(sha256(payload).digest()).digest()[:4] == checksum print(payload.hex() + " (" + ("true" if verified else "false") + ")") print(base58.b58decode(wif).hex()) print("\n*** [4] Private key") q2 = payload[1:-1].hex() if compressed else payload[1:].hex() assert int(q2, 16) == q, "failure" print(q2)