【问题标题】:C++ CNG NCrypt: Can't open persisted key from Key Storage ProviderC++ CNG NCrypt:无法从密钥存储提供程序打开持久密钥
【发布时间】:2022-12-09 13:34:28
【问题描述】:

我有两个程序。创建一个持久密钥并将其保存到密钥存储提供程序,然后对哈希进行签名并将签名写入注册表。第二个程序打开来自提供商的密钥并验证从注册表中获得的标志。 但我的问题是在第二个程序 NCryptOpenKey 中找不到密钥存储提供程序中的密钥!在浏览文档和互联网数小时后,我仍然不知道为什么。请指出我做错了什么。 代码示例:

变量和清理程序:

NCRYPT_PROV_HANDLE      hProv           = NULL;
NCRYPT_KEY_HANDLE       hKey            = NULL;
SECURITY_STATUS         secStatus       = ERROR_SUCCESS;
BCRYPT_ALG_HANDLE       hHashAlg        = NULL,
                        hSignAlg        = NULL;
BCRYPT_HASH_HANDLE      hHash           = NULL;
NTSTATUS                status          = STATUS_UNSUCCESSFUL;
DWORD                   cbData          = 0,
                        cbHash          = 0,
                        cbSignature     = 0,
                        cbHashObject    = 0;
PBYTE                   pbHashObject    = NULL;
PBYTE                   pbHash          = NULL,
                        pbSignature     = NULL;

static const WCHAR* KEY_NAME = TEXT("MyPersistedKey");

void Cleanup()
{
    if (hHashAlg)
        BCryptCloseAlgorithmProvider(hHashAlg, 0);

    if (hSignAlg)
        BCryptCloseAlgorithmProvider(hSignAlg, 0);

    if (hHash)
        BCryptDestroyHash(hHash);

    if (pbHashObject)
        HeapFree(GetProcessHeap(), 0, pbHashObject);

    if (pbHash)
        HeapFree(GetProcessHeap(), 0, pbHash);

    if (pbSignature)
        HeapFree(GetProcessHeap(), 0, pbSignature);

    if (hKey)
        NCryptDeleteKey(hKey, 0);

    if (hProv)
         NCryptFreeObject(hProv);
}

第一个程序

// open handle to KSP
if (FAILED(secStatus = NCryptOpenStorageProvider(&hProv, MS_KEY_STORAGE_PROVIDER, 0))) {
    Cleanup();
    return {};
}
// key doesn't exists. create it
if (FAILED(secStatus = NCryptCreatePersistedKey(hProv, &hKey, NCRYPT_ECDSA_P256_ALGORITHM, KEY_NAME, 0, 0))) {
    Cleanup();
    return {};
}
// create key on disk
if (FAILED(secStatus = NCryptFinalizeKey(hKey, 0))) {
    Cleanup();
    return {};
}
// get the length of the signature
if (FAILED(secStatus = NCryptSignHash(hKey, NULL, pbHash, cbHash, NULL, 0, &cbSignature, 0))) {
    Cleanup();
    return {};
}
// allocate the signature buffer
pbSignature = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbSignature);
if (NULL == pbSignature) {
    Cleanup();
    return {};
}
// sign the hash
if (FAILED(secStatus = NCryptSignHash(hKey, NULL, pbHash, cbHash, pbSignature, cbSignature, &cbSignature, 0))) {
    Cleanup();
    return {};
}

第二期节目

// open handle to KSP
if (FAILED(secStatus = NCryptOpenStorageProvider(&hProv, MS_KEY_STORAGE_PROVIDER, 0))) {
    Cleanup();
    return false;
}
// open key from KSP
if (FAILED(secStatus = NCryptOpenKey(hProv, &hKey, KEY_NAME, 0, 0))) {
    Cleanup();
    return false;
}

// verify signature with hash
status = NCryptVerifySignature(hKey, NULL, pbHash, cbHash, pbSignature, cbSignature, 0);
switch (status) {
case ERROR_SUCCESS:   // hash is verifyied
    Cleanup();
    return true;
case NTE_BAD_SIGNATURE:   // hash isn't verifyied
    Cleanup();
    return false;
default:
    Cleanup();
    return false;
}

【问题讨论】:

  • 你甚至不说是什么地位回来。需要猜这个吗?通常可能有 2 个原因 - 权限或进程使用不同的帐户运行 (SIDS)
  • NCryptOpenKey 返回 NTE_BAD_KEYSET
  • 认为您与不同的用户一起运行 2 个进程。说一个是服务,一个是用户
  • 我从 1 个用户运行我的程序

标签: c++ winapi cng wincrypt


【解决方案1】:

根据NCryptVerifySignature

密钥的句柄必须是相同的密钥(Symmetric keys)或 密钥对 (Asymmetric keys) 的公钥部分用于 使用 NCryptSignHash 函数对数据进行签名。

并且您需要导出公钥。请参阅 Signing Data with CNGSignHashWithPersistedKeys 示例。
删除磁盘上的密钥文件,将句柄传递给 NCryptDeleteKey 函数。您已删除Cleanup 中的密钥。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-23
    • 1970-01-01
    • 2018-08-07
    • 2023-02-01
    • 2021-01-24
    相关资源
    最近更新 更多