다음을 통해 공유


PlayReady 키 시드

PlayReady를 구현하는 서비스는 콘텐츠 키를 저장하고 관리하기 위해 키 관리 시스템(KMS)을 유지해야 합니다. 특히 {KID, Content Key}의 값은 서비스에서 관리하는 각 콘텐츠 자산에 대해 저장됩니다. 이러한 값은 암호화 시간에 저장되고 라이선스 발급 시 검색됩니다.

PlayReady는 복잡한 KMS 방지하는 편리한 방법을 제공합니다. 콘텐츠 키 시드 알고리즘을 사용하면 다양한 KID 및 고정 키 시드에서 콘텐츠 자산 컬렉션에 대해 다양한 콘텐츠 키를 파생할 수 있습니다.

Ck(KID) = f(KID, KeySeed)

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;
}