Split hybrid public keys into separate wire fields
The packed 1216-byte hybrid public had no consumer that wanted it whole -- everything unpacked immediately. Message layouts and the credential record now carry peer_m | peer_x as explicit fields; _PUB and the unpack-at-use idiom are gone. credential_id values change with the record layout. Step comments in the exchange methods explain what each solve/challenge proves.
This commit is contained in:
1 parent
168287ca98
commit
f035859fd2
5 files changed
+92
-73
No files matched your search
+13
-14
@@ -81,12 +81,12 @@ def test_registration_credential(psk):
|
||||
run_handshake(a, b)
|
||||
blob_a, blob_b = a.credential, b.credential
|
||||
assert len(blob_a) == len(blob_b) == _CREDENTIAL.size
|
||||
id_a, shared_a, pub_b, sas_a, vf_a = _CREDENTIAL.unpack(blob_a)
|
||||
id_b, shared_b, pub_a, sas_b, vf_b = _CREDENTIAL.unpack(blob_b)
|
||||
id_a, shared_a, pub_b_m, pub_b_x, sas_a, vf_a = _CREDENTIAL.unpack(blob_a)
|
||||
id_b, shared_b, pub_a_m, pub_a_x, sas_b, vf_b = _CREDENTIAL.unpack(blob_b)
|
||||
assert id_a != id_b # fresh random identity roots per party
|
||||
assert shared_a == shared_b # same rotated shared key
|
||||
assert pub_a == _public_from_idroot(id_a) # peer pubs match peer idroots
|
||||
assert pub_b == _public_from_idroot(id_b)
|
||||
assert (pub_a_m, pub_a_x) == _public_from_idroot(id_a) # pubs match idroots
|
||||
assert (pub_b_m, pub_b_x) == _public_from_idroot(id_b)
|
||||
assert sas_a == sas_b # the stored comparison digest
|
||||
assert vf_a and vf_b # confirmed by run_handshake's answers
|
||||
|
||||
@@ -317,7 +317,7 @@ def test_verification_not_required(psk):
|
||||
assert not a.verified and not b.verified
|
||||
assert est_a.sas == est_b.sas # the SAS is still exposed
|
||||
assert a.state == b.state == "established"
|
||||
assert _CREDENTIAL.unpack(a._store["x"])[4] is False # stored unverified
|
||||
assert _CREDENTIAL.unpack(a._store["x"])[5] is False # stored unverified
|
||||
|
||||
|
||||
def test_wrong_calls_rejected(psk):
|
||||
@@ -478,7 +478,7 @@ def test_unverified_resumption_is_silent(psk):
|
||||
a, b = make_sessions(psk)
|
||||
run_handshake(a, b, answer=None)
|
||||
cred_a, cred_b = a.credential, b.credential
|
||||
assert _CREDENTIAL.unpack(cred_a)[4] is False
|
||||
assert _CREDENTIAL.unpack(cred_a)[5] is False
|
||||
|
||||
a2, b2 = make_sessions(cred_a, cred_b)
|
||||
(m1,) = a2()
|
||||
@@ -492,7 +492,7 @@ def test_unverified_resumption_is_silent(psk):
|
||||
a2.confirm(True) # compared out of band: flag it verified
|
||||
b2.confirm(True)
|
||||
assert a2.verified and b2.verified
|
||||
assert _CREDENTIAL.unpack(a2._store["x"])[4] is True # flag flipped
|
||||
assert _CREDENTIAL.unpack(a2._store["x"])[5] is True # flag flipped
|
||||
|
||||
a3, b3 = make_sessions(a2._store["x"], b2._store["x"])
|
||||
run_handshake(a3, b3) # verified: silent as before
|
||||
@@ -639,7 +639,7 @@ def test_flag_flip_tolerates_parallel_confirm(psk):
|
||||
r1.confirm(True) # flips the slot to verified
|
||||
r2.confirm(True) # slot changed under it, but same credential
|
||||
assert r1.verified and r2.verified
|
||||
assert _CREDENTIAL.unpack(cli["s"])[4] is True
|
||||
assert _CREDENTIAL.unpack(cli["s"])[5] is True
|
||||
|
||||
|
||||
def test_commitment_reveal_checked(psk):
|
||||
@@ -695,8 +695,8 @@ def test_mitm_reused_reveal_detected(psk):
|
||||
# leg beta: the MITM recommits the stolen reveal toward bob
|
||||
hs = m_out._exchange
|
||||
hs._reveal = r_a
|
||||
hs._eph_m, hs._ephemeral, e_pub = _fresh_ephemeral()
|
||||
body = _MSG1_REGISTER.pack(e_pub, kdf("commit", e_pub, r_a))
|
||||
hs._eph_m, hs._ephemeral, e_m, e_x = _fresh_ephemeral()
|
||||
body = _MSG1_REGISTER.pack(e_m, e_x, kdf("commit", e_m, e_x, r_a))
|
||||
msg1m = bytes(encrypt(body, key=kdf("reg/msg1", psk), ad=b""))
|
||||
hs._chain.advance(msg1m) # startA was bypassed: advance the chain
|
||||
(m2b,) = b(msg1m)
|
||||
@@ -734,9 +734,8 @@ def test_foreign_mlkem_static_rejected_at_msg4(psk):
|
||||
# mlkem half, her own x25519 half): she cannot decapsulate bob's ct_se
|
||||
# challenge, so bob's confirm tag does not match her root and she burns
|
||||
a, b = make_sessions(psk)
|
||||
real = a._exchange._static_pub
|
||||
foreign = _public_from_idroot(secrets.token_bytes(32))
|
||||
a._exchange._static_pub = foreign[:1184] + real[1184:]
|
||||
# alice presents a static whose ML-KEM half she does not hold
|
||||
a._exchange._static_m = _public_from_idroot(secrets.token_bytes(32))[0]
|
||||
(m1,) = a()
|
||||
(m2,) = b(m1)
|
||||
(m3,) = a(m2)
|
||||
@@ -770,7 +769,7 @@ def test_credential_id(psk):
|
||||
run_handshake(a, b, answer=None)
|
||||
blob = a.credential
|
||||
# stable across the verified flag (metadata may change)
|
||||
flagged = _CREDENTIAL.pack(*_CREDENTIAL.unpack(blob)[:4], True)
|
||||
flagged = _CREDENTIAL.pack(*_CREDENTIAL.unpack(blob)[:5], True)
|
||||
assert credential_id(blob) == credential_id(flagged)
|
||||
# tied to the credential: a different record hashes differently
|
||||
assert credential_id(blob) != credential_id(psk) # rotation rotates it
|
||||
|
||||
Reference in new issue
Block a user