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 标识/证明生成。 这意味着声明是由使用证明标志 NCRYPT_ALLOW_KEY_ATTESTATION_FLAG 提升的 VBS 密钥生成的(请参阅下文的详细信息)。 |
以下是在创建证明声明时在 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 声明,在其他类型的声明中毫无意义。
- NCRYPTBUFFER_ATTESTATION_STATEMENT_SIGNATURE_PADDING 参数仅在 RSA 证明密钥的情况下对 NCRYPT_CLAIM_VBS_IDENTITY 声明是必需的。 在其他类型的声明中,这是毫无意义的。
声明使我们能够验证常规用途密钥是否与证明密钥相关联。
//
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 |