Skip to content

Commit 6bf5c79

Browse files
committed
test: update crypto tests
1 parent 6896c36 commit 6bf5c79

6 files changed

Lines changed: 160 additions & 94 deletions

File tree

pactus/crypto/address.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,12 @@ def from_string(cls, text: str) -> Address:
4040
raise ValueError(msg)
4141

4242
typ = AddressType(typ)
43-
if typ in (AddressType.VALIDATOR, AddressType.BLS_ACCOUNT, AddressType.ED25519_ACCOUNT):
43+
if typ in (
44+
AddressType.VALIDATOR,
45+
AddressType.BLS_ACCOUNT,
46+
AddressType.ED25519_ACCOUNT,
47+
AddressType.SECP256K1_ACCOUNT,
48+
):
4449
if len(data) != 20:
4550
msg = f"Invalid length: {len(data) + 1}"
4651
raise ValueError(msg)

pactus/crypto/bls/private_key.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ def __init__(self, scalar: int) -> None:
2121
self.scalar = scalar % curve_order
2222

2323
@classmethod
24-
def from_bytes(cls, buffer: bytes) -> PrivateKey:
25-
return cls(int.from_bytes(buffer, "big"))
24+
def from_bytes(cls, data: bytes) -> PrivateKey:
25+
return cls(int.from_bytes(data, "big"))
2626

2727
@classmethod
2828
def key_gen(cls, ikm: bytes = [], key_info: bytes = b"") -> PrivateKey:
@@ -59,8 +59,7 @@ def from_string(cls, text: str) -> PrivateKey:
5959
msg = "Private key data must be 32 bytes long"
6060
raise ValueError(msg)
6161

62-
scalar = int.from_bytes(data, "big")
63-
return cls(scalar)
62+
return cls.from_bytes(data)
6463

6564
def raw_bytes(self) -> bytes:
6665
return self.scalar.to_bytes(PRIVATE_KEY_SIZE, "big")

pactus/crypto/bls/public_key.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ class PublicKey:
1919
def __init__(self, point_g2: any) -> None:
2020
self.point_g2 = point_g2
2121

22+
@classmethod
23+
def from_bytes(cls, data: str) -> PublicKey:
24+
point_g2 = deserialize(bytes(data), is_ell2=True)
25+
26+
return cls(point_g2)
27+
2228
@classmethod
2329
def from_string(cls, text: str) -> PublicKey:
2430
hrp, typ, data = utils.decode_to_base256_with_type(text)
@@ -35,9 +41,7 @@ def from_string(cls, text: str) -> PublicKey:
3541
msg = "Public key data must be 96 bytes long"
3642
raise ValueError(msg)
3743

38-
point_g2 = deserialize(bytes(data), is_ell2=True)
39-
40-
return cls(point_g2)
44+
return cls.from_bytes(data)
4145

4246
@classmethod
4347
def aggregate(cls, pubs: list[PublicKey]) -> PublicKey:

tests/test_crypto_bls.py

Lines changed: 58 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,44 +3,76 @@
33
from pactus.crypto.bls import PrivateKey as BLSPrivateKey
44
from pactus.crypto.bls import PublicKey as BLSPublicKey
55
from pactus.crypto.bls import Signature as BLSSignature
6+
from pactus.crypto import Address
67

78

