Skip to content

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.