问题描述
我使用创建PKCS#10 CSR certreq
并设置了选项Exportable=TRUE
.这样可以成功在位置REQUEST
下创建一个密钥.我也有一个有效的证书,密钥在MY
中.如果我尝试访问其中任何一个,则CryptoAPI报告错误代码0x80090016
.
I create a PKCS#10 CSR with certreq
and have set the option Exportable=TRUE
. This successfully creates a key under the location REQUEST
. I also have a valid certificate with key in MY
. If I try to access any one of them the CryptoAPI reports error code 0x80090016
.
在不同的访问权限下运行至今无法解决此问题.
Running under different access rights could not solve this problem so far.
我的目标是同时获取MY
和REQUEST
中的键.如果我在其中任何一个上调用CryptAcquireContextA()
,它都会失败.
My goal is to get both the keys in MY
and REQUEST
. If I call CryptAcquireContextA()
on any of those, it fails.
Windows 7 x64
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引擎复制的.由于引擎发生故障,我创建了最小的代码来搜索错误.
This code is mostly copied from the OpenSSL capi engine. Since the engine failed, I created the smallest possible code to search the error.
如果运行此命令,它将失败,并显示输出Error: 0x80090016
.这表示根据 Microsoft 的三件事之一:
If I run this, it fails with the output Error: 0x80090016
. This means one of three things according to Microsoft:
- 密钥容器不存在.
- 您无权访问密钥容器.
- 受保护的存储服务未运行.
- 已启动的服务受保护的存储"
- 已验证的容器与MMC&
Local Computer
的证书管理单元 - 在用户上下文中在用户存储区上运行相同的代码-确实有效
- Started service "Protected Storage"
- Verified container exists with MMC & Certificate Snap-In for
Local Computer
- Ran the same code on the User store in user context - it worked
在进行一些谷歌搜索之后,我尝试更改文件系统上的权限.我通过查看代码的contname
变量并搜索文件来找到文件.我更改了对它们的权限(更准确地说,我更改了对父文件夹的权限).虽然这解决了MY
的问题,但看来我无法更改REQUEST
的问题.
After some googling, I tried to change permissions on the file system. I found the files by looking at the contname
variable of my code and searching for the file. I changed permissions on them (more accurate, I changed permissions on the parent folder). While this fixed the issue for MY
, it seems I cannot change it for REQUEST
.
这里需要注意的是,我的MY
容器似乎在这里:
One note here is that my container for MY
seems to be here:
%APPDATA%\Microsoft\Crypto\RSA\S-1-5-21-1650336054-1974872081-316617838-545102
对于REQUEST
,我在另一个地址下找到它:
For REQUEST
I found it under a different address:
%ALLUSERSPROFILE%\Microsoft\Crypto\RSA\MachineKeys
我不确定这里的工作方式,因此无法解释为什么将它们放置在不同的位置(一个以用户为中心,另一个以系统文件夹为单位). MY
存储区是使用常规管理员提示符和命令certreq -new inf_file.inf cert-csr.csr
创建的,收到证书后,我发布了certreq -accept cert.pem
.然后我用相同的命令创建了一个新的csr.
I am not sure on the workings here so I cannot explain why it would put them in different locations (one being user centric, the other one a system folder). The MY
store was created with a regular administrator prompt and the command certreq -new inf_file.inf cert-csr.csr
and after I received my certificate, I issued certreq -accept cert.pem
. Then I created a new csr with the same command.
我尝试使用以下特权执行程序:
I tried to execute my program with the following privileges:
- 我的本地用户帐户
- 管理员提示(cmd->以管理员身份启动)
- nt权限\系统(
whoami
输出)
- my local user account
- admin prompt (cmd->start as administrator)
- nt authority\system (
whoami
output)
要接收服务提示,我根据 MaaSters中心
To recieve a service prompt, I executed psexec.exe –ids cmd.exe
according to a tip from MaaSters Center
任何有关如何进一步缩小此问题范围的帮助或指导将不胜感激.
Any help or guidance on how to further narrow this problem down will be greatly appreciated.
推荐答案
我终于能够解决此问题,并且比我想象的要简单得多.我确定我会收到一个明确的容器名称,不需要更具体,但是CryptAcquireContext
实际上要求我传递一个标志CRYPT_MACHINE_KEYSET
.
I was finally able to solve this problem and it is a lot simpler than I thought. I was sure that I would receive an unambiguous container name and don't need to be more specific but CryptAcquireContext
actually requires me to pass a flag CRYPT_MACHINE_KEYSET
.
所以我的函数调用必须看起来像这样:
So my function call has to look like this:
CryptAcquireContextA(&hCryptProv, contname, provname, pinfo->dwProvType, CRYPT_MACHINE_KEYSET)
不幸的是,OpenSSL引擎不支持此功能,因此您必须在引擎中自行对其进行更改.
Unfortunately this is not supported by the OpenSSL engine, so you would have to alter it yourself in the engine.
这篇关于MS CryptoAPI-错误为0x80090016的计算机密钥库(NTE_BAD_KEYSET),带有certreq创建的密钥的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!