HTTP Dynamic Streaming (HDS)

Adding Primetime DRM

USP supports Primetime DRM for HDS.

Options for Primetime DRM

To enable encryption use the following options when generating the server manifest file:

--hds.key

The key id (KID) and content encryption key (CEK) are passed with the --hds.key option where KID and CEK are separated by a colon, e.g. --hds.key=KID:CEK

As no KID is used in Primetime DRM, this can be left empty. The CEK is a (random) 128 bit value and must be coded in base16 (hex).

--hds.key_iv

The 128 bit AES Initialization Vector (IV). This is a random 128 bit value.

--hds.drm_specific_data

The Primetime DRM specific data.

Can either be a Base64 string, or a file path with Base64 data. The file name must contain a '.' for example: base64_data.drm

See the Using the Primetime Java SDK on how to use the SDK to provide the encryption information.

Example

DRM_SPECIFIC_DATA=YOUR_ACCESS_DATA

mp4split -o video.ism \
  --hds.key=:0x0a0b0c0d0e0f00010203040506070809 \
  --hds.key_iv=000102030405060708090a0b0c0d0e0f \
  --hds.drm_specific_data=$DRM_SPECIFIC_DATA \
  video-500k.ismv video-800k.ismv video-1500k.ismv

Using the Primetime Java SDK

Use the byte[] getKey() class to get the 16-byte content encryption key using the KeyMetaData function. Convert this to a Base64 encoded string or a hex16 encoded string (see below also). This is the value for the option --hds.content_key.

Use the byte[] getDRMHeaderBytes() class to get the DRM header that is used in the manifest file for HTTP Streaming using the byte[] getDRMHeaderBytes() function. Convert this to a base64 encoded string. This is the value for the option --hds.drm_specific_data.

The --hds.key_iv value is a 128 bit random number to strengthen the encryption. Pass this as hex (base16), e.g. 000102030405060708090a0b0c0d0e0f.

Details of how to use the Primetime Java SDK can be found in the Adobe's documentation (page 20-24). The EncryptContent example has all the details on which files should be used (keys, policies etc) and when the encryption process is successful the result can be used to obtain the contentkey and the DRM data blob.

The SDK example expects an input file to be encrypted. Since we only use the SDK to generate the encryption information it is recommended to use a very small MP4 file (a single frame will do just fine).

The following can be done with the MediaEncrypterResult result:

The content encryption key (--hds.key)

Use the ContentEncryptionKey class to get the 16-byte content encryption key using the byte[] getKey() function. Convert this to a hex (base16) encoded string. This is the value for the option --hds.content_key.

ContentEncryptionKey cek = ContentEncryptionKey.generate();
String contentKey = convertToHex(cek.getKey());

Please note that the content id, content key (cek) and license server URL need to be set before encrypting the file. (There are functions like setContentEncryptionKey to do so).

In other words, the following section:

try {
  ContentEncryptionKey cek = ContentEncryptionKey.generate();

  // all other settings

  V2KeyParameters keyParams = MediaEncrypter.createKeyParameters(V2KeyParameters.class);
  keyParams.setLicenseServerUrl(licenseServerUrl);
  keyParams.setContentId(contentID);
  keyParams.setContentEncryptionKey(cek);

needs to come before the actual encryption:

MediaEncrypterResult result = encrypter.encryptContent(inputFile, outputFile, params);

The content key can be converted to a hex16 string with the following utility function:

private static String convertToHex(byte[] bytes) {

  private final static char[] HEX = new char[] {
    '0', '1', '2', '3', '4', '5', '6', '7',
    '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
  };

  StringBuffer hex = new StringBuffer(bytes.length * 2);

  for(int i = 0; i < byteArray.length; i++) {
    hex.append(HEX[(bytes[i] >> 4) & 15]);
    hex.append(HEX[(bytes[i] >> 0) & 15]);
  }
  return hex.toString();
}

The DRM meta data blob (--hds.drm_specific_data)

Use the KeyMetaData class to get the DRM header that is used in the manifest file for HTTP Streaming using the byte[] getDRMHeaderBytes() function. Convert this to a base64 encoded string. This is the value the option --hds.drm_specific_data.

KeyMetaData keyInfo = result.getKeyInfo().getKeyMetaData();

V2KeyMetaData v2 = (V2KeyMetaData) keyInfo;
byte[] header = v2.getDRMHeaderBytes();
String drm_specific_data = new String(Base64.toBase64(header));

The AES Initialization Vector (IV) (--hds.key_iv)

The --hds.key_iv value is a 128 bit random number to strengthen the encryption. It is not related to any options, it is just purely random and can be any 128 bit value. Convert this to hex (base16). This is the value for the option --hds.key_iv.