• 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.