The DRM Blog

Advanced Encryption Techniques: ContentProtection Tags for MPDs and PSSH Boxes for DASH.

Posted by Roman K. on Oct 25, 2017 1:52:40 PM

Here, at BuyDRM we support a wide array of encoding partners and solutions in the industry with our KeyOS Encyption Key API. This allows end users to choose from a myriad of choices based on their needs and financial possibilities. However, the existence of many different encoding/packaging partners also means that we needed to find a way to work with them in a conistent manner and provide a way for them to request all the required information to apply DRM protection in their products fast and easy.

As a result, we provide the KeyOS Encryption Key API that is responsible for generating encryption keys, headers, and PSSH box data for our encoding partners to use in their products.

We would like to provide some tips to those who are just getting into content encoding, who have already read numerous specs (ISO/IEC 23001-7, ISO/IEC 23009-1, PANTOS, and many others) and are ready to dive into encoding with encryption.

We will concentrate on MPEG-DASH in this article and will describe how to build ContentProtection tags that go into DASH Media Presentation Description file (MPD) and PSSH boxes that go into media content. This, of course, doesn’t cover the complete encryption process, but the intent of this post wasn’t to teach you how to write packaging software. We wrote this post because more and more customers are asking about how to create PROs and PSSHs to use in different scenarios and we thought that not only our customers, but also others may find answers on these questions useful.

Getting data required from the KeyOS Encryption Key API

MPEG-DASH is a very popular format because it allows you to cover a wide array of platforms thanks to its CENC support. The CENC spec defines encryption and key mapping mechanisms that may be utilized by one or more DRM systems to allow the decryption of the same file using different DRM systems which makes it possible to playback MPEG-DASH assets on devices that support PlayReady DRM or Widevine DRM [CENC].

Of course, it is not a panacea, and we look forward to seeing how CMAF will prove itself; however, currently we have MPEG-DASH and in order to make it work with different DRMs, you need to correctly apply DRM signaling into the manifest and initialization chunks.

Let’s assume you already made a request to the API and got your response. Aside from the content key that you get and should use to encrypt your content, you will also need PlayReady header and the Widevine PSSH box data. Both are returned by the API, but, you can’t use them out of the box in your MPD or PSSH boxes.

Building ContentProtection tags and PSSH boxes for PlayReady

First, let’s deal with adding PlayReady DRM support into the MPEG-DASH asset. DASH defines two types of ContentProtection Descriptor elements for ISO Media.

  1. With @schemeIdUri=”urn:mpeg:dash:mp4protection:2011” @value=”<scheme>”
  2. With @schemeIdUri=”urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx” @value=”DRMNAME version”

The first descriptor type indicates the four character code of the encryption scheme that is contained in the Protection Scheme Information Box (‘schi’) in each encrypted ISO Media track. This descriptor is inside the manifest to tell the client that the content is encrypted.

The second descriptor type indicates the UUID string for a particular DRM system that can provide a license and decryption key for the associated Adaptation Set [DASH-CENC]. In other words you define what DRMs are supported with encrypted asset.

The first descriptor will look like this:

<ContentProtection schemeIdUri="urn:mpeg:dash:mp4protection:2011" value="cenc" cenc:default_KID="4CD90DCF-5592-4573-8990-9C6A4D7199B2" />

Where the “default_KID” field’s value will come from the KeyOS Encryption Key API response KeyID field. The field will be presented in GUID format for your convenience.

The second descriptor type is just what we need to tell the client that we will support PlayReady, Widevine, or other DRMs. We will focus on PlayReady and Widevine for now. For PlayReady, based on the MPEG DASH PlayReady 1.2 specification [DASH-CENC], the descriptor will look as follows:

<ContentProtection xmlns:mspr="urn:microsoft:playready" schemeIdUri="urn:uuid:9A04F079-9840-4286-AB92-E65BE0885F95" value="Microsoft PlayReady">
    <mspr:pro> <!-- base64-encoded PlayReady Header Object --> </mspr:pro>
    <cenc:pssh> <!-- base64-encoded PlayReady 'pssh' complete box --> </cenc:pssh>
</ContentProtection>
    

The “mspr:pro” element is defined by Microsoft PlayReady, and includes only the PlayReady Header Object (PRO) [PRHEADER] information, not the box structure included in “pssh” and “cenc:pssh”. Including both “mspr:pro” and “cenc:pssh” will enable old players including a player based on Silverlight, and new players including web pages using script to play protected DASH presentations on HTML5 browsers.

