Generating a PlayReady Content Key Using a Key Seed and Key ID

The Key ID is a Microsoft™ GUID so it’s important to use the correct endianness when converting it to a byte array.

As a quick reminder, the format of the 128-bit GUID is:

Bits Bytes Name Endianness
32 4 Data1 Native
16 2 Data2 Native
16 2 Data3 Native
64 8 Data4 Big

The PlayReady license server only runs on little-endian architectures so the first three fields must also be little-endian. For example, the binary representation of “01020304-0506-0708-090A-AABBCCDDEEFF” should be { 0x04, 0x03, 0x02, 0x01, 0x06, 0x05, 0x08, 0x07, 0x09, 0x0A, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }.

The Key Seed should be at least 30 bytes long. Longer keys will be truncated to 30 bytes.

The 128-bit (16-byte) Content Key is calculated based on three SHA-256 hashes (32-byte):

  1. digest_A: Key Seed + Key ID
  2. digest_B: Key Seed + Key ID + Key Seed
  3. digest_C: Key Seed + Key ID + Key Seed + Key ID

The formula is:

contentKey[i] = digest_A[i] XOR digest_A[i + 16] XOR
                digest_B[i] XOR digest_B[i + 16] XOR
                digest_C[i] XOR digest_C[i + 16];

The complete reference algorithm can be found in the Microsoft documentation.

Finally, the Checksum can be calculated in two ways.

If ALGID is AESCTR:

  1. encrypt the 16-byte Key ID with the 16-byte Content Key using AES in ECB/NoPadding mode.
  2. Extract the first 8 bytes from the result and encode them to base64.

If ALGID is COCKTAIL:

  1. Create a 21-byte buffer
  2. Put the Content Key in the buffer and fill the rest with zeros.
  3. For five iterations: buffer = SHA-1 (buffer).
  4. Extract the first 7 bytes of the result and encode them to base64.

Sample output using Microsoft’s test Key Seed:

Key Seed (base64) XVBovsmzhP9gRIZxWfFta3VVRPzVEWmJsazEJ46I
Key ID 01020304-0506-0708-090A-AABBCCDDEEFF
Content Key (base64) GUf166PQbx+sgBADjyBMvw==
Checksum (AESCTR/base64) EV/EKanLDy4=
Advertisements

2 thoughts on “Generating a PlayReady Content Key Using a Key Seed and Key ID

    • Why: because Microsoft says the PlayReady Server APIs use GUIDs to pass in the Key IDs so any client will implement it that way. It doesn’t matter what you put in your byte array, what matters is the binary hex representation of that byte array as you need to take into account the endianess. See the example at the beginning of the post.

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s