Using Sample AES Encryption for HLS with Unified Origin
This tutorial explains how to configure Unified Origin to encrypt its HLS output with Sample AES encryption. It also demonstrates how you can test the output to check whether you have configured Origin correctly (i.e., whether its HLS output is encrypted and can be played back succesfully given the right environment).
All encryption for HTTP video streaming is AES 128 encryption, which is a symmetric key algorithm. This means that the same key is used to encrypt and decrypt the content. This Content Encryption Key (CEK) consists of 128 random bits (hence 'AES 128').
Note that Sample AES encryption as configured in this tutorial does not equal DRM. Sample AES encryption for HLS output is used for Apple's FairPlay DRM, but that is not what this tutorial is about. It is about using Sample AES encryption only. This means that Origin will encrypt its HLS output accordingly, and add the necessary signaling to the Master Playlist and Media Playlists that it will generate for its HLS output. This signaling includes the URL that the client will need to make a request to in order to get the CEK (so that it can decrypt the content).
Before you start
Before starting please make sure that:
Unified Origin is properly installed, which includes 'mp4split' (see: How to Install)
You have downloaded the Tears of Steel test content (see: Verify Your Setup)
Note
All of the commands in this tutorial can be run from your user's home
directory, but some of them might require you to use sudo
, depending on
the exact rights of your user and the configuration of your system.
Setting up your test environment
To set up your test environment make sure that Apache is running and that you
have stored the tears-of-steel
directory with the test content in the
DocumentRoot of the Apache virtual host that you configured for Origin. This
tutorial presumes that this DocumentRoot is located in the /var/www/
directory (i.e., the test content will be located in
/var/www/tears-of-steel
).
The options you will need to use
Sample AES encryption for HLS not only uses a CEK, but also uses a Key Initialization Vector (KIV). This KIV makes the encryption more secure by preventing repetitive patterns. Sample AES encryption for HLS does not use a key to the identify the content that is encrypted (often called a 'KID').
When configuring Origin to encrypt its HLS output with Sample AES you must specify a CEK, but you don't have to specify a KIV. If you do not specify a KIV, Origin will generate it automtically.
To specify the CEK, you use the --hls.key
option. It takes a combination of
a KID and CEK as its arguments (both hex encoded and seperated by a colon). As
we do not want to specify a KID in this particular case, we leave that part of
the argument for this option empty, like so: --hls.key=:${CEK}
.
To specify the KIV, you use the --hls.key_iv
option. This simply takes the
hex encoded KIV as its arugment, like so: --hls.key_iv=${KIV}
.
Two additional options are required to enable Sample AES encryption for Origin's HLS output:
--hls.playout=sample_aes
to actually specify that Sample AES encryption should be used (as opposed to the older, regular AES 128 encryption)--hls.license_server_url
to specify the URL that the client will need to make a request to in order to get the CEK (so that it can decrypt the content)
Create your own keys (CEK and KIV)
If you do not have a specific CEK and KIV that you want to use for the purpose of this tutorial, you can you can use 'openssl' to generate the necessary 'random' 128 bit strings.
The below command will generate a 128 bit (i.e., 16 byte) key in binary format
and write it to a file called content.key
. Later on in this tutorial, we'll
put this file alongside our test content on our server so that it can serve as
the endpoint that a client can make requests to to fetch key it needs for
decryption.
#!/bin/bash
openssl rand 16 > content.key
We now have our CEK stored in binary format (which is the format that the client
needs), but on the command-line we'll need to specify it in hex. To convert
it the key stored in the file to hex format, we'll use 'hexdump' and store the
result in a variable called CEK
:
#!/bin/bash
CEK=$(cat content.key | hexdump -e '16/1 "%02x"')
For our KIV, we'll use the same process except we won't use a file as the intermediary format, because we don't need it:
#!/bin/bash
KIV=$(openssl rand 16 | hexdump -e '16/1 "%02x"')
Move binary format CEK file alongside test content
To make a Sample AES workflow work, the client needs to be able to request the key from a URL that is specified in the (Master and) Media Playlists. This file must contain the CEK in binary format, like we have generated earlier.
We'll now move the file to directory in our DocumentRoot where our test content is stored:
#!/bin/bash
sudo mv content.key /var/www/tears-of-steel
Now that we moved content_encrypt.key
alongside the test content, it is
accessible from the outside and addressable through a URL. Specify the domain
name through which your Origin server can be accessed as origin_url
like
below and we can store the URL to our CEK in the content_key_url
variable:
origin_url="http://your-domain.com"
content_key_url="${origin_url}/content.key"
All preperations have been done now. The last step is to configure the actual stream by creating a server manifest.
Create server manifest to configure your stream
We'll configure this stream with audio in two bit rates, and video in four. We'll also use all of the options mentioned above to enable Sample AES encryption for our HLS output:
--hls.key=:${CEK}
to specify our CEK--hls.key_iv=${KIV}
to specify our KIV--hls.license_server_url=${content_key_url}
to specify endpoint for client to fetch CEK from--hls.playout=sample_aes
to enable Sample AES encryption for our HLS output
In addition, we'll use the two more general options to further configure our HLS output:
--hls.client_manifest_version=4
to make sure our HLS output supports basic features like multiple audio tracks--hls.minimum_fragment_length=4
to explicitly define the length of our HLS segments, instead of relying on the default (the choice is '4' here, because the Tears of Steel test content is encoded with a GOP length of 4 seconds)
This gives us the following command-line to create our server maniefst
tos-sample-aes.ism
:
#!/bin/bash
mp4split -o tos-sample-aes.ism \
--hls.key=:${CEK} \
--hls.key_iv=${KIV} \
--hls.license_server_url=${content_key_url} \
--hls.playout=sample_aes \
--hls.client_manifest_version=4 \
--hls.minimum_fragment_length=4 \
/var/www/tears-of-steel/tears-of-steel-aac-64k.mp4 \
/var/www/tears-of-steel/tears-of-steel-aac-128k.mp4 \
/var/www/tears-of-steel/tears-of-steel-avc1-400k.mp4 \
/var/www/tears-of-steel/tears-of-steel-avc1-750k.mp4 \
/var/www/tears-of-steel/tears-of-steel-avc1-1000k.mp4 \
/var/www/tears-of-steel/tears-of-steel-avc1-1500k.mp4
The last step is to move the server manifest alongside the test content:
#!/bin/bash
sudo mv tos-sample-aes.ism /var/www/tears-of-steel
Now you have completed the setup of your stream with Sample AES encrypted HLS output. Let's test it.
Test your stream
To test whether you have configured everything correctly, you can do two things:
Request the Master Playlist to see whether it contains the expected configuration
Try playout using Apple's native media player in Safari, or using hls.js
To request the Master Playlist:
curl -v ${origin_url}/tos-sample-aes.ism/.m3u8
The result of which should look, at the top, something like the partially presented Master Playlist below, which is taken from our Sample AES demo setup. Note the line that starts with '#EXT-X-SESSION-KEY', where 'METHOD' specifies 'SAMPLE-AES' and 'URI' points to the URL where the client can fetch the CEK:
#EXTM3U
#EXT-X-VERSION:4
## Created with Unified Streaming Platform (version=1.10.20-20861)
#EXT-X-SESSION-KEY:METHOD=SAMPLE-AES,URI="https://demo.unified-streaming.com/k8s/features/no-handler-origin/tears-of-steel/aes.key"
# AUDIO groups
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio-aacl-64",LANGUAGE="en",NAME="English",DEFAULT=YES,AUTOSELECT=YES,CHANNELS="2"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio-aacl-128",LANGUAGE="en",NAME="English",DEFAULT=YES,AUTOSELECT=YES,CHANNELS="2"
....
If you get the expected response, you should be able to play back your stream as well. Simply visit the URL to the Master Playlist in Safari and it should start automatically.
If it doesn't, one simple thing to check is whether you can make a successful request to the URL that points to the CEK, as signaled in your Master Playlist.
Also, to compare it with another Sample AES encrypted HLS stream generated by Origin, you can always use the one from our demo setup:
curl -v https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel-aes.ism/.m3u8
Finally, you can always contact us if you have any questions: unified-streaming.com/contact.