Building a PRO

To build something you need to understand what buildings blocks it consists of. In our case, those building blocks are bytes. Here is how PRO looks like:

  • 4 bytes – holds the size of the PlayReady header object in bytes. The length of a PlayReady header object should not exceed 15 kilobytes (KB).
  • 2 bytes – specifies the number of PlayReady records in the PlayReady object.
  • byte array – contains a variable number of records that contain information related to licenses and license acquisition.
    • 2 bytes – specifies the type of data stored in the record value field.
    • 2 bytes – specifies the size in bytes of the record value field.
    • byte array – the content of the object depends on the value of record type.

Besides that, the PRO specification requires the PRO to be in UTF-16 LE format.

Now, when you understand how PRO looks like in theory, let us construct one based on the information acquired from the KeyOS Encryption Key API. Let us presume you have this PlayReady header from the API:

<WRMHEADER xmlns="http://schemas.microsoft.com/DRM/2007/03/PlayReadyHeader" version="4.0.0.0"><DATA><PROTECTINFO><KEYLEN>16></KEYLEN><ALGID>AESCTR</ALGID></PROTECTINFO><KID>+rbqVgPoa0iAkLlEKCQUcA==</KID><LA_URL>http://sldrm.licensekeyserver.com/core/rightsmanager.asmx</LA_URL><DS_ID>VlR7IdsIJEuRd06Laqs2jw==</DS_ID><CUSTOMATTRIBUTES xmlns=""><CID>E363j+wos0O4KG5BXDt95A==</CID><DRMTYPE>smooth</DRMTYPE></CUSTOMATTRIBUTES><CHECKSUM>RV1yHHiLPak=</CHECKSUM></DATA></WRMHEADER>

Now imagine a binary array in which we will be putting our data. However, we will not be appending it, we will be PRE-pending it – we will go from the bottom up so to say, from finish to start. This makes it easier to calculate size of the data added into our imaginary array.

