Secure HLS streaming using DRM encryption with Wowza Streaming Engine

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

Notes:

 

Overview of encryption methods for HLS


Wowza Streaming Engine supports the following encryption methods for HLS streams:

  • AES-128 – The entire HLS chunk is encrypted using AES-128 encryption as described in the HLS specification. This method is supported directly by macOS and iOS players. Key rotation is supported.
     
  • SAMPLE-AES – The individual audio and video samples that make up an 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 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 HLS chunk is encrypted using Microsoft PlayReady encryption. This method is supported by BuyDRM player technology. Key rotation isn't supported.
Notes:

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 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 path [install-dir]/keys/sample.mp4.key.

The naming is similar for live and VOD MPEG-DASH adaptive bitrate streams referenced in SMIL files. For example, if you want to protect all of the streams in an adaptive group defined in the SMIL file sample.smil, create a key file with the path [install-dir]/keys/sample.smil.key. In this case, all of the streams in the adaptive group will be encrypted with the same 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, and 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 Control whether Wowza Streaming Engine appends the streaming session ID to encryption URLs in chunklist responses.
  • 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 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 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 the Wowza Streaming Engine Java API


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

Enabling the HLS encryption API

To turn on the newer 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

  1. Use a text editor to open the [install-dir]/conf/[application-name]/Application.xml file for your application.
  2. Add the cupertinoEncryptionAPIBased property to the <Properties> container element 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>
  1. Restart Wowza Streaming Engine to apply the change.

HLS encryption API methods

The following methods, when added to a server-side module, are called each time a live or on-demand 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)
{
}

public void onHTTPCupertinoRenditionEncryptionKeyVODChunk(HTTPStreamerSessionCupertino httpSession, String streamName, IHTTPStreamerCupertinoIndex index, 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 Streaming Engine 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 Streaming Engine 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 encryption – Wowza Streaming Engine includes simple method for AES-128 key delivery to players using web application server technology. For information, see Secure Apple HLS with AES-128 external encryption in Wowza Streaming Engine.

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 Use BuyDRM KeyOS DRM with Wowza Streaming Engine.

The ENVELOPE-PLAYREADY encryption method is supported by INSIDE Secure player technology. Contact our sales team for more information. 

More resources