共用方式為


NCryptVerifyClaim 函式 (ncrypt.h)

驗證金鑰證明宣告。

語法

SECURITY_STATUS NCryptVerifyClaim(
  [in]           NCRYPT_KEY_HANDLE hSubjectKey,
  [in, optional] NCRYPT_KEY_HANDLE hAuthorityKey,
  [in]           DWORD             dwClaimType,
  [in, optional] NCryptBufferDesc  *pParameterList,
  [in]           PBYTE             pbClaimBlob,
  [in]           DWORD             cbClaimBlob,
  [out]          NCryptBufferDesc  *pOutput,
  [in]           DWORD             dwFlags
);

參數

[in] hSubjectKey

宣告的主旨索引鍵句柄。

[in, optional] hAuthorityKey

驗證宣告時要使用的授權單位金鑰句柄。 此參數是選擇性的,因為特定宣告類型的授權單位金鑰是獨立的。

[in] dwClaimType

宣告的類型。

[in, optional] pParameterList

選擇性參數清單。

[in] pbClaimBlob

輸入宣告 Blob。

[in] cbClaimBlob

pbClaimBlob 緩衝區的大小,以位元組為單位。

[out] pOutput

輸出 Blob。

[in] dwFlags

NCRYPT_VBS_RETURN_CLAIM_DETAILS_FLAG 是在驗證 VBS 產生的宣告期間設定的新旗標。 如需詳細資訊,請參閱 備註一節 一節。

目前沒有定義其他旗標。 dwFlags 參數應該設定為所有其他驗證類型的 0

傳回值

傳回狀態代碼,指出函式的成功或失敗。

以下是驗證 VBS 金鑰保護證明宣告時,可能會從驗證 API 傳回的一些錯誤碼:

傳回碼 意義
NTE_BAD_TYPE 宣告類型輸入參數與輸入宣告 Blob 的類型不同。
STATUS_BAD_DATA 輸入宣告 Blob 無效。
STATUS_NO_MEMORY 記憶體(宣告驗證所需的)配置失敗。
STATUS_INVALID_PARAMETER 缺少強制輸入參數或其中一個參數具有不合法的值。
STATUS_FAIL_CHECK 輸入 Blob 宣告的檢查失敗。
NTE_BAD_VER 宣告 Blob 版本不符合驗證實作。
NTE_BAD_FLAGS 不支援 dwFlags 中提供的旗標。

言論

使用虛擬化型安全性保護/證明私鑰 (VBS)

注意

VBS 旗標的相關信息與發行前版本產品有關,在發行發行前可能會大幅修改。 Microsoft未就此處提供的資訊提供任何明示或默示擔保。

此 API 可協助根據 VBS 金鑰保護啟用安全性金鑰的進階證明,這是使用 VBS 保護及證明私鑰的 Windows 模組。 安全性密鑰的證明會證明此金鑰與錨定密鑰的關聯,也就是證明金鑰。 這項功能可藉由限制使用內容密鑰,來增強不同實體之間的通訊安全性層級。

API 會定義新的旗標,以支持根據 VBS 金鑰保護中的證明密鑰建立和驗證證明宣告。

以下是針對 API 定義的 dwClaimType 類型

宣告類型 描述
NCRYPT_CLAIM_VBS_ROOT 此類型表示產生的宣告是由 VBS 根金鑰所產生。
NCRYPT_CLAIM_VBS_IDENTITY 此類型表示產生的宣告是由 VBS身分識別/證明所產生。 這表示宣告是由使用證明旗標提升的 VBS 金鑰所產生 NCRYPT_ALLOW_KEY_ATTESTATION_FLAG(請參閱下方的詳細數據)。