89
class TestBLSCrypto(unittest.TestCase):
9-
def test_private_key_to_public_key(self):
10-
prv_str = "SECRET1PDRWTLP5PX0FAHDX39GXZJP7FKZFALML0D5U9TT9KVQHDUC99CMGQQJVK67"
11-
expected_pub_str = "public1p4u8hfytl2pj6l9rj0t54gxcdmna4hq52ncqkkqjf3arha5mlk3x4mzpyjkhmdl20jae7f65aamjrvqcvf4sudcapz52ctcwc8r9wz3z2gwxs38880cgvfy49ta5ssyjut05myd4zgmjqstggmetyuyg7v5jhx47a"
10+
def test_encoding(self):
11+
prv_data = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
12+
pub_data = "a7290fc800d2d14f2dc5e5cb416bebf3267dfed1c6c3a79c6edc4ebd1e657d956daa06a2fcaafd42c94b65b32d4d43ea1368f861006829c475b7d54763a502dfd717e9d51c5cc7deae2981e56090a821c9c5bcafc129b8599203ab99031f4ce7"
13+
val_addr_data = "01c40b914373d4fc9c1e4611ad0acd5f23abf58a0d"
14+
acc_addr_data = "02c40b914373d4fc9c1e4611ad0acd5f23abf58a0d"
15+
16+
prv_str = "SECRET1PQQQSYQCYQ5RQWZQFPG9SCRGWPUGPZYSNZS23V9CCRYDPK8QARC0SEZYD4L"
17+
pub_str = "public1p5u5sljqq6tg57tw9uh95z6lt7vn8mlk3cmp608rwm38t68n90k2km2sx5t724l2ze99ktvedf4p75ymglpssq6pfc36m0428vwjs9h7hzl5a28zucl02u2vpu4sfp2ppe8zmet7p9xu9nysr4wvsx86vuujrva2z"
18+
val_addr_str = "pc1pcs9ezsmn6n7fc8jxzxks4n2lyw4ltzsdc9v8qn"
19+
acc_addr_str = "pc1zcs9ezsmn6n7fc8jxzxks4n2lyw4ltzsd9wu6hw"
1220

1321
prv = BLSPrivateKey.from_string(prv_str)
14-
pub = prv.public_key()
15-
pub_str = pub.string()
22+
pub = BLSPublicKey.from_string(pub_str)
23+
val_addr = Address.from_string(val_addr_str)
24+
acc_addr = Address.from_string(acc_addr_str)
1625

17-
self.assertEqual(pub_str, expected_pub_str)
26+
self.assertEqual(prv_data, prv.raw_bytes().hex())
27+
self.assertEqual(pub_data, pub.raw_bytes().hex())
28+
self.assertEqual(val_addr_data, val_addr.raw_bytes().hex())
29+
self.assertEqual(acc_addr_data, acc_addr.raw_bytes().hex())
1830

19-
def test_public_key_to_address(self):
20-
pub_str = "public1p4u8hfytl2pj6l9rj0t54gxcdmna4hq52ncqkkqjf3arha5mlk3x4mzpyjkhmdl20jae7f65aamjrvqcvf4sudcapz52ctcwc8r9wz3z2gwxs38880cgvfy49ta5ssyjut05myd4zgmjqstggmetyuyg7v5jhx47a"
21-
expected_acc_addr_str = "pc1z5x2a0lkt5nrrdqe0rkcv6r4pfkmdhrr3mawvua"
22-
expected_val_addr_str = "pc1p5x2a0lkt5nrrdqe0rkcv6r4pfkmdhrr3xk73tq"
31+
msg = b"pactus"
32+
sig = BLSSignature.from_string(
33+
"8bdda74336efdf43b428a3811d3d6867a19e20889c91261b02a6b950b130f5bb22621394667c27660bfed2a8719d9c52"
34+
)
2335

24-
pub = BLSPublicKey.from_string(pub_str)
25-
acc_add_str = pub.account_address().string()
26-
val_add_str = pub.validator_address().string()
36+
self.assertTrue(pub.verify(msg, sig))
37+
self.assertEqual(sig.raw_bytes(), prv.sign(msg).raw_bytes())
38+
self.assertEqual(pub.raw_bytes(), prv.public_key().raw_bytes())
39+
self.assertEqual(val_addr.raw_bytes(), pub.validator_address().raw_bytes())
40+
self.assertEqual(acc_addr.raw_bytes(), pub.account_address().raw_bytes())
2741

28-
self.assertEqual(acc_add_str, expected_acc_addr_str)
29-
self.assertEqual(val_add_str, expected_val_addr_str)
42+
def test_sign_and_verify(self):
43+
prv1 = BLSPrivateKey.random()
44+
prv2 = BLSPrivateKey.random()
45+
pub1 = prv1.public_key()
46+
pub2 = prv2.public_key()
3047

