Condividi tramite


Valore di inizializzazione chiave PlayReady

I servizi che implementano PlayReady devono mantenere un sistema di gestione delle chiavi (Servizio di gestione delle chiavi) per archiviare e gestire le chiavi di contenuto. In particolare, i valori di {KID, Content Key} vengono archiviati per ogni asset di contenuto gestito dal servizio. Questi valori vengono archiviati in fase di crittografia e recuperati in fase di rilascio delle licenze.

PlayReady offre un modo pratico per evitare un Servizio di gestione delle chiavi complesso. L'algoritmo Content Key Seed consente la derivazione di chiavi di contenuto diverse per una raccolta di asset di contenuto, da un kid variabile e da un valore di inizializzazione delle chiavi fisso:

Ck(KID) = f(KID, KeySeed)

Di seguito è riportato l'algoritmo 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;
}