Current Security Architecture¶
Purpose¶
This document summarizes the current iOS security model at the business and system-flow level. It focuses on what is protected, where trust is established, and which trade-offs still exist.
Security Layers¶
| Layer | Responsibility |
|---|---|
| Transport security | Use TLS and production certificate/public-key pinning for app network channels. |
| Request authenticity | Sign API requests so the backend can detect tampering and replay attempts. |
| Authentication | Use bearer access tokens and refresh tokens to maintain sessions. |
| Secret storage | Store tokens, credentials, and trust data in device-protected persistence. |
| Device identity | Prefer Secure Enclave P-256 key material, with legacy RSA fallback where needed. |
| Key transparency | Verify peer public keys before using them for call key wrapping. |
| Media E2EE | Apply the active call session key to the LiveKit media pipeline. |
| Session cleanup | Clear active call key state when the call lifecycle ends. |
Call Security Flow¶
User starts or joins call
-> app verifies peer device keys
-> app creates or decrypts a call session key
-> app wraps the key per participant device
-> backend relays encrypted key material and room token
-> devices join media room
-> LiveKit E2EE encrypts audio/video with the session key
The backend coordinates the call but should not receive the raw media session key.
Key Transparency Reality¶
KT proof verification is local and fail-fast, but the caller behavior differs by flow:
| Flow | Behavior |
|---|---|
| Friend request trust warm-up | Invalid proofs are rejected and not cached. |
| Mid-call invite | Requires verified keys. |
| Rejoin host response | Requires a verified requester key. |
| Outgoing call | Can continue after warning if the user accepts. |
The outgoing override is the main security trade-off in the current app. Simpler target behavior: proof failure blocks call setup consistently.
TLS Pinning Reality¶
Production pinning is strict:
detect configured proxy
-> evaluate system trust
-> compare public-key hashes
-> allow only if a configured hash matches
Dev and staging use default system TLS validation to support local debugging.
Request Signing Reality¶
Every API request is signed with:
app id + method + url path + body + timestamp
The server can use this to validate request integrity and reduce replay risk.
Current Limitations¶
| Limitation | Current state |
|---|---|
| Outgoing KT override | User can proceed after KT proof failure. |
| Manual key sheet | Active call UI can reveal and rotate the current session key. |
| Pinning outside production | Dev/staging do not enforce app-level pinning. |
| Safety-number verification | Not available in the app. |
| KT consistency/rollback checking | Not available in the app. |