diff --git a/browser_cli/auth.py b/browser_cli/auth.py index 7e15c52..005c859 100644 --- a/browser_cli/auth.py +++ b/browser_cli/auth.py @@ -212,7 +212,7 @@ def pq_kex_client_encapsulate(public_key_hex: str) -> tuple[str, bytes]: """Encapsulate to a server ML-KEM public key. Returns (ciphertext_hex, secret).""" from cryptography.hazmat.primitives.asymmetric import mlkem pub = mlkem.MLKEM768PublicKey.from_public_bytes(bytes.fromhex(public_key_hex)) - ciphertext, shared_secret = pub.encapsulate() + shared_secret, ciphertext = pub.encapsulate() return ciphertext.hex(), shared_secret diff --git a/tests/test_auth.py b/tests/test_auth.py index 6cdb7af..9aef61c 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -12,6 +12,9 @@ from browser_cli.auth import ( load_authorized_keys_with_names, load_private_key, new_nonce, + pq_kex_client_encapsulate, + pq_kex_server_decapsulate, + pq_kex_server_keypair, sign, verify, ) @@ -108,6 +111,20 @@ class TestSignVerify: assert verify("aabbcc", b"nonce", {}, "00" * 64) is False +class TestPostQuantumKex: + def test_mlkem_roundtrip_when_backend_supports_it(self): + keypair = pq_kex_server_keypair() + if keypair is None: + pytest.skip("ML-KEM backend not available") + priv, pub = keypair + + ciphertext_hex, client_secret = pq_kex_client_encapsulate(pub.hex()) + server_secret = pq_kex_server_decapsulate(priv, ciphertext_hex) + + assert server_secret == client_secret + assert len(server_secret) == 32 + + class TestAuthorizedKeys: def test_add_and_load(self, tmp_path): path = tmp_path / "authorized_keys"