A Python port of the Invisible Internet Project (I2P)
at main 122 lines 4.1 kB view raw
1"""Tests for Blinding API and BlindData.""" 2 3import pytest 4from i2p_crypto.eddsa_blinding import HAS_NACL 5 6pytestmark = pytest.mark.skipif(not HAS_NACL, reason="pynacl not installed") 7 8from i2p_crypto.dsa import SigType 9from i2p_crypto.blinding import Blinding 10from i2p_crypto.eddsa_blinding import EdDSABlinding 11from i2p_data.key_types import SigningPublicKey, SigningPrivateKey 12from i2p_data.blind_data import BlindData, AuthType 13 14 15def _make_ed25519_spk(): 16 """Create a test Ed25519 signing public key.""" 17 seed = b"\x42" * 32 18 scalar = EdDSABlinding.seed_to_scalar(seed) 19 pub = EdDSABlinding.scalar_mult_base(scalar) 20 return SigningPublicKey(pub, sig_type=SigType.EdDSA_SHA512_Ed25519), seed 21 22 23def test_generate_alpha_deterministic(): 24 spk, _ = _make_ed25519_spk() 25 ts = 1700000000 26 a1 = Blinding.generate_alpha(spk, timestamp_sec=ts) 27 a2 = Blinding.generate_alpha(spk, timestamp_sec=ts) 28 assert a1.to_bytes() == a2.to_bytes() 29 assert len(a1.to_bytes()) == 32 30 31 32def test_generate_alpha_daily_rotation(): 33 spk, _ = _make_ed25519_spk() 34 a1 = Blinding.generate_alpha(spk, timestamp_sec=1700000000) 35 a2 = Blinding.generate_alpha(spk, timestamp_sec=1700086400) # +1 day 36 assert a1.to_bytes() != a2.to_bytes() 37 38 39def test_secret_changes_alpha(): 40 spk, _ = _make_ed25519_spk() 41 ts = 1700000000 42 a1 = Blinding.generate_alpha(spk, timestamp_sec=ts) 43 a2 = Blinding.generate_alpha(spk, timestamp_sec=ts, secret="mysecret") 44 assert a1.to_bytes() != a2.to_bytes() 45 46 47def test_blind_roundtrip(): 48 """blind(priv, alpha) * G == blind(pub, alpha*G).""" 49 spk, seed = _make_ed25519_spk() 50 ts = 1700000000 51 alpha = Blinding.generate_alpha(spk, timestamp_sec=ts) 52 53 blinded_pub = Blinding.blind(spk, alpha) 54 blinded_priv = Blinding.unblind(seed, alpha) 55 56 # Verify consistency: blinded_priv * G == blinded_pub 57 pub_from_priv = EdDSABlinding.scalar_mult_base(blinded_priv.to_bytes()) 58 assert pub_from_priv == blinded_pub.to_bytes() 59 60 61def test_b32_encode_decode_roundtrip(): 62 spk, _ = _make_ed25519_spk() 63 address = Blinding.encode_b32(spk) 64 assert address.endswith(".b32.i2p") 65 assert len(address) > 10 66 67 sig_in, sig_out, decoded_spk, flags = Blinding.decode_b32(address) 68 assert sig_in == SigType.EdDSA_SHA512_Ed25519 69 assert sig_out == SigType.RedDSA_SHA512_Ed25519 70 assert decoded_spk.to_bytes() == spk.to_bytes() 71 assert flags == 0 72 73 74def test_b32_with_flags(): 75 spk, _ = _make_ed25519_spk() 76 address = Blinding.encode_b32(spk, secret_required=True, per_client_auth=True) 77 _, _, _, flags = Blinding.decode_b32(address) 78 assert flags & 0x02 # secret_required 79 assert flags & 0x04 # per_client_auth 80 81 82# --- BlindData tests --- 83 84def test_blind_data_caching(): 85 spk, _ = _make_ed25519_spk() 86 bd = BlindData(SigType.EdDSA_SHA512_Ed25519, SigType.RedDSA_SHA512_Ed25519, spk) 87 ts = 1700000000 88 bp1 = bd.get_blinded_pubkey(ts) 89 bp2 = bd.get_blinded_pubkey(ts) 90 assert bp1.to_bytes() == bp2.to_bytes() 91 92 93def test_blind_data_daily_rotation(): 94 spk, _ = _make_ed25519_spk() 95 bd = BlindData(SigType.EdDSA_SHA512_Ed25519, SigType.RedDSA_SHA512_Ed25519, spk) 96 bp1 = bd.get_blinded_pubkey(1700000000) 97 bp2 = bd.get_blinded_pubkey(1700086400) 98 assert bp1.to_bytes() != bp2.to_bytes() 99 100 101def test_credential_deterministic(): 102 spk, _ = _make_ed25519_spk() 103 bd = BlindData(SigType.EdDSA_SHA512_Ed25519, SigType.RedDSA_SHA512_Ed25519, spk) 104 c1 = bd.get_credential() 105 c2 = bd.get_credential() 106 assert c1 == c2 107 assert len(c1) == 32 108 109 110def test_subcredential_changes_daily(): 111 spk, _ = _make_ed25519_spk() 112 bd = BlindData(SigType.EdDSA_SHA512_Ed25519, SigType.RedDSA_SHA512_Ed25519, spk) 113 sc1 = bd.get_subcredential(1700000000) 114 sc2 = bd.get_subcredential(1700086400) 115 assert sc1 != sc2 116 117 118def test_destination_hash(): 119 spk, _ = _make_ed25519_spk() 120 bd = BlindData(SigType.EdDSA_SHA512_Ed25519, SigType.RedDSA_SHA512_Ed25519, spk) 121 dh = bd.get_destination_hash(1700000000) 122 assert len(dh) == 32