Let us start. First, you put your PlayReady Header there in UTF-16 LE format.

    
3C 00 57 00 52 00 4D 00 48 00 45 00 41 00 44 00 45 00 52 00 20 00 78 00 6D 00 6C 00 6E 00 73 00 3D 00 22 
00 68 00 74 00 74 00 70 00 3A 00 2F 00 2F 00 73 00 63 00 68 00 65 00 6D 00 61 00 73 00 2E 00 6D 00 69 00 
63 00 72 00 6F 00 73 00 6F 00 66 00 74 00 2E 00 63 00 6F 00 6D 00 2F 00 44 00 52 00 4D 00 2F 00 32 00 30
00 30 00 37 00 2F 00 30 00 33 00 2F 00 50 00 6C 00 61 00 79 00 52 00 65 00 61 00 64 00 79 00 48 00 65 00
61 00 64 00 65 00 72 00 22 00 20 00 76 00 65 00 72 00 73 00 69 00 6F 00 6E 00 3D 00 22 00 34 00 2E 00 30
00 2E 00 30 00 2E 00 30 00 22 00 3E 00 3C 00 44 00 41 00 54 00 41 00 3E 00 3C 00 50 00 52 00 4F 00 54 00 
45 00 43 00 54 00 49 00 4E 00 46 00 4F 00 3E 00 3C 00 4B 00 45 00 59 00 4C 00 45 00 4E 00 3E 00 31 00 36 
00 0D 00 0A 00 3C 00 2F 00 4B 00 45 00 59 00 4C 00 45 00 4E 00 3E 00 3C 00 41 00 4C 00 47 00 49 00 44 00 
3E 00 41 00 45 00 53 00 43 00 54 00 52 00 3C 00 2F 00 41 00 4C 00 47 00 49 00 44 00 3E 00 3C 00 2F 00 50 
00 52 00 4F 00 54 00 45 00 43 00 54 00 49 00 4E 00 46 00 4F 00 3E 00 3C 00 4B 00 49 00 44 00 3E 00 2B 00
72 00 62 00 71 00 56 00 67 00 50 00 6F 00 61 00 30 00 69 00 41 00 6B 00 4C 00 6C 00 45 00 4B 00 43 00 51
00 55 00 63 00 41 00 3D 00 3D 00 3C 00 2F 00 4B 00 49 00 44 00 3E 00 3C 00 4C 00 41 00 5F 00 55 00 52 00
4C 00 3E 00 68 00 74 00 74 00 70 00 3A 00 2F 00 2F 00 73 00 6C 00 64 00 72 00 6D 00 2E 00 6C 00 69 00 63 
00 65 00 6E 00 73 00 65 00 6B 00 65 00 79 00 73 00 65 00 72 00 76 00 65 00 72 00 2E 00 63 00 6F 00 6D 00 
2F 00 63 00 6F 00 72 00 65 00 2F 00 72 00 69 00 67 00 68 00 74 00 73 00 6D 00 61 00 6E 00 61 00 67 00 65 
00 72 00 2E 00 61 00 73 00 6D 00 78 00 0D 00 0A 00 3C 00 2F 00 4C 00 41 00 5F 00 55 00 52 00 4C 00 3E 00 
3C 00 44 00 53 00 5F 00 49 00 44 00 3E 00 56 00 6C 00 52 00 37 00 49 00 64 00 73 00 49 00 4A 00 45 00 75 
00 52 00 64 00 30 00 36 00 4C 00 61 00 71 00 73 00 32 00 6A 00 77 00 3D 00 3D 00 3C 00 2F 00 44 00 53 00 
5F 00 49 00 44 00 3E 00 3C 00 43 00 55 00 53 00 54 00 4F 00 4D 00 41 00 54 00 54 00 52 00 49 00 42 00 55 
00 54 00 45 00 53 00 20 00 78 00 6D 00 6C 00 6E 00 73 00 3D 00 22 00 22 00 3E 00 3C 00 43 00 49 00 44 00 
3E 00 45 00 33 00 36 00 33 00 6A 00 2B 00 77 00 6F 00 73 00 30 00 4F 00 34 00 4B 00 47 00 35 00 42 00 58 
00 44 00 74 00 39 00 35 00 41 00 3D 00 3D 00 3C 00 2F 00 43 00 49 00 44 00 3E 00 3C 00 44 00 52 00 4D 00 
54 00 59 00 50 00 45 00 3E 00 73 00 6D 00 6F 00 6F 00 74 00 68 00 3C 00 2F 00 44 00 52 00 4D 00 54 00 59 
00 50 00 45 00 3E 00 3C 00 2F 00 43 00 55 00 53 00 54 00 4F 00 4D 00 41 00 0D 00 0A 00 54 00 54 00 52 00 
49 00 42 00 55 00 54 00 45 00 53 00 3E 00 3C 00 43 00 48 00 45 00 43 00 4B 00 53 00 55 00 4D 00 3E 00 52
00 56 00 31 00 79 00 48 00 48 00 69 00 4C 00 50 00 61 00 6B 00 3D 00 3C 00 2F 00 43 00 48 00 45 00 43 00 
4B 00 53 00 55 00 4D 00 3E 00 3C 00 2F 00 44 00 41 00 54 00 41 00 3E 00 3C 00 2F 00 57 00 52 00 4D 00 48 
00 45 00 41 00 44 00 45 00 52 00 3E 00

You then prepend the array with 2 bytes that define the size of the PlayReady Header. Remember, that we still write in Little Endian notation and we will continue for the whole PRO:

BE 03

Next go two bytes that represent the type of the box:

01 00

which stands for the record that contains a rights management header. You now have the PlayReady record ready, but the PRO is not finished yet. We continue adding to our array. Add two more bytes for the number of PlayReady records that we have:

01 00

And we finish with 4 bytes – the complete PRO size:

C8 03 00 00

Here is the resulting PRO:

C8 03 00 00 01 00 01 00 BE 03 3C 00 57 00 52 00 4D 00 48 00 45 00 41 00 44 00 45 00 52 00 20 00 78 00 6D
00 6C 00 6E 00 73 00 3D 00 22 00 68 00 74 00 74 00 70 00 3A 00 2F 00 2F 00 73 00 63 00 68 00 65 00 6D 00
61 00 73 00 2E 00 6D 00 69 00 63 00 72 00 6F 00 73 00 6F 00 66 00 74 00 2E 00 63 00 6F 00 6D 00 2F 00 44
00 52 00 4D 00 2F 00 32 00 30 00 30 00 37 00 2F 00 30 00 33 00 2F 00 50 00 6C 00 61 00 79 00 52 00 65 00
61 00 64 00 79 00 48 00 65 00 61 00 64 00 65 00 72 00 22 00 20 00 76 00 65 00 72 00 73 00 69 00 6F 00 6E 
00 3D 00 22 00 34 00 2E 00 30 00 2E 00 30 00 2E 00 30 00 22 00 3E 00 3C 00 44 00 41 00 54 00 41 00 3E 00
3C 00 50 00 52 00 4F 00 54 00 45 00 43 00 54 00 49 00 4E 00 46 00 4F 00 3E 00 3C 00 4B 00 45 00 59 00 4C
00 45 00 4E 00 3E 00 31 00 36 00 3C 00 2F 00 4B 00 45 00 59 00 4C 00 45 00 4E 00 3E 00 3C 00 41 00 4C 00
47 00 49 00 44 00 3E 00 41 00 45 00 53 00 43 00 54 00 52 00 3C 00 2F 00 41 00 4C 00 47 00 49 00 44 00 3E 
00 3C 00 2F 00 50 00 52 00 4F 00 54 00 45 00 43 00 54 00 49 00 4E 00 46 00 4F 00 3E 00 3C 00 4B 00 49 00
44 00 3E 00 54 00 39 00 79 00 51 00 7A 00 5A 00 4A 00 56 00 63 00 30 00 57 00 4A 00 6B 00 4A 00 78 00 71
00 54 00 58 00 47 00 5A 00 73 00 67 00 3D 00 3D 00 3C 00 2F 00 4B 00 49 00 44 00 3E 00 3C 00 4C 00 41 00
5F 00 55 00 52 00 4C 00 3E 00 68 00 74 00 74 00 70 00 3A 00 2F 00 2F 00 73 00 6C 00 64 00 72 00 6D 00 2E 
00 6C 00 69 00 63 00 65 00 6E 00 73 00 65 00 6B 00 65 00 79 00 73 00 65 00 72 00 76 00 65 00 72 00 2E 00
63 00 6F 00 6D 00 2F 00 63 00 6F 00 72 00 65 00 2F 00 72 00 69 00 67 00 68 00 74 00 73 00 6D 00 61 00 6E
00 61 00 67 00 65 00 72 00 2E 00 61 00 73 00 6D 00 78 00 3C 00 2F 00 4C 00 41 00 5F 00 55 00 52 00 4C 00 
3E 00 3C 00 44 00 53 00 5F 00 49 00 44 00 3E 00 56 00 6C 00 52 00 37 00 49 00 64 00 73 00 49 00 4A 00 45 
00 75 00 52 00 64 00 30 00 36 00 4C 00 61 00 71 00 73 00 32 00 6A 00 77 00 3D 00 3D 00 3C 00 2F 00 44 00 
53 00 5F 00 49 00 44 00 3E 00 3C 00 43 00 55 00 53 00 54 00 4F 00 4D 00 41 00 54 00 54 00 52 00 49 00 42 
00 55 00 54 00 45 00 53 00 20 00 78 00 6D 00 6C 00 6E 00 73 00 3D 00 22 00 22 00 3E 00 3C 00 43 00 49 00 
44 00 3E 00 54 00 39 00 79 00 51 00 7A 00 5A 00 4A 00 56 00 63 00 30 00 57 00 4A 00 6B 00 4A 00 78 00 71 
00 54 00 58 00 47 00 5A 00 73 00 67 00 3D 00 3D 00 3C 00 2F 00 43 00 49 00 44 00 3E 00 3C 00 44 00 52 00 
4D 00 54 00 59 00 50 00 45 00 3E 00 73 00 6D 00 6F 00 6F 00 74 00 68 00 3C 00 2F 00 44 00 52 00 4D 00 54
00 59 00 50 00 45 00 3E 00 3C 00 2F 00 43 00 55 00 53 00 54 00 4F 00 4D 00 41 00 54 00 54 00 52 00 49 00 
42 00 55 00 54 00 45 00 53 00 3E 00 3C 00 43 00 48 00 45 00 43 00 4B 00 53 00 55 00 4D 00 3E 00 78 00 56 
00 41 00 57 00 6F 00 6A 00 61 00 4A 00 72 00 7A 00 45 00 3D 00 3C 00 2F 00 43 00 48 00 45 00 43 00 4B 00 
53 00 55 00 4D 00 3E 00 3C 00 2F 00 44 00 41 00 54 00 41 00 3E 00 3C 00 2F 00 57 00 52 00 4D 00 48 00 45
00 41 00 44 00 45 00 52 00 3E 00

Yellow bytes specify the size of the PRO header. Two bytes (green) define number of PlayReady records. Two more bytes (blue) define the type of the PlayReady record and based on the specification the 00 01 means that the record contains the record with rights management header inside. Last two bytes (grey) specify the size of the rights management header, which follows in UTF-16 LE. Here is how it looks like in HEX editor:

pr_header_obj.png

Figure 1. PlayReady Header Object

 

Building a Complete PSSH Box.

The PRO is done. We now need to create the PSSH box so our Common Encryption scenario would work and client would know that the asset could play back the asset after getting the PlayReady license. For this, according to the [CENC] specification we need to create the “<cenc:pssh>” tag inside the MPEG-DASH manifest. We already have the PRO, all is left is to wrap it into complete PSSH box, which has the following structure if we will look on it under the microscope, which is our hex editor:

  • 4 bytes – the size of the PSSH box
  • 4 bytes – the constant “PSSH”
  • 4 bytes – flags based on the [ISOBMFF] specification
  • 16 bytes – unique key system identifier
  • 4 bytes – size of the data inside the PSSH box
  • byte array – data itself

Considering we already have the PRO, we just keep prepending (move from bottom to the top in the structure list mentioned above) into the byte array to get our PSSH box. First, add 4 bytes to define the size of the data inside the PSSH box. This is the size of the entire PRO. Please, note that that now we do not use Little Endian notation:

00 00 03 C8

Then 16 bytes that uniquely identify the PlayReady Key System [SYSTEM-IDS]. This value may be considered a constant:

9A 04 F0 79 98 40 42 86 AB 92 E6 5B E0 88 5F 95

The value of the flags map and the version for this box is zero, so, add 4 empty bytes:

00 00 00 00

And 4 more with another constant – “PSSH”, which looks like this in HEX:

70 73 73 68

We finish with adding 4 bytes that define the size of the complete PSSH box:

00 00 03 E8

The complete PSSH box looks like this.

00 00 03 E8 70 73 73 68 00 00 00 00 9A 04 F0 79 98 40 42 86 AB 92 E6 5B E0 88 5F 95 00 00 03 C8 C8
03 00 00 01 00 01 00 B2 03 3C 00 57 00 52 00 4D 00 48 00 45 00 41 00 44 00 45 00 52 00 20 00 78 00 
6D 00 6C 00 6E 00 73 00 3D 00 22 00 68 00 74 00 74 00 70 00 3A 00 2F 00 2F 00 73 00 63 00 68 00 65
00 6D 00 61 00 73 00 2E 00 6D 00 69 00 63 00 72 00 6F 00 73 00 6F 00 66 00 74 00 2E 00 63 00 6F 00 
6D 00 2F 00 44 00 52 00 4D 00 2F 00 32 00 30 00 30 00 37 00 2F 00 30 00 33 00 2F 00 50 00 6C 00 61 
00 79 00 52 00 65 00 61 00 64 00 79 00 48 00 65 00 61 00 64 00 65 00 72 00 22 00 20 00 76 00 65 00
72 00 73 00 69 00 6F 00 6E 00 3D 00 22 00 34 00 2E 00 30 00 2E 00 30 00 2E 00 30 00 22 00 3E 00 3C 
00 44 00 41 00 54 00 41 00 3E 00 3C 00 50 00 52 00 4F 00 54 00 45 00 43 00 54 00 49 00 4E 00 46 00 
4F 00 3E 00 3C 00 4B 00 45 00 59 00 4C 00 45 00 4E 00 3E 00 31 00 36 00 3C 00 2F 00 4B 00 45 00 59 
00 4C 00 45 00 4E 00 3E 00 3C 00 41 00 4C 00 47 00 49 00 44 00 3E 00 41 00 45 00 53 00 43 00 54 00 
52 00 3C 00 2F 00 41 00 4C 00 47 00 49 00 44 00 3E 00 3C 00 2F 00 50 00 52 00 4F 00 54 00 45 00 43 
00 54 00 49 00 4E 00 46 00 4F 00 3E 00 3C 00 4B 00 49 00 44 00 3E 00 54 00 39 00 79 00 51 00 7A 00 
5A 00 4A 00 56 00 63 00 30 00 57 00 4A 00 6B 00 4A 00 78 00 71 00 54 00 58 00 47 00 5A 00 73 00 67 
00 3D 00 3D 00 3C 00 2F 00 4B 00 49 00 44 00 3E 00 3C 00 4C 00 41 00 5F 00 55 00 52 00 4C 00 3E 00 
68 00 74 00 74 00 70 00 3A 00 2F 00 2F 00 73 00 6C 00 64 00 72 00 6D 00 2E 00 6C 00 69 00 63 00 65
00 6E 00 73 00 65 00 6B 00 65 00 79 00 73 00 65 00 72 00 76 00 65 00 72 00 2E 00 63 00 6F 00 6D 00 
2F 00 63 00 6F 00 72 00 65 00 2F 00 72 00 69 00 67 00 68 00 74 00 73 00 6D 00 61 00 6E 00 61 00 67 
00 65 00 72 00 2E 00 61 00 73 00 6D 00 78 00 3C 00 2F 00 4C 00 41 00 5F 00 55 00 52 00 4C 00 3E 00 
3C 00 44 00 53 00 5F 00 49 00 44 00 3E 00 56 00 6C 00 52 00 37 00 49 00 64 00 73 00 49 00 4A 00 45 
00 75 00 52 00 64 00 30 00 36 00 4C 00 61 00 71 00 73 00 32 00 6A 00 77 00 3D 00 3D 00 3C 00 2F 00 
44 00 53 00 5F 00 49 00 44 00 3E 00 3C 00 43 00 55 00 53 00 54 00 4F 00 4D 00 41 00 54 00 54 00 52
00 49 00 42 00 55 00 54 00 45 00 53 00 20 00 78 00 6D 00 6C 00 6E 00 73 00 3D 00 22 00 22 00 3E 00 
3C 00 43 00 49 00 44 00 3E 00 54 00 39 00 79 00 51 00 7A 00 5A 00 4A 00 56 00 63 00 30 00 57 00 4A 
00 6B 00 4A 00 78 00 71 00 54 00 58 00 47 00 5A 00 73 00 67 00 3D 00 3D 00 3C 00 2F 00 43 00 49 00 
44 00 3E 00 3C 00 44 00 52 00 4D 00 54 00 59 00 50 00 45 00 3E 00 73 00 6D 00 6F 00 6F 00 74 00 68 
00 3C 00 2F 00 44 00 52 00 4D 00 54 00 59 00 50 00 45 00 3E 00 3C 00 2F 00 43 00 55 00 53 00 54 00 
4F 00 4D 00 41 00 54 00 54 00 52 00 49 00 42 00 55 00 54 00 45 00 53 00 3E 00 3C 00 43 00 48 00 45 
00 43 00 4B 00 53 00 55 00 4D 00 3E 00 78 00 56 00 41 00 57 00 6F 00 6A 00 61 00 4A 00 72 00 7A 00 
45 00 3D 00 3C 00 2F 00 43 00 48 00 45 00 43 00 4B 00 53 00 55 00 4D 00 3E 00 3C 00 2F 00 44 00 41
00 54 00 41 00 3E 00 3C 00 2F 00 57 00 52 00 4D 00 48 00 45 00 41 00 44 00 45 00 52 00 3E 00

