← Back
Home › Systems › Communication and media

drm

Distributes encrypted video through ordinary CDNs and decides per viewer and device who may decrypt it, by issuing keys through a separate license exchange.

Widevine, FairPlay

Open the drm pagedrm Hdr histogramdata-structures: Log-linear bucketed histograms with bounded relative error for latency percentilesDeterministic simulationtestingdistributed: Run the whole system in one thread under a seeded scheduler with simulated network, disk and clock, so every failure replays from its seed.›Primary-backup replicationdistributed: One node orders all writes and ships them to standbys; the acknowledgement rule (none, one, all) sets what a crash loses, and an external arbiter decides who takes over.›Process supervisionhardware-os: A parent process starts services, reaps their exits and restarts them under a delay and burst-limit policy, then stops them with SIGTERM before SIGKILL.›Common Encryption (CENC)media: ISO/IEC 23001-7 fixes how MP4 samples are encrypted and where key ID, IVs and clear/protected byte ranges are stored, so one file serves many DRM systems.›AEAD (AES-GCM,ChaCha20-Poly1305)security: Authenticated encryption that encrypts and detects tampering in one call; the only kind of symmetric encryption you should use.›Coverage-guided fuzzingsecurity: Mutate inputs, run an instrumented target, and keep any input that reaches a new code edge; feedback turns blind guessing into incremental search.›Digital signatures (Ed25519)security: Small, fast, deterministic public-key signatures that prove who produced a message; the default for tokens, releases and protocols.›Envelope encryptionsecurity: Encrypt each object with its own data key and wrap that key under a KMS-held key, so rotation re-wraps 60 bytes and deleting a key shreds data.›HKDF key derivation(extract-and-expand)security: HMAC-based two-step key derivation: extract a uniform pseudorandom key from any secret, then expand it into as many context-bound keys as you need.›Message authentication codes(HMAC, CMAC, Poly1305, KMAC)security: A keyed short tag proving a message is unmodified and came from a key holder; pick HMAC, CMAC, KMAC or a one-time polynomial MAC by what primitive you already have.›Mutual TLSsecurity: TLS where the client also proves a certificate key, so every connection carries a verified, rotatable machine identity.›Remote attestationsecurity: Hardware-signed evidence (TPM quotes, SGX/TDX quotes, SEV-SNP reports, key attestation) proving device, key or enclave state to a verifierSecrets managementsecurity: Keep keys and passwords out of code and logs, give workloads short-lived identity instead of static keys, and make rotation routine.›Sessions vs tokenssecurity: Opaque server-side sessions in cookies for browsers, short-lived signed tokens between services; revocation decides most cases.›Trusted execution environmentssecurity: Enclaves/confidential VMs with remote attestation for computing on sealed dataX509 certificatessecurity: Certificate chains, path validation, SANs, revocation and short-lived issuancePoint-in-time recoverystorage: Periodic base backups plus a continuously archived change log let you rebuild the state as of any instant, then branch from there.›Graceful drainingsystems: On a termination signal, stop taking new work, finish in-flight work until a deadline, tell clients to reconnect elsewhere, then exit; clients resume from a token.›Token bucketsystems: A bucket of up to b tokens refilled at rate r; requests spend tokens, enforcing an average rate while allowing bursts of b.›Cooperative schedulingconcurrency: Green threads/coroutines yielding at await points on a user-space schedulerFault injectiondistributed: Inject latency, errors, kills and partitions via proxies, netem or hooksRecord replaydistributed: Record every nondeterministic input (time, randomness, I/O, model and tool outputs, per-tick player input) and re-execute deterministically for debugging, replays and state rebuildLeasesdistributed: A lock that expires on its own: bounded-time ownership that survives crashes and partitions, given bounded clock drift and fencing tokens on writes.›Health checkingsystems: Decide per backend whether to route to it using probes and real-traffic errors, with consecutive-count hysteresis, capped ejection and a panic fallback.›PRNGs (PCG, xoshiro)numerics: Small, fast, statistically strong non-cryptographic generators: PCG32 and xoshiro256**, with seeding, parallel streams and unbiased ranges.›Constant time codesecurity: Writing secret-dependent code without branches or memory lookups on secrets; constant-time compare and selectCode coverage instrumentationcompilers: Insert counters into compiled code to record which blocks, edges or lines ran; a spanning tree of the control-flow graph cuts the counters needed.›Delta debuggingcompilers: Ddmin minimization of failing inputs or change setsFast hash functionsdata-structures: Non-cryptographic hashes built from 64×64→128-bit multiplies and xor-shifts; pick by key size, trust level and whether the hash is persisted.›Sanitizerssecurity: ASan/UBSan/TSan shadow memory and instrumentation to catch memory bugsAes key wrapsecurity: AES Key Wrap (RFC 3394/5649) and AES-GCM-SIV for deterministic, authenticated wrapping of key material+ 8 moreTransparent interceptionnetworking: Redirect traffic to a local proxy (iptables TPROXY/REDIRECT, eBPF) without app changesSyscall interceptionsecurity: Intercept syscalls via ptrace, seccomp user notify or a user-space kernelFencing tokensdistributed: A number that grows with every lock grant and is checked by the protected resource, so a paused ex-holder's late write is rejected.›Control-flow graphcompilers: Split a linear instruction list into basic blocks and connect them by jumps; the graph every optimizer, SSA builder and dataflow pass walks.›Minimum spanning treegraphs: Cheapest set of edges connecting all vertices; Kruskal sorts edges and joins components with union-find, Prim grows one tree, Boruvka merges in parallel rounds.›Failure bisectionsearch-sort: Binary search over commits, batches or inputs to isolate a failure+ 6 moreEbpfhardware-os: Verified in-kernel programs on hooks (kprobes, XDP, tc) with mapsPtrace process controlhardware-os: Ptrace: attach, read and write registers and memory, single-step, intercept signalsSeccomp bpfsecurity: Syscall filtering with seccomp BPF programsBFS and DFSgraphs: The two basic graph traversals; BFS gives hop distances and levels, DFS gives discovery/finish order for cycles, components and topological order.›d-ary heapdata-structures: Array heap with d children per node (d = 4 typical): half the binary heap's depth, siblings in one cache line, faster priority queues.›Union-findgraphs: Disjoint-set forest with union by size and path compression; merges sets and answers same-set queries in effectively constant time.›+ 3 moreSparse matrices (CSR)numerics: Compressed sparse row stores only nonzeros as row pointers, column indices and values; SpMV streams them once, so it is memory-bandwidth bound.›

