Swift-native Two-MLS-PQ (post-quantum MLS) built on swift-mls.
The first piece is the 0xFDEA ML-KEM-768 cipher-suite provider — a
conformer to swift-mls's MLS.CipherSuiteProvider for the private-range suite
MLS_128_ML_KEM_768_AES128GCM_SHA256_Ed25519. It supplies the ML-KEM-768 KEM
and RFC 9180 base-mode HPKE over it, and reuses swift-mls suite-1's symmetric
stack (HKDF-SHA256 / AES-128-GCM / SHA-256 / Ed25519) unchanged.
The APQ combiner, the post-quantum ratchet, and the session layer will land here next, as the Rust implementation is retired.
The provider uses Apple CryptoKit's ML-KEM-768, so its types are
@available(iOS 26, macOS 26). The package's link floor is iOS 17 / macOS 14
(swift-mls's floor); the OS-26 requirement applies only when calling the
provider.
| Role | Value | Suite |
|---|---|---|
| Classical | 0x0003 |
MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519 (curve25519ChaCha) |
| Post-quantum | 0xFDEA |
MLS_128_ML_KEM_768_AES128GCM_SHA256_Ed25519 (FIPS 203, private range) |
Public keys (1184 B) and ciphertexts (1088 B) are the standard FIPS 203 wire
format. The private key is CryptoKit's 96-byte integrityCheckedRepresentation
(seed-bearing), which is not interchangeable with other providers' secret
formats.
On-wire size of each frame kind is measured and recorded in
docs/protocol/message-sizes.md, the Swift
counterpart of the Rust reference's benches/sizes.rs. Reproduce with:
swift test --filter PayloadSizesTestsThe following pieces of the Rust reference have not landed in this port yet:
- Header encryption / §A.1 envelope — frames are not yet header-encrypted, so Rust↔Swift interop is not yet possible.
- Persistence / archive — no durable session storage yet.
- Invitation dedup ledger — replayed invitations are not yet deduplicated.
- The GCE ban / rule 8 on receive — not yet enforced on the receive path.
- §A.5 self-drive — the initiator does not yet auto-drive a re-key round.
Dual-licensed under Apache 2.0 and MIT.