A Python port of the Invisible Internet Project (I2P)
1"""Tests for i2p_crypto ElGamal — 2048-bit encryption/decryption."""
2
3import pytest
4
5
6class TestElGamalEngine:
7 def test_encrypt_decrypt_roundtrip(self):
8 from i2p_crypto.elgamal import ElGamalEngine
9 pub, priv = ElGamalEngine.generate_keypair()
10 data = b"Hello, ElGamal!"
11 ct = ElGamalEngine.encrypt(data, pub)
12 assert len(ct) == 514
13 pt = ElGamalEngine.decrypt(ct, priv)
14 assert pt == data
15
16 def test_encrypt_decrypt_empty(self):
17 from i2p_crypto.elgamal import ElGamalEngine
18 pub, priv = ElGamalEngine.generate_keypair()
19 ct = ElGamalEngine.encrypt(b"", pub)
20 pt = ElGamalEngine.decrypt(ct, priv)
21 assert pt == b""
22
23 def test_encrypt_decrypt_max_size(self):
24 from i2p_crypto.elgamal import ElGamalEngine, MAX_CLEARTEXT
25 pub, priv = ElGamalEngine.generate_keypair()
26 data = b"X" * MAX_CLEARTEXT
27 ct = ElGamalEngine.encrypt(data, pub)
28 pt = ElGamalEngine.decrypt(ct, priv)
29 assert pt == data
30
31 def test_reject_oversized_data(self):
32 from i2p_crypto.elgamal import ElGamalEngine, MAX_CLEARTEXT
33 pub, _ = ElGamalEngine.generate_keypair()
34 with pytest.raises(ValueError):
35 ElGamalEngine.encrypt(b"X" * (MAX_CLEARTEXT + 1), pub)
36
37 def test_ciphertext_size(self):
38 from i2p_crypto.elgamal import ElGamalEngine, CIPHERTEXT_SIZE
39 pub, _ = ElGamalEngine.generate_keypair()
40 ct = ElGamalEngine.encrypt(b"test", pub)
41 assert len(ct) == CIPHERTEXT_SIZE
42
43 def test_wrong_key_fails(self):
44 from i2p_crypto.elgamal import ElGamalEngine
45 pub1, priv1 = ElGamalEngine.generate_keypair()
46 _, priv2 = ElGamalEngine.generate_keypair()
47 ct = ElGamalEngine.encrypt(b"secret", pub1)
48 pt = ElGamalEngine.decrypt(ct, priv2)
49 assert pt is None # Hash mismatch
50
51 def test_corrupted_ciphertext_fails(self):
52 from i2p_crypto.elgamal import ElGamalEngine
53 pub, priv = ElGamalEngine.generate_keypair()
54 ct = bytearray(ElGamalEngine.encrypt(b"test", pub))
55 ct[100] ^= 0xFF
56 pt = ElGamalEngine.decrypt(bytes(ct), priv)
57 assert pt is None
58
59 def test_wrong_size_ciphertext(self):
60 from i2p_crypto.elgamal import ElGamalEngine
61 _, priv = ElGamalEngine.generate_keypair()
62 assert ElGamalEngine.decrypt(b"too short", priv) is None
63
64 def test_randomized_ciphertext(self):
65 """Same plaintext should produce different ciphertext each time."""
66 from i2p_crypto.elgamal import ElGamalEngine
67 pub, _ = ElGamalEngine.generate_keypair()
68 ct1 = ElGamalEngine.encrypt(b"same", pub)
69 ct2 = ElGamalEngine.encrypt(b"same", pub)
70 assert ct1 != ct2
71
72 def test_key_sizes(self):
73 from i2p_crypto.elgamal import ElGamalEngine
74 pub, priv = ElGamalEngine.generate_keypair()
75 assert len(pub) == 256
76 assert len(priv) == 256
77
78 def test_various_data_sizes(self):
79 from i2p_crypto.elgamal import ElGamalEngine
80 pub, priv = ElGamalEngine.generate_keypair()
81 for size in [1, 10, 50, 100, 200, 222]:
82 data = bytes(range(size % 256)) * (size // 256 + 1)
83 data = data[:size]
84 ct = ElGamalEngine.encrypt(data, pub)
85 pt = ElGamalEngine.decrypt(ct, priv)
86 assert pt == data, f"Failed for size {size}"