How it is built

Architecture overview

A DRM system lets a service distribute encrypted video to the public and still decide, per viewer and per device, who may decrypt it. The media is encrypted once at packaging time and served from an ordinary CDN to everyone. The content key never travels with it. A player that wants to play asks a license server for the key, proves who it is and what device it runs on, and receives the key wrapped for one specific decryption module on that device. The decryption module (the content decryption module, CDM) holds the key where the application cannot read it and decrypts samples on request.

The idea that makes it work is separating the cheap, public part from the small, guarded part. Bulk bytes (the media) are public, cacheable, identical for all viewers. The only secret-bearing traffic is the license exchange: a few kilobytes per playback start, which a service can protect carefully (attestation of the device, signed requests, short-lived tokens, rate limits, per-user policy) without the cost showing up in bandwidth. The business rules (which title, which resolution, how long, how many devices) live in the license server's policy, and the device-side module enforces them.

Parts:

 PACKAGING (once per title)                     PLAYBACK (per viewer)
 source ─► encoder ─► packager ──► CDN ──► player (browser / app / TV)
              │     (CENC, key id)  ▲          │ 1. read key id + init data from file
              │                     │          ▼
              │              encrypted      CDM ◄─┐  (hardware-backed where available)
              ▼              segments        │    │ 4. wrapped key
         key service                         │ 2. license request (signed, device cert)
        (envelope-encrypted keys)            ▼    │
              ▲                       ┌── license server ──┐
              └─── content key ◄──────┤  auth + entitlement │── store (replicated, WAL, backups)
                                      │  attestation check  │
                                      └── rate limit, log ──┘
                         3. app proof of entitlement (token) goes along the request

