fec6a7bba4
Existing interop tests covered wire-format round-trips but never actually
ran ciphertext from IETF/OpenMLS/mls-rs test vectors through our crypto
code paths. That left two major spec bugs unverified by CI — the wrong
HPKE Welcome-context and the wrong "eae_prk" DHKEM label — because
both sides of every round-trip were wrong the same way.
Tighten coverage with cross-implementation KATs:
CryptoBasicsInteropTest
+ testEncryptWithLabelDecryptsIetfVector: decrypt the IETF
encrypt_with_label vector directly (kem_output + ciphertext), not
just our own round-trip output.
WelcomeInteropTest
+ testX25519Rfc7748Vectors: RFC 7748 §6.1 X25519 KATs.
+ testX25519DhMatchesJavaXdh: compare against JDK 11+ XDH on the IETF
encrypt_with_label priv/kem_output.
+ testWelcomeInitKeyMatchesPrivateKey: init_pub == publicFromPrivate
(init_priv) for every IETF welcome vector.
+ testIetfKeyPackageSelfSignatureVerifies: exercises Ed25519 +
SignContext + LeafNode TLS encoding against OpenMLS output.
+ testIetfWelcomeFullDecryptAndGroupInfoSignature: end-to-end path
through HPKE GroupSecrets decrypt → welcome_key derivation → AEAD
GroupInfo decrypt → GroupInfoTBS Ed25519 verify against signer_pub.
+ testPassiveClientWelcomeDecryptsGroupInfoAndFindsLeaf: same
end-to-end path on passive-client-welcome.json, plus ratchet-tree
leaf lookup and signer-leaf GroupInfo verify. Skips vectors with
external_psks (we don't model PSK secret derivation here) and with
no ratchet tree (delivery-service lookup).
The TreeKEM UpdatePath KAT was considered but needs the full direct
path / copath / resolution / LCA plumbing from MlsGroup.processCommit
to pick which HPKE ciphertext a given leaf should decrypt. Not worth
the duplication in a test — the "UpdatePathNode" HPKE path now has KAT
coverage indirectly via the IETF encrypt_with_label vector above
(same HPKE stack, different label).
https://claude.ai/code/session_01HfHdd5S5rvxUW2ihEpLGJr