共用方式為


NCryptCreateClaim 函式 (ncrypt.h)

建立金鑰證明宣告。

語法

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

參數

[in] hSubjectKey

建立宣告的主旨索引鍵句柄。

[in, optional] hAuthorityKey

宣告所依據的授權單位密鑰句柄。

[in] dwClaimType

宣告的類型。

[in, optional] pParameterList

選擇性參數清單。

[out] pbClaimBlob

所建立宣告 Blob 的輸出。

[in] cbClaimBlob

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

[out] pcbResult

所建立宣告 Blob 的輸出。

[in] dwFlags

目前未定義旗標。 dwFlags 參數應設定為 0

傳回值

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

言論

使用虛擬化型安全性保護/證明私鑰 (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 緩衝區中設定的緩衝區類型:

緩衝區類型 描述
NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_HASH 在 NCryptCreateClaim 中建立證明宣告時,要設定於參數緩衝區中的緩衝區類型。 這是 NCRYPT_CLAIM_VBS_IDENTITY 宣告的必要參數類型。

此參數會設定要透過證明宣告建立使用的哈希函式類型。 此參數的值定義於 ncrypt.h 中(例如 CNG 演演算法識別碼中的常數):

#define NCRYPT_SHA1_ALGORITHM BCRYPT_SHA1_ALGORITHM
#define NCRYPT_SHA256_ALGORITHM BCRYPT_SHA256_ALGORITHM
#define NCRYPT_SHA384_ALGORITHM BCRYPT_SHA384_ALGORITHM
#define NCRYPT_SHA512_ALGORITHM BCRYPT_SHA512_ALGORITHM
NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING_SCHEME 在 NCryptCreateClaim 中建立證明宣告時,要設定於參數緩衝區中的緩衝區類型。 這是強制參數,以防所建立 NCRYPT_CLAIM_VBS_IDENTITY 宣告中的證明金鑰是 RSA 金鑰。

此參數會設定簽章函式類型的填補配置,以透過證明宣告建立來使用。 此參數的選擇性值定義於 bcrypt.h 中(例如 NCryptSignHash中的 dwFlags 常數):

#define BCRYPT_PAD_PSS 0x00000008
NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING_ALGO NCryptCreateClaim中建立證明宣告時,參數緩衝區中要設定的新緩衝區類型。 這是強制參數,以防所建立 NCRYPT_CLAIM_VBS_IDENTITY 宣告中的證明金鑰是 RSA 金鑰。 參數是 Null 終止 Unicode 字串的指標,可識別用來建立填補的密碼編譯演算法。 此演算法必須是哈希演算法。 此參數的值定義於 ncrypt.h 中(例如 CNG 演演算法識別碼中的常數):

#define NCRYPT_SHA1_ALGORITHM BCRYPT_SHA1_ALGORITHM
#define NCRYPT_SHA256_ALGORITHM BCRYPT_SHA256_ALGORITHM
#define NCRYPT_SHA384_ALGORITHM BCRYPT_SHA384_ALGORITHM
#define NCRYPT_SHA512_ALGORITHM BCRYPT_SHA512_ALGORITHM
NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING_SALT_SIZE NCryptCreateClaim中建立證明宣告時,參數緩衝區中要設定的新緩衝區類型。 這是強制參數,以防所建立 NCRYPT_CLAIM_VBS_IDENTITY 宣告中的證明金鑰是 RSA 金鑰。

參數代表要用於填補之隨機鹽的大小,以位元組為單位。
NCRYPTBUFFER_ATTESTATION_STATEMENT_NONCE 在 NCryptCreateClaim 中建立證明宣告時,要設定於參數緩衝區中的緩衝區類型。 此參數是 NCRYPTBUFFER_CLAIM_KEYATTESTATION_NONCE的別名。

例子

這個範例說明新 API 旗標的使用方式 NCRYPT_ALLOW_KEY_ATTESTATION_FLAG。 此外,宣告建立的 nonce 值是由 NCRYPTBUFFER_ATTESTATION_STATEMENT_NONCE 參數類型所設定。

此範例包含下列主要步驟:

  1. 系統會建立新的證明金鑰。 密鑰是使用 API 函式 NCryptSetProperty特製化。 證明的產生是以簽署金鑰為基礎。
  2. 系統會建立宣告以進行進一步證明。 宣告與證明金鑰和內建 VBS 金鑰相關聯。 藉由提供證明密鑰,可以在 NCryptVerifyClaim 中驗證宣告。
  3. 證明索引鍵對象已釋出,以避免記憶體流失。
// Create an attestation/identity key. This function is invoked in the main code flow below.
NCRYPT_KEY_HANDLE CreateAttestationKey(NCRYPT_PROV_HANDLE provider)
{

    NCRYPT_KEY_HANDLE attestationKey = NULL;
    HRESULT hr;

    if (FAILED(hr = NCryptCreatePersistedKey(
                    provider,
                    &attestationKey,
                    BCRYPT_RSA_ALGORITHM,
                    L"AttestationKey", // a unique name for the attestation key in the key store
                    0, //dwLegacyKeySpec, not used
                    NCRYPT_REQUIRE_VBS_FLAG/*This flag targets VBS */)))
    {
        wprintf(L"Error creating an Attestation Identity Key with NCryptCreatePersistedKey(): 0x%X\n", hr);
        goto cleanup;
    }

    // This is a new flag. It’s used to enable the capability in an attestation key.
    DWORD keyUsagePolicy = NCRYPT_ALLOW_KEY_ATTESTATION_FLAG;
    if (FAILED(hr = NCryptSetProperty(
                    attestationKey,
                    NCRYPT_KEY_USAGE_PROPERTY,
                    (PUCHAR)&keyUsagePolicy,
                    sizeof(keyUsagePolicy),
                    0 /*dwFlags*/)))
    {
        wprintf(L"Error setting property with NCryptSetProperty (): 0x%X\n", hr);
        goto cleanup;
    }

    DWORD keySizeBits = 2048; // minimum allowed RSA key size
    if (FAILED(hr = NCryptSetProperty(
                    attestationKey,
                    NCRYPT_LENGTH_PROPERTY,
                    (PUCHAR)&keySizeBits,
                    sizeof(keySizeBits),
                    0 /*dwFlags*/)))
    {
        wprintf(L"Error setting property with NCryptSetProperty (): 0x%X\n", hr);
        goto cleanup;
    }
    
    if (FAILED(hr = NCryptFinalizeKey(attestationKey, 0 /*dwFlags*/)))
    {
        wprintf(L"Error finalizing key with NCryptFinalizeKey (): 0x%X\n", hr);
        goto cleanup;
    }

    return attestationKey;
cleanup:
    if (attestationKey != NULL)
    {
        NCryptFreeObject(attestationKey);
    }

    return NULL;
}

HRESULT CreateAttestation()
{
    HRESULT hr = S_OK;
    NCRYPT_PROV_HANDLE provider = NULL;
    
    BYTE nonce[] = "TheSuperSecretNonce";
    // This way of setting parameters is an existent pattern for NCrypt APIs
    NCryptBuffer paramBuffers[] =
    {
        { sizeof(nonce), NCRYPTBUFFER_ATTESTATION_STATEMENT_NONCE, (PBYTE)&nonce },
    };
    NCryptBufferDesc params = { NCRYPTBUFFER_VERSION, ARRAYSIZE(paramBuffers), paramBuffers };
    
    if (FAILED(hr = NCryptOpenStorageProvider(&provider, MS_KEY_STORAGE_PROVIDER, 0)))
    {
        wprintf(L"Error opening storage provider in NCryptOpenStorageProvider: 0x%X\n", hr);
        goto cleanup;
    }
    
    // Create a VBS attestation key
    NCRYPT_KEY_HANDLE attestationKey = CreateAttestationKey(provider);
    if (attestationKey == NULL)
    {
        hr = E_ABORT;
        goto cleanup;
    }
    
    DWORD bytesWritten = 0;
    
    if (FAILED(hr = NCryptCreateClaim(
                    attestationKey, // key that is being attested here and may attest other keys.
                    NULL, // implies that IDKS (VBS root signing key) will be used.
                    NCRYPT_CLAIM_VBS_ROOT, // used to attest a key with IDKS (VBS root signing key).
                    &params, // parameters list
                    NULL, // getting the size
                    0, // getting the size
                    &bytesWritten,
                    0 /*dwFlags*/)))
    {
        wprintf(L"Error creating claim with NCryptCreateClaim (): 0x%X\n", hr);
        goto cleanup;
    }
    
    DWORD claimBufferSize = bytesWritten;
    
    PBYTE claimBuffer = (PBYTE) HeapAlloc(GetProcessHeap(), 0,claimBufferSize);
    if (NULL == claimBuffer)
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        wprintf(L"Error allocating buffer for the claim: 0x%X\n", hr);
        goto cleanup;
    }
    
    bytesWritten = 0;
    if (FAILED(hr = NCryptCreateClaim(
                    attestationKey, // key that is being attested here and may attest other keys.
                    NULL, //implies that IDKS (VBS root signing key) will be used.
                    NCRYPT_CLAIM_VBS_ROOT, // used to attest with IDKS (VBS root signing key).
                    &params, // parameters list
                    claimBuffer,
                    claimBufferSize,
                    &bytesWritten,
                    0)))
    {
        wprintf(L"Error creating claim with NCryptCreateClaim (): 0x%X\n", hr);
        goto cleanup;
    }
    
    wprintf(L"The claim is created successfully. It may be shared with the verifier side.\n");

cleanup:
    if (provider != NULL)
    {
        NCryptFreeObject(provider);
    }
    if (attestationKey != NULL)
    {
        NCryptFreeObject(attestationKey);
    }
    if (claimBuffer)
    {
        HeapFree(GetProcessHeap(), 0, claimBuffer);
    }
    
    return hr;
}

