我目前正在开发一个小的示例程序,使用Crypto Next Generation (Windows Crypto API)来生成密钥,将其存储在我计算机上的TPM中,对一些数据进行加密,然后检索并解密数据。
我选择RSA加密是因为它是我的TPM唯一支持的算法。
我知道我可以通过以下方式作为提供商访问TPM:
// Open handle to TPM
if (FAILED(secStatus = NCryptOpenStorageProvider(
&hProv,
MS_PLATFORM_CRYPTO_PROVIDER,
0)))
{
wprintf(L"**** Error 0x%x returned by NCryptOpenStorageProvider\n", secStatus);
goto Cleanup;
}并且我可以生成密钥(哪些文档声明应该将其保存在我的提供程序中):
// Create a persistent key
if (FAILED(secStatus = NCryptCreatePersistedKey(
hProv,
&hKey,
NCRYPT_RSA_ALGORITHM,
L"RSAKey0",
0,
0)))
{
wprintf(L"**** Error 0x%x returned by NCryptCreatePersistedKey\n", secStatus);
goto Cleanup;
}(然后设置length、finalize等)
我的数据似乎是通过运行以下命令来加密的:
// Encrypt Data
if (!NT_SUCCESS(status = NCryptEncrypt(
hKey, // hKey
InputData, // pbInput
InputDataSize, // cbInput
NULL, // pPaddingInfo
encryptedBuffer, // pbOutput
encryptedBufferSize, // cbOutput
&encryptedBufferSize, // pcbResult
NCRYPT_PAD_PKCS1_FLAG))) // dwFlags
{
wprintf(L"**** Failed to encrypt data. Error 0x%x returned by NCryptEncrypt\n", status);
goto Cleanup;
}这看起来工作正常,没有错误,数据看起来是加密的。(我担心我可能误解了这里使用RSA加密和生成持久密钥而不是密钥对的函数用法,但因为我不需要共享公钥,所以我假设这应该是可行的)
但是,当尝试使用以下命令检索密钥时:
// Get key from TPM
if (FAILED(secStatus = NCryptOpenKey(
hProv,
&hKey,
L"RSAKey0",
0,
0)))
{
wprintf(L"**** Error 0x%x returned by NCryptOpenKey\n", secStatus);
goto Cleanup;
}我收到一个NTE_BAD_KEYSET错误。这表明没有找到钥匙。
潜在地,我发现我可能遗漏的唯一函数是NCryptExportKey,但是如果我理解正确的话,它会将密钥导出到一个内存块,而不是TPM (应该保存在CreatePersistedKey上)。
我是否错过了确保密钥存储在我的TPM中的步骤?
另外,我使用NCryptDeleteKey来清理我的加密函数,但是文档指出这只释放了密钥句柄,而不是实际存储的密钥。如何在TPM中存储密钥后将其删除?
发布于 2020-04-16 08:30:03
NCryptDeleteKey确实从你的TPM中删除了密钥,并清除了句柄。
这是通过使用枚举和列出关键字的实验发现的。
发布于 2021-10-01 20:25:13
NCryptCreatePersistedKey之后需要调用NCryptFinalizeKey(),否则它实际上永远不会存储到TPM中。这才是真正的魔术发生的地方。例如,如果您没有提升/ admin,它将在这里失败,并显示E_ACCESS。
https://stackoverflow.com/questions/61226988
复制相似问题