Создание заголовка PlayReady

Упаковщику необходимо включить заголовок PlayReady в зашифрованное содержимое.

Подробное описание заголовка PlayReady и объекта PlayReady см. в спецификации заголовка PlayReady.

Заголовок PlayReady содержит сведения о воспроизводимом содержимом, включая идентификаторы ключей (KID), которые определяют ключи, используемые для шифрования данных, URL-адрес приобретения лицензии по умолчанию сервера лицензий PlayReady и любые пользовательские данные, которые требуется включить. Ключ и KID, используемые для шифрования содержимого, должны быть переданы серверу лицензирования PlayReady, который будет выдавать лицензии для этого конкретного содержимого, как правило, через систему управления ключами (KMS).

Примечание

Корпорация Майкрософт не предоставляет систему управления ключами в PlayReady.

Следующий XML-код содержит пример заголовка PlayReady, который может быть вставлен в заголовок сегментированного MP4-файла, как правило, для содержимого по запросу. Он содержит список ИДЕНТИФИКАТОРов (идентификаторов ключей шифрования содержимого), необходимых для расшифровки содержимого клиентом. Это наиболее распространенный способ сигнализировать эти ИДЕНТИФИКАТОРы для файла или потока по запросу.

<WRMHEADER xmlns="http://schemas.microsoft.com/DRM/2007/03/PlayReadyHeader" version="4.3.0.0">
  <DATA>
    <PROTECTINFO>
      <KIDS>
        <KID ALGID="AESCTR" VALUE="PV1LM/VEVk+kEOB8qqcWDg=="></KID>
        <KID ALGID="AESCTR" VALUE="tuhDoKUN7EyxDPtMRNmhyA=="></KID>
      </KIDS>
    </PROTECTINFO>
    <LA_URL>http://rm.contoso.com/rightsmanager.asmx</LA_URL>
    <DS_ID>AH+03juKbUGbHl1V/QIwRA==</DS_ID>
  </DATA>
</WRMHEADER>

Следующий XML-код содержит пример заголовка PlayReady для динамического линейного содержимого. Он не включает в себя КИД, так как ключи шифрования содержимого (и связанные с ними ИДЕНТИФИКАТОРы) иногда изменяются (например, очень часто или на границе программы, или каждый час или каждый день). Идентификаторы KID, используемые для потока содержимого, будут сигнализироваться в заголовках сегмента, и не обязательно включать их в заголовок PlayReady верхнего уровня потока. Для свойства DECRYPTORSETUP задано значение ONDEMAND. Это означает, что заголовок PlayReady и расшифровка будут заданы по запросу, то есть, когда клиенту потребуется начать расшифровку сегмента. На этом этапе клиент получит доступ к другому заголовку PlayReady в заголовке сегмента, чтобы выяснить, что используетСЯ KID.

Примечание

DECRYPTORSETUP = ONDEMAND не означает, что содержимое обслуживается по запросу, это фактически противоположное.

<WRMHEADER version="4.2.0.0" xmlns="http://schemas.microsoft.com/DRM/2007/03/PlayReadyHeader">
  <DATA>
    <DECRYPTORSETUP>ONDEMAND</DECRYPTORSETUP>
  </DATA>
</WRMHEADER>

Существует несколько способов создания генератора заголовков PlayReady в упаковщике. В следующих разделах описано, как можно создать заголовок PlayReady.

Метод 1. Создание собственного кода на основе спецификации заголовка PlayReady

Спецификация объекта и заголовка PlayReady является общедоступной, поэтому можно написать код на устройстве или службе, создающей объект PlayReady и заголовок PlayReady, чтобы упаковать содержимое.

Генератор заголовков PlayReady должен иметь входные параметры, такие как:

  • Содержимое по запросу или динамическое линейное содержимое.
  • KID или список ИДЕНТИФИКАТОРов, которые используются для защиты всего ресурса.
  • Используемый тип шифрования (AESCTR или AESCBC).
  • Defaut LA URL — URL-адрес по умолчанию сервера лицензирования PlayReady, который будет выдавать лицензии, если он известен во время упаковки.
  • Идентификатор службы домена по умолчанию, если служба использует домены.

Теперь можно создать объект PlayReady и связанный с ним заголовок PlayReady. В следующем примере кода показано, как создать объект PlayReady, содержащий заголовок PlayReady, используемый для содержимого по запросу.

