Valeur initiale de la clé PlayReady
Les services qui implémentent PlayReady doivent gérer un système de gestion des clés (KMS) pour stocker et gérer les clés de contenu. Plus précisément, les valeurs de {KID, Clé de contenu} sont stockées pour chaque ressource de contenu gérée par le service. Ces valeurs sont stockées au moment du chiffrement et récupérées au moment de l’émission de licence.
PlayReady offre un moyen pratique d’éviter un KMS complexe. L’algorithme d’amorçage de clé de contenu permet la dérivation de différentes clés de contenu pour une collection de ressources de contenu, à partir d’un kid variable et d’une valeur initiale de clé fixe :
Ck(KID) = f(KID, KeySeed)
Voici l’algorithme standard PlayReady :
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;
}