11import pytest
22
3- from cyphersyntax .identity import Identity
4- from cyphersyntax .session import SessionFactory , AeadSuite
53from cyphersyntax .errors import ReplayDetectedError
4+ from cyphersyntax .identity import Identity
5+ from cyphersyntax .kdf import derive_message_key
6+ from cyphersyntax .session import AeadSuite , SessionFactory
67
78
89@pytest .mark .parametrize ("suite" , [AeadSuite .AES_GCM_SIV , AeadSuite .CHACHA20_POLY1305 ])
910def test_roundtrip (suite ):
1011 alice = Identity .generate ("alice" )
1112 bob = Identity .generate ("bob" )
12- alice_session , bob_session = SessionFactory .pair_for_tests (alice = alice , bob = bob , suite = suite )
13+ alice_session , bob_session = SessionFactory .pair_for_tests (
14+ alice = alice ,
15+ bob = bob ,
16+ suite = suite ,
17+ )
1318
1419 blob = alice_session .encrypt (b"hello bob" )
1520 assert bob_session .decrypt (blob ) == b"hello bob"
1621
1722
23+ @pytest .mark .parametrize ("suite" , [AeadSuite .AES_GCM_SIV , AeadSuite .CHACHA20_POLY1305 ])
24+ def test_first_message_key_material_is_separated_by_direction (suite ):
25+ alice = Identity .generate ("alice" )
26+ bob = Identity .generate ("bob" )
27+ alice_session , bob_session = SessionFactory .pair_for_tests (
28+ alice = alice ,
29+ bob = bob ,
30+ suite = suite ,
31+ )
32+
33+ assert alice_session .root_key == bob_session .root_key
34+
35+ alice_key , alice_nonce = derive_message_key (
36+ alice_session .root_key ,
37+ 0 ,
38+ suite .value ,
39+ sender_public_key = alice_session .local_ephemeral_public_bytes ,
40+ recipient_public_key = alice_session .remote_ephemeral_public_bytes ,
41+ )
42+ bob_key , bob_nonce = derive_message_key (
43+ bob_session .root_key ,
44+ 0 ,
45+ suite .value ,
46+ sender_public_key = bob_session .local_ephemeral_public_bytes ,
47+ recipient_public_key = bob_session .remote_ephemeral_public_bytes ,
48+ )
49+
50+ assert alice_key != bob_key
51+ assert alice_nonce != bob_nonce
52+
53+
54+ @pytest .mark .parametrize ("suite" , [AeadSuite .AES_GCM_SIV , AeadSuite .CHACHA20_POLY1305 ])
55+ def test_bidirectional_first_messages_roundtrip (suite ):
56+ alice = Identity .generate ("alice" )
57+ bob = Identity .generate ("bob" )
58+ alice_session , bob_session = SessionFactory .pair_for_tests (
59+ alice = alice ,
60+ bob = bob ,
61+ suite = suite ,
62+ )
63+
64+ alice_packet = alice_session .encrypt (b"hello bob" )
65+ bob_packet = bob_session .encrypt (b"hello alice" )
66+
67+ assert bob_session .decrypt (alice_packet ) == b"hello bob"
68+ assert alice_session .decrypt (bob_packet ) == b"hello alice"
69+
70+
71+ @pytest .mark .parametrize ("suite" , [AeadSuite .AES_GCM_SIV , AeadSuite .CHACHA20_POLY1305 ])
72+ def test_public_factory_bidirectional_roundtrip (suite ):
73+ alice = Identity .generate ("alice" )
74+ bob = Identity .generate ("bob" )
75+ alice_session = SessionFactory .initiator (
76+ local_identity = alice ,
77+ remote_name = bob .name ,
78+ remote_x25519_public_key = bob .x25519_public_bytes (),
79+ suite = suite ,
80+ )
81+ bob_session = SessionFactory .responder (
82+ local_identity = bob ,
83+ remote_name = alice .name ,
84+ remote_x25519_public_key = alice .x25519_public_bytes (),
85+ peer_ephemeral_public_key = alice_session .local_ephemeral_public_bytes ,
86+ suite = suite ,
87+ )
88+
89+ assert alice_session .root_key == bob_session .root_key
90+
91+ alice_packet = alice_session .encrypt (b"public hello bob" )
92+ bob_packet = bob_session .encrypt (b"public hello alice" )
93+
94+ assert bob_session .decrypt (alice_packet ) == b"public hello bob"
95+ assert alice_session .decrypt (bob_packet ) == b"public hello alice"
96+
97+
1898def test_tamper_detection ():
1999 alice = Identity .generate ("alice" )
20100 bob = Identity .generate ("bob" )
@@ -40,7 +120,15 @@ def test_replay_detection():
40120def test_hybrid_ready_schedule_changes_root_key ():
41121 alice = Identity .generate ("alice" )
42122 bob = Identity .generate ("bob" )
43- a1 , b1 = SessionFactory .pair_for_tests (alice = alice , bob = bob , supplemental_secret = b"" )
44- a2 , b2 = SessionFactory .pair_for_tests (alice = alice , bob = bob , supplemental_secret = b"pq-layer" )
123+ a1 , b1 = SessionFactory .pair_for_tests (
124+ alice = alice ,
125+ bob = bob ,
126+ supplemental_secret = b"" ,
127+ )
128+ a2 , b2 = SessionFactory .pair_for_tests (
129+ alice = alice ,
130+ bob = bob ,
131+ supplemental_secret = b"pq-layer" ,
132+ )
45133 assert a1 .root_key != a2 .root_key
46134 assert b1 .root_key != b2 .root_key
0 commit comments