起始 COPP 會話
[與此頁面相關的功能 DirectShow是舊版功能。 它已被 MediaPlayer、 IMFMediaEngine和 Media Foundation 中的音訊/視訊擷取取代。 這些功能已針對Windows 10和Windows 11進行優化。 Microsoft 強烈建議新程式碼盡可能使用 MediaPlayer、 IMFMediaEngine 和 音訊/視訊擷取 ,而不是 DirectShow。 Microsoft 建議使用舊版 API 的現有程式碼盡可能重寫為使用新的 API。
若要起始認證輸出保護通訊協定 (COPP) 會話,您必須準備 簽章,這是包含下列數位串連的陣列:
- 驅動程式傳回的 128 位亂數。 (取得驅動程式的憑證鏈結中,此值會顯示為guidRandom。)
- 128 位對稱 AES 金鑰。
- 狀態要求的 32 位起始序號。
- COPP 命令的 32 位起始序號。
產生對稱 AES 金鑰,如下所示:
DWORD dwFlag = 0x80; // Bit length: 128-bit AES.
dwFlag <<= 16; // Move this value to the upper 16 bits.
dwFlag |= CRYPT_EXPORTABLE; // We want to export the key.
CryptGenKey(
hCSP, // Handle to the CSP.
CALG_AES_128, // Use 128-bit AES block encryption algorithm.
dwFlag,
&m_hAESKey // Receives a handle to the AES key.
);
CryptGenKey函式會建立對稱金鑰,但金鑰仍保留在 CSP 中。 若要將金鑰匯出至位元組陣列,請使用 CryptExportKey 函式。 這是呼叫 CryptGenKey時使用 CRYPT_EXPORTABLE 旗標的原因。 下列程式碼會匯出金鑰,並將其複製到
pData
陣列。
DWORD cbData = 0;
BYTE *pData = NULL;
// Get the size of the blob.
CryptExportKey(hAESKey, 0, PLAINTEXTKEYBLOB, 0, NULL, &cbData);
// Allocate the array and call again.
pData = new BYTE[cbData];
CryptExportKey(hAESKey, 0, PLAINTEXTKEYBLOB, 0, pData, &cbData);
中傳回的資料
pData
具有下列配置:
BLOBHEADER header
DWORD cbSize
BYTE key[]
不過,密碼編譯API 標頭中未定義符合此配置的結構。 您可以定義一個或執行一些指標算術。 例如,若要驗證金鑰的大小:
DWORD *pcbKey = (DWORD*)(pData + sizeof(BLOBHEADER));
if (*pcbKey != 16)
{
// Wrong size! Should be 16 bytes (128 bits).
}
若要取得索引鍵本身的指標:
BYTE *pKey = pData + sizeof(BLOBHEADER) + sizeof(DWORD);
接下來,產生 32 位的亂數,以作為 COPP 狀態要求的開始序列。 建立亂數的建議方法是呼叫 CryptGenRandom 函式。 請勿在 C 執行時間程式庫中使用 rand 函式,因為它不是真正隨機的。 產生第二個 32 位亂數,以作為 COPP 命令的開始序列。
UINT uStatusSeq; // Status sequence number.
UINT uCommandSeq; // Command sequence number.
CryptGenRandom(hCSP, sizeof(UINT), &uStatusSeq);
CryptGenRandom(hCSP, sizeof(UINT), &uCommandSeq);
現在您可以準備 COPP 簽章。 這是 256 位元組陣列,定義為 AMCOPPSignature 結構。 將陣列的內容初始化為零。 然後,將四個數字複製到陣列,也就是驅動程式的亂數、AES 索引鍵、狀態序號,以及該順序的命令序號。 最後,交換整個陣列的位元組順序。
根據 CryptEncrypt的檔:
- 「使用 RSA 金鑰呼叫 **CryptEncrypt** 加密的純文字資料長度是金鑰模數減十一個位元組的長度。 第十一個位元組是 PKCS \#1 填補選擇的最小值。」
在此情況下,模數為 256 個位元組,因此訊息長度上限為 245 個位元組, (256 – 11) 。 AMCOPPSignature結構是 256 個位元組,但簽章中有意義的資料只有 40 個位元組。 下列程式碼會加密簽章,並提供結果
CoppSig
.
AMCOPPSignature CoppSig;
ZeroMemory(&CoppSig, sizeof(CoppSig));
// Copy the signature data into CoppSig. (Not shown.)
// Encrypt the signature:
const DWORD RSA_PADDING = 11; // 11-byte padding.
DWORD cbDataOut = sizeof(AMCOPPSignature);
DWORD cbDataIn = cbDataOut - RSA_PADDING;
CryptEncrypt(
hRSAKey,
NULL, // No hash object.
TRUE, // Final block to encrypt.
0, // Reserved.
&CoppSig, // COPP signature.
&cbDataOut,
cbDataIn
);
現在,將加密的陣列傳遞至 IAMCertifiedOutputProtection::SessionSequenceStart:
hr = pCOPP->SessionSequenceStart(&CoppSig);
if (SUCCEEDED(hr))
{
// Ready to send COPP commands and status requests.
}
如果此方法成功,您就可以將 COPP 命令和狀態要求傳送給驅動程式。
相關主題