c-MS CryptoAPI-机器密钥库,错误为0x80090016(NTE_BAD_KEYSET),创建了certre



摘要

我用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%xn", err);
}
CryptGetUserKey(hCryptProv, pinfo->dwKeySpec, &hUserkey);

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

错误

如果我运行这个,它将失败,并输出Error: 0x80090016。根据微软的说法,这意味着三件事之一:

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

到目前为止我做了什么

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

文件系统权限

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

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

%APPDATA%MicrosoftCryptoRSAS-1-5-21-1650336054-1974872081-316617838-545102

对于REQUEST,我在另一个地址下找到了它:

%ALLUSERSPROFILE%MicrosoftCryptoRSAMachineKeys

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

不同的特权级别

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

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

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

词尾词

对于如何进一步缩小这一问题的任何帮助或指导,我们将不胜感激。

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

所以我的函数调用必须看起来像这样:

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

不幸的是,OpenSSL引擎不支持这一点,因此您必须在引擎中自行更改它。

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

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

最新更新