pssh-box
This crate defines Rust data structures allowing you to store, parse and serialize Protection System Specific Header (PSSH) boxes, which provide data for the initialization of a Digital Rights Management (DRM) system.
PSSH boxes are used:
-
in an MP4 box of type
psshin an MP4 fragment (CMAF/MP4/ISOBMFF containers) -
in a
<cenc:pssh>element in a DASH MPD manifest -
in DRM initialization data passed to the Encrypted Media Extension of a web browser
-
in an EXT-X-SESSION-KEY field of an m3u8 playlist.
A PSSH box includes information for a single DRM system. This library supports the PSSH data formats for the following DRM systems:
- Widevine, owned by Google, widely used for DASH streaming
- PlayReady, owned by Microsoft, widely used for DASH streaming
- WisePlay, owned by Huawei
- Irdeto
- Marlin
- Nagra
- The unofficial variant of Apple FairPlay that is used for DASH-like streaming by Netflix
- Common Encryption
PSSH boxes contain (depending on the DRM system) information on the key_ID for which to obtain a content key, the encryption scheme used (e.g. cenc, cbc1, cens or cbcs), the URL of the licence server, and checksum data.
Features
This crate provides the following functionality:
-
parse PSSH boxes from binary buffers (as found in an MP4 fragment), or from a base64-encoded string (as found in a
<cenc:pssh>element in an MPD manifest), or from a hex-encoded string. -
scan a binary buffer for the location of PSSH boxes, using the function
find_iter. -
find PSSH boxes in a binary slice (function
find_boxes_buffer) or in a stream of octets (functionfind_boxes_stream). -
pretty print a PSSH, using function
pprint. -
serialize a PSSH box to binary, base64 or hexadecimal (base 16) formats, using methods
to_bytes(),to_base64()andto_hex()on aPsshBoxstruct.
A commandline utility for decoding PSSH boxes and PSSH data in various formats is available in
example/decode-pssh.rs.
If you wish to use this functionality in web applications, you may be interested in the pssh-box-wasm library, which provides functionality for using this code as WebAssembly.
Usage
let boxes = from_base64("AAAAZ3Bzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAEcSEKqL5HpT2ymw4FM7KEUKHLsaA3NmciIkYWE4YmU0N2EtNTNkYi0yOWIwLWUwNTMtM2IyODQ1MGExY2JiKgJTREjj3JWbBg==")
.unwrap();
assert_eq!(boxes.len(), 1);
let pssh = &boxes[0];
assert_eq!(pssh.system_id, WIDEVINE_SYSTEM_ID);
if let PsshData::Widevine(ref pd) = pssh.pssh_data {
assert!(pd.provider.clone().is_some_and(|p| p.eq("sfr")));
assert_eq!(pd.key_id[0], hex::decode("aa8be47a53db29b0e0533b28450a1cbb").unwrap());
assert_eq!(pd.content_id, Some(hex::decode("61613862653437612d353364622d323962302d653035332d336232383435306131636262").unwrap()));
}
Build
When building this crate, the protobuf interface definition (.proto file) for Widevine PSSH data
must be converted into Rust structs. This step is specified in the build.rs file. There are three
supported conversion methods, selected using the following crate options:
-
protox: use theprotoxcrate (implemented fully in Rust). This is likely to tbe the most convenient for most users. -
vendored-protoc: use theprotobuf-srccrate to build a vendored version of the protoc compiler and use that. This requires a working C++ compiler and cmake support, and tends to be rather unreliable (in particular, the abseil-cpp component of protobuf often causes build failures on any mildly unusual platform). To build on Windows, the simplest solution seems to be the UCRT64 environment of MSYS2; see our GitHub continuous integration workflow for one recipe that works. -
no features: use the
protocbinary installed on the build host
License
This project is licensed under the MIT license. For more information, see the LICENSE file.