31-
def test_sign(self):
32-
prv_str = "SECRET1PDRWTLP5PX0FAHDX39GXZJP7FKZFALML0D5U9TT9KVQHDUC99CMGQQJVK67"
33-
prv = BLSPrivateKey.from_string(prv_str)
34-
prv.public_key()
3548
msg = b"pactus"
36-
prv.sign(msg)
37-
BLSSignature.from_string(
38-
"923d67a8624cbb7972b29328e15ec76cc846076ccf00a9e94d991c677846f334ae4ba4551396fbcd6d1cab7593baf3b7"
39-
)
49+
sig1 = prv1.sign(msg)
50+
sig2 = prv2.sign(msg)
51+
52+
self.assertTrue(pub1.verify(msg, sig1))
53+
self.assertTrue(pub2.verify(msg, sig2))
54+
self.assertFalse(pub1.verify(msg, sig2))
55+
self.assertFalse(pub2.verify(msg, sig1))
56+
57+
# Verify a signature for a different message is rejected
58+
different_msg = b"different"
59+
sig3 = prv1.sign(different_msg)
60+
self.assertFalse(pub1.verify(msg, sig3))
61+
62+
def test_multiple_signatures(self):
63+
# Test that multiple signatures for the same message and key are deterministic
64+
prv = BLSPrivateKey.random()
65+
pub = prv.public_key()
66+
67+
msg = b"pactus"
68+
sig1 = prv.sign(msg)
69+
sig2 = prv.sign(msg)
70+
71+
# Both signatures should verify
72+
self.assertTrue(pub.verify(msg, sig1))
73+
self.assertTrue(pub.verify(msg, sig2))
4074

41-
# self.assertEqual(sig.string(), expected_sig.string())
42-
# self.assertTrue(pub.verify(msg, sig))
43-
# self.assertFalse(pub.verify(b"foo", sig))
75+
self.assertEqual(sig1.raw_bytes(), sig2.raw_bytes())
4476

