封裝程式必須在加密的內容中包含 PlayReady 標頭。
如需 PlayReady 標頭和 PlayReady 物件的詳細說明,請參閱 PlayReady 標頭規格。
PlayReady 標頭包含正在播放的內容相關信息,包括識別用來加密數據之密鑰的金鑰標識碼 (KID),以及 PlayReady 授權伺服器的預設授權取得 URL,以及您想要包含的任何自定義數據。 用來加密內容的金鑰和 KID 必須與 PlayReady 授權伺服器共用,該伺服器將發行該特定內容的授權,通常是透過金鑰管理系統(KMS)。
備註
Microsoft不提供具有 PlayReady 的金鑰管理系統。
下列 XML 程式代碼提供一個 PlayReady 標頭的範例,此標頭通常會插入隨選內容的區段 MP4 檔案的標頭區。 它包含用戶端解密內容所需的 KID 清單(內容加密金鑰的識別碼)。 這是向隨選檔案或數據流發出這些 KID 訊號的最常見方式。
<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 程式代碼提供 Live Linear 內容的 PlayReady 標頭範例。 它不包含任何 KID,因為內容加密密鑰(及其相關聯的 KID)偶爾會變更(例如,非常頻繁,或在程式界限,或每小時,或每天)。 用於內容數據流的 KID 會在區段標頭中發出訊號,而且不需要在數據流最上層 PlayReady 標頭中包含其中任何一個。 DECRYPTORSETUP 屬性會設定為 ONDEMAND,這表示 PlayReady 標頭和解密器會視需要設定,這表示客戶端實際上需要開始解密區段 ,此時用戶端將可以存取區段標頭中的另一個 PlayReady Header,以找出涉及哪些 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 Header 的設備或服務中撰寫程式代碼可以封裝內容,而且相當簡單。
PlayReady 標頭產生器必須具有輸入參數,例如:
- 隨選內容或即時線性內容。
- KID 或用來保護整個資產的 KID 清單。
- 使用的加密類型(AESCTR 或 AESCBC)。
- Default LA URL — 如果在封裝時已知,將由 PlayReady 授權伺服器發出授權的預設 URL。
- 如果服務使用網域,則為預設網域服務標識符。
您現在可以建立 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 - 使用 PlayReady 伺服器 API
如果您是 PlayReady Server SDK 授權者,伺服器 SDK 會包含 PlayReadyHeader 類別,可用來建構 PlayReady Header。 其中包含您可以使用的方法,以及您可以填入 PlayReady 標頭所需資訊的屬性。
PlayReadyHeader 類別會在您使用 PlayReady Server SDK 授權收到的 PlayReady 檔中詳細說明。 PlayReady Server SDK 也包含範例封裝程式 (AESPackaging),示範如何建立 PlayReady 標頭。
如同方法 1,您將需要密鑰管理系統所產生的 KeyID、加密類型 (AESCTR 或 AESCBC)、PlayReady 授權伺服器的 URL,以及選擇性的網域服務標識符。
方法 3 - 使用 Windows 應用程式
開始之前所需的事項。
- 您必須擁有金鑰管理系統所產生的 KeyID。。
- 您必須知道加密類型 (AESCTR 或 AESCBC)。
- 使用 Windows 10 PlayReadyContentHeader 類別,在 PlayReady 物件內建立 PlayReady 標頭。
如同先前的方法,您需要密鑰管理系統所產生的 KeyID、加密類型 (AESCTR 或 AESCBC)、PlayReady 授權伺服器的 URL,以及選擇性的網域服務標識符。