def test_wif_from_prvkey() -> None: prvkey = "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: 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.to_bytes(ec.nsize, "big") with pytest.raises(ValueError, match="private key not in 1..n-1: "): 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 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_p2pkh_from_wif() -> None: seed = b"00" * 32 # better be a documented test case rxprv = bip32.rootxprv_from_seed(seed) path = "m/0h/0h/12" xprv = bip32.derive(rxprv, path) wif = wif_from_prvkey(xprv) assert wif == b"KyLk7s6Z1FtgYEVp3bPckPVnXvLUWNCcVL6wNt3gaT96EmzTKZwP" pubkey, _ = pubkeyinfo_from_prvkey(wif) address = p2pkh(pubkey) xpub = bip32.xpub_from_xprv(xprv) address2 = slip132.address_from_xpub(xpub) assert address == address2 err_msg = "not a private key: " with pytest.raises(ValueError, match=err_msg): wif_from_prvkey(xpub)
def test_p2pkh_from_wif() -> None: seed = b"\x00" * 32 # better be a documented test case rxprv = bip32.rootxprv_from_seed(seed) path = "m/0h/0h/12" xprv = bip32.derive(rxprv, path) wif = wif_from_prvkey(xprv) assert wif == b"L2L1dqRmkmVtwStNf5wg8nnGaRn3buoQr721XShM4VwDbTcn9bpm" pubkey, _ = pubkeyinfo_from_prvkey(wif) address = p2pkh(pubkey) xpub = bip32.xpub_from_xprv(xprv) address2 = slip132.address_from_xpub(xpub) assert address == address2 err_msg = "not a private key: " with pytest.raises(ValueError, match=err_msg): wif_from_prvkey(xpub)
def test_one_prvkey_multiple_addresses(self): msg = "Paolo is afraid of ephemeral random numbers" # Compressed WIF wif = b'Kx45GeUBSMPReYQwgXiKhG9FzNXrnCeutJp4yjTd5kKxCitadm3C' pubkey, network = pubkey_info_from_prvkey(wif) address1 = p2pkh(pubkey, network) address2 = p2wpkh_p2sh(pubkey, network) address3 = p2wpkh(pubkey, network) # sign with no address (or compressed P2PKH) sig1 = bms.sign(msg, wif) # True for Bitcoin Core self.assertTrue(bms.verify(msg, address1, sig1)) # True for Electrum p2wpkh_p2sh self.assertTrue(bms.verify(msg, address2, sig1)) # True for Electrum p2wpkh self.assertTrue(bms.verify(msg, address3, sig1)) # sign with p2wpkh_p2sh address (BIP137) sig2 = bms.sign(msg, wif, address2) # False for Bitcoin Core self.assertFalse(bms.verify(msg, address1, sig2)) # True for BIP137 p2wpkh_p2sh self.assertTrue(bms.verify(msg, address2, sig2)) # False for BIP137 p2wpkh self.assertFalse(bms.verify(msg, address3, sig2)) # sign with p2wpkh address (BIP137) sig3 = bms.sign(msg, wif, address3) # False for Bitcoin Core self.assertFalse(bms.verify(msg, address1, sig3)) # False for BIP137 p2wpkh_p2sh self.assertFalse(bms.verify(msg, address2, sig3)) # True for BIP137 p2wpkh self.assertTrue(bms.verify(msg, address3, sig3)) # uncompressed WIF / P2PKH address q, network, _ = prvkey_info_from_prvkey(wif) wif2 = wif_from_prvkey(q, network, False) pubkey, network = pubkey_info_from_prvkey(wif2) address4 = p2pkh(pubkey, network) # sign with uncompressed P2PKH sig4 = bms.sign(msg, wif2, address4) # False for Bitcoin Core compressed p2pkh self.assertFalse(bms.verify(msg, address1, sig4)) # False for BIP137 p2wpkh_p2sh self.assertFalse(bms.verify(msg, address2, sig4)) # False for BIP137 p2wpkh self.assertFalse(bms.verify(msg, address3, sig4)) # True for Bitcoin Core uncompressed p2pkh self.assertTrue(bms.verify(msg, address4, sig4)) self.assertRaises(ValueError, bms.sign, msg, wif2, address1) self.assertRaises(ValueError, bms.sign, msg, wif, address4)
def test_msgsign_p2pkh(self): msg = "test message" # sigs are taken from (Electrum and) Bitcoin Core q = "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb" # uncompressed wif1u = wif_from_prvkey(q, "mainnet", False) self.assertEqual( wif1u, b"5KMWWy2d3Mjc8LojNoj8Lcz9B1aWu8bRofUgGwQk959Dw5h2iyw") pubkey1u, _ = pubkeyinfo_from_prvkey(wif1u) add1u = base58address.p2pkh(pubkey1u) self.assertEqual(add1u, b"1HUBHMij46Hae75JPdWjeZ5Q7KaL7EFRSD") sig1u = bms.sign(msg, wif1u) self.assertTrue(bms.verify(msg, add1u, sig1u)) self.assertEqual(sig1u[0], 27) exp_sig1u = ("G/iew/NhHV9V9MdUEn/LFOftaTy1ivGPKPKyMlr8OSokNC755fAxpST" "hNRivwTNsyY9vPUDTRYBPc2cmGd5d4y4=").encode() self.assertEqual(bms.serialize(*sig1u), exp_sig1u) # compressed wif1c = wif_from_prvkey(q, "mainnet", True) self.assertEqual( wif1c, b"L41XHGJA5QX43QRG3FEwPbqD5BYvy6WxUxqAMM9oQdHJ5FcRHcGk") pubkey1c, _ = pubkeyinfo_from_prvkey(wif1c) add1c = base58address.p2pkh(pubkey1c) self.assertEqual(add1c, b"14dD6ygPi5WXdwwBTt1FBZK3aD8uDem1FY") sig1c = bms.sign(msg, wif1c) self.assertTrue(bms.verify(msg, add1c, sig1c)) self.assertEqual(sig1c[0], 31) exp_sig1c = ("H/iew/NhHV9V9MdUEn/LFOftaTy1ivGPKPKyMlr8OSokNC755fAxpST" "hNRivwTNsyY9vPUDTRYBPc2cmGd5d4y4=").encode() self.assertEqual(bms.serialize(*sig1c), exp_sig1c) self.assertFalse(bms.verify(msg, add1c, sig1u)) self.assertFalse(bms.verify(msg, add1u, sig1c)) rf, r, s, = sig1c sig1c_malleated_rf = bms.serialize(rf + 1, r, s) self.assertFalse(bms.verify(msg, add1c, sig1c_malleated_rf)) sig1c_malleated_s = bms.serialize(rf, r, ec.n - s) self.assertFalse(bms.verify(msg, add1c, sig1c_malleated_s)) sig1c_malleated_rf_s = bms.serialize(rf + 1, r, ec.n - s) self.assertTrue(bms.verify(msg, add1c, sig1c_malleated_rf_s))
def test_msgsign_p2pkh(self): msg = 'test message' # sigs are taken from (Electrum and) Bitcoin Core # first private key q1 = 91634880152443617534842621287039938041581081254914058002978601050179556493499 # uncompressed wif1u = wif_from_prvkey(q1, 'mainnet', False) self.assertEqual( wif1u, b'5KMWWy2d3Mjc8LojNoj8Lcz9B1aWu8bRofUgGwQk959Dw5h2iyw') pubkey1u, _ = pubkey_info_from_prvkey(wif1u) add1u = base58address.p2pkh(pubkey1u) self.assertEqual(add1u, b'1HUBHMij46Hae75JPdWjeZ5Q7KaL7EFRSD') sig1u = bms.sign(msg, wif1u) self.assertTrue(bms.verify(msg, add1u, sig1u)) self.assertEqual(sig1u[0], 27) exp_sig1u = b'G/iew/NhHV9V9MdUEn/LFOftaTy1ivGPKPKyMlr8OSokNC755fAxpSThNRivwTNsyY9vPUDTRYBPc2cmGd5d4y4=' self.assertEqual(bms.serialize(*sig1u), exp_sig1u) # compressed wif1c = wif_from_prvkey(q1, 'mainnet', True) self.assertEqual( wif1c, b'L41XHGJA5QX43QRG3FEwPbqD5BYvy6WxUxqAMM9oQdHJ5FcRHcGk') pubkey1c, _ = pubkey_info_from_prvkey(wif1c) add1c = base58address.p2pkh(pubkey1c) self.assertEqual(add1c, b'14dD6ygPi5WXdwwBTt1FBZK3aD8uDem1FY') sig1c = bms.sign(msg, wif1c) self.assertTrue(bms.verify(msg, add1c, sig1c)) self.assertEqual(sig1c[0], 31) exp_sig1c = b'H/iew/NhHV9V9MdUEn/LFOftaTy1ivGPKPKyMlr8OSokNC755fAxpSThNRivwTNsyY9vPUDTRYBPc2cmGd5d4y4=' self.assertEqual(bms.serialize(*sig1c), exp_sig1c) self.assertFalse(bms.verify(msg, add1c, sig1u)) self.assertFalse(bms.verify(msg, add1u, sig1c)) rf, r, s, = sig1c sig1c_malleated_rf = bms.serialize(rf + 1, r, s) self.assertFalse(bms.verify(msg, add1c, sig1c_malleated_rf)) sig1c_malleated_s = bms.serialize(rf, r, ec.n - s) self.assertFalse(bms.verify(msg, add1c, sig1c_malleated_s)) sig1c_malleated_rf_s = bms.serialize(rf + 1, r, ec.n - s) self.assertTrue(bms.verify(msg, add1c, sig1c_malleated_rf_s))
def test_address_from_wif() -> None: q = 0x19E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725 test_cases: List[Tuple[bool, str, str, str]] = [ ( False, "mainnet", "5J1geo9kcAUSM6GJJmhYRX1eZEjvos9nFyWwPstVziTVueRJYvW", "1LPM8SZ4RQDMZymUmVSiSSvrDfj1UZY9ig", ), ( True, "mainnet", "Kx621phdUCp6sgEXPSHwhDTrmHeUVrMkm6T95ycJyjyxbDXkr162", "1HJC7kFvXHepkSzdc8RX6khQKkAyntdfkB", ), ( False, "testnet", "91nKEXyJCPYaK9maw7bTJ7ZcCu6dy2gybvNtUWF1LTCYggzhZgy", "mzuJRVe3ERecM6F6V4R6GN9B5fKiPC9HxF", ), ( True, "testnet", "cNT1UjhUuGWN37hnmr754XxvPWwtAJTSq8bcCQ4pUrdxqxbA1iU1", "mwp9QoLuLK65XZUFKhPtvfujBjmgkZnmPx", ), ] for compressed, network, wif, address in test_cases: assert wif.encode() == wif_from_prvkey(q, network, compressed) assert prvkeyinfo_from_prvkey(wif) == (q, network, compressed) b58 = p2pkh(wif) assert b58 == address.encode() _, payload, net, is_script = h160_from_b58address(b58) assert net == network assert not is_script if compressed: b32 = p2wpkh(wif) assert (payload, network, is_script) == witness_from_b32address(b32)[1:] b = p2wpkh_p2sh(wif) _, payload2, net, is_script = h160_from_b58address(b) assert is_script assert (hash160(b"\x00\x14" + payload), network) == (payload2, net) else: err_msg = "not a private or compressed public key: " with pytest.raises(ValueError, match=err_msg): p2wpkh(wif) # type: ignore with pytest.raises(ValueError, match=err_msg): p2wpkh_p2sh(wif) # type: ignore
def test_msgsign_p2pkh() -> None: msg = "test message" # sigs are taken from (Electrum and) Bitcoin Core q = "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb" # uncompressed wif1u = wif_from_prvkey(q, "mainnet", False) assert wif1u == b"5KMWWy2d3Mjc8LojNoj8Lcz9B1aWu8bRofUgGwQk959Dw5h2iyw" add1u = base58address.p2pkh(wif1u) assert add1u == b"1HUBHMij46Hae75JPdWjeZ5Q7KaL7EFRSD" sig1u = bms.sign(msg, wif1u) assert bms.verify(msg, add1u, sig1u) assert sig1u[0] == 27 exp_sig1u = "G/iew/NhHV9V9MdUEn/LFOftaTy1ivGPKPKyMlr8OSokNC755fAxpSThNRivwTNsyY9vPUDTRYBPc2cmGd5d4y4=" assert bms.encode(*sig1u) == exp_sig1u.encode() # compressed wif1c = wif_from_prvkey(q, "mainnet", True) assert wif1c == b"L41XHGJA5QX43QRG3FEwPbqD5BYvy6WxUxqAMM9oQdHJ5FcRHcGk" add1c = base58address.p2pkh(wif1c) assert add1c == b"14dD6ygPi5WXdwwBTt1FBZK3aD8uDem1FY" sig1c = bms.sign(msg, wif1c) assert bms.verify(msg, add1c, sig1c) assert sig1c[0] == 31 exp_sig1c = "H/iew/NhHV9V9MdUEn/LFOftaTy1ivGPKPKyMlr8OSokNC755fAxpSThNRivwTNsyY9vPUDTRYBPc2cmGd5d4y4=" assert bms.encode(*sig1c) == exp_sig1c.encode() assert not bms.verify(msg, add1c, sig1u) assert not bms.verify(msg, add1u, sig1c) rf, r, s = sig1c sig1c_malleated_rf = bms.encode(rf + 1, r, s) assert not bms.verify(msg, add1c, sig1c_malleated_rf) sig1c_malleated_s = bms.encode(rf, r, ec.n - s) assert not bms.verify(msg, add1c, sig1c_malleated_s) sig1c_malleated_rf_s = bms.encode(rf + 1, r, ec.n - s) assert bms.verify(msg, add1c, sig1c_malleated_rf_s)
def test_p2pkh_from_wif(self): seed = b"00" * 32 # better be random rxprv = bip32.rootxprv_from_seed(seed) path = "m/0h/0h/12" xprv = bip32.derive(rxprv, path) wif = wif_from_prvkey(xprv) self.assertEqual( wif, b'KyLk7s6Z1FtgYEVp3bPckPVnXvLUWNCcVL6wNt3gaT96EmzTKZwP') pubkey, _ = pubkey_info_from_prvkey(wif) address = p2pkh(pubkey) xpub = bip32.xpub_from_xprv(xprv) address2 = slip32.address_from_xpub(xpub) self.assertEqual(address, address2) self.assertRaises(ValueError, wif_from_prvkey, xpub)
def test_info_from_prvkey(self): xprv = ( "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiC" "hkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi").encode() xprv_str = xprv.decode("ascii") xprv_dict = bip32.deserialize(xprv) wif = wif_from_prvkey(xprv) wif_str = wif.decode("ascii") ref_tuple = (xprv_dict["q"], "mainnet", True) # BIP32 self.assertEqual(ref_tuple, prvkeyinfo_from_prvkey(xprv, "mainnet")) self.assertEqual(ref_tuple, prvkeyinfo_from_prvkey(xprv)) self.assertEqual(ref_tuple, prvkeyinfo_from_prvkey(xprv_str)) self.assertEqual(ref_tuple, prvkeyinfo_from_prvkey(" " + xprv_str + " ")) self.assertEqual(ref_tuple, prvkeyinfo_from_prvkey(xprv_dict)) # Invalid decoded size: 6 bytes instead of 82 xpub = "notakey" self.assertRaises(ValueError, prvkeyinfo_from_prvkey, xpub) # prvkeyinfo_from_prvkey(xpub) # xkey is not a private one xpub = ( "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2g" "Z29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8").encode() self.assertRaises(ValueError, prvkeyinfo_from_prvkey, xpub) # prvkeyinfo_from_prvkey(xpub) # xkey is not a private one xpub_dict = bip32.deserialize(xpub) self.assertRaises(ValueError, prvkeyinfo_from_prvkey, xpub_dict) # prvkeyinfo_from_prvkey(xpub_dict) # WIF keys (bytes or string) self.assertEqual(ref_tuple, prvkeyinfo_from_prvkey(wif)) self.assertEqual(ref_tuple, prvkeyinfo_from_prvkey(wif_str)) self.assertEqual(ref_tuple, prvkeyinfo_from_prvkey(" " + wif_str + " "))
def test_pubkeyinfo_from_key(self): # prvkeys xprv = ( "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiC" "hkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi").encode() xprv_str = xprv.decode("ascii") xprv_dict = bip32.deserialize(xprv) q, network, _ = _prvkeyinfo_from_xprv(xprv) ec = NETWORKS[network]["curve"] q_bytes = q.to_bytes(ec.nsize, "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(pubkeyinfo_from_key(q)[0], Q_compr) self.assertEqual(pubkeyinfo_from_key(q_bytes)[0], Q_compr) # int prvkey, uncompressed result self.assertEqual( pubkeyinfo_from_key(q, compressed=False)[0], Q_uncompr) self.assertEqual( pubkeyinfo_from_key(q_bytes, compressed=False)[0], Q_uncompr) # compressed wif prvkey, both results self.assertEqual(pubkeyinfo_from_key(wif1)[0], Q_compr) self.assertRaises(ValueError, pubkeyinfo_from_key, wif1, compressed=False) # uncompressed wif prvkey, both results self.assertRaises(ValueError, pubkeyinfo_from_key, wif2, compressed=True) self.assertEqual(pubkeyinfo_from_key(wif2)[0], Q_uncompr) # (compressed) BIP32 prvkey, compressed results self.assertEqual(pubkeyinfo_from_key(xprv)[0], Q_compr) self.assertEqual(pubkeyinfo_from_key(xprv_str)[0], Q_compr) self.assertEqual(pubkeyinfo_from_key(" " + xprv_str + " ")[0], Q_compr) self.assertEqual(pubkeyinfo_from_key(xprv_dict)[0], Q_compr) # (compressed) BIP32 prvkey, uncompressed result self.assertRaises(ValueError, pubkeyinfo_from_key, xprv, compressed=False) self.assertRaises(ValueError, pubkeyinfo_from_key, xprv_str, compressed=False) self.assertRaises(ValueError, pubkeyinfo_from_key, " " + xprv_str + " ", compressed=False) self.assertRaises(ValueError, pubkeyinfo_from_key, xprv_dict, compressed=False) # (compressed) BIP32 pubkey, compressed results self.assertEqual(pubkeyinfo_from_key(xpub)[0], Q_compr) self.assertEqual(pubkeyinfo_from_key(xpub_str)[0], Q_compr) self.assertEqual(pubkeyinfo_from_key(" " + xpub_str + " ")[0], Q_compr) self.assertEqual(pubkeyinfo_from_key(xpub_dict)[0], Q_compr) # (compressed) BIP32 pubkey, uncompressed result self.assertRaises(ValueError, pubkeyinfo_from_key, xpub, compressed=False) self.assertRaises(ValueError, pubkeyinfo_from_key, xpub_str, compressed=False) self.assertRaises(ValueError, pubkeyinfo_from_key, " " + xpub_str + " ", compressed=False) self.assertRaises(ValueError, pubkeyinfo_from_key, xpub_dict, compressed=False) # compressed SEC Octets (pubkey), compressed results self.assertEqual(pubkeyinfo_from_key(Q_compr)[0], Q_compr) self.assertEqual(pubkeyinfo_from_key(Q_compr_hexstr)[0], Q_compr) self.assertEqual( pubkeyinfo_from_key(" " + Q_compr_hexstr + " ")[0], Q_compr) # compressed SEC Octets (pubkey), uncompressed results self.assertRaises(ValueError, pubkeyinfo_from_key, Q_compr, compressed=False) self.assertRaises(ValueError, pubkeyinfo_from_key, Q_compr_hexstr, compressed=False) self.assertRaises( ValueError, pubkeyinfo_from_key, " " + Q_compr_hexstr + " ", compressed=False, ) self.assertRaises(ValueError, pubkeyinfo_from_key, b"\x00" + Q_compr) self.assertRaises(ValueError, pubkeyinfo_from_key, Q_compr_hexstr + "00") # uncompressed SEC Octets (pubkey), uncompressed results self.assertEqual(pubkeyinfo_from_key(Q_uncompr)[0], Q_uncompr) self.assertEqual(pubkeyinfo_from_key(Q_uncompr_hexstr)[0], Q_uncompr) self.assertEqual( pubkeyinfo_from_key(" " + Q_uncompr_hexstr + " ")[0], Q_uncompr) # uncompressed SEC Octets (pubkey), compressed results self.assertRaises(ValueError, pubkeyinfo_from_key, Q_uncompr, compressed=True) self.assertRaises(ValueError, pubkeyinfo_from_key, Q_uncompr_hexstr, compressed=True) self.assertRaises( ValueError, pubkeyinfo_from_key, " " + Q_uncompr_hexstr + " ", compressed=True, ) self.assertRaises(ValueError, pubkeyinfo_from_key, b"\x00" + Q_uncompr) self.assertRaises(ValueError, pubkeyinfo_from_key, Q_uncompr_hexstr + "00") # native tuple input, both results self.assertEqual(pubkeyinfo_from_key(Q)[0], Q_compr) self.assertEqual( pubkeyinfo_from_key(Q, compressed=False)[0], Q_uncompr) # pubkeyinfo_from_pubkey does not accept prvkey inputs self.assertRaises(TypeError, pubkeyinfo_from_pubkey, q) self.assertRaises(ValueError, pubkeyinfo_from_pubkey, q_bytes) self.assertRaises(ValueError, pubkeyinfo_from_pubkey, xprv) self.assertRaises(ValueError, pubkeyinfo_from_pubkey, xprv_str) self.assertRaises(ValueError, pubkeyinfo_from_pubkey, xprv_dict) self.assertRaises(ValueError, pubkeyinfo_from_pubkey, wif1) self.assertRaises(ValueError, pubkeyinfo_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, _pubkeyinfo_from_xpub, xpub_dict_bad) # _pubkeyinfo_from_xpub(xpub_dict_bad) # Invalid point: 7 is not a field element Q = INF self.assertRaises(ValueError, pubkeyinfo_from_key, Q) Q_compr = b"\x02" + Q[0].to_bytes(ec.psize, "big") self.assertRaises(ValueError, pubkeyinfo_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, pubkeyinfo_from_key, Q_uncompr) Q_compr_hexstr = Q_compr.hex() self.assertRaises(ValueError, pubkeyinfo_from_key, Q_compr_hexstr) Q_uncompr_hexstr = Q_uncompr.hex() self.assertRaises(ValueError, pubkeyinfo_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, 78) self.assertRaises(ValueError, pubkeyinfo_from_key, xpub) xpub_str = xpub.decode("ascii") self.assertRaises(ValueError, pubkeyinfo_from_key, xpub_str)
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(f"rf3: {sig3[0]}") print(f" r3: {hex(sig3[1]).upper()}") print(f" s3: {hex(sig3[2]).upper()}") bsmsig3 = encode(*sig3) print("4. Serialized signature:") print(bsmsig3.decode()) print("5. Verify signature") print("Bitcoin Core p2pkh:", verify(msg, address1, sig3)) print("BIP137 p2wpkh_p2sh:", verify(msg, address2, sig3)) print("BIP137 p2wpkh :", verify(msg, address3, sig3)) # uncompressed WIF / P2PKH address q, network, _ = prvkeyinfo_from_prvkey(wif) wif2 = wif_from_prvkey(q, network, compressed=False) print("\n1. Uncompressed WIF :", wif2.decode()) pubkey, network = pubkeyinfo_from_prvkey(wif2) address4 = p2pkh(pubkey) print("2. Uncompressed P2PKH address:", address4.decode()) print("3. Sign message with uncompressed p2pkh:") sig4 = sign(msg, wif2, address4) print(f"rf4: {sig4[0]}") print(f" r4: {hex(sig4[1]).upper()}") print(f" s4: {hex(sig4[2]).upper()}") bsmsig4 = encode(*sig4) print("4. Serialized signature:") print(bsmsig4.decode())
def test_one_prvkey_multiple_addresses() -> None: msg = "Paolo is afraid of ephemeral random numbers" # Compressed WIF wif = b"Kx45GeUBSMPReYQwgXiKhG9FzNXrnCeutJp4yjTd5kKxCitadm3C" addr_p2pkh_compressed = p2pkh(wif) addr_p2wpkh_p2sh = p2wpkh_p2sh(wif) addr_p2wpkh = p2wpkh(wif) # sign with no address sig1 = bms.sign(msg, wif) # True for Bitcoin Core bms.assert_as_valid(msg, addr_p2pkh_compressed, sig1) assert bms.verify(msg, addr_p2pkh_compressed, sig1) # True for Electrum p2wpkh_p2sh bms.assert_as_valid(msg, addr_p2wpkh_p2sh, sig1) assert bms.verify(msg, addr_p2wpkh_p2sh, sig1) # True for Electrum p2wpkh bms.assert_as_valid(msg, addr_p2wpkh, sig1) assert bms.verify(msg, addr_p2wpkh, sig1) # sign with no p2pkh address sig1 = bms.sign(msg, wif, addr_p2pkh_compressed) # True for Bitcoin Core bms.assert_as_valid(msg, addr_p2pkh_compressed, sig1) assert bms.verify(msg, addr_p2pkh_compressed, sig1) # True for Electrum p2wpkh_p2sh bms.assert_as_valid(msg, addr_p2wpkh_p2sh, sig1) assert bms.verify(msg, addr_p2wpkh_p2sh, sig1) # True for Electrum p2wpkh bms.assert_as_valid(msg, addr_p2wpkh, sig1) assert bms.verify(msg, addr_p2wpkh, sig1) err_msg = "invalid recovery flag: " # sign with p2wpkh_p2sh address (BIP137) sig2 = bms.sign(msg, wif, addr_p2wpkh_p2sh) # False for Bitcoin Core with pytest.raises(BTClibValueError, match=err_msg): bms.assert_as_valid(msg, addr_p2pkh_compressed, sig2) assert not bms.verify(msg, addr_p2pkh_compressed, sig2) # True for BIP137 p2wpkh_p2sh bms.assert_as_valid(msg, addr_p2wpkh_p2sh, sig2) assert bms.verify(msg, addr_p2wpkh_p2sh, sig2) # False for BIP137 p2wpkh with pytest.raises(BTClibValueError, match=err_msg): bms.assert_as_valid(msg, addr_p2wpkh, sig2) assert not bms.verify(msg, addr_p2wpkh, sig2) # sign with p2wpkh address (BIP137) sig3 = bms.sign(msg, wif, addr_p2wpkh) # False for Bitcoin Core with pytest.raises(BTClibValueError, match=err_msg): bms.assert_as_valid(msg, addr_p2pkh_compressed, sig3) assert not bms.verify(msg, addr_p2pkh_compressed, sig3) # False for BIP137 p2wpkh_p2sh with pytest.raises(BTClibValueError, match=err_msg): bms.assert_as_valid(msg, addr_p2wpkh_p2sh, sig3) assert not bms.verify(msg, addr_p2wpkh_p2sh, sig3) # True for BIP137 p2wpkh bms.assert_as_valid(msg, addr_p2wpkh, sig3) assert bms.verify(msg, addr_p2wpkh, sig3) # uncompressed WIF / p2pkh address q, network, _ = prvkeyinfo_from_prvkey(wif) wif2 = wif_from_prvkey(q, network, False) addr_p2pkh_uncompressed = p2pkh(wif2) # sign with uncompressed p2pkh sig4 = bms.sign(msg, wif2, addr_p2pkh_uncompressed) # False for Bitcoin Core compressed p2pkh with pytest.raises(BTClibValueError, match="wrong p2pkh address: "): bms.assert_as_valid(msg, addr_p2pkh_compressed, sig4) assert not bms.verify(msg, addr_p2pkh_compressed, sig4) # False for BIP137 p2wpkh_p2sh # FIXME: puzzling error message # it should have been "wrong p2wpkh-p2sh address: " with pytest.raises(BTClibValueError, match="wrong p2pkh address: "): bms.assert_as_valid(msg, addr_p2wpkh_p2sh, sig4) assert not bms.verify(msg, addr_p2wpkh_p2sh, sig4) # False for BIP137 p2wpkh with pytest.raises(BTClibValueError, match=err_msg): bms.assert_as_valid(msg, addr_p2wpkh, sig4) assert not bms.verify(msg, addr_p2wpkh, sig4) # True for Bitcoin Core uncompressed p2pkh bms.assert_as_valid(msg, addr_p2pkh_uncompressed, sig4) assert bms.verify(msg, addr_p2pkh_uncompressed, sig4) # unrelated different wif wif3 = b"KwdMAjGmerYanjeui5SHS7JkmpZvVipYvB2LJGU1ZxJwYvP98617" addr_p2pkh_compressed = p2pkh(wif3) addr_p2wpkh_p2sh = p2wpkh_p2sh(wif3) addr_p2wpkh = p2wpkh(wif3) # False for Bitcoin Core compressed p2pkh with pytest.raises(BTClibValueError, match="wrong p2pkh address: "): bms.assert_as_valid(msg, addr_p2pkh_compressed, sig1) assert not bms.verify(msg, addr_p2pkh_compressed, sig1) # False for BIP137 p2wpkh_p2sh with pytest.raises(BTClibValueError, match="wrong p2wpkh-p2sh address: "): bms.assert_as_valid(msg, addr_p2wpkh_p2sh, sig1) assert not bms.verify(msg, addr_p2wpkh_p2sh, sig1) # False for BIP137 p2wpkh with pytest.raises(BTClibValueError, match="wrong p2wpkh address: "): bms.assert_as_valid(msg, addr_p2wpkh, sig1) assert not bms.verify(msg, addr_p2wpkh, sig1) # FIXME: puzzling error message err_msg = "not a private or compressed public key for mainnet: " with pytest.raises(BTClibValueError, match=err_msg): bms.sign(msg, wif2, addr_p2pkh_compressed) err_msg = "mismatch between private key and address" with pytest.raises(BTClibValueError, match=err_msg): bms.sign(msg, wif, addr_p2pkh_uncompressed)
def test_wif_from_prvkey(self): 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]) self.assertEqual(v[0].strip(), wif.decode("ascii")) q, network, compressed = prvkeyinfo_from_prvkey(v[0]) self.assertEqual(q, int(prvkey, 16)) self.assertEqual(network, v[1]) self.assertEqual(compressed, v[2]) # not a 32-bytes private key badq = 33 * b"\x02" self.assertRaises(ValueError, wif_from_prvkey, badq, "mainnet", True) # wif_from_prvkey(badq, 'mainnet', True) # private key not in (0, n) badq = ec.n self.assertRaises(ValueError, wif_from_prvkey, badq, "mainnet", True) # wif_from_prvkey(badq, 'mainnet', True) # Not a private key WIF: missing leading 0x80 payload = b"\x81" + badq.to_bytes(ec.nsize, "big") badwif = b58encode(payload) self.assertRaises(ValueError, prvkeyinfo_from_prvkey, badwif) # prvkeyinfo_from_prvkey(badwif) # Not a compressed WIF: missing trailing 0x01 payload = b"\x80" + badq.to_bytes(ec.nsize, "big") + b"\x00" badwif = b58encode(payload) self.assertRaises(ValueError, prvkeyinfo_from_prvkey, badwif) # prvkeyinfo_from_prvkey(badwif) # Not a WIF: wrong size (35) payload = b"\x80" + badq.to_bytes(ec.nsize, "big") + b"\x01\x00" badwif = b58encode(payload) self.assertRaises(ValueError, prvkeyinfo_from_prvkey, badwif) # prvkeyinfo_from_prvkey(badwif) # Not a WIF: private key not in (0, n) payload = b"\x80" + badq.to_bytes(ec.nsize, "big") badwif = b58encode(payload) self.assertRaises(ValueError, prvkeyinfo_from_prvkey, badwif)
def test_int_from_prvkey(self): # BIP32 xprv = b"xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi" xprv_str = xprv.decode('ascii') xprv_dict = bip32.deserialize(xprv) # WIF wif = wif_from_prvkey(xprv) wif_str = wif.decode('ascii') # bytes qbytes = xprv_dict['key'][1:] qhex = qbytes.hex() # int q = xprv_dict['q'] self.assertEqual(q, int_from_prvkey(q)) # bytes self.assertEqual(q, int_from_prvkey(qbytes)) self.assertRaises(ValueError, int_from_prvkey, b'\x00' + qbytes) self.assertEqual(q, int_from_prvkey(qhex)) self.assertEqual(q, int_from_prvkey(' ' + qhex + ' ')) self.assertRaises(ValueError, int_from_prvkey, qhex + '00') # WIF self.assertEqual(q, int_from_prvkey(wif)) self.assertRaises(ValueError, int_from_prvkey, wif + b'\x00') self.assertEqual(q, int_from_prvkey(wif_str)) self.assertEqual(q, int_from_prvkey(' ' + wif_str + ' ')) # BIP32 self.assertEqual(q, int_from_prvkey(xprv)) self.assertRaises(ValueError, int_from_prvkey, xprv + b'\x00') self.assertEqual(q, int_from_prvkey(xprv_str)) self.assertEqual(q, int_from_prvkey(' ' + xprv_str + ' ')) self.assertEqual(q, int_from_prvkey(xprv_dict)) # wrong private key int q = ec.n self.assertRaises(ValueError, int_from_prvkey, q) # bytes qbytes = q.to_bytes(32, byteorder='big') qhex = qbytes.hex() self.assertRaises(ValueError, int_from_prvkey, qbytes) self.assertRaises(ValueError, int_from_prvkey, qhex) # WIF t = b'\x80' + qbytes + b'\x01' wif = b58encode(t) wif_str = wif.decode('ascii') self.assertRaises(ValueError, int_from_prvkey, wif) self.assertRaises(ValueError, int_from_prvkey, wif_str) # BIP32 t = xprv_dict['version'] t += xprv_dict['depth'].to_bytes(1, 'big') t += xprv_dict['parent_fingerprint'] t += xprv_dict['index'] t += xprv_dict['chain_code'] t += b'\x00' + qbytes xprv = b58encode(t) xprv_str = xprv.decode('ascii') self.assertRaises(ValueError, int_from_prvkey, xprv) self.assertRaises(ValueError, int_from_prvkey, xprv_str) # wrong private key int q = 0 self.assertRaises(ValueError, int_from_prvkey, q) # bytes qbytes = q.to_bytes(32, byteorder='big') qhex = qbytes.hex() self.assertRaises(ValueError, int_from_prvkey, qbytes) self.assertRaises(ValueError, int_from_prvkey, qhex) # WIF t = b'\x80' + qbytes + b'\x01' wif = b58encode(t) wif_str = wif.decode('ascii') self.assertRaises(ValueError, int_from_prvkey, wif) self.assertRaises(ValueError, int_from_prvkey, wif_str) # BIP32 t = xprv_dict['version'] t += xprv_dict['depth'].to_bytes(1, 'big') t += xprv_dict['parent_fingerprint'] t += xprv_dict['index'] t += xprv_dict['chain_code'] t += b'\x00' + qbytes xprv = b58encode(t) xprv_str = xprv.decode('ascii') self.assertRaises(ValueError, int_from_prvkey, xprv) self.assertRaises(ValueError, int_from_prvkey, xprv_str) # pub key xpub = b'xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8' self.assertRaises(ValueError, int_from_prvkey, xpub)
def test_point_from_key(self): # prvkeys xprv = ( "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiC" "hkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi").encode() xprv_str = xprv.decode("ascii") xprv_dict = bip32.deserialize(xprv) q, network, _ = _prvkeyinfo_from_xprv(xprv) ec = NETWORKS[network]["curve"] q_bytes = q.to_bytes(ec.nsize, "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, 78) 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_int_from_prvkey(self): # BIP32 xprv = ( "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiC" "hkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi").encode() xprv_str = xprv.decode("ascii") xprv_dict = bip32.deserialize(xprv) # WIF wif = wif_from_prvkey(xprv) wif_str = wif.decode("ascii") # bytes qbytes = xprv_dict["key"][1:] qhex = qbytes.hex() # int q = xprv_dict["q"] self.assertEqual(q, int_from_prvkey(q)) # bytes self.assertEqual(q, int_from_prvkey(qbytes)) self.assertRaises(ValueError, int_from_prvkey, b"\x00" + qbytes) self.assertEqual(q, int_from_prvkey(qhex)) self.assertEqual(q, int_from_prvkey(" " + qhex + " ")) self.assertRaises(ValueError, int_from_prvkey, qhex + "00") # WIF self.assertEqual(q, int_from_prvkey(wif)) self.assertRaises(ValueError, int_from_prvkey, wif + b"\x00") self.assertEqual(q, int_from_prvkey(wif_str)) self.assertEqual(q, int_from_prvkey(" " + wif_str + " ")) # BIP32 self.assertEqual(q, int_from_prvkey(xprv)) self.assertRaises(ValueError, int_from_prvkey, xprv + b"\x00") self.assertEqual(q, int_from_prvkey(xprv_str)) self.assertEqual(q, int_from_prvkey(" " + xprv_str + " ")) self.assertEqual(q, int_from_prvkey(xprv_dict)) # wrong private key int q = ec.n self.assertRaises(ValueError, int_from_prvkey, q) # bytes qbytes = q.to_bytes(32, byteorder="big") qhex = qbytes.hex() self.assertRaises(ValueError, int_from_prvkey, qbytes) self.assertRaises(ValueError, int_from_prvkey, qhex) # WIF t = b"\x80" + qbytes + b"\x01" wif = b58encode(t) wif_str = wif.decode("ascii") self.assertRaises(ValueError, int_from_prvkey, wif) self.assertRaises(ValueError, int_from_prvkey, wif_str) # BIP32 t = xprv_dict["version"] t += xprv_dict["depth"].to_bytes(1, "big") t += xprv_dict["parent_fingerprint"] t += xprv_dict["index"] t += xprv_dict["chain_code"] t += b"\x00" + qbytes xprv = b58encode(t, 78) xprv_str = xprv.decode("ascii") self.assertRaises(ValueError, int_from_prvkey, xprv) self.assertRaises(ValueError, int_from_prvkey, xprv_str) # wrong private key int q = 0 self.assertRaises(ValueError, int_from_prvkey, q) # bytes qbytes = q.to_bytes(32, byteorder="big") qhex = qbytes.hex() self.assertRaises(ValueError, int_from_prvkey, qbytes) self.assertRaises(ValueError, int_from_prvkey, qhex) # WIF t = b"\x80" + qbytes + b"\x01" wif = b58encode(t) wif_str = wif.decode("ascii") self.assertRaises(ValueError, int_from_prvkey, wif) self.assertRaises(ValueError, int_from_prvkey, wif_str) # BIP32 t = xprv_dict["version"] t += xprv_dict["depth"].to_bytes(1, "big") t += xprv_dict["parent_fingerprint"] t += xprv_dict["index"] t += xprv_dict["chain_code"] t += b"\x00" + qbytes xprv = b58encode(t, 78) xprv_str = xprv.decode("ascii") self.assertRaises(ValueError, int_from_prvkey, xprv) self.assertRaises(ValueError, int_from_prvkey, xprv_str) # pub key xpub = ( "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2g" "Z29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8").encode() self.assertRaises(ValueError, int_from_prvkey, xpub)