Media encryption
How audio and video are protected between the apps and the media server, and what that does not cover.
Summary
On the hosted platform every media packet, in both directions, is encrypted and authenticated with AES-256-GCM. Keys are agreed for each session with an ephemeral ECDH (P-256) exchange and derived with HKDF-SHA256. The media server does not accept or send anything in the clear, and ignores every packet that does not belong to an authenticated session.
Only standard primitives from the platform libraries are used: OpenSSL on the server, the Android platform providers in the SDK.
How a session is set up
- The app proves it can receive at its network address (a stateless cookie round trip; replies are never larger than requests).
- It presents the media grant, proves it holds the media key, and sends a fresh public key.
- The media server checks the grant's signature, lifetime, revocation and proof, answers with its own fresh public key and proves it holds the media key too.
- Both sides derive one key per direction. A new grant, a reconnect or a renewal always produces new keys.
- From then on each packet carries the session id and a counter in the clear (authenticated) and the payload encrypted, with a 16-byte tag.
What is enforced
- Packets from senders without a valid session are dropped without an answer.
- A modified, forged or replayed packet is dropped (64-packet replay window in each direction).
- A user can publish only the streams named in the grant; the audience role cannot publish.
- Rooms of different projects are separate even when their ids are equal.
- An expired or revoked grant ends the session; the SDK then needs a new token from your server.
- Recorded traffic cannot be decrypted later with the grant or the media key alone: session keys depend on the ephemeral exchange.
- A network change (Wi-Fi to mobile) keeps the session; only an authenticated, newer packet can move it.
What it is not
- It is not end-to-end encryption between participants. The media server decrypts each packet in memory to forward it, and encrypts it again for every receiver.
- Packet sizes, timing, stream ids and network addresses are visible to the network, as with any real-time transport.
- A private lab media server started without grant keys speaks the old unencrypted framing; it refuses to start on a public address.
- The protocol has not yet had an independent security review. It is built only from reviewed primitives and is covered by automated tests, including tests that disable each check on purpose.
Source references
sfu/src/media_auth.cppsfu/tests/media_auth_test.cpptoken-service/internal/mediagrant/wire.gosdk/android/fahswe-rtc/src/main/java/com/fahswe/rtc/media/MediaAuthClient.java
Was this page helpful?