Encryption & DRM with Multiple Keys

Encryption with multiple keys allows you to encrypt different tracks in a stream with different keys, instead of using one key to encrypt all audio and video tracks. For example:

  • Encrypt audio with different key than video

  • Encrypt some audio or video tracks, but not all of them

  • Encrypt premium features with different key than standard features

  • Encrypt all tracks with separate keys for complete flexibility

One reason to use encryption with multiple keys is to support a setup where different tracks are associated with DRM licenses that have different requirements. Such a setup is possible using only one encryption key, but becomes more secure when using multiple keys so that each key is only associated with a particular license. The latter approach is recommended by all major DRM systems.

This page provides an overview with examples of how to use encryption and DRM with multiple keys using Unified Packager.

Note

If you want information about using DRM with multiple keys for Unified Origin, have a look at Using DRM with Multiple Keys.

Multiple keys 'cenc' CENC encryption for DASH with Widevine and PlayReady

How to encrypt your content according to the CENC 'cenc' encryption scheme and add the necessary signaling for DRM is shown in the example below. When setting up DRM with multiple keys for Widevine and PlayReady, you need to specify the Protection Scheme Specific Header (PSSH) box for both DRM systems:

#!/bin/bash

KID1=c001de8e567b5fcfbc22c565ed5bda24
CEK1=533a583a843436a536fbe2a5821c4b6c

KID2=cbd1104bbc6f59ca91ac940b67032d80
CEK2=643d5329c8072509ae8003577b19d92f