以下是在驗證證明宣告時,pParameterList 緩衝區中設定的緩衝區類型:

  • NCRYPT_VBS_ROOT_KEY_ATTESTATION_CLAIM_DETAILS

    NCryptBuff NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_ROOT_DETAILS erDesc nCryptVerifyClaim NCryptVerifyClaim 中,dwClaimType 設定為 NCRYPT_CLAIM_VBS_ROOT的新 結構。 結構定義為:

    typedef struct _NCRYPT_VBS_ROOT_KEY_ATTESTATION_CLAIM_DETAILS
    {
        ULONG ulKeyFlags;
        ULONGLONG ullTrustletId;
        ULONG ulTrustletSecurityVersion;
        ULONG ulTrustletDebuggable;
    } NCRYPT_VBS_ROOT_KEY_ATTESTATION_CLAIM_DETAILS, *PNCRYPT_VBS_ROOT_KEY_ATTESTATION_CLAIM_DETAILS;
    

    結構包含下列專案:

    • ulKeyFlags – 識別金鑰所設定 NCRYPT_VBS_KEY_FLAG_* 值的組合。
    • ullTrustletId – 建立宣告之 VBS Trustlet 原則元數據中的硬式編碼標識符整數。
    • ulTrustletSecurityVersion – 建立宣告之 VBS Trustlet 的安全性版本號碼。 此版本反映哪些安全性更新已套用至 trustlet,因此表示其安全性層級。
    • ulTrustletDebuggable – 指出建立宣告的 VBS Trustlet 是否可偵錯。 1 值表示 trustlet 可偵錯,且 0 表示無法偵錯的 trustlet

    如果未來需要進一步的信息專案,則會定義新的結構和對應的結構類型。

    注意

    這個輸出參數必須在不再參考之後釋放。

  • NCRYPT_VBS_IDENTITY_KEY_ATTESTATION_CLAIM_DETAILS

    要設定為 NCryptBuffer 的新結構, NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_IDENTITY_DETAILS 類型為 NCryptBufferDesc nCryptVerifyClaim dwClaimType 設為 NCRYPT_CLAIM_VBS_IDENTITY的輸出 參數。 結構定義為:

    typedef struct _NCRYPT_VBS_IDENTITY_KEY_ATTESTATION_CLAIM_DETAILS
    {
        ULONG ulKeyFlags;
        LPCWSTR pszSignatureHashAlg;
        ULONG ulPaddingScheme;
        LPCWSTR pszPaddingHashAlg;
        ULONG ulPaddingSalt;
    } NCRYPT_VBS_IDENTITY_KEY_ATTESTATION_CLAIM_DETAILS, *PNCRYPT_VBS_IDENTITY_KEY_ATTESTATION_CLAIM_DETAILS;
    

    結構包含下列專案:

    • ulKeyFlags – 識別金鑰所設定 NCRYPT_VBS_KEY_FLAG_* 值的組合。
    • pszSignatureHashAlg - 宣告簽章哈希演算法 Unicode 字串的指標。
    • ulPaddingScheme - 透過在 BCryptSignHash 中建立宣告所使用之簽署演算法的填補配置。
    • pszPaddingHashAlg - 透過在 BCryptSignHash中建立宣告所使用之宣告填補哈希演算法的 Unicode 字串指標。
    • ulPaddingSalt - 透過在 BCryptSignHash 中建立宣告所使用之簽署演算法的填補鹽。

    如果未來需要進一步的信息專案,則會定義新的結構和對應的結構類型。

    注意

    這個輸出參數必須在不再參考之後釋放。 發行此參數的範例程式代碼會在下列程式碼範例中提供

  • NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_ROOT_DETAILS

    NCryptBuffer 參數中設定的新緩衝區類型,NCryptBufferDesc*pOutput 參數 NCryptVerifyClaim。 這個類型表示 NCryptBuffer 包含資料結構 NCRYPT_VBS_ROOT_KEY_ATTESTATION_CLAIM_DETAILS

  • NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_IDENTITY_DETAILS

    NCryptBuffer 參數中設定的新緩衝區類型,NCryptBufferDesc*pOutput 參數 NCryptVerifyClaim。 這個類型表示 NCryptBuffer 包含資料結構 NCRYPT_VBS_IDENTITY_KEY_ATTESTATION_CLAIM_DETAILS

  • NCRYPT_VBS_RETURN_CLAIM_DETAILS_FLAG

    這是在驗證 VBS 產生的宣告期間,dwFlags 輸入參數中設定的新旗標。 設定此旗標 NCryptVerifyClaim 會產生具有內部 NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_ROOT_DETAILSNCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_IDENTITY_DETAILS 參數緩衝區類型的 NCryptBufferDesc 輸出參數。

    下表描述輸入和輸出資料結構類型在成功案例中具有 NCRYPT_VBS_RETURN_CLAIM_DETAILS_FLAG的關聯性:

    輸入 輸出
    dwClaimType = NCRYPT_CLAIM_VBS_ROOT 具有內部 NCRYPT_VBS_ROOT_KEY_ATTESTATION_CLAIM_DETAILS 信息結構的 NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_ROOT_DETAILS 緩衝區類型。
    dwClaimType = NCRYPT_CLAIM_VBS_IDENTITY 具有內部 NCRYPT_VBS_IDENTITY_KEY_ATTESTATION_CLAIM_DETAILS 信息結構的 NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_IDENTITY_DETAILS 緩衝區類型。

