X509Certificate - 密钥集不存在

Posted

技术标签:

【中文标题】X509Certificate - 密钥集不存在【英文标题】:X509Certificate - Keyset does not exist 【发布时间】:2011-09-17 13:09:35 【问题描述】:

我有一个使用 WCF 的 WinForms 应用程序,并将证书作为参数传递给函数:

mySvcClient.SendDocument(cert.Export(X509ContentType.SerializedCert, "password"));
...

在 WCF 服务中,我从字节数组重新创建了证书:

public void SendDocument (byte[] binaryCert)
   
     X509Certificate2 cert = new X509Certificate2(binaryCert, "password");
...

但是当使用证书对xml进行签名时,出现错误“Keyset does not exist”:

if (cert.HasPrivateKey) // WORKS!!!
   
    signedXml.SigningKey = cert.PrivateKey; // THROW "keyset does not exist" EXCEPTION
...

在我的电脑中,应用程序 100% 运行!但是在 WebServer 中,我得到了这个错误!

问题是:即使 X509Certificate2 是从字节数组重新创建的,我需要一些特殊权限才能访问私钥吗?

谢谢!

【问题讨论】:

该链接可能对您有所帮助...***.com/a/39223239/3857542 我遇到了同样的问题,这是唯一对我有用的解决方案***.com/a/57667772/591656 【参考方案1】:

如果您使用的是windows server 2008或windows 7,那么您需要读取私钥的权限。

    使用 FindPrivateKey 工具查找路径。 例如:

FindPrivateKey My LocalMachine -n​​ "CN=MyCert" –a

它返回路径:C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys[文件名]

    转到该路径并打开文件属性

    转到安全选项卡

    点击“编辑”,然后点击“添加”

    在打开的对话框中写入:IIS AppPool\[您的应用程序池名称],然后单击确定

现在您的应用程序池有权读取此私钥。

【讨论】:

另一种设置证书权限的方法是通过证书管理单元,此处描述:***.com/a/3176253/844207【参考方案2】:

我遇到了这个问题,我的证书有私钥但我收到了这个错误(“密钥集不存在”)

原因:您的网站在“网络服务”帐户下运行或权限较低。

解决方案:将应用程序池标识更改为“本地系统”,重置 IIS 并再次检查。如果它开始工作,那就是权限/较少权限问题,您也可以模拟然后使用其他帐户。

【讨论】:

似乎还有一种情况,即使您的应用程序池标识是具有正确权限的帐户,您仍然需要授予 IIS_IUSRS 组具有读取权限才能完成操作,如果您尝试访问应用程序的 Application_Start 中的私钥。 就我而言,我必须将应用程序池标识更改为 Local System 并提供对 IIS_IUSRS 的私钥访问权限。证书需要安装在本地计算机商店。 这是开发环境和部署的一种更简单的方法。 不要在生产环境中使用本地系统权限,不建议这样做,因为您对应用程序池的权限超过管理员权限。很危险。【参考方案3】:

我也遇到了同样的问题,但我不知道怎么做(真为我感到羞耻),但它奏效了:

var certificate = new X509Certificate2(filePath, password,
    X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet);

certificate.PrivateKey; // before: error "KeySet does not exist"!

using (certificate.GetRSAPrivateKey())   // pure black magic

certificate.PrivateKey; // after: just works! lol

希望有人能解答这个谜题。

【讨论】:

@Everyone 请注意,根据 MSDN 页面,此解决方案适用于 .Net 4.6 或更高版本。 这解决了我的问题。 PrivateKey 在我的本地机器上工作,但在部署的代码上没有工作。 不起作用。仍然随机抛出“Keyset不存在”【参考方案4】:

Vano Maisuradze 回答有效。如果您正在寻找 FindPrivateKey 工具,它包含在适用于 .NET Framework 4 的 Windows Communication Foundation (WCF) 和 Windows Workflow Foundation (WF) 示例中,可在此处找到:http://www.microsoft.com/en-us/download/confirmation.aspx?id=21459

下载并解压后,在 Visual Studio 中打开项目:WF_WCF_Samples\WCF\Setup\FindPrivateKey\CS 并进行编译。然后打开命令提示符并导航到:WF_WCF_Samples\WCF\Setup\FindPrivateKey\CS\bin

然后继续 Vano Maisuradze 的回答

【讨论】:

【参考方案5】:

我认为问题在于您需要将密钥添加到机器的证书存储中。

【讨论】:

【参考方案6】:

默认情况下,应用程序池身份帐户无权访问证书存储。

您要么更改为 Vaibhav.Inspired 指出的 Network Services 帐户,要么授予对证书的访问权限。

要允许访问,请执行以下命令:

WinHttpCertCfg.exe -g -c LOCAL_MACHINE\MY -s "IssuedToName" -a “帐户名”

注意事项:

- The tool may need to be installed first. The setup will place the tool at `C:\Program Files (x86)\Windows Resource Kits\Tools\WinHttpCertCfg.exe`.
- `IssuedName` is the issuer property of the certificate that the application will attempt to access
- The command must be run from command prompt with elevated privileges

参考:https://support.microsoft.com/en-us/help/901183/how-to-call-a-web-service-by-using-a-client-certificate-for-authentica第二步

您还需要在安装证书时启用Mark this key as exportable 选项。

【讨论】:

【参考方案7】:

几个故障排除步骤:

    以管理员身份运行程序 如果是部署在 IIS 中的 Web 应用程序 -> 则将 IIS_IUSRS 添加到证书权限。在 Personal 中选择证书,右键单击-> Manage Private Keys -> 添加用户。 如果处于调试状态,则在管理员模式下运行 Visual Studio 以解决此问题

【讨论】:

以上是关于X509Certificate - 密钥集不存在的主要内容,如果未能解决你的问题,请参考以下文章

System.Security.Cryptography.CryptographicException:密钥集不存在

从 x509Certificate2 启动 RSACryptoServiceProvider 的最佳方式?

RSAParameters 到 pfx (X509Certificate2) 的转换

将Bytes []解析为C#中的X509Certificate

密钥集不存在怎样解决?

System.Security.Cryptography.CryptographicException,密钥集不存在