“ Keyset 不存在”,但只能通过 WCF

我有一些代码可以调用使用 X.509认证的第三方 Web 服务。

如果我直接调用代码(使用单元测试) ,那么它工作起来没有任何问题。

在部署时,此代码将通过 WCF 服务调用。我已经添加了第二个调用 WCF 服务的单元测试,但是当我调用第三方 Web 服务上的方法时,CryptographicException消息 "Keyset does not exist"会导致这个测试失败。

我假设这是因为我的 WCF 服务将尝试使用不同的用户来调用第三方 Web 服务。

有人能在这个问题上提供更多的解释吗?

224975 次浏览

这可能是证书上的权限问题。

在运行单元测试时,您将在自己的用户上下文中执行这些测试,用户上下文(取决于 客户证书所在的存储区)将访问该证书的私钥。

但是,如果您的 WCF 服务托管在 IIS 下,或者作为 Windows 服务,那么它很可能将在服务帐户(网络服务、本地服务或其他受限帐户)下运行。

您需要对私钥设置适当的权限,以允许该服务帐户访问该私钥。MSDN 有 详情

我昨晚也有同样的问题。对私钥的权限设置正确,除了键集不存在错误之外,一切都很正常。最后,证书首先导入到当前用户存储,然后移动到本地机器存储。然而,这并没有移动私钥,它仍然在

文件和设置管理员..。

而不是

文档和设置所有用户..。

虽然对密钥的权限设置正确,但 ASPNET 无法访问它。当我们重新导入证书以便将私钥放在 All users 分支中时,问题就消失了。

这很可能是因为 IIS 用户不能访问证书的私钥。您可以通过以下步骤来设置..。

  1. 开始→运行→ MMC
  2. 文件→添加/删除管理单元
  3. 添加证书管理单元
  4. 选择电脑帐户,然后点击下一步
  5. 选择 LocalComputer (默认值) ,然后单击 Finish
  6. 在 Console Root 的左面板上,导航到 证书(本地计算机)→个人→证书
  7. 你的证书很可能在这里。
  8. 右键单击您的证书→所有任务→管理私钥
  9. 在这里设置您的私钥设置。

如果对应用程序池使用 ApplicationPoolIdentity,则可能在注册表编辑器中指定“虚拟”用户的权限时出现问题(系统中没有这样的用户)。

因此,使用 Subinacl命令行工具来启用设置注册表 ACL,或者类似这样的工具。

我发现一些缺失的信息,帮助我得到我的 WCF 服务与消息级别的安全超过“钥匙集不存在”,我不断运行,尽管授予权限的所有密钥生成的例子在互联网上。

最后,我将私钥导入到本地计算机上的可信人员存储中,然后授予私钥正确的权限。

这为我填补了空白,最终允许我实现具有消息级别安全性的 WCF 服务。我正在建立一个周转基金,必须是 HIPPA 兼容。

我也有同样的问题。 我已经下了命令

findprivatekey root localmachine -n "CN="CertName"

结果显示私钥位于 c: ProgramData 文件夹中,而不是 C: Document 和 settings。

当我从 c: ProgramData 文件夹中删除密钥时,再次运行 findPrivatekey 命令不能成功。也就是说。它找不到钥匙。

但是如果我搜索了之前命令返回的同一个密钥,我仍然可以在

C: 文档和设置所有用户. 。

因此,据我所知,IIS 或托管的 WCF 并没有从 C: Document and settings All 用户那里找到私钥。

我只是想补充一个理智检查的答案。即使在我的机器上将证书安装到正确的存储区并且拥有客户端的所有安全特权之后,我仍然得到了完全相同的错误。原来我把客户证明和服务证明搞混了。如果你已经尝试了以上所有的方法,我会再次检查你是否有这两种方法。 一旦我这样做了,我的应用程序就成功地调用了 Web 服务。 再说一次,只是个心智检查。

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

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

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

完全令人沮丧,我有同样的问题,并尝试上述大部分。导出的证书正确地拥有读取 C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys中文件的权限,但事实证明它对文件夹没有权限。加进去就成功了

在 IIS7上使用 openAM Fedlet 时收到此错误

更改默认网站的用户帐户解决了这个问题。理想情况下,您希望这是一个服务帐户。甚至可能是 IUSR 的账户。建议查找 IIS 加固的方法,以完全确定它。

在 VisualStudio 中运行 WCF 应用程序时遇到了同样的问题。通过以管理员身份运行 VisualStudio 解决了这个问题。

当我运行 MVC 应用程序的时候,我得到了一个错误: “ Keyset 不存在”。

解决方案是: 向运行应用程序池的帐户提供对个人证书的访问。在我的例子中,添加 IIS _ IUSRS 并选择正确的位置解决了这个问题。

RC on the Certificate - > All tasks -> Manage Private Keys -> Add->
For the From this location : Click on Locations and make sure to select the Server name.
In the Enter the object names to select : IIS_IUSRS and click ok.

要解决从 IIS 浏览时“键集不存在”的问题: 可能是私人许可

查看并给予许可:

  1. 运行 > mmc > yes
  2. 点击文件
  3. 点击添加/删除管理单元..。
  4. 双击证书
  5. 电脑帐户
  6. 下一个
  7. 结束
  8. 好吧
  9. 点击证书(本地计算机)
  10. 点击个人
  11. 单击“证书”

给予许可:

  1. 右击证书名称
  2. 所有任务 > 管理私钥..。
  3. 添加并给予特权(添加 IIS _ IUSRS 并给予它特权对我来说很有用)

