Use BuyDRM KeyOS DRM with Wowza Streaming Engine

This article provides instructions for integrating Wowza Streaming Engine™ media server software with the built-in BuyDRM KeyOS module. With the KeyOS module, Wowza Streaming Engine can protect HLS and MPEG-DASH live and video-on-demand streams using Microsoft PlayReady encryption for playback using the BuyDRM desktop and mobile player technology.

Before you start


You should complete the following tasks:

  • Sign up for the BuyDRM KeyOS service at BuyDRM.com. After you sign up, you'll get an email from BuyDRM with your UserKey.

Add the BuyDRM KeyOS module in Wowza Streaming Engine


  1. In Wowza Streaming Engine Manager, click the Applications tab at the top of the page and select your application in the contents panel.
  2. On the application details page, click DRM in the contents panel, and then click Enable BuyDRM.
  3. On the Setup tab of the BuyDRM details page, enter the BuyDRM user key that was sent to you when you registered for BuyDRM KeyOS.
  4. Under Stream Protection, select the streaming formats that you want to encrypt using the BuyDRM encryption service.
    • Protect Apple HLS streaming - Apply PlayReady encryption to HLS streams.
    • Protect MPEG-DASH Streaming - Apply PlayReady encryption to MPEG-DASH streams.
  5. Under Stream Name Mapping, click Add New Mapping to map stream names to PlayReady key information.
  6. In the Add New Stream Mapping dialog box, specify the following settings, and then click Add.
    • Stream Name - The name of the stream you wish to protect.
    • Key ID - The ID of the content key used to encrypt the content.
    • Content ID - The unique file ID within the KeyOS infrastructure.
    • Media ID - The BuyDRM media ID.
    Note: The values for Key ID, Content ID, and Media ID can be set to either an explicit value or to a variable. For more information, see Use BuyDRM map files to protect live and video-on-demand streams.
  7. Click Save and restart Wowza Streaming Engine.

Add the BuyDRM KeyOS module in XML


Alternatively, you can add and configure the BuyDRM KeyOS module by editing the Application.xml configuration file in a text editor. If you configured the module in Wowza Streaming Engine Manager, skip this section.

  1. Navigate to [install-dir]/conf/[application] and open Application.xml in a text editor.
  2. Add the following <Module> block as the last entry in the <Modules> container element:
    <Module>
        <Name>ModuleDRMBuyDRM</Name>
        <Description>ModuleDRMBuyDRM</Description>
        <Class>com.wowza.wms.drm.module.buydrm.ModuleDRMBuyDRM</Class>
    </Module>
  3. Add the following properties to the <Properties> container element at the bottom of the Application.xml file (be sure to get the correct <Properties> container element as there are several in the file):
    <Property>
        <Name>drmBuyDRMUserKey</Name>
        <Value>[user-key]</Value>
    </Property>
    <Property>
        <Name>drmBuyDRMStreamNameMapFile</Name>
        <Value>${com.wowza.wms.context.VHostConfigHome}/conf/buydrmstreammap.txt</Value>
    </Property>
    <Property>
        <Name>drmBuyDRMProtectCupertinoStreaming</Name>
        <Value>true</Value>
        <Type>Boolean</Type>
    </Property>
    <Property>
        <Name>drmBuyDRMProtectMpegDashStreaming</Name>
        <Value>true</Value>
        <Type>Boolean</Type>
    </Property>
    <Property>
        <Name>drmBuyDRMIfFailFakeKey</Name>
        <Value>true</Value>
        <Type>Boolean</Type>
    </Property>
    <Property>
        <Name>drmBuyDRMDebugLog</Name>
        <Value>true</Value>
        <Type>Boolean</Type>
    </Property>
    <Property>
        <Name>drmBuyDRMActionLog</Name>
        <Value>true</Value>
        <Type>Boolean</Type>
    </Property>
    <Property>
        <Name>cupertinoEncryptionAPIBased</Name>
        <Value>true</Value>
        <Type>Boolean</Type>
    </Property>
     
    Note: The [user-key] is the BuyDRM user key that was sent to you when you registered for BuyDRM KeyOS.
  4. Using a text editor, create a file named buydrmstreammap.txt in the [install-dir]/conf directory.
  5. Add BuyDRM mapping entries in the buydrmstreammap.txt file for each stream you're protecting. The following is an example of a buydrmstreammap.txt file:
    sample.mp4={keyId:F6005DCF-7F93-4B8E-85C7-F908840DA059,contentId:F6005DCF-7F93-4B8E-85C7-F908840DA059,mediaId:${Application.Name}/${AppInstance.Name}/${Stream.Name}}
    mymusic.mp4={keyId:E45F3254-846D-BBE4-4FD6-E467B78A0910,contentId:E45F3254-846D-BBE4-4FD6-E467B78A0910,mediaId:mymusic}
    music*={keyId:${KeyIdGenerator.Random},contentId:${KeyId},mediaId:music-${Stream.Name}}
    video*={keyId:${KeyIdGenerator.Random},contentId:${KeyId},mediaId:video-${Stream.Name}}
    myStream*={keyId:${KeyIdGenerator.Random},contentId:${KeyId},mediaId:video-${Stream.Name},adaptiveGroup:myAbrGroup}
    myExtraAbrStream_1080p={keyId:${KeyIdGenerator.Random},contentId:${KeyId},mediaId:video-${Stream.Name},adaptiveGroup:myAbrGroup}
    *={keyId:${KeyIdGenerator.Random},contentId:${KeyId},mediaId:${Stream.Name}}

    The buydrmstreammap.txt file is used to map stream names to PlayReady key information. Each map entry in the file requires a keyId, contentId, and mediaId property. The value for each property can be set to either an explicit value or to a variable. For more information, see Use BuyDRM map files to protect live and video-on-demand streams.

    The last entry in the example file protects any stream name that isn't matched by any of the lines above using a randomly generated keyId. If a catch-all wildcard isn't defined, then any streams that don't match the rules provided won't be encrypted.

    Note: If the buydrmstreammap.txt file isn't found or is incorrect, the drmBuyDRMIfFailFakeKey property can be used to randomly generate a fake key for encrypting the streams. The default property value (true) causes the content to be encrypted with the fake key. If this property is set to false, the stream won't be encrypted.

