CryptographicException'Keyset不存在',但仅限于WCF

时间:2009-03-02 13:25:15

标签: .net wcf x509

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

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

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

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

任何人都可以对这个问题有所了解吗?

18 个答案:

答案 0 :(得分:262)

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

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

答案 1 :(得分:163)

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

运行单元测试时,您将在自己的用户上下文中执行这些操作,这取决于客户端证书所在的商店中的内容)是否可以访问该证书的私钥。 / p>

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

您需要在私钥上设置适当的权限,以允许该服务帐户访问它。 MSDN有the details

答案 2 :(得分:38)

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

C:\ Documents and settngs \ Administrator ...

而不是

C:\ Documents and settngs \所有用户......

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

答案 3 :(得分:21)

从IIS浏览时解决“密钥集不存在”: 可能是私人许可

查看并授予权限:

  1. 润GT; MMC>是
  2. 点击文件
  3. 点击添加/删除管理单元...
  4. 双击证书
  5. 计算机帐户
  6. 下一步
  7. 完成
  8. 确定
  9. 单击证书(本地计算机)
  10. 点击个人
  11. 单击“证书”
  12. 授予权限:

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

答案 4 :(得分:16)

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

答案 5 :(得分:10)

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

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

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

答案 6 :(得分:8)

完全令人沮丧,我遇到了同样的问题并尝试了上述大部分内容。导出的证书正确地具有读取C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys中的文件的权限,但事实证明它没有该文件夹的权限。添加它并且它起作用

答案 7 :(得分:3)

我也有类似的问题。 我使用了命令

findprivatekey root localmachine -n "CN="CertName" 

结果显示私钥位于c:\ ProgramData文件夹而不是C:\ Documents和settngs \所有用户..

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

但如果我搜索前面命令返回的相同密钥,我仍然可以在

中找到密钥

C:\ Documents and settngs \所有用户..

据我了解,IIS或托管的WCF没有从C:\ Documents和settngs \ All users中找到私钥..

答案 8 :(得分: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. 

答案 9 :(得分:1)

我发现了一些缺少的信息,这些信息帮助我获得了带有消息级安全性的WCF服务,而不是“Keyset不存在”,尽管授予了从互联网上的示例生成的所有密钥的权限,但我一直在运行。

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

这填补了我的空白,最后允许我实现具有消息级安全性的WCF服务。我正在构建一个必须符合HIPPA标准的WCF。

答案 10 :(得分:1)

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

我尝试了FindPrivateKey,但是找不到私钥,并且使用powershell的$cert.privatekey.cspkeycontainerinfo.uniquekeycontainername为空/空。

幸运的是,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 。 / p>

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

答案 11 :(得分: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.

答案 12 :(得分: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));

Reference 1

Reference 2

答案 13 :(得分:0)

我刚刚将证书重新安装在本地计算机上,然后工作正常

答案 14 :(得分:0)

我在我的服务结构项目中看到此问题后,用于验证我们的密钥保险库已过期的证书并且已经过轮换,这改变了指纹。我收到此错误是因为我错过了更新此块中applicationManifest.xml文件中的指纹,这正是其他答案所建议的 - 给予NETWORK SERVICE(我所有的exes运行,as azure servicefabric cluster的标准配置)权限访问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 -->
&#13;
&#13;
&#13;

答案 15 :(得分:0)

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

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

答案 16 :(得分:0)

我只想添加一个健全性检查答案。即使在将证书安装到我的机器上的正确存储并且具有客户端的所有正确安全权限之后,我也得到完全相同的错误。结果我混淆了我的clientCertificate和我的服务证书。如果你已经尝试了以上所有,我会仔细检查你是否有这两个。 一旦我这样做,我的应用程序成功调用了Web服务。 再一次,只是一个理智的检查员。

答案 17 :(得分:0)

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

因此,使用subinacl - 启用set registry ACL的命令行工具,或类似的东西。