1# Cryptography23Full audit-ready summary: [`docs/CRYPTO_SUMMARY.md`](https://github.com/richardmetzner/SophaxChat/blob/main/docs/CRYPTO_SUMMARY.md) 4Threat model: [`SECURITY.md`](https://github.com/richardmetzner/SophaxChat/blob/main/SECURITY.md)56All primitives are from Apple's **CryptoKit** (audited, hardware-accelerated via Secure Enclave where available). No third-party cryptographic libraries for core operations.78---910## Primitive summary1112| Layer | Operation | Algorithm | Key size |13|---|---|---|---|14| Identity signing | Sign / Verify | Ed25519 | 256-bit |15| Key agreement | DH exchange | X25519 | 256-bit |16| Symmetric encryption | AEAD | ChaCha20-Poly1305 | 256-bit |17| At-rest encryption | AEAD | AES-256-GCM | 256-bit |18| Key derivation | KDF | HKDF-SHA256 | — |19| Group ratchet | MAC | HMAC-SHA256 | 256-bit |20| Identity export | KDF | PBKDF2-SHA256 | 720 000 iter |21| Key transparency | MAC | HMAC-SHA256 | 256-bit |2223---2425## Key types and storage2627| Key | Lifetime | Storage | Accessible |28|---|---|---|---|29| Identity Key (IK) — Ed25519 + X25519 | Permanent | Keychain | `WhenUnlockedThisDeviceOnly` |30| Signed Prekey (SPK) | 7 days | Keychain | `WhenUnlockedThisDeviceOnly` |31| One-Time Prekeys (OTPKs × 20) | Single use | Keychain | `WhenUnlockedThisDeviceOnly` |32| Double Ratchet state | Per session | Keychain | `WhenUnlockedThisDeviceOnly` |33| Sender Key chains | Per group member | Keychain | `WhenUnlockedThisDeviceOnly` |34| Message store encryption key | Permanent | Keychain | `WhenUnlockedThisDeviceOnly` |3536No key material is ever written to UserDefaults, iCloud, or device backups.3738---3940## X3DH — session setup4142Extended Triple Diffie-Hellman establishes a shared secret between two parties who have never communicated, providing:43-**Forward secrecy** from the first message (OTPK consumed)44-**Cryptographic binding** to both long-term identities4546```47SK = HKDF-SHA256(48 DH(IK_sender, IK_recipient) ‖ // mutual identity binding49 DH(EK_sender, IK_recipient) ‖ // ephemeral × identity50 DH(EK_sender, SPK_recipient) ‖ // ephemeral × signed prekey51 DH(EK_sender, OTPK_recipient) // ephemeral × one-time prekey52)53```5455The ephemeral key `EK_sender` is generated fresh per session and discarded immediately after KDF. The OTPK is consumed and deleted.5657---5859## Double Ratchet + Header Encryption6061After X3DH, all messages use the Double Ratchet Algorithm (Signal spec §3–§4):6263### Symmetric ratchet (every message)64```65messageKey = HMAC-SHA256(chainKey, 0x01)66chainKey = HMAC-SHA256(chainKey, 0x02)67ciphertext = ChaCha20-Poly1305(messageKey, plaintext, AD)68```6970### DH ratchet (every reply)71A new X25519 ephemeral key pair is generated on each reply, rotating the root key and providing **break-in recovery** (post-compromise security).7273### Header Encryption (SophaxChat extension)74Message headers (ratchet public key, sequence numbers) are encrypted with a separate rotating `headerKey` derived during the DH ratchet step. Relay nodes cannot observe:75- Who is speaking to whom (beyond endpoint)76- Sequence numbers / message order77- Ratchet key material7879---8081## Sealed Sender8283Before transmission, every message is wrapped in an additional layer that hides the sender's identity from relay nodes:8485```86ephemeralKey = X25519.generate()87sharedSecret = HKDF(DH(ephemeralKey, IK_recipient))88sealedOuter = ChaCha20-Poly1305(sharedSecret, innerMessage ‖ senderID)89wire = { ephemeralKey.publicKey, sealedOuter }90```9192A relay node sees only `ephemeralKey.publicKey` and an opaque ciphertext. Only the intended recipient can unseal the outer layer and learn the sender's identity.9394---9596## At-rest encryption9798| Store | Key derivation | Algorithm |99|---|---|---|100| Message database | Random 256-bit key in Keychain | AES-256-GCM |101| Attachment blobs | Random 256-bit key per file in Keychain | AES-256-GCM |102103File protection class: `FileProtectionType.complete` — files are inaccessible while the device is locked, even to the OS.104105---106107## Identity export / backup108109Backup passphrase requirements:110- Minimum **16 characters**111- PBKDF2-SHA256 with **720 000 iterations** (≈ 2× Signal's 2024 default)112- Random 32-byte salt stored with the export113114Key material is zeroed from memory immediately after serialisation.115116---117118## Key Transparency Log119120Every identity key change is appended to a local HMAC-SHA256 verified log (append-only, stored in UserDefaults). The HMAC key is stored in Keychain. Tampering with the log (e.g. to erase evidence of a key change) is detectable.121122---123124## Known limitations125126-**No independent security audit** — highest priority before v1.0. See [`SECURITY.md`](https://github.com/richardmetzner/SophaxChat/blob/main/SECURITY.md).127-**No post-quantum cryptography** — X25519 and Ed25519 are classical. Harvest-now-decrypt-later attacks are a long-term concern. MLS (RFC 9420) is designed to support PQC algorithm negotiation in future.128-**Metadata on local network** — BLE/WiFi Direct presence reveals that the app is running to nearby devices. Tor mode eliminates IP-level metadata for TCP connections.