【问题标题】:MS CryptoAPI - Machine Keystore with Error 0x80090016 (NTE_BAD_KEYSET) with certreq created keysMS CryptoAPI - 带有错误 0x80090016 (NTE_BAD_KEYSET) 的机器密钥库,带有 certreq 创建的密钥
【发布时间】:2012-07-16 15:55:04
【问题描述】:

总结

我使用certreq 创建了一个PKCS#10 CSR,并设置了选项Exportable=TRUE。这成功地在位置REQUEST 下创建了一个密钥。我还有一个有效的证书,其密钥为MY。如果我尝试访问其中任何一个,CryptoAPI 会报告错误代码0x80090016

在不同的访问权限下运行目前无法解决这个问题。

目标

我的目标是同时获得MYREQUEST 中的密钥。如果我在其中任何一个上调用CryptAcquireContextA(),它就会失败。

系统

Windows 7 x64

示例源代码

我的完整代码如下所示:

hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, "REQUEST");
pCert = CertFindCertificateInStore(hStore, X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR_A, "CERTIFICATE_SUBJECT", NULL);

CertGetCertificateContextProperty(pCert, CERT_KEY_PROV_INFO_PROP_ID, NULL, &len);
pinfo = (CRYPT_KEY_PROV_INFO *) malloc(len);
CertGetCertificateContextProperty(pCert, CERT_KEY_PROV_INFO_PROP_ID, pinfo, &len);

provname = wide_to_asc(pinfo->pwszProvName);
contname = wide_to_asc(pinfo->pwszContainerName);

if(!CryptAcquireContextA(&hCryptProv, contname, provname, pinfo->dwProvType, 0)) {
    err = GetLastError();
    fprintf(stderr, "Error: 0x%x\n", err);
}
CryptGetUserKey(hCryptProv, pinfo->dwKeySpec, &hUserkey);

这段代码主要是从OpenSSL capi 引擎复制而来的。由于引擎出现故障,我创建了尽可能小的代码来搜索错误。

错误

如果我运行它,它会失败并输出Error: 0x80090016。根据Microsoft,这意味着三件事之一:

  • 密钥容器不存在。
  • 您无权访问密钥容器。
  • 受保护的存储服务未运行。

到目前为止我做了什么?

  • 已启动服务“受保护的存储”
  • 已验证容器与 Local Computer 的 MMC 和证书管理单元一起存在
  • 在用户上下文中的用户存储上运行相同的代码 - 它有效

文件系统权限

经过一番谷歌搜索后,我尝试更改文件系统的权限。我通过查看代码的contname 变量并搜索文件找到了这些文件。我更改了它们的权限(更准确地说,我更改了父文件夹的权限)。虽然这解决了MY 的问题,但我似乎无法为REQUEST 更改它。

这里需要注意的是,我的 MY 容器似乎在这里:

%APPDATA%\Microsoft\Crypto\RSA\S-1-5-21-1650336054-1974872081-316617838-545102

对于REQUEST,我在不同的地址下找到了它:

%ALLUSERSPROFILE%\Microsoft\Crypto\RSA\MachineKeys

我不确定这里的工作原理,所以我无法解释为什么会将它们放在不同的位置(一个以用户为中心,另一个以系统文件夹为中心)。 MY 存储是使用常规管理员提示和命令 certreq -new inf_file.inf cert-csr.csr 创建的,在我收到证书后,我发布了 certreq -accept cert.pem。然后我用相同的命令创建了一个新的 csr。

不同的权限级别

我尝试使用以下权限执行我的程序:

  • 我的本地用户帐户
  • 管理员提示符(cmd->以管理员身份启动)
  • nt 权限\系统(whoami 输出)

为了接收服务提示,我根据MaaSters Center 的提示执行了psexec.exe –ids cmd.exe

最后的话

任何有关如何进一步缩小此问题的帮助或指导将不胜感激。

【问题讨论】:

    标签: c openssl cryptoapi


    【解决方案1】:

    我终于能够解决这个问题,它比我想象的要简单得多。我确信我会收到一个明确的容器名称,不需要更具体,但 CryptAcquireContext 实际上要求我传递一个标志 CRYPT_MACHINE_KEYSET

    所以我的函数调用必须如下所示:

    CryptAcquireContextA(&hCryptProv, contname, provname, pinfo->dwProvType, CRYPT_MACHINE_KEYSET)
    

    很遗憾,OpenSSL 引擎不支持此功能,因此您必须自己在引擎中进行更改。

    【讨论】:

      【解决方案2】:

      请参阅 MSDN:“由非管理员用户创建的没有此标志的密钥容器只能由创建密钥容器的用户和本地系统帐户访问。”

      在此处完成详细信息:https://msdn.microsoft.com/en-us/library/windows/desktop/aa379886(v=vs.85).aspx

      【讨论】:

        猜你喜欢
        • 2011-05-10
        • 2013-04-06
        • 2021-03-27
        • 2019-06-21
        • 2020-05-08
        • 1970-01-01
        • 2017-08-07
        • 1970-01-01
        • 2021-06-22
        相关资源
        最近更新 更多