我在我的服务面料项目中遇到了这个问题,因为用于验证我们的密钥库的证书过期并被旋转,从而改变了指纹。我得到这个错误是因为我错过了更新这个代码块中 applicationManifest.xml 文件中的拇指指纹,这正是其他答案所建议的——给予 NETWORK SERVICE (我所有的前任都以天蓝色服务纤维集群的标准配置运行)权限来访问 LOCALMACHINE MY cert store 位置。

注意“ X509FindValue”属性值。

<!-- this block added to allow low priv processes (such as service fabric processes) that run as NETWORK SERVICE to read certificates from the store -->
<Principals>
<Users>
<User Name="NetworkService" AccountType="NetworkService" />
</Users>
</Principals>
<Policies>
<SecurityAccessPolicies>
<SecurityAccessPolicy ResourceRef="AzureKeyvaultClientCertificate" PrincipalRef="NetworkService" GrantRights="Full" ResourceType="Certificate" />
</SecurityAccessPolicies>
</Policies>
<Certificates>
<SecretsCertificate X509FindValue="[[THIS KEY ALSO NEEDS TO BE UPDATED]]" Name="AzureKeyvaultClientCertificate" />
</Certificates>
<!-- end block -->

我刚刚在本地机器上重新安装了我的证书,然后它就工作正常了

这是我唯一的解决办法。

    // creates the CspParameters object and sets the key container name used to store the RSA key pair
CspParameters cp = new CspParameters();
cp.KeyContainerName = "MyKeyContainerName"; //Eg: Friendly name


// instantiates the rsa instance accessing the key container MyKeyContainerName
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp);
// add the below line to delete the key entry in MyKeyContainerName
// rsa.PersistKeyInCsp = false;


//writes out the current key pair used in the rsa instance
Console.WriteLine("Key is : \n" + rsa.ToXmlString(true));

参考文献1

参考文献2

来自 Steve Sheldon 的答案为我解决了这个问题,但是,由于我是没有 GUI 的脚本证书权限,所以我需要一个可脚本化的解决方案。我费了好大劲才找到我的私人钥匙。私钥不在 -C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys中,最后我发现它实际上在 C:\ProgramData\Microsoft\Crypto\Keys中。下面我将描述我是如何发现这一点的:

我尝试了 FindPrivateKey,但是它找不到私有密钥,并且使用 powershell 时 $cert.privatekey.cspkeycontainerinfo.uniquekeycontainername为 null/null。

幸运的是,certutil -store my列出了证书,并提供了编写解决方案脚本所需的详细信息。

= = = = = = = = = = = = = = = = = = = 证书1 = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 编号: 162f1b54fe78c7c8fa9df09 发行人: CN = * . internal.xxxxxxx.net 注: 23/08/201914:04 注释: 2020年2月23日14:24 主题: CN = * . xxxxxxnet 签名与公开密钥匹配 根证书: 主题与发行人相符 Cert Hash (sha1) : xxxa5f0e9f0ac8b7dd634xx 密钥容器 = {407EC7EF-8701-42BF-993F-CDEF8328DD } 唯一容器名称: 8787033f8ccb5836115b87acb _ ca96c65a-4b42-a145-eee62128a # # * ^ ——私钥的文件名 微软软件密钥存储提供程序 私钥不是可导出的纯文本 加密测试通过 CertUtil:-store 命令成功完成。

然后我扫描了 c\ProgramData\Microsoft\Crypto\文件夹,在 C: ProgramData Microsoft 加密密钥中找到了文件 877033f8ccb5836115b87acb _ ca96c65a-4b42-a145-eee62128a

给我的服务帐户读取访问这个文件为我修复的问题

This issue is got resolved after adding network service role.


CERTIFICATE ISSUES
Error :Keyset does not exist means System might not have access to private key
Error :Enveloped data …
Step 1:Install certificate in local machine not in current user store
Step 2:Run certificate manager
Step 3:Find your certificate in the local machine tab and right click manage privatekey and check in allowed personnel following have been added:
a>Administrators
b>yourself
c>'Network service'
And then provide respective permissions.


## You need to add 'Network Service' and then it will start working.

我在 PowerShell 脚本中得到了同样的错误。对我来说,解决方法只是作为管理员运行脚本。因此,请确保您正在运行的尝试检索证书的应用程序以管理员身份运行。

这个问题是旧的,但它浮现在我今天和所有的阅读,我确实提到许可,但这不是我的情况。事实证明,我创建的新(Windows 服务)项目在默认情况下启用了此选项。 属性-> 构建-> 偏好32位。

通过取消选中此选项并重新部署此错误,一切工作正常。

希望这能帮到那些与许可无关的人。

在使用 SNK 数据签名文件时,我遇到了这个异常。 诀窍是在 CspParameter 中将 KeyNumber 设置为2(签名) ,例如:

$params = New-Object System.Security.Cryptography.CspParameters
$params.KeyNumber = 2


$rsa = New-Object System.Security.Cryptography.RSACryptoServiceProvider($params)
$rsa.ImportCspBlob($snk)
$signature = $rsa.SignData($inputBytes, [Security.Cryptography.HashAlgorithmName]::SHA256, [Security.Cryptography.RSASignaturePadding]::Pkcs1)


我在一个比赛条件下经历了这个异常。我在并行进程中使用同一个 PFX 文件大约10k 次(可能有50个并行进程) ,在大约1% 的情况下出现异常。我假设进程共享相同的私钥文件,句柄计数器有时计数错误或类似的情况,然后删除密钥文件,尽管另一个进程仍然需要它。

捕获异常并重新尝试使用同一个 X509Cericate2对象没有帮助。我现在没有进一步研究,但是我相信忽略并行化会有所帮助。