下一個範例說明如何使用新的 API 參數來建立一般用途的密碼編譯密鑰和相關聯的證明宣告。 此一般用途金鑰可用來產生證明宣告。

宣告建立的哈希演算法類型和填補分別設定在 NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_HASHNCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING_[SCHEME/ALGO/SALT_SIZE] 參數中。

請注意:

  • NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_HASH 參數僅適用於 NCRYPT_CLAIM_VBS_IDENTITY 宣告,在其他類型的宣告中是毫無意義的。
  • 只有在 RSA 證明金鑰的情況下,NCRYPT_CLAIM_VBS_IDENTITY 宣告才需要 NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING 參數。 在其他類型的宣告中,這是毫無意義的。

宣告可讓我們確認一般用途密鑰是否與證明金鑰相關聯。

//
HRESULT hr = S_OK;
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 attestationKey = NULL;

// Open the attestation key, created in CreateAttestationKey(), see previous example
if (FAILED(hr = NCryptOpenKey(
                provider,
                &attestationKey,
                L"AttestationKey",
                0, //dwLegacyKeySpec, not used
                0 ,/* dwFlags */)))
{
    wprintf(L"Error openning the attestation key with NCryptOpenKey (): 0x%X\n", hr);
    goto cleanup;
}

NCRYPT_KEY_HANDLE tokenKey = NULL; // Token key that is bound to the security token

