pycenc
Pure-Python CENC (Common Encryption) decryptor for fragmented MP4.
pycenc decrypts cenc-encrypted DASH/fragmented MP4 files (the scheme used by Widevine, PlayReady, and ClearKey) using a content key you already have. It is a pure-Python alternative to Bento4's mp4decrypt — no compiled dependencies, just the cryptography library.
What this is: an implementation of ISO/IEC 23001-7 (CENC) — a published standard for common encryption of fragmented MP4. It performs standard AES-128-CTR decryption given a content key.
What this is not: it does not obtain keys. There is no CDM, no key exchange, no license server, no network access. You supply the key; the library does the crypto. (Obtaining keys from a DRM system is a separate concern this library does not address.)
Install
pip install pycenc
# or, from source:
uv tool install . # or: pip install .
CLI
pycenc --key KID:KEY input.m4s output.mp4
# KID is accepted but informational (single key decrypts all samples):
pycenc --key 3adcf39a811a5ab45f901e5b835b688c input.m4s output.mp4
Library
from pycenc import decrypt_bytes, decrypt_file
# in-memory
with open("encrypted.m4s", "rb") as f:
data = f.read()
clear = decrypt_bytes(key_bytes, data) # -> bytes
# file-based
with open("encrypted.m4s", "rb") as fi, open("decrypted.mp4", "wb") as fo:
decrypt_file(key_bytes, fi, fo)
key_bytes is a 16-byte AES-128 content key.
How it works
- Walks the ISO BMFF box tree (
moov/trak/moof/traf/mdat) without external parsers. - For each fragment, reads the
sencbox (per-sample IVs + subsample split) and thetrunbox (sample sizes), then decrypts each sample's encrypted bytes with AES-128-CTR. - Auto-detects the IV size (8 or 16 bytes) and whether subsample encryption is used — some files in the wild carry non-compliant
sencflags ortencreportingper_sample_iv_size=0, so detection validates each interpretation against the box length rather than trusting the flags. - Produces a clean, muxable MP4: strips the CENC boxes (
sinf/senc/saiz/saio/pssh), restores sample-entry types (encv→avc1,enca→mp4a), recomputes box sizes, and fixestrun.data_offset. The output opens directly in ffmpeg and standard players.
Supported
| Scheme | Status |
|---|---|
cenc (AES-CTR, full-sample & subsample) |
✅ |
cbcs (pattern, AES-CBC) |
planned |
cens (partial, AES-CTR) |
planned |
| Feature | Status |
|---|---|
| Single content key per file | ✅ |
| Multi-key (per-track KID matching) | planned |
Limitations
- Single content key per file (the common case). Multi-key support is planned.
cencscheme only for now;cbcs/censare on the roadmap.- Reads the file into memory (fine for typical streaming segments; streaming I/O is a future improvement).
License
MIT — see LICENSE.
Release files for pycenc 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pycenc-0.1.0.tar.gz | 9.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pycenc-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 20.3 kB
Release files / pycenc-0.1.0.tar.gz
| Download URL | pycenc-0.1.0.tar.gz |
|---|---|
| Size | 9.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6145b1990bff96016ed31810a36765e0baa67ba220a35940f8dd5972efd5031b
|
|
BLAKE2b-256 checksum How to use checksums |
a5fb29187aa79e04ca02adfb8e0995a0a9c1d87510ebfa6965d5aed62711f1e4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / pycenc-0.1.0-py3-none-any.whl
| Download URL | pycenc-0.1.0-py3-none-any.whl |
|---|---|
| Size | 11.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e73308aabcf7f005327bb41ba21c598408825b7a3d88463c9843ced1405506c6
|
|
BLAKE2b-256 checksum How to use checksums |
bd636eabfe86fd6bd5717466f3f1d11038005aeecf9b34d8f8da3d77dff8ad5c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|