First 4 bytes (yellow) specify the box of the complete PSSH box. Next 4 bytes define the type of the box which is PSSH in our case. 4 zero bytes (blue). 16 bytes (pink) that define the unique key system ID. In our case it is PlayReady. Last 4 bytes (grey) define the size of the data of the PSSH box. The data then follows. And here is how it looks like in the hex editor:

ppsh_box.png

Figure 2. Complete PSSH box with PRO inside for MPEG-DASH CENC (w/ PlayReady)

 

Building PSSH box for Widevine

Building PSSH box for Widevine to include into the MPEG-DASH manifest and into the encrypted file is not that different from building one for PlayReady. The structure of the box is the same. What changes is the Key System ID and the data of the PSSH box.

For Widevine PSSH box you will require the contents of the “WVHeader” field which you can find in a response from the KeyOS Encryption Key API. You can request this field by specifying “<fl_GenerateWVHeader>true</fl_GenerateWVHeader>” when making a call to the API.

Let’s presume you got this value as a response from the API:

CAESEFbqtvroA0hrgJC5RCgkFHAaC2J1eWRybWtleW9zIhCPt34TKOxDs7gobkFcO33kKgJIRA==

It is the Base64 representation of the following byte array:

08 01 12 10 56 ea b6 fa e8 03 48 6b 80 90 b9 44 28 24 14 70 1a 0b 62 75 79 64 72 6d 6b 65 79 6f 73
22 10 8f b7 7e 13 28 ec 43 b3 b8 28 6e 41 5c 3b 7d e4 2a 02 48 44

Let’s prepend it with all required PSSH box bytes and we get this as a result:

00 00 00 57 70 73 73 68 00 00 00 00 ED EF 8B A9 79 D6 4A CE A3 C8 27 DC D5 1D 21 ED 00 00 00 37 08
01 12 10 56 ea b6 fa e8 03 48 6b 80 90 b9 44 28 24 14 70 1a 0b 62 75 79 64 72 6d 6b 65 79 6f 73 22 
10 8f b7 7e 13 28 ec 43 b3 b8 28 6e 41 5c 3b 7d e4 2a 02 48 44

First 4 bytes (yellow) specify the box of the complete PSSH box. Next 4 bytes define the type of the box which is PSSH in our case. 4 zero bytes (blue). 16 bytes (pink) that define the unique key system ID which is “ED EF 8B A9 79 D6 4A CE A3 C8 27 DC D5 1D 21 ED” [SYSTEM-IDS] in case of Widevine and uniquely identifies it. Last 4 bytes (grey) define the size of the data of the PSSH box. The data then follows. And here is how it looks like in the hex editor:

Figure 3. Complete PSSH box with Widevine header inside for MPEG-DASH CENC (w/ Widevine)

Congratulations, you now have values for ContentProtection tags inside the MPEG-DASH manifest:

<ContentProtection schemeIdUri="urn:mpeg:dash:mp4protection:2011" value="cenc" cenc:default_KID="CD90DC4F-5592-4573-8990-9C6A4D7199B2" />
<ContentProtection xmlns:mspr="urn:microsoft:playready" schemeIdUri="urn:uuid:9A04F079-9840-4286-AB92-E65BE0885F95" value="Microsoft PlayReady">
    <mspr:pro> vAMAAAEAAQCyAzwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4AVAA5AHkAUQB6AFoASgBWAGMAMABXAEoAawBKAHgAcQBUAFgARwBaAHMAZwA9AD0APAAvAEsASQBEAD4APABMAEEAXwBVAFIATAA+AGgAdAB0AHAAOgAvAC8AcwBsAGQAcgBtAC4AbABpAGMAZQBuAHMAZQBrAGUAeQBzAGUAcgB2AGUAcgAuAGMAbwBtAC8AYwBvAHIAZQAvAHIAaQBnAGgAdABzAG0AYQBuAGEAZwBlAHIALgBhAHMAbQB4ADwALwBMAEEAXwBVAFIATAA+ADwARABTAF8ASQBEAD4AVgBsAFIANwBJAGQAcwBJAEoARQB1AFIAZAAwADYATABhAHEAcwAyAGoAdwA9AD0APAAvAEQAUwBfAEkARAA+ADwAQwBVAFMAVABPAE0AQQBUAFQAUgBJAEIAVQBUAEUAUwAgAHgAbQBsAG4AcwA9ACIAIgA+ADwAQwBJAEQAPgBUADkAeQBRAHoAWgBKAFYAYwAwAFcASgBrAEoAeABxAFQAWABHAFoAcwBnAD0APQA8AC8AQwBJAEQAPgA8AEQAUgBNAFQAWQBQAEUAPgBzAG0AbwBvAHQAaAA8AC8ARABSAE0AVABZAFAARQA+ADwALwBDAFUAUwBUAE8ATQBBAFQAVABSAEkAQgBVAFQARQBTAD4APABDAEgARQBDAEsAUwBVAE0APgB4AFYAQQBXAG8AagBhAEoAcgB6AEUAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA=</mspr:pro>
    <cenc:pssh>AAAD3HBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAA7y8AwAAAQABALIDPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBUADkAeQBRAHoAWgBKAFYAYwAwAFcASgBrAEoAeABxAFQAWABHAFoAcwBnAD0APQA8AC8ASwBJAEQAPgA8AEwAQQBfAFUAUgBMAD4AaAB0AHQAcAA6AC8ALwBzAGwAZAByAG0ALgBsAGkAYwBlAG4AcwBlAGsAZQB5AHMAZQByAHYAZQByAC4AYwBvAG0ALwBjAG8AcgBlAC8AcgBpAGcAaAB0AHMAbQBhAG4AYQBnAGUAcgAuAGEAcwBtAHgAPAAvAEwAQQBfAFUAUgBMAD4APABEAFMAXwBJAEQAPgBWAGwAUgA3AEkAZABzAEkASgBFAHUAUgBkADAANgBMAGEAcQBzADIAagB3AD0APQA8AC8ARABTAF8ASQBEAD4APABDAFUAUwBUAE8ATQBBAFQAVABSAEkAQgBVAFQARQBTACAAeABtAGwAbgBzAD0AIgAiAD4APABDAEkARAA+AFQAOQB5AFEAegBaAEoAVgBjADAAVwBKAGsASgB4AHEAVABYAEcAWgBzAGcAPQA9ADwALwBDAEkARAA+ADwARABSAE0AVABZAFAARQA+AHMAbQBvAG8AdABoADwALwBEAFIATQBUAFkAUABFAD4APAAvAEMAVQBTAFQATwBNAEEAVABUAFIASQBCAFUAVABFAFMAPgA8AEMASABFAEMASwBTAFUATQA+AHgAVgBBAFcAbwBqAGEASgByAHoARQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==</cenc:pssh>