// Create VBS token (general purpose) key
if (FAILED(hr = NCryptCreatePersistedKey(
                provider,
                &tokenKey,
                BCRYPT_RSA_ALGORITHM,
                L"TokenKey",
                0, //dwLegacyKeySpec, not used
                NCRYPT_REQUIRE_VBS_FLAG /*This flag targets VBS*/)))
{
    wprintf(L"Error creating an token key with NCryptCreatePersistedKey(): 0x%X\n", hr);
    goto cleanup;
}

DWORD keySizeBits = 2048;
if (FAILED(hr = NCryptSetProperty(
                tokenKey,
                NCRYPT_LENGTH_PROPERTY,
                (PUCHAR)&keySizeBits,
                sizeof(keySizeBits),
                0 /*dwFlags*/)))
{
    wprintf(L"Error setting property with NCryptSetProperty (): 0x%X\n", hr);
    goto cleanup;
}

if (FAILED(hr = NCryptFinalizeKey(tokenKey, 0 /*dwFlags*/)))
{
    wprintf(L"Error finalizing key with NCryptFinalizeKey (): 0x%X\n", hr);
    goto cleanup;
}

DWORD bytesWritten = 0;

DWORD hashAlgoType; // This is a new flag. It’s used to set type of hash algorithm of the claim// Set specific hash function type to produce the claim
wchar_t pHashAlgo[] = NCRYPT_SHA512_ALGORITHM;
// Set specific padding scheme for hash function to produce the claim
ULONG paddingScheme = BCRYPT_PAD_PSS;
wchar_t pPaddingAlgo[] = NCRYPT_SHA256_ALGORITHM;
ULONG paddingSalt = 345;