The same design appears under different brand names: Widevine, FairPlay Streaming and PlayReady are three such systems, each with its own license protocol and device module, which is why one encrypted file must work for several of them (see Common Encryption below).

How the parts fit together

Packager

The packager encrypts every media sample with AES under a content key named by a 16-byte key id, leaves the bytes a player must parse in the clear, and writes the key id and system-specific init data (pssh boxes) into the file. This is Common Encryption (CENC), defined by ISO/IEC 23001-7: the file is encrypted once and any DRM system that understands the scheme can obtain the key through its own license exchange. The schemes are cenc (AES-CTR), cbc1, cens and cbcs (the last two use a block pattern; cbcs is what HLS fragmented MP4 uses per RFC 8216). Why this block and not a custom envelope: a service wants one set of encrypted segments on the CDN for all platforms, not one copy per DRM vendor. The encryption of samples is a stream-cipher or CBC pass, not AEAD (AES-GCM, ChaCha20-Poly1305): media segments have no room for per-sample authentication tags and are checked by container structure; AEAD belongs to the license exchange and key storage instead. Content keys come from a csprng (no page yet), the operating system's secure random source.

Key management

Content keys are the crown jewels of the service, and there can be millions of them. Envelope encryption is the storage pattern: each content key is encrypted under a key-encryption key held in a key management service or hardware module, so the database holds only wrapped keys and rotating the key-encryption key means re-wrapping, not re-encrypting media. Deterministic key wrapping (aes-key-wrap, no page yet; RFC 3394 and RFC 5649) is the standard way to wrap a small key under another key. HKDF key derivation (extract-and-expand) derives per-session or per-purpose keys from a master secret so that the same master never directly protects two things. Secrets management governs how the service itself reaches the key-encryption key: short-lived identity, no keys in images or logs, routine rotation. The contract with the license server is narrow: a call that takes a key id and returns the content key, available only to authenticated license-server instances.

License server

The license server receives a request from the CDM, validates it, decides whether this user may watch this title on this device now, and answers with the content key wrapped to the device's module. Its authentication has two layers. The device layer (below) proves the module is genuine. The user layer proves entitlement: the app calls its own backend, which authenticates the user with OAuth 2 and OpenID Connect or a session (Sessions vs tokens), and passes the license server a signed claim in the request. A JSON Web Token (JWT) is a common form of that claim; the verifier must pin the algorithm, check expiry, audience and issuer, and look up the key by id. Signatures use Digital signatures (Ed25519) or an RSA or ECDSA alternative, and shorter integrity checks use Message authentication codes (HMAC, CMAC, Poly1305, KMAC). Between the backend and the license server, Mutual TLS gives each service a verified identity. The comparison of secrets and tags goes through constant-time-code (no page yet) routines, so response time does not leak how many bytes matched.

Playback cannot start until the licence answer arrives, so the licence round trip is the latency users feel. hdr-histogram (no page yet) records the time of each licence request, split into device check, entitlement lookup and key unwrap, as percentiles. The budget is set on the slow tail, because a few seconds of delay at start is what drives people to abandon a stream, and the same numbers show whether a rate limit or a store failover has begun to hurt.

Device trust

