CryptographicException'密钥集不存在',但仅通过WCF


157

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

如果我直接调用代码(使用单元测试),它将正常工作。

部署后,将通过WCF服务调用此代码。我添加了另一个调用WCF服务的单元测试,但是当我在第三方Web服务上调用方法时,此失败并CryptographicException显示消息"Keyset does not exist"

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

任何人都可以在这个问题上提出更多的建议吗?

Answers:


168

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

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

但是,如果您的WCF服务托管在IIS下或作为Windows服务托管,则可能会在服务帐户(网络服务,本地服务或其他受限制的帐户)下运行。

您将需要在私钥上设置适当的权限,以允许该服务帐户对其进行访问。MSDN有详细信息


运行calcs帮助我解决了一个完全不同的问题,谢谢
约翰·

3
我以管理员身份运行我的APP,问题不再存在。
derek

1
MSDN文档的 +1 和列出的步骤甚至适用于Web应用程序
Naren

向证书安全权限添加“网络服务”对我来说解决了这个问题,谢谢!
OpMt

276

这很可能是因为IIS用户无权访问证书的私钥。您可以按照以下步骤进行设置...

  1. 开始->运行-> MMC
  2. 文件->添加/删除管理单元
  3. 添加证书管理单元
  4. 选择计算机帐户,然后单击下一步
  5. 选择本地计算机(默认),然后单击完成
  6. 在控制台根目录的左侧面板上,导航至证书(本地计算机)->个人->证书
  7. 您的证书很可能会在这里。
  8. 右键单击您的证书->所有任务->管理私钥
  9. 在此处设置您的私钥设置。

1
值得一提的是,除非我的环境配置错误,否则这不是Server 2003上的选项。我可以在Windows 7上执行此操作。
肖恩·哈伯德

在这里设置私钥是什么意思??我的意思是您只能添加具有访问权限的用户!
mastervv 2012年

10
谢谢,只想指出一点,如果您使用iis7.5,并且应用程序池作为applicationpoolidentity运行,则必须授予IIS AppPool \ DefaultAppPool用户对该文件的权限。这为我解决了问题。
罗南·费斯廷格

25
我必须授予IIS_IUSRS权限才能使其正常工作。
TrueEddie 2014年

1
如果在运行IIS Express时遇到此问题,则需要提供自己的登录权限。
2015年

38

昨晚我遇到了同样的问题。私钥的权限设置正确,除Keyset不存在错误外,其他一切似乎都很好。最后,结果证明证书首先被导入到当前的用户存储中,然后又被移至本地计算机存储中。但是-并没有移动私钥,该私钥仍在

C:\ Documents and settngs \ Administrator ...

代替

C:\ Documents and settngs \ All users ...

正确设置了密钥的足够权限,ASPNET无法访问它。当我们重新导入证书,以便将私钥放在“所有用户”分支中时,问题消失了。


同样的问题。微软需要停止让安全部门来庇护。
Paul Stovell 2011年

2
经过3个小时的损失,这解决了我的问题-谢谢。我使用了FindPrivateKey示例,并困惑了为什么它似乎出现在用户的密钥库中,即使它通过MMC管理单元出现在LocalMachine中也是如此。
罗伯·波特

我会花数小时浪费您啤酒的时间,而这就像其他答案所告诉我的那样,浪费了权限。
Scott Scowden

谢谢你,谢谢你,谢谢你!由于这个可怕的问题,我已经失去了大约2.5个小时的生命,如果没有看到这个,我敢肯定我会失去2.5天。
Frank Tzanabetis

相反,我有同样的问题。首先安装在本地计算机上,然后安装在当前用户中。从两个商店中删除所有证书,然后在“当前用户”下重新安装已修复它。
Bart Verkoeijen

24

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

要查看并给予许可:

  1. 运行> MMC>是
  2. 点击文件
  3. 单击添加/删除管理单元。
  4. 双击证书
  5. 电脑帐号
  6. 下一个
  7. 单击证书(本地计算机)
  8. 点击个人
  9. 点击证书

授予许可:

  1. 右键单击证书名称
  2. 所有任务>管理私钥…
  3. 添加并赋予特权(添加IIS_IUSRS并赋予它特权对我有效)

1
如果您在应用程序池下运行,请添加此用户,而不是“ IIS AppPool \ DefaultAppPool”
Sameer Alibhai

这也对我有帮助。一旦我给IIS_IUSRS授予权限,它便开始工作。
安德烈莫哈(Andrej Mohar)'18

18

尝试从Visual Studio运行WCF应用程序时遇到了相同的问题。通过以管理员身份运行Visual Studio来解决此问题。


11

我已经遇到了这个问题,我的证书拥有私钥,但是却出现此错误(密钥集不存在”

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

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


8

完全令人沮丧的是,我遇到了同样的问题,并尝试了上述大多数方法。导出的证书正确具有读取中的文件的权限C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys,但是事实证明,它对该文件夹没有权限。添加了它就可以了


我尝试了很多事情来解决这个问题,但是这个成功了!
Gyum Fox,

哇-没想到它能起作用,但确实可以。我添加IISAPPPool\www.mywebsite.com了我的appool的Windows用户名,它起作用了:-)
Simon_Weaver

