共用方式為


證書吊銷清單

[與此頁面相關聯的功能,DirectShow是舊版功能。 它已被 MediaPlayer、imfMediaEngine 取代,並在媒體基金會 音訊/視訊擷取。 這些功能已針對 Windows 10 和 Windows 11 進行優化。 Microsoft強烈建議新程式代碼盡可能在媒體 基礎中使用 MediaPlayerIMFMediaEngine 音訊/視訊擷取,而不是 DirectShow。 Microsoft建議使用舊版 API 的現有程式代碼,盡可能改寫成使用新的 API。]

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

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

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

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

注意

若要使用 IWMDRMReader 介面,您必須從 Microsoft取得靜態 DRM 連結庫,並將您的應用程式連結至此連結庫檔案。 如需詳細資訊,請參閱 Windows 媒體格式 SDK 檔中的<取得必要的 DRM 連結庫>主題。

 

如果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 簽章

 

注意

所有整數值都是不帶正負號,並以 big-endian(網路位元組順序)表示法表示。

 

CRL 區段描述

標頭

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

撤銷專案

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

憑證

憑證區段包含一個 32 位值,指出 XML 憑證及其憑證鏈結的長度(以位元組為單位),以及包含證書頒發機構單位 (CA) 之 XML 憑證的位元組陣列,以及Microsoft為 Root 的憑證鏈結。 憑證必須由具有發出CRL授權的CA簽署。

注意

憑證不得以 Null 終止。

 

簽章

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

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

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