PlayReady Key Seed
Dienste, die PlayReady implementieren, müssen ein Key Management System (KMS) beibehalten, um Inhaltsschlüssel zu speichern und zu verwalten. Insbesondere werden die Werte von {KID, Content Key} für jede Inhaltsressource gespeichert, die vom Dienst verwaltet wird. Diese Werte werden zur Verschlüsselungszeit gespeichert und zur Lizenzausstellungszeit abgerufen.
PlayReady bietet eine bequeme Möglichkeit, eine komplexe KMS zu vermeiden. Der Content Key Seed-Algorithmus ermöglicht die Ableitung verschiedener Inhaltsschlüssel für eine Sammlung von Inhaltsressourcen, von einer unterschiedlichen KID und einem fixed Key Seed:
Ck(KID) = f(KID, KeySeed)
Nachfolgend sehen Sie den PlayReady-Standardalgorithmus:
byte[] GeneratePlayReadyContentKey(byte[] keySeed, Guid keyId)
{
const int DRM_AES_KEYSIZE_128 = 16;
byte[] contentKey = new byte[DRM_AES_KEYSIZE_128];
//
// Truncate the key seed to 30 bytes, key seed must be at least 30 bytes long.
//
byte[] truncatedKeySeed = new byte[30];
Array.Copy(keySeed, truncatedKeySeed, truncatedKeySeed.Length);
//
// Get the keyId as a byte array
//
byte[] keyIdAsBytes = keyId.ToByteArray();
//
// Create sha_A_Output buffer. It is the SHA of the truncatedKeySeed and the keyIdAsBytes
//
SHA256Managed sha_A = new SHA256Managed();
sha_A.TransformBlock(truncatedKeySeed, 0, truncatedKeySeed.Length, truncatedKeySeed, 0);
sha_A.TransformFinalBlock(keyIdAsBytes, 0, keyIdAsBytes.Length);
byte[] sha_A_Output = sha_A.Hash;
//
// Create sha_B_Output buffer. It is the SHA of the truncatedKeySeed, the keyIdAsBytes, and
// the truncatedKeySeed again.
//
SHA256Managed sha_B = new SHA256Managed();
sha_B.TransformBlock(truncatedKeySeed, 0, truncatedKeySeed.Length, truncatedKeySeed, 0);
sha_B.TransformBlock(keyIdAsBytes, 0, keyIdAsBytes.Length, keyIdAsBytes, 0);
sha_B.TransformFinalBlock(truncatedKeySeed, 0, truncatedKeySeed.Length);
byte[] sha_B_Output = sha_B.Hash;
//
// Create sha_C_Output buffer. It is the SHA of the truncatedKeySeed, the keyIdAsBytes,
// the truncatedKeySeed again, and the keyIdAsBytes again.
//
SHA256Managed sha_C = new SHA256Managed();
sha_C.TransformBlock(truncatedKeySeed, 0, truncatedKeySeed.Length, truncatedKeySeed, 0);
sha_C.TransformBlock(keyIdAsBytes, 0, keyIdAsBytes.Length, keyIdAsBytes, 0);
sha_C.TransformBlock(truncatedKeySeed, 0, truncatedKeySeed.Length, truncatedKeySeed, 0);
sha_C.TransformFinalBlock(keyIdAsBytes, 0, keyIdAsBytes.Length);
byte[] sha_C_Output = sha_C.Hash;
for (int i = 0; i < DRM_AES_KEYSIZE_128; i++)
{
contentKey[i] = Convert.ToByte(sha_A_Output[i] ^ sha_A_Output[i + DRM_AES_KEYSIZE_128]
^ sha_B_Output[i] ^ sha_B_Output[i + DRM_AES_KEYSIZE_128]
^ sha_C_Output[i] ^ sha_C_Output[i + DRM_AES_KEYSIZE_128]);
}
return contentKey;
}