#Add your PlayReady DRM specific PSSH data (same for all tracks)
PR_PSSH="AAAIQHBzc2gBAAAAmgTweZhAQoarkuZb4IhflQAAAAXAAd6OVntfz7wixWXtW9oky9EQS7xvWcqRrJQLZwMtgAXn4Y6/AFIJsKfJwLrs1tv1JLkyjp9T/aElcK+cfit2gKWVAyddWCK2vVxvxIxLqwAAB8zMBwAAAQABAMIHPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMgAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAUwA+ADwASwBJAEQAIABBAEwARwBJAEQAPQAiAEEARQBTAEMAVABSACIAIABDAEgARQBDAEsAUwBVAE0APQAiAEoAbwBYAGQANABaAHMAQQBoAGgAOAA9ACIAIABWAEEATABVAEUAPQAiAGoAdAA0AEIAdwBIAHQAVwB6ADEAKwA4AEkAcwBWAGwANwBWAHYAYQBKAEEAPQA9ACIAPgA8AC8ASwBJAEQAPgA8AEsASQBEACAAQQBMAEcASQBEAD0AIgBBAEUAUwBDAFQAUgAiACAAQwBIAEUAQwBLAFMAVQBNAD0AIgBvAE0ARwBjADYAVABsAGMAQwB6AG8APQAiACAAVgBBAEwAVQBFAD0AIgBTAHgARABSAHkAMgArADgAeQBsAG0AUgByAEoAUQBMAFoAdwBNAHQAZwBBAD0APQAiAD4APAAvAEsASQBEAD4APABLAEkARAAgAEEATABHAEkARAA9ACIAQQBFAFMAQwBUAFIAIgAgAEMASABFAEMASwBTAFUATQA9ACIAZgBlAFIAMgBLADUAUABBAEoAYwBVAD0AIgAgAFYAQQBMAFUARQA9ACIAagB1AEgAbgBCAFEAQwAvAEMAVgBLAHcAcAA4AG4AQQB1AHUAegBXADIAdwA9AD0AIgA+ADwALwBLAEkARAA+ADwASwBJAEQAIABBAEwARwBJAEQAPQAiAEEARQBTAEMAVABSACIAIABDAEgARQBDAEsAUwBVAE0APQAiAEkASABZAHcASQBtAFEAQgBFAHkATQA9ACIAIABWAEEATABVAEUAPQAiAE0AcgBrAGsAOQBaACsATwAvAFYATwBoAEoAWABDAHYAbgBIADQAcgBkAGcAPQA9ACIAPgA8AC8ASwBJAEQAPgA8AEsASQBEACAAQQBMAEcASQBEAD0AIgBBAEUAUwBDAFQAUgAiACAAQwBIAEUAQwBLAFMAVQBNAD0AIgA3ADQAQwB5ADAAZwBiADYAOAB4ADQAPQAiACAAVgBBAEwAVQBFAD0AIgBBADUAVwBsAGcARgAwAG4ASQBsAGkAMgB2AFYAeAB2AHgASQB4AEwAcQB3AD0APQAiAD4APAAvAEsASQBEAD4APAAvAEsASQBEAFMAPgA8AC8AUABSAE8AVABFAEMAVABJAE4ARgBPAD4APABMAEEAXwBVAFIATAA+AGgAdAB0AHAAcwA6AC8ALwB0AGUAcwB0AC4AcABsAGEAeQByAGUAYQBkAHkALgBtAGkAYwByAG8AcwBvAGYAdAAuAGMAbwBtAC8AcwBlAHIAdgBpAGMAZQAvAHIAaQBnAGgAdABzAG0AYQBuAGEAZwBlAHIALgBhAHMAbQB4AD8AYwBmAGcAPQAoAGsAaQBkADoAagB0ADQAQgB3AEgAdABXAHoAMQArADgASQBzAFYAbAA3AFYAdgBhAEoAQQA9AD0ALABjAG8AbgB0AGUAbgB0AGsAZQB5ADoAVQB6AHAAWQBPAG8AUQAwAE4AcQBVADIAKwArAEsAbABnAGgAeABMAGIAQQA9AD0AKQAsACgAawBpAGQAOgBTAHgARABSAHkAMgArADgAeQBsAG0AUgByAEoAUQBMAFoAdwBNAHQAZwBBAD0APQAsAGMAbwBuAHQAZQBuAHQAawBlAHkAOgBaAEQAMQBUAEsAYwBnAEgASgBRAG0AdQBnAEEATgBYAGUAeABuAFoATAB3AD0APQApACwAKABrAGkAZAA6AGoAdQBIAG4AQgBRAEMALwBDAFYASwB3AHAAOABuAEEAdQB1AHoAVwAyAHcAPQA9ACwAYwBvAG4AdABlAG4AdABrAGUAeQA6AHgAcABnAGoARgBKAHoAVgAyAGQAZgBXAGwAaABmAE4AMABkAEcAbQB1AHcAPQA9ACkALAAoAGsAaQBkADoATQByAGsAawA5AFoAKwBPAC8AVgBPAGgASgBYAEMAdgBuAEgANAByAGQAZwA9AD0ALABjAG8AbgB0AGUAbgB0AGsAZQB5ADoAUgBiAHIAOAAxAFgAZABCADcANABjAFoAcgBUAHgANQArAHMAbwBkADcAZwA9AD0AKQAsACgAawBpAGQAOgBBADUAVwBsAGcARgAwAG4ASQBsAGkAMgB2AFYAeAB2AHgASQB4AEwAcQB3AD0APQAsAGMAbwBuAHQAZQBuAHQAawBlAHkAOgBoAEsALwBNAFIAQwBVADcAcABuAHYATgByAE0AUAA2AHoARgBYAEsAWQB3AD0APQApADwALwBMAEEAXwBVAFIATAA+ADwALwBEAEEAVABBAD4APAAvAFcAUgBNAEgARQBBAEQARQBSAD4A"

#Add your Widevine DRM specific PSSH data (same for all tracks)
WV_PSSH="AAAAKXBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAAAkiAT1I49yVmwY="

mp4split -o tos-aac-128k-dash-cenc.cmfa  \
  --cenc.key=${KID1}:${CEK1} \
  --iss.drm_specific_data=${PR_PSSH} \
  --widevine.drm_specific_data=${WV_PSSH} \
  tears-of-steel-aac-128k.mp4

mp4split -o tos-avc1-400k-dash-cenc.cmfv \
  --iss.key=${KID2}:${CEK2} \
  --iss.drm_specific_data=${PR_PSSH} \
  --widevine.drm_specific_data=${WV_PSSH} \
  tears-of-steel-avc1-400k.mp4

mp4split -o tos-avc1-1500k-dash-cenc.cmfv \
  --iss.key=${KID2}:${CEK2} \
  --iss.drm_specific_data=${PR_PSSH} \
  --widevine.drm_specific_data=${WV_PSSH} \
  tears-of-steel-avc1-1500k.mp4