// This way of setting parameters is an existent pattern for NCrypt APIs
NCryptBuffer paramBuffers[] =
{
    { sizeof(NCRYPT_SHA512_ALGORITHM), NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_HASH, (PBYTE)&pHashAlgo },
    { sizeof(paddingScheme), NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING_SCHEME , (PBYTE)&paddingScheme },
    { sizeof(NCRYPT_SHA256_ALGORITHM), NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING_ALGO, (PBYTE)&pPaddingAlgo },
    { sizeof(paddingSalt, NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING_SALT_SIZE, (PBYTE)&paddingSalt }
};
NCryptBufferDesc params = { NCRYPTBUFFER_VERSION, ARRAYSIZE(paramBuffers), paramBuffers };

if (FAILED(hr = NCryptCreateClaim(
                tokenKey, // key that is being attested
                attestationKey,
                NCRYPT_CLAIM_VBS_IDENTITY, // attest general-purpose key with an attestation (identity) key.
                &params, // parameters list
                NULL, // getting the size
                0, // getting the size
                &bytesWritten,
                0 /*dwFlags*/)))
{
    wprintf(L"Error creating claim with NCryptCreateClaim (): 0x%X\n", hr);
    goto cleanup;
}

DWORD claimBufferSize = bytesWritten;

PBYTE claimBuffer = (PBYTE) HeapAlloc(GetProcessHeap(), 0,claimBufferSize);
if (NULL == claimBuffer)
{
    hr = HRESULT_FROM_WIN32(GetLastError());
    wprintf(L"Error allocating buffer for the claim: 0x%X\n", hr);
    goto cleanup;
}
bytesWritten = 0;

if (FAILED(hr = NCryptCreateClaim(
                tokenKey, // key that is being attested
                attestationKey, // we assume that it is already initialized
                NCRYPT_CLAIM_VBS_IDENTITY, // attest general-purpose key with an attestation (identity) key
                &params,
                claimBuffer,
                claimBufferSize,
                &bytesWritten,
                0)))
{
    wprintf(L"Error creating claim with NCryptCreateClaim (): 0x%X\n", hr);
    goto cleanup;
}

wprintf(L"The claim is created successfully. It may be shared with the verifier side.\n");

cleanup:
    if (provider != NULL)
    {
    NCryptFreeObject(provider);
    }
    if (tokenKey != NULL)
    {
    NCryptFreeObject(tokenKey);
    }
    if (attestationKey != NULL)
    {
    NCryptDeleteKey(attestationKey);
    }
    if (claimBuffer)
    {
    HeapFree(GetProcessHeap(), 0, claimBuffer);
    }
    
return hr;

要求

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