PARITY: post-quantum is shipped on both clients #90
@@ -45,17 +45,35 @@ everything above the protocol.
|
||||
| Device identity + prekey rotation | ✅ | ✅ | retired prekeys retained past the relay window |
|
||||
| Vault (encryption at rest) | ✅ | ✅ | Android Keystore, AES-GCM, record name bound into the AAD |
|
||||
|
||||
| ML-KEM-768 (PQ agreement) | ⚠️ | ⚪ | see below |
|
||||
| ML-DSA-65 (PQ identity) | ⚠️ | ⚪ | see below |
|
||||
| ML-KEM-768 (PQ agreement) | ✅ | ✅ | cross-engine verified — see below |
|
||||
| ML-DSA-65 (PQ identity) | ✅ | ✅ | see below |
|
||||
|
||||
⚠️ **The post-quantum gap is not what it looks like.** iOS has `PQKEM.swift` and
|
||||
`PQSign.swift`, and they are inert: CryptoKit exposes ML-KEM only on iOS 26 and
|
||||
the app targets iOS 16, so no shipped iOS build does post-quantum anything.
|
||||
Android has no platform ML-KEM at any API level. So the two clients are
|
||||
*currently equal in effect* and the honest parity target is v1/v2 negotiation
|
||||
that degrades cleanly — which the Android engine already does, and the interop
|
||||
harness asserts. Closing this properly is a separate decision (implement, or
|
||||
take a vetted library) and it should be made once, for both clients.
|
||||
🔴 **These two rows said ⚪ and ⚠️, and both were wrong — understating, which
|
||||
is the same direction relay#45 warns about and the same one that had the
|
||||
comparison page scoring a competitor unfairly.** The note that used to sit here
|
||||
said iOS's PQ files were inert because CryptoKit exposes ML-KEM only on iOS 26
|
||||
while the app targeted 16, that Android had no ML-KEM at any API level, and so
|
||||
"neither client does post-quantum anything today". None of that is true now, and
|
||||
the middle claim was never quite the point.
|
||||
|
||||
- **Android** uses BouncyCastle's `MLKEMExtractor` / `MLKEMGenerator` — FIPS 203,
|
||||
a real implementation shipped in the engine. There is no *platform* ML-KEM on
|
||||
Android at any API level, which is what the old note was reaching for, and it
|
||||
is why the engine carries its own rather than a reason it has none.
|
||||
- **iOS** uses CryptoKit's `MLKEM768`, and it is **unconditional**:
|
||||
`project.yml` sets the deployment target to 26.0, so the runtime gate that
|
||||
made those files inert is gone. `PQKEM.swift` says so at the top.
|
||||
|
||||
⚠️ Corrected by a run, not by reading the source. The cross-engine harness
|
||||
(`test/interop-swift-kotlin.mjs`) establishes it end to end: *"Android picks v3
|
||||
for an iPhone peer"*, *"the first Android envelope carries a PQ ratchet step"*,
|
||||
*"the iPhone agrees the session is v3"*, and *"a v3 session survives being
|
||||
archived and restored mid-conversation"* — with the same four in the other
|
||||
direction.
|
||||
|
||||
⚠️ The honest limit, which has not changed: post-quantum protection counts only
|
||||
once **both** ends have it, so today that means two Android phones, or an
|
||||
Android phone and an iPhone running a build that has not shipped yet.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user