moq-e2ee
End-to-end encryption for Media over QUIC groups, datagrams,
and track names. Profile moq-e2ee-00 from
draft-lcurley-moq-e2ee.
Relays forward ciphertext. Content keys never enter moq-net. The TypeScript twin is @moq/e2ee.
Shape
The application distributes a Credential { context, kid, secret } over its own
authenticated channel. Every publisher instance mints an Epoch and binds it as a
Generation, which derives the opaque track names and keys for that instance alone:
let credential = new?;
let generation = credential.generation;
let path = credential.path?.join;
let name = generation.name?;
let producer = generation.produce?;
A subscriber discovers instances under credential.path(semantic), takes the greatest
epoch from the last path segment, binds the same generation, and calls
generation.consume(subscriber) on a track whose name it derived or read from the
decrypted catalog. Nothing survives a publisher instance: a restart mints a new epoch.
Processing
AES-128-GCM is inline and synchronous. cargo bench -p moq-e2ee measures the whole
protected write path, including the moq-net group: a 1 KiB grouped frame and a
160-byte Opus-sized datagram each cost a few microseconds on one core, so encryption
is a tiny fraction of real time and there is no async pump.
Memory is bounded: a producer retains no ciphertext, and a consumer keeps a 1024-bit datagram duplicate window below the greatest sequence it opened.