例子

此範例說明現有 API 的使用方式,以驗證與 NCryptCreateClaim一起產生的證明宣告。

驗證 API 可以在本機叫用(在產生宣告 Blob 的電腦上)或遠端叫用。 驗證程式需要這些元素,對應至宣告產生金鑰:

  • 宣告 Blob
  • 公用證明金鑰 Blob
  • 公用令牌 (一般用途) 金鑰 Blob

如果已設定輸入 NCRYPT_VBS_RETURN_CLAIM_DETAILS_FLAG 旗標,驗證 API 會產生其中一個輸出信息結構,NCRYPT_VBS_ROOT_KEY_ATTESTATION_CLAIM_DETAILSNCRYPT_VBS_IDENTITY_KEY_ATTESTATION_CLAIM_DETAILS。 這些結構的記憶體會在程式碼流程結尾釋放,以避免記憶體流失。

HRESULT VerifyClaim(
       BCRYPT_RSAKEY_BLOB *pAttestPublicKeyBlob,
       BCRYPT_RSAKEY_BLOB *pTokenPublicKeyBlob,
       PBYTE pRootClaim,
       DWORD rootClaimSize,
       PBYTE pIdentityClaim,
       DWORD identityClaimSize)
{

    HRESULT hr = S_OK;
    DWORD bytesWritten = 0;

    NCRYPT_PROV_HANDLE provider = NULL;

    if (FAILED(hr = NCryptOpenStorageProvider(&provider, MS_KEY_STORAGE_PROVIDER, 0)))
    {
        wprintf(L"Error opening storage provider in NCryptOpenStorageProvider: 0x%X\n", hr);
        goto cleanup;
    }

    NCRYPT_KEY_HANDLE attestPublicKey = NULL;

    if (FAILED(hr = NCryptImportKey(
                       provider,
                       NULL,
                       BCRYPT_RSAPUBLIC_BLOB,
                       NULL,
                       &attestPublicKey,
                       (PBYTE)pAttestPublicKeyBlob,
                       GetRsaPublicKeyBlobSize(pAttestPublicKeyBlob),
                       0)))
    {
        wprintf(L"Unable to create a key handle for attestation public key blob with NCryptImportKey(): 0x%X\n", hr);
        goto cleanup;
    }

    NCRYPT_KEY_HANDLE tokenPublicKey = NULL;

    if (FAILED(hr = NCryptImportKey(
                       provider,
                       NULL,
                       BCRYPT_RSAPUBLIC_BLOB,
                       NULL,
                       &tokenPublicKey,
                       (PBYTE)pTokenPublicKeyBlob,
                       GetRsaPublicKeyBlobSize(pTokenPublicKeyBlob),
                       0)))
    {
        wprintf(L"Unable to create a key handle for token public key blob with NCryptImportKey(): 0x%X\n", hr);
        goto cleanup;
    }

    NCryptBufferDesc rootOutput{};

    // Verify the VBS root claim using the attestation/identity public key
    if (FAILED(hr = NCryptVerifyClaim(
                       attestPublicKey,
                       NULL,
                       NCRYPT_CLAIM_VBS_ROOT, // Created claim by IDKS (VBS root signing key)
                       NULL, // parameters
                       pRootClaim,
                       rootClaimSize,
                       &rootOutput,
                       NCRYPT_VBS_RETURN_CLAIM_DETAILS_FLAG /*dwFlags*/)))
    {
        switch (hr)
        {
            case STATUS_OBJECT_TYPE_MISMATCH:
                wprintf(L"The dwClaimType parameter’s value is different than the claim’s type.\n-----\n", hr);
                break;
            case STATUS_BAD_DATA:
                wprintf(L"Something wrong in one of the data structures. E.g. Magic value mismatch\n-----\n", hr);
                break;
            case STATUS_NO_MEMORY:
                wprintf(L"Memory allocation failed\n-----\n", hr);
                break;
            case STATUS_INVALID_PARAMETER:
                wprintf(L"Missing mandatory parameter or one of the parameters has a bad value.\n-----\n", hr);
                break;
            case STATUS_FAIL_CHECK:
                wprintf(L"One of the claim checks has failed.\n-----\n", hr);
                break;
            default:
                wprintf(L"Unable to verify VBS root claim from NCryptVerifyClaim(): 0x%X\n-----\n", hr);
        }
        goto cleanup;
    }

    PNCryptBuffer pRootOutBuffer;
    DWORD count;

    // Look into the retrieved VBS root claim details
    for (count = 0; count < rootOutput.cBuffers; ++count)
    {
        pRootOutBuffer = rootOutput.pBuffers[count];
        if (pRootOutBuffer->BufferType == NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_ROOT_DETAILS)
        {
            PNCRYPT_VBS_ROOT_KEY_ATTESTATION_CLAIM_DETAILS pDetails =
            (PNCRYPT_VBS_ROOT_KEY_ATTESTATION_CLAIM_DETAILS) pRootOutBuffer->pvBuffer;
            wprintf(L"The claim trustlet id is: %lu\n-----\n", pDetails->ullTrustletId);
            wprintf(L"The claim trustlet Security Version number is: %llu\n-----\n", pDetails->ulTrustletSecurityVersion);
        }
    }

    NCryptBufferDesc identityOutput{};

    // Verify the identity claim using the attestation/identity and token public keys
    if (FAILED(hr = NCryptVerifyClaim(
                        tokenPublicKey,
                        attestPublicKey,
                        NCRYPT_CLAIM_VBS_IDENTITY, // Claim created by an attestation/identity key
                        NULL, // parameters
                        pIdentityClaim,
                        identityClaimSize,
                        &identityOutput,
                        NCRYPT_VBS_RETURN_CLAIM_DETAILS_FLAG /*dwFlags*/)))
    {
        wprintf(L"Unable to verify identity claim from NCryptVerifyClaim(): 0x%X\n-----\n", hr);
        goto cleanup;
    }

    PNCryptBuffer pIdentityOutBuffer;

    // Look into the retrieved identity claim details
    for (count = 0; count < identityOutput.cBuffers; ++count)
    {
        pIdentityOutBuffer = identityOutput.pBuffers[count];
        if (pIdentityOutBuffer->BufferType == NCRYPTBUFFER_VBS_ATTESTATION_STATEMENT_IDENTITY_DETAILS)
        {
            PNCRYPT_VBS_IDENTITY_KEY_ATTESTATION_CLAIM_DETAILS pDetails =
            (PNCRYPT_VBS_IDENTITY_KEY_ATTESTATION_CLAIM_DETAILS) pIdentityOutBuffer->pvBuffer;
            wprintf(L"The claim hash algorithm is: %S\n-----\n", pDetails-> pszSignatureHashAlg);
            wprintf(L"The claim padding scheme is: %lu\n-----\n", pDetails->ulPaddingScheme);
        }
    }

    wprintf(L"Verify claim for root and identity types passed successfully\n");

    cleanup:

    if (provider != NULL)
    {
        NCryptFreeObject(provider);
    }
    if (attestPublicKey != NULL)
    {
        CryptDestroyKey(attestPublicKey);
    }
    if (tokenPub != NULL)
    {
        CryptDestroyKey(tokenPublicKey);
    }
    if (rootOutput.pBuffers != NULL)
    {
        for (count = 0; count < rootOutput.cBuffers; ++count)
        {
            NCryptFreeBuffer(rootOutput.pBuffers[count].pvBuffer);
        }
        NCryptFreeBuffer(rootOutput.pBuffers);
    }

    if (identityOutput.pBuffers != NULL)
    {
        for (count = 0; count < identityOutput.cBuffers; ++count)
        {
            NCryptFreeBuffer(identityOutput.pBuffers[count].pvBuffer);
        }
        NCryptFreeBuffer(identityOutput.pBuffers);
    }

    return hr;
}

DWORD GetRsaPublicKeyBlobSize(BCRYPT_RSAKEY_BLOB* publicKeyBlob)
{
    return sizeof(BCRYPT_RSAKEY_BLOB) +
                publicKeyBlob->cbModulus +
                publicKeyBlob->cbPublicExp;
}

要求

要求 價值
最低支援的用戶端 Windows 10 [傳統型應用程式 |UWP 應用程式]
支援的最低伺服器 Windows Server 2016 [傳統型應用程式 |UWP 應用程式]
目標平臺 窗戶
標頭 ncrypt.h
連結庫 Ncrypt.lib
DLL Ncrypt.dll