Without device trust, the key would simply be handed to any program that asks. The license server therefore needs evidence that the requester is a module it recognizes. Three blocks stack: Secure boot chain (each stage verifies the next, anchored in an immutable root), measured-boot (no page yet) (each stage's hash is recorded in a TPM-style register), and remote-attestation (no page yet) (hardware-signed evidence of that state, checked by the server against a certificate chain, x509-certificates, no page yet). Device keys live in hardware-backed-keystore (no page yet) storage, or in a trusted-execution-environments (no page yet) enclave where the CDM runs. The license server's policy can then tie output quality to trust: a verified hardware path may receive high-resolution keys, a software-only module only lower resolution. This is the reason the policy engine and the attestation check are in the same service. Which levels and how many exist is vendor-specific; each system's documentation describes its own. For example, Widevine's public page says its licenses are issued through a Cloud License Service or a License Server SDK, with requests processed via a proxy.

Abuse control

License requests come from a closed set of clients, which makes abuse patterns visible: account sharing, key scraping from a patched player, request floods. A Token bucket per account and per device bounds the average request rate while allowing the burst that a seek or a channel change causes. The limit is a control, not a security boundary; the real protection is that the key is useless outside an attested module. The alternative algorithms (GCRA, sliding-window counters) differ in memory and smoothness, not in purpose.

Store and availability

A license server has to be up whenever any viewer presses play, and it must never lose a key or an entitlement. The state is small and write-light: content keys, device registrations, entitlement and revocation lists, audit records. A single primary with synchronous replication to a standby fits: Primary-backup replication, with the acknowledgement rule decided by how much loss is acceptable and an external arbiter or Leases with Fencing tokens deciding who is primary, so a paused old primary cannot write after takeover. Each node's store uses a Write-ahead log for durability; Point-in-time recovery with base backups in Object storage covers operator mistakes and corruption, which replication copies faithfully. Health checking removes bad instances from rotation, Graceful draining lets in-flight license requests finish at deploy time, and Process supervision restarts a crashed process. The classic recovery algorithm (ARIES recovery) and the Buffer pool matter only if the store is a self-built database; with an off-the-shelf database they are the database's concern.

Assurance

A license service parses attacker-controlled messages (the request from the device) and handles keys, so the cost of one bug is large. Coverage-guided fuzzing of the request parser, with Code coverage instrumentation as its feedback, finds crashes and mis-parses before attackers do. Deterministic simulation testing runs the replication and failover logic under a seeded scheduler with simulated network faults, so a rare split-brain bug replays exactly. fault-injection (no page yet), delta-debugging (no page yet) and sanitizers (no page yet) support those two.

Data and control flow

Flow 1: packaging a title

  1. The packager reads the encoded streams and asks the key service for a content key and key id for each track (often separate keys for audio, SD, HD and UHD video).
  2. It encrypts every sample under the track's key with the chosen scheme (cenc or cbcs) and writes the key id, scheme, per-sample IVs and clear/protected ranges into the file.
  3. It adds one pssh box per DRM system the service supports, then uploads the segments and manifest to object storage and the CDN.
  4. The key service stores the content key envelope-encrypted and registers the title's key ids with the license server's entitlement rules.

Flow 2: starting playback

  1. The player downloads the manifest and the first segment; the file's init data names the key id.
  2. In a browser, the page calls the Encrypted Media Extensions API: requestMediaKeySystemAccess selects a key system and its capabilities, createMediaKeys creates the key object, and generateRequest on a session passes the init data to the CDM (W3C EME).
  3. The CDM produces a license request and signals it to the page as a message event. The page sends it, with the user's entitlement token, to the license server over TLS.
  4. The server verifies the token and the device evidence, checks policy and rate limits, loads the wrapped content key, wraps it for this device and returns the license.
  5. The page passes the response to the session's update call. The CDM stores the key in its protected area and reports key status through a keystatuseschange event.
  6. The player feeds encrypted samples to the CDM, which decrypts them into a protected path or returns them to the decoder. Time to first frame includes this round trip, so the license server must answer in tens of milliseconds, not seconds (order of).

Flow 3: revocation and rotation

  1. A device model is found compromised, or a user stops paying. The service adds the device or user to the revocation or entitlement store.
  2. New license requests from those devices are refused. Licenses already issued stay valid until they expire, so license duration is the lever: short for live and rentals, longer for offline downloads.
  3. For live streams, content keys rotate during the stream; the player asks for new licenses ahead of time, which is why the license server's availability, not its bandwidth, is the critical path.

Scaling

The license endpoint is small and read-mostly, so it scales horizontally, with the following limits in the order they appear. First are TLS handshakes and signature verifications per second at a peak, such as a popular live event starting; keep sessions alive, use fast signatures, and spread load across regions. Second is the key store read path: cache unwrapped keys in memory only for as long as the policy allows, or cache the wrapped form and unwrap through the key service. Third is the key management service, which is often rate-limited by its provider; batch unwraps and cache. Fourth is the primary for writes: writes are rare (registrations, revocations), so a single primary suffices; read replicas serve license reads. Fifth is regional availability: place replicas near users, but keep a single write authority to avoid divergent entitlements. Last is abuse load, which a Token bucket and early rejection of unauthenticated requests absorb before the expensive parts.

Failure modes

FailureSymptomCauseFix
Playback never startsSpinner after press, license request failsLicense server down, token expired, clock skewMulti-region servers, clock sync, retry with backoff, clear client error
Black screen with audioAudio plays, video does notDevice refused the HD key because its trust level is too lowPolicy fallback to a lower resolution track
Wrong keyGarbled picture or decrypt errorKey id mismatch between packager and key service, or wrong schemeVerify key id and scheme at packaging; tests on every target device
One platform failsWorks in browser, fails on a TVMissing pssh for that system, or cenc against a device that only supports cbcsPackage for both schemes or standardize on one, test the matrix
License stormLatency spike when a live event startsEveryone requests at once; no rate limitingSpread license fetch with jitter, pre-fetch, scale out
Stale revocationA banned device still playsLong-lived licenses, caches not invalidatedShorter license duration, push revocations to caches
Key leakContent appears on pirate sitesKey extracted from a weak (software-only) moduleLower-tier devices get lower resolutions; revoke the device model
Split brainTwo primaries accept writesFailover without fencingLeases with fencing tokens; arbiter outside the pair
Parser crashLicense server dies on a crafted requestMemory-safety bug in parsingFuzz the parser, use a memory-safe language, isolate the process

Real implementations

namewhat it isrepolicencenotes
Shaka Packagermedia packager with DASH, HLS and encryptionshaka-project/shaka-packagerBSD-3-ClauseCENC packaging; README lists DASH and HLS packaging and encryption
Shaka PlayerJavaScript player with EME supportshaka-project/shaka-playerApache-2.0DRM playback in browsers
dash.jsDASH reference playerDash-Industry-Forum/dash.jsBSD-3-ClauseMPEG-DASH playback in browsers
Media3 / ExoPlayerAndroid media libraryandroidx/mediaApache-2.0Android media library; the Widevine page names ExoPlayer for Android playback
WidevineGoogle's DRM systemdevelopers.google.com/widevineproprietarydocuments the Cloud License Service and License Server SDK
FairPlay StreamingApple's DRM systemdeveloper.apple.com/streaming/fpsproprietaryfor HLS on Apple platforms
PlayReadyMicrosoft's DRM systemlearn.microsoft.com/playreadyproprietaryofficial documentation

No complete open-source production license server is listed, because none was verified for this page. Streaming services that use these systems include Netflix, Disney and Warner Bros. Discovery; their internal designs are not public.

Sources

  • W3C, Encrypted Media Extensions. spec
  • W3C, Encrypted Media Extensions: Initialization Data Format Registry, cenc format. spec
  • ISO/IEC 23001-7, Common encryption in ISO base media file format files (standard; cited by number).
  • RFC 8216, HTTP Live Streaming. rfc
  • RFC 3394, Advanced Encryption Standard (AES) Key Wrap Algorithm; RFC 5649, AES Key Wrap with Padding Algorithm (RFC 3394: rfc; RFC 5649: rfc).
  • Widevine DRM overview. docs
  • Apple, FairPlay Streaming. docs
  • Microsoft, PlayReady. docs
  • DASH Industry Forum guidelines. docs

Similar systems

Share the most building blocks with this one.