Note

You can use the --widevine.drm_specific_data option to specify a Base64 blob, point to a binary file that holds the "protobuf" PSSH data, or specify the full PSSH box. It is recommended to do the latter. When specifying a full PSSH box, mp4split will change a v1 PSSH box into a v0 PSSH box for maximum compatibility.

For details about obtaining valid Widevine PSSH or testing see Widevine DRM Encryption API and check out Widevine tools.

When you have packaged and encrypted the content, creating the MPD is very straightforward. Content protection signaling is automatically added to the MPD based on the protection information stored in the media files. When PlayReady or Widevine information is present, these schemes are added to the MPD. Marlin has no explicit signaling in the media files, and is always added to the MPD:

#!/bin/bash

mp4split --package_mpd -o tears-of-steel-cenc.mpd \
  tos-aac-128k-dash-cenc.cmfa \
  tos-avc1-400k-dash-cenc.cmfv \
  tos-avc1-1500k-dash-cenc.cmfv

Note

For more information about packaging DASH, check Packaging for MPEG-DASH.

Multiple keys 'cbcs' CENC encryption for fMP4 HLS

For fMP4 HLS you need to encrypt your content according to the CENC 'cbcs' encryption scheme. To do so, you add the following parameters to your command-line when packaging your content to CMAF (the keys below are meant as an example only).

--cenc.key=10000000100010001000100000000001:3a2a1b68dd2bd9b2eeb25e84c4776668 \
--cenc.key_iv=f9d9d5f5f3b5bc0372856df068f9f6a2 \
--scheme_type=cbcs

If you want to use different keys for different tracks (i.e., encryption with multiple keys) you simply signal add different keys on the command-line when packaging each of the tracks:

#!/bin/bash

KID1=10000000100010001000100000000001
KIV1=$(openssl rand -hex 16)
CEK1=$(openssl rand -hex 16)

KID2=20000000200020002000200000000002
KIV2=$(openssl rand -hex 16)
CEK2=$(openssl rand -hex 16)

# Store binary representation of each key in a file (used in next step)
echo ${CEK1} | xxd -p -r > cek1.key
echo ${CEK2} | xxd -p -r > cek2.key

mp4split -o tos-8s-128k-cbcs.cmfa \
  --fragment_duration=384/48 \
  --cenc.key=${KID1}:${CEK1} \
  --cenc.key_iv=${KIV1} \
  --scheme_type=cbcs \
  tears-of-steel-aac-128k.mp4

mp4split -o tos-8s-1500k-cbcs.cmfv \
  --fragment_duration=192/24 \
  --cenc.key=${KID2}:${CEK2} \
  --cenc.key_iv=${KIV2} \
  --scheme_type=cbcs \
  tears-of-steel-avc1-1500k.mp4

To add the necessary signaling of the relevant key to the Media Playlist of each track, make use of the --encrypt_key_url option to specify the link to the file that contains the encryption key of the track that you are creating the playlist for:

For example:

#!/bin/bash

# URLs that resolve to the key files
LA_URL_1=https://license-server/cek1.key
LA_URL_2=https://license-server/cek2.key

mp4split -o tos-128k-fmp4-cbcs.m3u8 \
  --encrypt_key_url=${LA_URL_1} \
  tos-8s-128k-cbcs.cmfa

mp4split -o tos-1500k-fmp4-cbcs.m3u8 \
  --encrypt_key_url=${LA_URL_2} \
  tos-8s-1500k-cbcs.cmfv

Then, with all the Media Playlists in place, you generate the I-frame Playlists and Master Playlist as you normally would.

Note

For more information about packaging fMP4 HLS, check Packaging HTTP Live Streaming with fragmented MP4 (fMP4 HLS).

Adding FairPlay DRM

When you want to use FairPlay DRM, you have to set the --encrypt_key_url to signal the URL of your FairPlay licensing server. Additionally, you have to add the option --key_format="com.apple.streamingkeydelivery" when generating your Media Playlists.

#!/bin/bash

KID1=10000000100010001000100000000001
KID2=20000000200020002000200000000002

