How to secure Apple HLS streaming using DRM encryption

There are several ways to use DRM encryption to protect Apple HLS streams. This article describes the newer schemes and API for controlling this encryption for live and on-demand Apple HLS streaming. For some of the protection schemes, the API supports multiple protection schemes as well as key rotation. Apple HLS streams can also be protected by using key files stored in the Wowza media server's keys folder ([install-dir]/keys).

Notes:
  • Wowza Streaming Engine™ software or Wowza Media Server™ software version 3.5.0 or later is required.
     
  • To use the SAMPLE-AES encryption method, Wowza Streaming Engine or Wowza Media Server version 3.6.3 is required.
     
  • SAMPLE-AES on iOS 7 requires that the EXT-X-VERSION tag in m3u8 URLs be set to version 5 or greater. To see how to set the version number, go to How to change the EXT-X-VERSION for Apple HLS.

Contents


Overview of encryption methods for Apple HLS
On-the-fly encryption with key files On-the-fly encryption with Wowza server-side API Key delivery to players

Overview of encryption methods for Apple HLS


Wowza media server software supports the following encryption methods for Apple HLS streams:
 
  • AES-128 - The entire Apple HLS chunk is encrypted using AES-128 encryption as described in the Apple HLS specification. This method is supported directly by iOS-based and OS X players. Key rotation is supported.
     
  • SAMPLE-AES - The individual audio and video samples that make up an Apple HLS chunk are encrypted using AES-128 encryption. This method is supported directly on devices running iOS 6.0 and greater. Key rotation is supported.
     
  • ENVELOPE-PLAYREADY - The entire Apple HLS chunk is encrypted using Microsoft PlayReady envelope encryption. This method is supported by INSIDE Secure player technology. Key rotation isn't supported.
     
  • CHUNK-PLAYREADY: The entire Apple HLS chunk is encrypted using Microsoft PlayReady encryption. This method is supported by BuyDRM player technology. Key rotation isn't supported.
Each of these methods are referenced in this article.

On-the-fly encryption with key files


