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.