// This function gets values from the key management system and your specified encryption mode
// (and optionally the domainID), creates a PlayReady Header, adds the header to a 
// PlayReady Object, and stores them in a file in UTF-16 little endian format

void buildRMObject(string KeyID1, string KeyID2, string encryptMode, string domainID)
{
	// The string parameters include the following:
	// KeyID1, KeyID2 - The key identifiers - these values are returned from the key management system or
	//                                        the KeySeed mechanism
	// encryptMode - the encryption mode used to encrypt content, can be AESCTR or AESCBC
	// domainID - the optional domain service identifier (only used for domains)

	string xmlString = "<WRMHEADER xmlns=\"http://schemas.microsoft.com/DRM/2007/03/PlayReadyHeader\" version=\"4.3.0.0\"><DATA><PROTECTINFO><KIDS><KID ALGID=\"";
	xmlString.append(encryptMode);
	xmlString.append("\" VALUE=\"");
	xmlString.append(KeyID1);
	xmlString.append("\"></KID><KID ALGID=\"");
	xmlString.append(encryptMode);
	xmlString.append("\" VALUE=\"");
	xmlString.append(KeyID2);
	xmlString.append("\"></KID></KIDS></PROTECTINFO><LA_URL>http://rm.contoso.com/rightsmanager.asmx</LA_URL><DS_ID>");
	xmlString.append(domainID);
	xmlString.append("</DS_ID></DATA></WRMHEADER>");

	// Convert the PlayReady header to UFT-16 format
	wstring_convert<codecvt_utf8_utf16<wchar_t>> convert;
	wstring utf16XML = convert.from_bytes(xmlString);

	// Calculate the length of the PlayReady Header
	int32_t headerLength = (utf16XML.size() * sizeof(wchar_t));
	// Calculate the length of the PlayReady Object
	int32_t objectLength = headerLength + 10;
	// Set the number of PlayReady object records (in this case, 1)
	int16_t recordCount = 1;
	// Set the record type (in this case, a PlayReady Header)
	// If this was an embedded license store, this value would be 3
	int16_t recordType = 1;

	// Write the PlayReady Object and PlayReady Header to a file
	wofstream wofs("C:\\Temp\\PRObject.txt", ios::binary);
	wofs.imbue(locale(wofs.getloc(),
			  new codecvt_utf16<wchar_t, 0x10ffff, little_endian>));
	wofs.write(reinterpret_cast<const wchar_t *>(&objectLength), 2);
	wofs.write(reinterpret_cast<const wchar_t *>(&recordCount), 1);
	wofs.write(reinterpret_cast<const wchar_t *>(&recordType), 1);
	wofs.write(reinterpret_cast<const wchar_t *>(&headerLength), 1);
	wofs <<  utf16XML;
}

Метод 2. Использование API сервера PlayReady

Если вы являетесь лицензией пакета SDK для сервера PlayReady Server, пакет SDK сервера содержит класс PlayReadyHeader , который можно использовать для создания заголовка PlayReady. Он включает методы, которые можно использовать, и свойства, которые можно заполнить сведениями, необходимыми для заголовка PlayReady.

Класс PlayReadyHeader подробно описан в документации по PlayReady, которую вы получаете с лицензией пакета SDK для Сервера PlayReady. Пакет SDK для сервера PlayReady также включает пример упаковщика (AESPackaging), демонстрирующий создание заголовка PlayReady.

Как и в методе 1, вам потребуются идентификаторы keyID, созданные системой управления ключами, тип шифрования (AESCTR или AESCBC), URL-адрес сервера лицензирования PlayReady и, при необходимости, идентификатор службы домена.

Метод 3. Использование приложения Windows

Все, что вам нужно, прежде чем начать.

  1. У вас должны быть идентификаторы ключей, созданные системой управления ключами.
  2. Необходимо знать тип шифрования (AESCTR или AESCBC).
  3. Создайте заголовок PlayReady внутри объекта PlayReady с помощью класса PlayReadyContentHeader Windows 10.

Как и в предыдущих методах, вам потребуются идентификаторы KeyID, созданные системой управления ключами, тип шифрования (AESCTR или AESCBC), URL-адрес сервера лицензирования PlayReady и при необходимости идентификатор службы домена.