Play encrypted content


BuyDRM will provide you with KeyOS Licensing API documents to enable playback of encrypted content. Contact BuyDRM.

BuyDRM KeyOS Android and iOS players

Encrypted HLS and MPEG-DASH streams can be played using the technologies provided in the BuyDRM KeyOS Android and iOS player SDKs.
 
  1. Get the BuyDRM KeyOS Android or iOS player directly from BuyDRM, or build a player from the respective player SDK.
     
  2. Create an authorization for the player.
     
  3. Configure the player's vector file to use the authorization and point to the stream from Wowza Streaming Engine.

The following is an example BuyDRM vector file for an application named myApplication and a stream named sample.mp4.

<?xml version="1.0" encoding="utf-8" ?>
<contents version="1.0">
    <content>
        <name>MPEG-DASH Streaming</name>
        <uri>http://localhost:1935/myApplication/mp4:sample.mp4/manifest.mpd</uri>
        <extra name="playready-lic-acq-url">https://pr-keyos.licensekeyserver.com/core/rightsmanager.asmx</extra>
        <extra name="playready-lic-acq-custom">PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxLZXlPU0F1dGhlbnRpY2F0aW9uWE1MPjxEYXRhPjxQb2xpY3k+PE1pbmltdW1TZWN1cml0eUxldmVsPjE1MDwvTWluaW11bVNlY3VyaXR5TGV2ZWw+PC9Qb2xpY3k+PEdlbmVyYXRpb25UaW1lPjIwMTMtMDUtMDcgMjE6MDk6MTEuMDAwPC9HZW5lcmF0aW9uVGltZT48RXhwaXJhdGlvblRpbWU+MjAxNC0wNS0wNyAyMTowOToxMS4wMDA8L0V4cGlyYXRpb25UaW1lPjxVbmlxdWVJZD4zNWFkZTU1ZDMzODE0M2QzODNmNjRmYTFjMmJmZDRlMDwvVW5pcXVlSWQ+PFJTQVB1YktleUlkPjIwZDJjNWYyNGRmNzdjZThlYjBjYjE3NWJiOGI1OTA0PC9SU0FQdWJLZXlJZD48L0RhdGE+PFNpZ25hdHVyZT5PUTVrZDR5MFdiMTAvU1VQdm1ZYnZVK3d5M0dQTCttZ3dpOVlOT3BWUElYTXQ2THU4SkpUQjNid0hlbndtb0RrZjllTHhjNncvT21GeTJNekYraFpKLzd2NUhaVVNEK2lRNDA0ZHVJRXZTbER4ZW0xK0dFejlsT1VJdXh1a3pIVzIrbE05ZEc0TzU1U2FwSXdjNHZIK3cyZ1ZiaWNkcGdackVkQW8yOXNmN0NGbHR1S0lKY2hwMmF0Vm0xaFdvUmZ0eWlBZVZkR0MxVjFuS1JqdlZPNFZuNERFdnR1MmY2MitETC9LSUU1UG9GVnQzV0dJU3E4aUxQcXpaMXhoRHVraDlsTDdxcnRhbkRqR3hJeDNjQWpOQlRicmhYMGk0VnUxYU15YnRhcU05QjdUUS80Z0F0NlE3WUx3UEpQeHphNXZuNlZLNmxMWVRCeWRlSDNDL0hhVVE9PTwvU2lnbmF0dXJlPjwvS2V5T1NBdXRoZW50aWNhdGlvblhNTD4K</extra>
    </content>
    <content>
        <name>Apple HLS Streaming</name>
        <uri>http://localhost:1935/myApplication/mp4:sample.mp4/playlist.m3u8</uri>
        <extra name="playready-lic-acq-url">https://pr-keyos.licensekeyserver.com/core/rightsmanager.asmx</extra>
        <extra name="playready-lic-acq-custom">PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxLZXlPU0F1dGhlbnRpY2F0aW9uWE1MPjxEYXRhPjxQb2xpY3k+PE1pbmltdW1TZWN1cml0eUxldmVsPjE1MDwvTWluaW11bVNlY3VyaXR5TGV2ZWw+PC9Qb2xpY3k+PEdlbmVyYXRpb25UaW1lPjIwMTMtMDUtMDcgMjE6MDk6MTEuMDAwPC9HZW5lcmF0aW9uVGltZT48RXhwaXJhdGlvblRpbWU+MjAxNC0wNS0wNyAyMTowOToxMS4wMDA8L0V4cGlyYXRpb25UaW1lPjxVbmlxdWVJZD4zNWFkZTU1ZDMzODE0M2QzODNmNjRmYTFjMmJmZDRlMDwvVW5pcXVlSWQ+PFJTQVB1YktleUlkPjIwZDJjNWYyNGRmNzdjZThlYjBjYjE3NWJiOGI1OTA0PC9SU0FQdWJLZXlJZD48L0RhdGE+PFNpZ25hdHVyZT5PUTVrZDR5MFdiMTAvU1VQdm1ZYnZVK3d5M0dQTCttZ3dpOVlOT3BWUElYTXQ2THU4SkpUQjNid0hlbndtb0RrZjllTHhjNncvT21GeTJNekYraFpKLzd2NUhaVVNEK2lRNDA0ZHVJRXZTbER4ZW0xK0dFejlsT1VJdXh1a3pIVzIrbE05ZEc0TzU1U2FwSXdjNHZIK3cyZ1ZiaWNkcGdackVkQW8yOXNmN0NGbHR1S0lKY2hwMmF0Vm0xaFdvUmZ0eWlBZVZkR0MxVjFuS1JqdlZPNFZuNERFdnR1MmY2MitETC9LSUU1UG9GVnQzV0dJU3E4aUxQcXpaMXhoRHVraDlsTDdxcnRhbkRqR3hJeDNjQWpOQlRicmhYMGk0VnUxYU15YnRhcU05QjdUUS80Z0F0NlE3WUx3UEpQeHphNXZuNlZLNmxMWVRCeWRlSDNDL0hhVVE9PTwvU2lnbmF0dXJlPjwvS2V5T1NBdXRoZW50aWNhdGlvblhNTD4K</extra>
    </content>
