共用方式為


憑證撤銷清單

[與此頁面相關的功能 DirectShow是舊版功能。 它已被 MediaPlayerIMFMediaEngineMedia Foundation 中的音訊/視訊擷取取代。 這些功能已針對Windows 10和Windows 11進行優化。 Microsoft 強烈建議新程式碼盡可能使用 MediaPlayerIMFMediaEngine音訊/視訊擷取 ,而不是 DirectShow。 Microsoft 建議使用舊版 API 的現有程式碼盡可能重寫為使用新的 API。

本主題描述如何使用認證輸出保護通訊協定 (COPP) 時,檢查 CRL (CRL) 撤銷的驅動程式清單。

CRL 包含已撤銷憑證的摘要,而且只能由 Microsoft 提供及簽署。 CRL 是透過數位版權管理散發, (DRM) 授權。 CRL 可以撤銷驅動程式憑證鏈結中的任何憑證。 如果鏈結中的任何憑證遭到撤銷,該憑證及其在鏈結中的所有憑證也會遭到撤銷。

若要取得 CRL,應用程式必須使用 Windows 媒體格式 SDK 版本 9 或更新版本,然後執行下列步驟:

  1. 呼叫 WMCreateReader 以建立 Windows 媒體格式 SDK 讀取器物件。
  2. 查詢 IWMDRMReader 介面的讀取器物件。
  3. 使用 g_wszWMDRMNet_Revocation 值呼叫 IWMDRMReader::GetDRMProperty 以取得 CRL。 您必須呼叫這個方法兩次:一次可取得要配置的緩衝區大小,一次以填滿緩衝區。 第二個呼叫會傳回包含 CRL 的字串。 整個字串是以 base-64 編碼。
  4. 解碼 base-64 編碼字串。 您可以使用 CryptStringToBinary 函式來執行此動作。 此函式是 CryptoAPI 的一部分。

注意

若要使用 IWMDRMReader 介面,您必須從 Microsoft 取得靜態 DRM 程式庫,並將您的應用程式連結至此程式庫檔案。 For more information, see the topic "Obtaining the Required DRM Library" in the Windows Media Format SDK documentation.

 

如果 CRL 不存在於使用者的電腦上, GetDRMProperty 方法會傳回NS_E_DRM_UNSUPPORTED_PROPERTY。 目前,取得 CRL 的唯一方法是取得 DRM 授權。

下列程式碼顯示傳回 CRL 的函式:

////////////////////////////////////////////////////////////////////////
//  Name: GetCRL
//  Description: Gets the certificate revocation list (CRL).
//
//  ppBuffer: Receives a pointer to the buffer that contains the CRL.
//  pcbBuffer: Receives the size of the buffer returned in ppBuffer.
//
//  The caller must free the returned buffer by calling CoTaskMemFree.
////////////////////////////////////////////////////////////////////////
HRESULT GetCRL(BYTE **ppBuffer, DWORD *pcbBuffer)
{
    IWMReader *pReader = NULL;
    IWMDRMReader *pDrmReader = NULL;
    HRESULT hr = S_OK;

    // DRM attribute data.
    WORD cbAttributeLength = 0;
    BYTE *pDataBase64 = NULL;
    WMT_ATTR_DATATYPE type;

    // Buffer for base-64 decoded CRL.
    BYTE *pCRL = NULL;
    DWORD cbCRL = 0;

    // Create the WMReader object.
    hr = WMCreateReader(NULL, 0, &pReader);

    // Query for the IWMDRMReader interface.
    if (SUCCEEDED(hr))
    {
        hr = pReader->QueryInterface(
            IID_IWMDRMReader, (void**)&pDrmReader);
    }

    // Call GetDRMProperty once to find the size of the buffer.
    if (SUCCEEDED(hr))
    {
        hr = pDrmReader->GetDRMProperty(
            g_wszWMDRMNET_Revocation,
            &type,
            NULL,
            &cbAttributeLength
            );
    }

    // Allocate a buffer.
    if (SUCCEEDED(hr))
    {
        pDataBase64 = (BYTE*)CoTaskMemAlloc(cbAttributeLength);
        if (pDataBase64 == NULL)
        {
            hr = E_OUTOFMEMORY;
        }
    }

    // Call GetDRMProperty again to get the property.
    if (SUCCEEDED(hr))
    {
        hr = pDrmReader->GetDRMProperty(
            g_wszWMDRMNET_Revocation,
            &type,
            pDataBase64,
            &cbAttributeLength
            );
    }

    // Find the size of the buffer for the base-64 decoding.
    if (SUCCEEDED(hr))
    {
        BOOL bResult = CryptStringToBinary(
            (WCHAR*)pDataBase64,    // Base-64 encoded string.
            0,                      // Null-terminated.
            CRYPT_STRING_BASE64,    
            NULL,                   // Buffer (NULL).
            &cbCRL,                 // Receives the size of the buffer. 
            NULL, NULL              // Optional.
            );
        if (!bResult)
        {
            hr = __HRESULT_FROM_WIN32(GetLastError());
        }
    }

    // Allocate a buffer for the CRL.
    if (SUCCEEDED(hr))
    {
        pCRL = (BYTE*)CoTaskMemAlloc(cbCRL);
        if (pCRL == NULL)
        {
            hr = E_OUTOFMEMORY;
        }
    }

    // Base-64 decode to get the CRL.
    if (SUCCEEDED(hr))
    {
        BOOL bResult = CryptStringToBinary(
            (WCHAR*)pDataBase64,    // Base-64 encoded string.
            0,                      // Null-terminated.
            CRYPT_STRING_BASE64,    
            pCRL,                   // Buffer.
            &cbCRL,                 // Receives the size of the buffer. 
            NULL, NULL              // Optional.
            );
        if (!bResult)
        {
            hr = __HRESULT_FROM_WIN32(GetLastError());
        }
    }

    // Return the buffer to the caller. Caller must free the buffer.
    if (SUCCEEDED(hr))
    {
        *ppBuffer = pCRL;
        *pcbBuffer = cbCRL;
    }
    else
    {
        CoTaskMemFree(pCRL);
    }

    CoTaskMemFree(pDataBase64);
    SAFE_RELEASE(pReader);
    SAFE_RELEASE(pDrmReader);
    return hr;
}

接下來,應用程式必須確認 CRL 是否有效。 若要這樣做,請確認 CRL 憑證是 CRL 的一部分,是由 Microsoft 根憑證直接簽署,且 SignCRL 元素值設定為 1。 此外,請確認 CRL 的簽章。

驗證 CRL 之後,應用程式就可以儲存它。 儲存之前,也應該先檢查 CRL 版本號碼,讓應用程式一律儲存最新版本。

CRL 具有下列格式。

區段 目錄
標頭 32 位 CRL 版本32 位的專案數
撤銷專案 多個 160 位撤銷專案
憑證 32 位憑證長度Variable-length 憑證
簽名 8 位簽章類型16 位簽章長度Variable-length 簽章

 

注意

所有整數值都是不帶正負號,並以大端 (網路位元組順序標記法) 標記法。

 

CRL 區段描述

標頭包含 CRL 的版本號碼和 CRL 中的撤銷專案數目。 CRL 可以包含零個或多個專案。

撤銷專案

每個撤銷專案都是撤銷憑證的 160 位摘要。 將此摘要與憑證內的 DigestValue 元素進行比較。

證書

憑證區段包含 32 位值,指出 XML 憑證及其憑證鏈結的位元組) 長度 (,以及包含憑證授權單位單位 (CA (CA) 的 XML 憑證以及具有 Microsoft 作為根目錄的憑證鏈結的位元組陣列。 憑證必須由具有發出 CRL 授權的 CA 簽署。

注意

憑證不得為 Null 終止。

 

簽名

簽章區段包含簽章類型和長度,以及數位簽章本身。 8 位類型設定為 2,表示它使用 SHA-1 搭配 1024 位 RSA 加密。 長度是 16 位值,其中包含以位元組為單位的數位簽章長度。 數位簽章會計算在 CRL 的所有先前區段上。

簽章是使用 PKCS #1 (2.1 版) 中定義的 RSAUTH-PSS 數位簽章配置來計算。 雜湊函式是 SHA-1,定義于聯邦資訊處理標準 (FIPS) 180-2,而遮罩產生函式則是 MGF1,其定義于 PKCS #1 (2.1 版) 一節中。 RSASP1 和 RSAVP1 作業使用 RSA 搭配 1024 位模數,且驗證指數為 65537。

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