-
Notifications
You must be signed in to change notification settings - Fork 3
kithara drm
Documentation reviewed from source revision 19ca073f2. This records the documented contract at that revision; it is not a new runtime validation. API and usage · All crates.
HLS wraps DecryptContext as a kithara-assets ResourceProcessor / ChunkSink pair in kithara-hls/src/decrypt_processor.rs. Decryption runs once, on resource commit, inside kithara-assets' processing writer:
- The committed resource is read back in 64 KB chunks (
processing::writer::CHUNK_SIZE). - Each chunk goes through
aes128_cbc_process_chunk(), from a pooled input buffer into a pooled output buffer. - The plaintext is written back into the same resource at a running output offset.
- The final chunk (
is_last = true) strips PKCS7 padding and returns the shorter plaintext length, which becomes the resource's committed length.
Invariants:
- Input length must be a multiple of the 16-byte AES block size; an unaligned chunk is a hard error.
- Chunks are not independent: an intermediate chunk decrypts with
NoPaddingand advancesctx.ivto its own last ciphertext block, so chunks must be fed in order by oneChunkSink.ResourceProcessor::begin()hands out a fresh sink (clonedDecryptContext) per commit so a retried commit restarts from the segment IV. - No heap allocation on the decrypt path; the two 64 KB staging buffers come from the caller's registered
u8pool inPoolRegion. -
DecryptProcessor::identity()is thekey || ivbytes — that is what makes a cached processed resource identifiable. -
DecryptContextandDecryptProcessorredact key material fromDebug.
IV derivation happens in kithara-hls's KeyStore:
- If
#EXT-X-KEYprovides an explicit IV, it is used directly. - Otherwise the IV is derived from the segment sequence number:
[0u8; 8] || sequence.to_be_bytes(). - Key and IV are both 16 bytes; a fetched key of any other length is rejected.
- Optional key unwrapping/processing for in-house DRM also happens in
KeyStore, before aDecryptContextis built. Only the final plaintext key is cached (in memory and on disk); request-specific wire material never touches disk.
kithara-drm owns the policy-neutral request contract and its registry, not domain or URL policy:
-
KeyRequestResolver::prepareoptionally returns a final wire URL, policy headers, and the processor paired with that response. -
KeyProcessorRegistryconsults resolvers in registration order and returns the first prepared request. -
Nonemeans the key stays on the plain AES-128 path. -
KeyRequestFactoryproduces fresh per-fetch headers and a processor derived from the same request material. Consumers must not reuse that pair across fetches.
PreparedKeyRequest redacts its URL, headers, and processor from Debug because URLs and headers may carry credentials. Concrete domain matching, query shaping, and static provider headers belong to the composition layer: kithara-play's DomainKeyPolicy implements KeyRequestResolver, and kithara-app builds the registry.