You can encrypt live and on-demand on the fly by using key files. Key files are text files that have a file name that's the same as the name of the stream you're playing and a .key file name extension. They are stored in the [install-dir]/keys folder. For example, if you want to protect the live stream myStream, then you'd create a key file with the following path:
[install-dir]/keys/myStream.key
The naming convention is similar for an on-demand stream. To protect the stream sample.mp4, create a key file with the following path:
[install-dir]/keys/sample.mp4.key
If the stream is at a path location such as [install-dir]/content/myfiles/sample.mp4, then the key file should be at a parallel location in the keys folder:
[install-dir]/keys/myfiles/sample.mp4.key
For each of the available encryption methods, the key file would contain content similar to the following (the below keys are fabricated and won't function properly to encrypt/decrypt content):

AES-128 encryption

cupertinostreaming-aes128-method: AES-128
cupertinostreaming-aes128-url: http://mycompanykeyserver.com/authenticate.aspx
cupertinostreaming-aes128-key: 0x123456789ABCDEF123456789ABCDEF12
cupertinostreaming-aes128-iv: 0xFEDCBA9876543210FEDCBA9876543210
cupertinostreaming-aes128-iv-include-in-chunklist: true
cupertinostreaming-aes128-key-format-version: 1

SAMPLE-AES encryption

cupertinostreaming-aes128-method: SAMPLE-AES
cupertinostreaming-aes128-url: http://mycompanykeyserver.com/authenticate.aspx
cupertinostreaming-aes128-key: 0x123456789ABCDEF123456789ABCDEF12
cupertinostreaming-aes128-iv: 0xFEDCBA9876543210FEDCBA9876543210
cupertinostreaming-aes128-iv-include-in-chunklist: true
cupertinostreaming-aes128-key-format: identity
cupertinostreaming-aes128-key-format-version: 1

ENVELOPE-PLAYREADY encryption

cupertinostreaming-aes128-method: ENVELOPE-PLAYREADY
cupertinostreaming-playready-key-id: 53EABD36-CBCF-492F-8C39-AE9582F339B4
cupertinostreaming-playready-license-url: http://myplayreadyserver.com/authenticate.aspx
cupertinostreaming-playready-content-key: 0x123456789ABCDEF123456789ABCDEF12
cupertinostreaming-playready-checksum: FUlWv6jnlTc=
cupertinostreaming-playready-algorithm: AESCTR

CHUNK-PLAYREADY encryption

cupertinostreaming-aes128-method: CHUNK-PLAYREADY
cupertinostreaming-playready-key-id: 53EABD36-CBCF-492F-8C39-AE9582F339B4
cupertinostreaming-playready-license-url: http://myplayreadyserver.com/authenticate.aspx
cupertinostreaming-playready-content-key: 0x123456789ABCDEF123456789ABCDEF12
cupertinostreaming-playready-checksum: FUlWv6jnlTc=
cupertinostreaming-playready-algorithm: AESCTR

Key file fields

  • cupertinostreaming-aes128-method - Specifies the encryption method. Supported values are: AES-128, SAMPLE-AES, ENVELOPE-PLAYREADY, CHUNK-PLAYREADY 

AES-128-specific fields

The following fields are valid when the encryption method is either AES-128 or SAMPLE-AES:
 
  • cupertinostreaming-aes128-url - Specifies the URL that's used by a player to retrieve the decryption key required for playback.
     
    Note: By default, Wowza Streaming Engine appends the streaming session ID to encryption URLs in the chunklist response. Some content protection technologies, such as Apple FairPlay Streaming (FPS), may not work properly with this default setting. In Wowza Streaming Engine 4.5.0, you can set a property to instruct Wowza Streaming Engine to not append the session ID, if needed. For more information, see How to control streaming session ID appended to encryption URLs in chunklist responses (cupertinoAppendQueryParamsToEncUrl).
  • cupertinostreaming-aes128-key - The hexadecimal-encoded, 128-bit content encryption key.
     
  • cupertinostreaming-aes128-iv - The hexadecimal-encoded initialization vector (IV) used for encryption. If omitted, the chunk ID is used as the IV per the Apple HLS specification.
     
  • cupertinostreaming-aes128-iv-include-in-chunklist - (Wowza Streaming Engine 4.5.0 and later) Controls whether the IV is displayed in the chunklist. The default value (true) displays the IV in the chunklist. When using FairPlay Streaming (FPS) technology to protect Apple HLS streams, set the value to false because the IV is delivered as part of FairPlay key exchange.
     
  • cupertinostreaming-aes128-key-format - The key format to report in the chunklist, either identity or com.apple.streamingkeydelivery.
     
  • cupertinostreaming-aes128-key-format-version - The key format version to report in the chunklist.

PlayReady-specific fields

The following fields are valid when the encryption method is either ENVELOPE-PLAYREADY or CHUNK-PLAYREADY):
 
  • cupertinostreaming-playready-key-id - The key ID for this asset.
     
  • cupertinostreaming-playready-license-url - The license URL that's used by a player for authentication and to retrieve the decryption key required for playback.
     
  • cupertinostreaming-playready-content-key - The base64-encoded, 128-bit content encryption key.
     
  • cupertinostreaming-playready-checksum - A special checksum of the key ID that's required to authenticate the player.
     
  • cupertinostreaming-playready-algorithm - The PlayReady encryption algorithm. The most common value is AESCTR
Note: Key rotation is accomplished by changing the encryption key periodically during streaming. You shouldn't rotate the key for every chunk because this will force the player to retrieve the decryption key for every chunk. PlayReady-based encryption methods don't support key rotation. Also, remember that you must provide a unique encryption URL for a given encryption key.

On-the-fly encryption with Wowza server-side API