</contents>


If you're not testing on the same computer running Wowza Streaming Engine, change localhost to the server's IP address or hostname.

Deny connections from RTSP clients


To deny RTSP playback, change <RTP>/<Authentication>/<PlayMethod> to digest:

<PlayMethod>digest</PlayMethod>

Use the Wowza Streaming Engine Java API to capture keyId, contentId, and mediaId


If you want to be notified when a stream is started that uses the BuyDRM protection mechanism so you can capture the keyId, contentId, and mediaId used for streaming, you can create a class that implements the IBuyDRMStreamActionNotify interface and add it as a listener to the BuyDRM module. Following is an example class that implements this interface:
 

import com.wowza.wms.application.*;
import com.wowza.wms.drm.module.buydrm.*;
import com.wowza.wms.httpstreamer.model.*;
import com.wowza.wms.logging.*;

public class BuyDRMStreamActionNotifyExample implements IBuyDRMStreamActionNotify
{
public void onBuyDRMHTTPCupertinoStreamingPlayReadyCreateVOD(IApplicationInstance appInstance, IHTTPStreamerSession httpSession, BuyDRMKeyInfo buyDRMKeyInfo)
{
WMSLoggerFactory.getLogger(null).info("BuyDRMStreamActionNotifyExample.onBuyDRMHTTPCupertinoStreamingPlayReadyCreateVOD: appInstance: "+appInstance.getContextStr());
WMSLoggerFactory.getLogger(null).info("BuyDRMStreamActionNotifyExample.onBuyDRMHTTPCupertinoStreamingPlayReadyCreateVOD: httpSession: "+httpSession.getSessionId());
WMSLoggerFactory.getLogger(null).info("BuyDRMStreamActionNotifyExample.onBuyDRMHTTPCupertinoStreamingPlayReadyCreateVOD: buyDRMKeyInfo: "+buyDRMKeyInfo.toString());
}

public void onBuyDRMHTTPCupertinoStreamingPlayReadyCreateLive(IApplicationInstance appInstance, String streamName, BuyDRMKeyInfo buyDRMKeyInfo)
{
WMSLoggerFactory.getLogger(null).info("BuyDRMStreamActionNotifyExample.onBuyDRMHTTPCupertinoStreamingPlayReadyCreateLive: appInstance: "+appInstance.getContextStr());
WMSLoggerFactory.getLogger(null).info("BuyDRMStreamActionNotifyExample.onBuyDRMHTTPCupertinoStreamingPlayReadyCreateLive: streamName: "+streamName);
WMSLoggerFactory.getLogger(null).info("BuyDRMStreamActionNotifyExample.onBuyDRMHTTPCupertinoStreamingPlayReadyCreateLive: buyDRMKeyInfo: "+buyDRMKeyInfo.toString());
}
}


