共用方式為


起始 COPP 會話

[與此頁面相關的功能 DirectShow是舊版功能。 它已被 MediaPlayerIMFMediaEngineMedia Foundation 中的音訊/視訊擷取取代。 這些功能已針對Windows 10和Windows 11進行優化。 Microsoft 強烈建議新程式碼盡可能使用 MediaPlayerIMFMediaEngine音訊/視訊擷取 ,而不是 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 命令和狀態要求傳送給驅動程式。

使用認證輸出保護通訊協定 (COPP)