4577
def test_key_gen(self):
4678
tests = [

tests/test_crypto_ed25519.py

Lines changed: 51 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,49 +3,71 @@
33
from pactus.crypto.ed25519 import PrivateKey as Ed25519PrivateKey
44
from pactus.crypto.ed25519 import PublicKey as Ed25519PublicKey
55
from pactus.crypto.ed25519 import Signature as Ed25519Signature
6+
from pactus.crypto import Address
67

78

89
class TestEd25519Crypto(unittest.TestCase):
9-
def test_private_key_to_public_key(self):
10-
prv_str = "SECRET1RJ6STNTA7Y3P2QLQF8A6QCX05F2H5TFNE5RSH066KZME4WVFXKE7QW097LG"
11-
expected_pub_str = (
12-
"public1ry2cqw5yfhmr7ve8nctgzg6wgcyc73xqr2uud486jgsq7wu253egsx6msep"
13-
)
10+
def test_encoding(self):
11+
prv_data = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
12+
pub_data = "03a107bff3ce10be1d70dd18e74bc09967e4d6309ba50d5f1ddc8664125531b8"
13+
addr_data = "0396a882c41ef85a07c75a6416a57fcce95aad4a3f"
14+
15+
prv_str = "SECRET1RQQQSYQCYQ5RQWZQFPG9SCRGWPUGPZYSNZS23V9CCRYDPK8QARC0SW5D8X2"
16+
pub_str = "public1rqwss00lnecgtu8tsm5vwwj7qn9n7f43snwjs6hcamjrxgyj4xxuq5agu5g"
17+
addr_str = "pc1rj65g93q7lpdq0366vst22l7va9d26j3l2vr0em"
1418

1519
prv = Ed25519PrivateKey.from_string(prv_str)
16-
pub = prv.public_key()
17-
pub_str = pub.string()
20+
pub = Ed25519PublicKey.from_string(pub_str)
21+
addr = Address.from_string(addr_str)
1822

19-
self.assertEqual(pub_str, expected_pub_str)
23+
self.assertEqual(prv_data, prv.raw_bytes().hex())
24+
self.assertEqual(pub_data, pub.raw_bytes().hex())
25+
self.assertEqual(addr_data, addr.raw_bytes().hex())
2026

21-
def test_public_key_to_address(self):
22-
pub_str = "public1ry2cqw5yfhmr7ve8nctgzg6wgcyc73xqr2uud486jgsq7wu253egsx6msep"
23-
expected_acc_addr_str = "pc1reer4damrrdxznmrrl7a9acy7x5cwe6dyt8ftv4"
27+
msg = b"pactus"
28+
sig = Ed25519Signature.from_string(
29+
"1fc2c800499342d08242db9c3eb654027cb7b821e6af9ede56dfdb67e824f15bddb419d2db3fd5aaf3ef1a9ebb9a9deb749380f0d6a110cbe95319fe9f794305"
30+
)
2431

25-
pub = Ed25519PublicKey.from_string(pub_str)
26-
acc_add_str = pub.account_address().string()
32+
self.assertTrue(pub.verify(msg, sig))
33+
self.assertEqual(sig.raw_bytes(), prv.sign(msg).raw_bytes())
34+
self.assertEqual(pub.raw_bytes(), prv.public_key().raw_bytes())
35+
self.assertEqual(addr.raw_bytes(), pub.account_address().raw_bytes())
2736

28-
self.assertEqual(acc_add_str, expected_acc_addr_str)
37+
def test_sign_and_verify(self):
38+
prv1 = Ed25519PrivateKey.random()
39+
prv2 = Ed25519PrivateKey.random()
40+
pub1 = prv1.public_key()
41+
pub2 = prv2.public_key()
2942

30-
def test_sign(self):
31-
prv_str = "secret1r0up878rawjec2evjnd4k42a4g4pcardesjk48jtn64qwjnfv7veqal53e2"
32-
prv = Ed25519PrivateKey.from_string(prv_str)
33-
pub = prv.public_key()
3443
msg = b"pactus"
35-
sig = prv.sign(msg)
44+
sig1 = prv1.sign(msg)
45+
sig2 = prv2.sign(msg)
3646

37-
valid_sig = Ed25519Signature.from_string(
38-
"55eaa9656158874bff726c8d62abe0a5b66d2434705f46b58c905a42f1b39fb95f640fbacac97e6e6862220fe7b4f249a0f79dc3d37b4460156c58580778b70e"
39-
)
47+
self.assertTrue(pub1.verify(msg, sig1))
48+
self.assertTrue(pub2.verify(msg, sig2))
49+
self.assertFalse(pub1.verify(msg, sig2))
50+
self.assertFalse(pub2.verify(msg, sig1))
4051

41-
invalid_sig = Ed25519Signature.from_string(
42-
"5a61ecb3c08825010678f12c036cec2e1dd1b8767ed9fd95a97f560dfd6196b600fdc7bba22f13eae19ca578b920eb807eb6cd956d55f1d778fee75155d4ea07"
43-
)
52+
# Verify a signature for a different message is rejected
53+
different_msg = b"different"
54+
sig3 = prv1.sign(different_msg)
55+
self.assertFalse(pub1.verify(msg, sig3))
56+
57+
def test_multiple_signatures(self):
58+
# Test that multiple signatures for the same message and key are deterministic
59+
prv = Ed25519PrivateKey.random()
60+
pub = prv.public_key()
61+
62+
msg = b"pactus"
63+
sig1 = prv.sign(msg)
64+
sig2 = prv.sign(msg)
65+
66+
# Both signatures should verify
67+
self.assertTrue(pub.verify(msg, sig1))
68+
self.assertTrue(pub.verify(msg, sig2))
4469

45-
self.assertTrue(pub.verify(msg, valid_sig))
46-
self.assertFalse(pub.verify(msg, invalid_sig))
47-
self.assertEqual(sig.string(), valid_sig.string())
48-
self.assertEqual(sig.raw_bytes(), valid_sig.raw_bytes())
70+
self.assertEqual(sig1.raw_bytes(), sig2.raw_bytes())
4971

5072

5173
if __name__ == "__main__":

tests/test_crypto_secp256k1.py

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,52 +3,56 @@
33
from pactus.crypto.secp256k1 import PrivateKey as Secp256k1PrivateKey
44
from pactus.crypto.secp256k1 import PublicKey as Secp256k1PublicKey
55
from pactus.crypto.secp256k1 import Signature as Secp256k1Signature
6+
from pactus.crypto import Address
67

78

89
class TestSecp256k1Crypto(unittest.TestCase):
9-
def test_private_key_to_public_key(self):
10-
prv_str = "secret1yqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsd25y3e"
11-
expected_pub_str = (
12-
"public1yqvdcf32k0vfxgsyet5ldt246q4jaw8scx3sysx0lnstlt6w4m5rc7k3ysjp"
13-
)
14-
15-
prv = Secp256k1PrivateKey.from_string(prv_str)
16-
pub = prv.public_key()
17-
pub_str = pub.string()
10+
def test_encoding(self):
11+
prv_data = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
12+
pub_data = "036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2"
13+
addr_data = "042bc1db7e0797c45b918dc401093c9257c6012b4c"
1814

19-
self.assertEqual(pub_str, expected_pub_str)
20-
21-
def test_public_key_to_address(self):
22-
pub_str = "public1yqvdcf32k0vfxgsyet5ldt246q4jaw8scx3sysx0lnstlt6w4m5rc7k3ysjp"
23-
expected_acc_addr_str = "pc1yj7ag28h54jf4e09nnednjhgmg60srnvj7uu39v"
15+
prv_str = "SECRET1YQQQSYQCYQ5RQWZQFPG9SCRGWPUGPZYSNZS23V9CCRYDPK8QARC0SPVXU8Z"
16+
pub_str = "public1yqdkke2kzfzheda405lusfa2sy5aq70hn7k4zle5r322my9nfz35wyfamrfs"
17+
addr_str = "pc1y90qakls8jlz9hyvdcsqsj0yj2lrqz26vqu7l0z"
2418

19+
prv = Secp256k1PrivateKey.from_string(prv_str)
2520
pub = Secp256k1PublicKey.from_string(pub_str)
26-
acc_add_str = pub.account_address().string()
21+
addr = Address.from_string(addr_str)
2722

28-
self.assertEqual(acc_add_str, expected_acc_addr_str)
23+
self.assertEqual(prv_data, prv.raw_bytes().hex())
24+
self.assertEqual(pub_data, pub.raw_bytes().hex())
25+
self.assertEqual(addr_data, addr.raw_bytes().hex())
2926

30-
def test_sign_and_verify(self):
31-
prv_str = "secret1yqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqsd25y3e"
32-
prv = Secp256k1PrivateKey.from_string(prv_str)
33-
pub = prv.public_key()
3427
msg = b"pactus"
35-
sig = prv.sign(msg)
36-
37-
# Verify the signature is correct length (64 bytes)
38-
self.assertEqual(len(sig.raw_bytes()), 64)
28+
sig = Secp256k1Signature.from_string(
29+
"16e6f8bcdb92964a35773aae200628a5b470b6488d42ceef6538da0b4ffd3b42098dd821eea96f66ba02c9c4473443ab51c411ab78adfbb90d53b07ca1d6862b"
30+
)
3931

40-
# Verify the signature verifies correctly
4132
self.assertTrue(pub.verify(msg, sig))
33+
self.assertEqual(sig.raw_bytes(), prv.sign(msg).raw_bytes())
34+
self.assertEqual(pub.raw_bytes(), prv.public_key().raw_bytes())
35+
self.assertEqual(addr.raw_bytes(), pub.account_address().raw_bytes())
36+
37+
def test_sign_and_verify(self):
38+
prv1 = Secp256k1PrivateKey.random()
39+
prv2 = Secp256k1PrivateKey.random()
40+
pub1 = prv1.public_key()
41+
pub2 = prv2.public_key()
42+
43+
msg = b"pactus"
44+
sig1 = prv1.sign(msg)
45+
sig2 = prv2.sign(msg)
4246

43-
# Verify an invalid signature is rejected
44-
invalid_sig_bytes = b"\x00" * 64
45-
invalid_sig = Secp256k1Signature.from_string(invalid_sig_bytes.hex())
46-
self.assertFalse(pub.verify(msg, invalid_sig))
47+
self.assertTrue(pub1.verify(msg, sig1))
48+
self.assertTrue(pub2.verify(msg, sig2))
49+
self.assertFalse(pub1.verify(msg, sig2))
50+
self.assertFalse(pub2.verify(msg, sig1))
4751

4852
# Verify a signature for a different message is rejected
4953
different_msg = b"different"
50-
sig2 = prv.sign(different_msg)
51-
self.assertFalse(pub.verify(msg, sig2))
54+
sig3 = prv1.sign(different_msg)
55+
self.assertFalse(pub1.verify(msg, sig3))
5256

5357
def test_key_generation(self):
5458
# Test random key generation

0 commit comments

Comments
 (0)