</ContentProtection>
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed" value="Widevine">
    <cenc:pssh>AAAAV3Bzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAADcIARIQVuq2+ugDSGuAkLlEKCQUcBoLYnV5ZHJta2V5b3MiEI+3fhMo7EOzuChuQVw7feQqAkhE</cenc:pssh>
</ContentProtection>

and PSSH boxes to include into the encrypted chunks.

Summary and the future

As you saw from the above examples, little work needs to be done in order to implement with KeyOS Encryption API.

  • Make a request to the KeyOS Encryption Key API and request both PlayReady and Widevine headers in a response.
  • To create PRO and PSSH for PlayReady signaling, make sure you convert returned PlayReady header into UTF-16 LE before creating PRO based on it. When PRO is created, you can go a bit further and create PSSH.
  • To create PSSH for Widevine signaling, make sure you request the PSSH data from the KeyOS Encryption Key API. When returned, just build complete PSSH structure around it.

We are looking into extending our APIs to include complete PSSH boxes and PRO objects and will be notifying our customers and encoding partners as soon as it is implemented.

Nevertheless, we also understand that standards are a must if you want to survive in a constantly changing world. Those add organization and structure to otherwise chaotic implementations and random data models flying around in the internet. This is why we started looking into Content Protection Information Exchange Format (CPIX). CPIX allow exchanging content keys and DRM information among entities needing it in many possibly different workflows for preparing DASH content and applying protection to it. We are currently implementing CPIX support through our existing APIs.

While there is no information on the release dates or potentially supported features, we will move forward in this direction to make the KeyOS Platform even more flexible for our partners and customers.

References

[ISOBMFF]

ISO/IEC. Information technology — Coding of audio-visual objects — Part 12: ISO Base Media File Format. December 2015. International Standard. URL: http://standards.iso.org/ittf/PubliclyAvailableStandards/c068960_ISO_IEC_14496-12_2015.zip

[CENC]

ISO/IEC. ISO/IEC 23001-7:2016, Information technology — MPEG systems technologies — Part 7: Common encryption in ISO base media file format files. International Standard. URL: https://www.iso.org/obp/ui/#iso:std:iso-iec:23001:-7:ed-3:v1:en

[PRHEADER]


[DASH-CENC]


[SYSTEM-IDS]

DASH-IF. Protection, Generic Identifiers. URL: http://dashif.org/identifiers/protection/


Introducing the KeyOS Widevine Everywhere Program

Find out more by clicking below

widevine_everywhere


 Subscribe to The DRM Blog and get the 2016 DRM Deployment Guide

TheDRMBlog

SUBSCRIBE


View Past Episodes From Our "Spotlight On DRM" Webinar Series

New Call-to-action

Spotlight On DRM Webinar Series


BuyDRM – Your Single Source for Multi-DRM Solutions 

Playready Widevine Fairplay

Offering PlayReady, Widevine, and FairPlay, we can help you deliver protected content to any device in any situation whether online or offline or both.

Established in 2001, we are a market-leading Multi-DRM service provider. Over the last fifteen years we have seen drastic changes in the content protection arena as a variety of new technologies have entered the marketplace. Through our pioneering efforts in this field and decades of experience in digital media, we have your bases covered with the KeyOS Multi-DRM Platform supporting PlayReady, Widevine, and FairPlay DRMs. KeyOS supports all of the popular consumer platforms and business models.

Want to Learn More?

If you are either just beginning your search or are a seasoned streaming media pro, we think our team can help you. 

CONTACT US

Contact us to learn more about our solution.  We would be happy to setup a call to evaluate your scenario and find out how we can help you.  Our consultations are always free. Our KeyOS platform powers the biggest names in media across the globe and we are eager to assist you as well. 

Topics: Blog, Multi-DRM, DRM, encryption, PSSH