mp4split -o tos-128k-fmp4-fp.m3u8 \
  --encrypt_key_url=skd://${KID1} \
  --key_format="com.apple.streamingkeydelivery" \
  tos-8s-128k-cbcs.cmfa

mp4split -o tos-1500k-fmp4-fp.m3u8 \
  --encrypt_key_url=skd://${KID2} \
  --key_format="com.apple.streamingkeydelivery" \
  tos-8s-1500k-cbcs.cmfv

Then, with all the Media Playlists in place, you generate the I-frame Playlists and Master Playlist as you normally would.

Multiple keys encryption for HLS TS with SAMPLE-AES

Below you find an example of how to use SAMPLE-AES encryption with multiple keys for HLS TS. As the first step, you will have to create as many 128-bit CEKs as you will need (2, in the below example). In this case, the CEK is just a file with 16 random bytes. It is possible to use 'openssl' to create the key:

#!/bin/bash

openssl rand 16 > cek1.key
openssl rand 16 > cek2.key

After you have created the keys, you can use them to encrypt the tracks that you want to encrypt. Below, the audio track is encrypted with the first CEK, while the video track is encrypted with the second CEK:

#!/bin/bash

# URLs that resolve to the key files
LA_URL_1=https://license-server/cek1.key
LA_URL_2=https://license-server/cek2.key

mp4split --package_hls -o presentation_a1/prog_index.m3u8 \
  --fragment_duration=384/48 \
  --encrypt_key_file=cek1.key \
  --encrypt_key_url=${LA_URL_1} \
  --stream_encrypt \
  --base_media_file=a2_ \
  tears-of-steel-aac-128k.mp4

mp4split --package_hls -o presentation_v2/prog_index.m3u8 \
  --fragment_duration=192/24 \
  --encrypt_key_file=cek2.key \
  --encrypt_key_url=${LA_URL_2} \
  --stream_encrypt \
  --base_media_file=v1_ \
  tears-of-steel-avc1-1500k.mp4

After you have packaged your content as HLS TS, you can create the necessary Master Playlist like you normally would:

#!/bin/bash

mp4split --package_hls -o presentation.m3u8 \
  presentation_a1/prog_index.m3u8 \
  presentation_v1/prog_index.m3u8 \
  presentation_v1/iframe_index.m3u8

Note

For more information about packaging HLS TS, check Packaging HTTP Live Streaming (HLS) with TS.

Multiple keys encryption for HLS TS with Apple FairPlay

If you want to use DRM with multiple keys for HLS TS with FairPlay, you will have to create separates files with all the keys first. Each file must contain both a 128-bit CEK and a 128-bit key IV. This is simply a file with 32 random bytes, where the first 16 bytes represent the CEK and the remaining 16 bytes represent the key IV. It is possible to use 'openssl' to create these files:

#!/bin/bash

openssl rand 32 > cek1-kiv1.key
openssl rand 32 > cek2-kiv2.key

The command-lines to package HLS TS with MP4 as input are the same as in the above example, although we need to add specific signaling for FairPlay protection (i.e., --streaming-key-delivery).

The mp4split command is:

#!/bin/bash

# URLs that resolve to the key files
LA_URL_1=https://license-server/cek1.key
LA_URL_2=https://license-server/cek2.key

# Example that packages an audio track with the first set of CEK and Key IV
mp4split --package_hls -o presentation_a1/prog_index.m3u8 \
  --fragment_duration=384/24 \
  --encrypt_key_file=cek1-kiv1.key \
  --encrypt_key_url=${LA_URL_1} \
  --stream_encrypt \
  --streaming_key_delivery \
  --base_media_file=a1_ \
  tears-of-steel-aac-128k.mp4

# Example that packages a video track with the second set of CEK and Key IV
mp4split --package_hls -o presentation_v1/prog_index.m3u8 \
  --fragment_duration=192/24 \
  --encrypt_key_file=cek2-kiv2.key \
  --encrypt_key_url=${LA_URL_2} \
  --stream_encrypt \
  --streaming_key_delivery \
  --base_media_file=v1_ \
  tears-of-steel-avc1-1500k.mp4

Creating the Master Playlist is identical to the previous example.

Please note that within FairPlay the encrypt-key-url is only for information, a client typically implements different means of locating the license server and fetch keys.