Similar to the key files that are described in the previous section, you can protect Apple HLS streams by passing key data to a Wowza media server through the server-side API. You'll need to install the Wowza IDE and know how server-side programming works.

Enabling the Apple HLS encryption API

To turn on the newer Apple HLS encryption API, you must add the cupertinoEncryptionAPIBased property to your application configuration. You can do this in Wowza Streaming Engine Manager or by using a text editor.

Wowza Streaming Engine Manager configuration

  1. In Wowza Streaming Engine Manager, click the Applications tab and select your application in the contents panel.
     
  2. In the details page, click the Properties tab, and then click Custom in the Quick Links bar.
     
    Note: Access to the Properties tab is limited to administrators with advanced permissions. For more information, see Manage credentials.
  3. In the Custom section, click Edit.
     
  4. Click Add Custom Property, specify the following settings in the Add Custom Property dialog box, and then click Add:
     
    • Path - Select /Root/Application.
       
    • Name - Enter cupertinoEncryptionAPIBased.
       
    • Type - Select Boolean.
       
    • Value - Enter true.
  5. Click Save, and then restart the application when prompted to apply the changes.

XML configuration

Use a text editor to open the [install-dir]/conf/[application]/Application.xml file for your application and add the cupertinoEncryptionAPIBased property to the <Properties> container at the end of the file. Be sure to add the property to the correct <Properties> container in Application.xml as there are several such containers in the file:
<Property>
	<Name>cupertinoEncryptionAPIBased</Name>
	<Value>true</Value>
	<Type>Boolean</Type>
</Property>
You must restart the Wowza media server to apply the change.

Apple HLS encryption API methods

The following methods, when added to a server-side module, are called each time a live or on-demand Apple HLS chunk is created, giving you the opportunity to control how that chunk is encrypted:
public void onHTTPCupertinoEncryptionKeyVODChunk(HTTPStreamerSessionCupertino httpSession, IHTTPStreamerCupertinoIndex index, CupertinoEncInfo encInfo, long chunkId, int mode)
{
}

public void onHTTPCupertinoEncryptionKeyLiveChunk(ILiveStreamPacketizer liveStreamPacketizer, String streamName, CupertinoEncInfo encInfo, long chunkId, int mode)
{
}
The encInfo variable holds the current encryption information for a given stream and is used to control stream encryption. It's also used to rotate keys as needed, if supported by the encryption method that you're using. The following code examples show how to set encryption for each of the encryption methods:

AES-128 encryption 

encInfo.setEncMethod(CupertinoEncInfo.METHOD_AES_128);
encInfo.setEncUrl("http://mycompanykeyserver.com/authenticate.aspx");
encInfo.setEncKeyBytes(BufferUtils.decodeHexString("123456789ABCDEF123456789ABCDEF12"));
encInfo.setEncIVBytes(BufferUtils.decodeHexString("FEDCBA9876543210FEDCBA9876543210"));
encInfo.setEncKeyFormatVersion("1");

SAMPLE-AES Encryption

encInfo.setEncMethod(CupertinoEncInfo.METHOD_SAMPLE_AES);
encInfo.setEncUrl("http://mycompanykeyserver.com/authenticate.aspx");
encInfo.setEncKeyBytes(BufferUtils.decodeHexString("123456789ABCDEF123456789ABCDEF12"));
encInfo.setEncIVBytes(BufferUtils.decodeHexString("FEDCBA9876543210FEDCBA9876543210"));
encInfo.setEncKeyFormat(CupertinoEncInfo.APPLE_KEYFORMAT_IDENTITY);
encInfo.setEncKeyFormatVersion("1");

ENVELOPE-PLAYREADY Encryption 

encInfo.setEncMethod(CupertinoEncInfo.METHOD_ENVELOPE_PLAYREADY);

PlayReadyKeyInfo playReadyKeyInfo = new PlayReadyKeyInfo();
encInfo.setPlayReadyKeyInfo(playReadyKeyInfo);