To add this class to your [install-dir]/conf/[application]/Application.xml file, add the following property with the full path to your class to the <Properties> container at the end of the Application.xml file (make sure to add it in the correct <Properties> container as there are several in the file):
 
<Property>
    <Name>drmBuyDRMActionNotifyClass</Name>
    <Value>com.wowza.wms.plugin.test.buydrm.BuyDRMStreamActionNotifyExample</Value>
</Property>

API-based stream map


You can replace the buydrmstreammap.txt file with a Java class that's invoked each time a new stream is to be PlayReady encrypted. The following is an example mapping class:
 
package com.wowza.wms.plugin.test.buydrm;

import com.wowza.wms.application.*;
import com.wowza.wms.httpstreamer.smoothstreaming.httpstreamer.*;

public class BuyDRMStreamNameToKeyInfoExample implements IBuyDRMStreamNameToKeyInfo
{
    private IApplicationInstance appInstance = null;

    public void init(IApplicationInstance appInstance)
    {
        this.appInstance = appInstance;
    }

    public BuyDRMKeyInfo streamNameToKeyInfo(String typeStr, IApplicationInstance appInstance, String streamName, HTTPStreamerSessionSmoothStreamer httpSession)
    {
        BuyDRMKeyInfo result = null;

        if (streamName.equals("sample.mp4"))
        {
            result = new BuyDRMKeyInfo();
            result.setKeyId("F6005DCF-7F93-4B8E-85C7-F908840DA059");
            result.setContentId("F6005DCF-7F93-4B8E-85C7-F908840DA059");
            result.setMediaId("sampletest");
        }
        else if (streamName.startsWith("video-"))
        {
            result = new BuyDRMKeyInfo();
            result.setKeyId("${KeyIdGenerator.SharedSecret}");
            result.setContentId("${KeyId}");
            result.setMediaId("${Stream.Name}");
        }

        return result;
    }


}


To use the Java API instead of the map file, replace the drmBuyDRMStreamNameMapFile property with the following property that points to the full path to the custom mapping class:
 
<Property>
    <Name>drmBuyDRMStreamNameMapClass</Name>
    <Value>com.wowza.wms.plugin.test.buydrm.BuyDRMStreamNameToKeyInfoExample</Value>
</Property>
 
Note: If the streamNameToKeyInfo returns null, the stream won't be protected.

nDVR-specific instructions

There are additional steps and considerations if you're using DRM with the nDVR feature.
 
  • For nDVR, you must include the ?dvr query parameter in the playback URL. For example:

http://localhost:1935/myApplication/mp4:sample.mp4/manifest.mpd?dvr

  • The DRM module must be enabled during nDVR recording as well as playback.
     
  • When using nDVR in a live repeater (origin-edge) scenario, the DRM module must be enabled on both the origin and edge servers.
  • In origin-edge mode, both origin and edge servers use a common shared secret string to encrypt data sent between instances. The dvrEncryptionSharedSecret or liveRepeaterEncryptionSharedSecret properties may be used to customize the shared secret that's used. For more information about these properties, see nDVR advanced configuration.