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 參數類型所設定。
此範例包含下列主要步驟:
- 系統會建立新的證明金鑰。 密鑰是使用 API 函式 NCryptSetProperty特製化。 證明的產生是以簽署金鑰為基礎。
- 系統會建立宣告以進行進一步證明。 宣告與證明金鑰和內建 VBS 金鑰相關聯。 藉由提供證明密鑰,可以在 NCryptVerifyClaim 中驗證宣告。
- 證明索引鍵對象已釋出,以避免記憶體流失。
// 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).
¶ms, // 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).
¶ms, // 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_HASH 和 NCRYPTBUFFER_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.
¶ms, // 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
¶ms,
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 |