-
Notifications
You must be signed in to change notification settings - Fork 0
Security Properties
Yura Filatov edited this page Aug 8, 2026
·
3 revisions
| Property | Status | Notes |
|---|---|---|
| Private key extraction | ✅ Not possible | SE-wrapped; operations performed inside SE chip |
| Private key at rest | ✅ SE-wrapped in Keychain | Protected by SE hardware key, not stored inside the SE |
| Key agreement (classical) | ✅ ECDH P-256 | Industry standard |
| Key agreement (PQ) | ✅ Hybrid ECDH + ML-KEM-1024 | NIST Level 5, SE-backed, iOS 26+ |
| Session key derivation | ✅ HKDF-SHA256 | Domain-separated info strings per path |
| Content encryption | ✅ AES-256-GCM | Authenticated encryption, quantum-resistant |
| Nonce reuse | ✅ Random per message | Each seal call generates a fresh nonce |
| Bundle integrity | ✅ AAD covers version + key-exchange fields | Tampering causes GCM failure |
| Forward secrecy | ✅ Per-message, v3fs | Ephemeral + single-use prekeys; SE deletion on decrypt |
| FS quantum resistance | ✅ Direct (PQ contacts) | ML-KEM secrets mixed into every FS session key |
| FS quantum resistance | Prekeys protected by classical encryption of delivery payload | |
| Prekey confidentiality | ✅ Encrypted in transit | Public keys travel only inside AES-GCM ciphertext |
| Metadata leakage | ✅ No contact identifiers on wire | WirePrekey carries id + publicKey only |
| ML-KEM private key isolation | ✅ Secure Enclave | SE reference released after decapsulation, never persisted |
| ML-KEM secret storage | Stored in SwiftData under hybrid local DB key, not SE-wrapped | |
| MITM during exchange | ✅ Diceware verification + peer ID guard | Human-verifiable, nonce-freshened |
| Proximity spoofing | ✅ UWB hardware enforcement | ≤ 0.25m threshold |
| Server-side exposure | ✅ None | No backend exists |
| Remote account takeover | ✅ No attack surface | No phone number, server account, or password |
| Identity re-verification | ✅ Challenge-response | Signed ECDSA challenge; proves SE key continuity without re-exchange |
| Backward compatibility | ✅ Classical fallback | v1 peers and iOS < 26 exchange classically, no breakage |
| Android interoperability | ❌ Not supported | iOS + Secure Enclave only |
| PIN app lock | ✅ Implemented | SE-bound AES-GCM verifier; constant-time 500ms gate; incremental lockout; grace period |
| Duress PIN / decoy view | ✅ Static + live-protocol indistinguishability | Visually identical at rest and behaviorally identical live — inbound bundles are never rejected because of restriction state, closing the accept/reject test a coercer could otherwise use to detect duress mode. Accepted residuals: a hidden contact's genuinely new message can still render on screen during a coercion window (decryption itself must not vary by depth); a contact created during duress before this protection existed can't be identified retroactively |
| Coercion-resistant toggle | ✅ Implemented | Gate lowers without removing verifiers; unknown PIN at depth > 0 silently creates new layer |
| Key rotation on activation | ✅ Implemented | 11-step atomic sequence; staged key; WAL-checkpoint ordering; rollback on failure |
| Layer store (sensitive contact recovery) | ✅ Implemented | 32-slot fixed-size AES-GCM file; exists from first launch; excluded from backup |
| Multi-layer duress | ✅ Implemented | Up to 32 nested layers; cold-start routing aliases; cascade deactivation |
| SQLite freed-page zeroing | ✅ secure_delete = ON
|
Set in DB header at launch; persists for all connections including SwiftData |
| Store file protection | ✅ completeFileProtection
|
Stamped on store, WAL, and SHM on every ModelContext save; excluded from backup |