playReadyKeyInfo.setKeyId(BufferUtils.decodeHexString("53EABD36-CBCF-492F-8C39-AE9582F339B4".replace("-", "")));
playReadyKeyInfo.setLicenseURL("http://myplayreadyserver.com/authenticate.aspx");
playReadyKeyInfo.setContentKey(BufferUtils.decodeHexString("123456789ABCDEF123456789ABCDEF12"));
playReadyKeyInfo.setChecksum(Base64.decode("FUlWv6jnlTc="));

CHUNK-PLAYREADY encryption 

encInfo.setEncMethod(CupertinoEncInfo.METHOD_CHUNK_PLAYREADY);

PlayReadyKeyInfo playReadyKeyInfo = new PlayReadyKeyInfo();
encInfo.setPlayReadyKeyInfo(playReadyKeyInfo);

playReadyKeyInfo.setKeyId(BufferUtils.decodeHexString("53EABD36-CBCF-492F-8C39-AE9582F339B4".replace("-", "")));
playReadyKeyInfo.setLicenseURL("http://myplayreadyserver.com/authenticate.aspx");
playReadyKeyInfo.setContentKey(BufferUtils.decodeHexString("123456789ABCDEF123456789ABCDEF12"));
playReadyKeyInfo.setChecksum(Base64.decode("FUlWv6jnlTc="));
Notes:
  • You can resolve the BufferUtils and Base64 classes by using the following import:
    import com.wowza.util.*;
    For example, to apply AES-128 encryption to a live stream named myStream, add the following code to a Wowza media server module:
    public void onHTTPCupertinoEncryptionKeyLiveChunk(ILiveStreamPacketizer liveStreamPacketizer, String streamName, CupertinoEncInfo encInfo, long chunkId, int mode)
    {
    	if (streamName.equals("myStream"))
    	{
    		encInfo.setEncMethod(CupertinoEncInfo.METHOD_AES_128);
    		encInfo.setEncUrl("http://mycompanykeyserver.com/authenticate.aspx");
    		encInfo.setEncKeyBytes(BufferUtils.decodeHexString("123456789ABCDEF123456789ABCDEF12"));
    		encInfo.setEncIVBytes(BufferUtils.decodeHexString("FEDCBA9876543210FEDCBA9876543210"));
    		encInfo.setEncKeyFormatVersion("1");
    	}
    }
  • Key rotation is accomplished by changing the encryption key periodically during streaming. You shouldn't rotate the key for every chunk because this will force the player to retrieve the decryption key for every chunk. PlayReady-based encryption methods don't support key rotation. Also, remember that you must provide a unique encryption URL for a given encryption key.

Key delivery to players


Wowza media server software doesn't include key server delivery features. It has some basic features for AES-128 key delivery; however, these features are provided only for convenience. The following options are available for key delivery:

AES-128 or SAMPLE-AES encryption
Wowza media server includes a simple method for AES-128 key delivery to players. For more information, see How to use the internal method of AES-128 encryption to secure streams sent to Apple iOS devices (ModuleEncryptionHandlerCupertinoStreaming).

There's also a simple example of how to do AES-128 key delivery using web application server technology. For more information, see How to secure Apple HTTP Live Streaming (AES-128 - external method).

CHUNK-PLAYREADY and ENVELOPE-PLAYREADY
There are several options for key delivery when using CHUNK-PLAYREADY and ENVELOPE-PLAYREADY. The CHUNK-PLAYREADY encryption method is supported by BuyDRM player technology and Wowza DRM. For more information about how to use the BuyDRM DRM option, see How to set up and test BuyDRM KeyOS DRM (PlayReady).

The ENVELOPE-PLAYREADY encryption method is supported by INSIDE Secure player technology. Contact sales@wowza.com for more information.
Originally Published: 10-10-2012.
Updated: For Wowza Streaming Engine 4.5.0 on 06-23-2016.
 

If you're having problems or want to discuss this article, post in our forum.