有人知道为什么这样吗?是因为它

不要这样!当文件夹..RSA \ MachineKeys的基本权限更改时,服务器进入导入证书并显示为“ Microsoft Software KSP”提供程序类型的“不良状态”。更多详细信息reddit.com/r/sysadmin/comments/339ogk/…
Dhanuka777'1

3

我也有完全类似的问题。我已经使用了命令

findprivatekey root localmachine -n "CN="CertName" 

结果显示私钥位于c:\ ProgramData文件夹中,而不是C:\ Documents和settngs \ All用户。

当我从c:\ ProgramData文件夹中删除密钥时,再次运行findPrivatekey命令不会成功。即。它找不到密钥。

但是,如果我搜索先前命令返回的相同密钥,我仍然可以在其中找到密钥

C:\ Documents and settngs \ All users ..

因此,据我了解,IIS或托管的WCF并未从C:\ Documents and settngs \ All用户中找到私钥。


2
你好这个链接会告诉你如何解决这个问题,也找到findprivatekey工具: blogs.msdn.microsoft.com/dsnotes/2015/08/13/...
塔希尔·哈立德

3

我收到错误消息:当我运行MVC应用程序时,CryptographicException'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. 

2

史蒂夫·谢尔顿(Steve Sheldon)的答案为我解决了这个问题,但是,由于我不使用gui编写证书权限脚本,因此我需要一个可编写脚本的解决方案。我很难找到我的私钥存储在哪里。私钥不在-C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys,最终我发现它确实在C:\ProgramData\Microsoft\Crypto\Keys。下面我描述如何发现这一点:

我尝试过,FindPrivateKey但是找不到私钥,然后使用powershell$cert.privatekey.cspkeycontainerinfo.uniquekeycontainername为null / empty。

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

================ Certificate 1 ================ Serial Number: 162f1b54fe78c7c8fa9df09 Issuer: CN=*.internal.xxxxxxx.net NotBefore: 23/08/2019 14:04 NotAfter: 23/02/2020 14:24 Subject: CN=*.xxxxxxxnet Signature matches Public Key Root Certificate: Subject matches Issuer Cert Hash(sha1): xxxxa5f0e9f0ac8b7dd634xx Key Container = {407EC7EF-8701-42BF-993F-CDEF8328DD} Unique container name: 8787033f8ccb5836115b87acb_ca96c65a-4b42-a145-eee62128a ##* ^-- filename for private key*## Provider = Microsoft Software Key Storage Provider Private key is NOT plain text exportable Encryption test passed CertUtil: -store command completed successfully.

然后我扫描了c\ProgramData\Microsoft\Crypto\文件夹并在C:\ ProgramData \ Microsoft \ Crypto \ Keys中找到了文件8787033f8ccb5836115b87acb_ca96c65a-4b42-a145-eee62128a

授予我的服务帐户对该文件的读取访问权限为我解决了问题


1
使用“ certutil -store my”是解决我的问题的关键。我使用“唯一容器名称”来定位文件,并使用Sysinternals Process Monitor来解决证书文件上的“访问被拒绝”错误。就我而言,我必须为NT Authority \ IUSR用户提供对证书文件的读取访问权限。
hsop

1

我发现了一些丢失的信息,尽管授予了Internet上示例生成的所有密钥的权限,但这些消息仍使我始终遇到的“密钥集不存在”使我的WCF服务获得了消息级别的安全性。

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

这为我填补了空白,最终使我能够实现具有消息级别安全性的WCF服务。我正在构建必须符合HIPPA的WCF。



0

如果将ApplicationPoolIdentity用于应用程序池,则可能在注册表编辑器中为该“虚拟”用户指定权限(系统中没有该用户)时会遇到问题。

因此,请使用subinacl-启用设置注册表ACL或类似功能的命令行工具。


0

我只想添加一个健全性检查答案。即使在将证书安装到计算机上的正确存储区并为客户端具有所有正确的安全特权之后,我也得到了完全相同的错误。原来我混淆了我的clientCertificate和我的服务证书。如果您已经尝试了以上所有方法,那么我将再次检查您是否拥有这两点。完成此操作后,我的应用程序成功调用了Web服务。再次,只是一个健全性检查器。


0

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

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


0

在用于对我们的密钥保险库进行身份验证的证书过期并被轮换使用后,我在服务结构项目中遇到了这一问题,从而更改了指纹。我收到此错误,是因为我错过了在此块中的applicationManifest.xml文件中更新指纹的功能,而该指纹恰恰做了其他答案的建议-给了NETWORK SERVICE(我所有的exe文件都运行为Azure Servicefabric群集的标准配置)权限访问LOCALMACHINE \ MY证书存储位置。

注意“ 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 -->


0

这是唯一为我工作的解决方案。

    // 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


0
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.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.