CryptoNextGeneration:在 TPM 中存储密钥

CryptoNextGeneration : Storing a key in the TPM

我目前正在使用 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;
    }

(然后设置长度,完成等)

而且我的数据似乎是由 运行:

加密的
    // 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 加密和生成持久密钥而不是密钥对的功能用法,但因为我不想共享 public 密钥,所以我认为这应该有效)

但是,当尝试使用以下方法检索密钥时:

    // 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, but if I understand it right that exports the key to a blob of memory and not to the TPM (which should have been saved upon CreatePersistedKey)。

我是否缺少确保密钥存储在我的 TPM 中的步骤?

此外,我正在使用 NCryptDeleteKey 作为我的加密函数的清理,但文档指出这只是释放密钥句柄而不是实际存储的密钥。将密钥存储在 TPM 后,如何将其删除?

NCryptDeleteKey 会从您的 TPM 中删除密钥并清理句柄。

这是通过使用枚举和列表键进行实验发现的。

NCryptCreatePersistedKey 需要跟进对 NCryptFinalizeKey() 的调用,否则它永远不会实际存储到 TPM。这就是真正的魔法发生的地方。例如,如果你没有提升/管理员权限,它将在此处失败并显示 E_ACCESS