176

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

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

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

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

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

4

21 回答 21

300

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

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

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

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

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

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

于 2009-03-02T13:40:43.293 回答
39

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

C:\Documents and settngs\Administrator...

代替

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

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

于 2009-12-07T10:52:42.327 回答
30

解决IIS浏览时“Keyset不存在”的问题: 可能是私有权限

查看和授予权限:

  1. 运行>mmc>是
  2. 点击文件
  3. 点击添加/删除管理单元...</li>
  4. 双击证书
  5. 电脑账户
  6. 下一个
  7. 结束
  8. 单击证书(本地计算机)
  9. 点击个人
  10. 单击证书

授予权限:

  1. 右键单击证书名称
  2. 所有任务>管理私钥…</li>
  3. 添加并授予权限(添加 IIS_IUSRS 并授予它权限对我有用)
于 2016-08-30T09:09:22.787 回答
21

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

于 2014-01-11T21:51:42.507 回答
11

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

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

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

于 2013-07-09T14:07:56.763 回答
10

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

于 2013-07-17T13:29:41.970 回答
4

我收到错误消息:当我运行 MVC 应用程序时,CryptographicException 'Keyset does not exist'。

解决方案是:授予运行应用程序池的帐户访问个人证书的权限。就我而言,它是添加 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. 
于 2016-08-23T16:04:29.363 回答
3

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

findprivatekey root localmachine -n "CN="CertName" 

结果显示私钥在 c:\ProgramData 文件夹中,而不是 C:\Documents 和 settngs\All users..

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

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

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

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

于 2012-10-25T10:09:52.737 回答
2

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\Keysc\ProgramData\Microsoft\Crypto\中找到文件8787033f8ccb5836115b87acb_ca96c65a-4b42-a145-eee62128a

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

于 2019-10-01T08:28:09.010 回答
1

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

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

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

于 2012-06-26T16:18:42.797 回答
1

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

于 2018-07-31T16:24:49.167 回答
1

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

于 2021-09-02T19:42:00.590 回答
0

如果您将 ApplicationPoolIdentity 用于您的应用程序池,您可能无法在注册表编辑器中为该“虚拟”用户指定权限(系统中没有这样的用户)。

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

于 2011-08-09T13:38:29.853 回答
0

我只是想添加一个健全性检查答案。即使在我的机器上将证书安装到正确的商店并为客户端拥有所有正确的安全权限后,我也遇到了完全相同的错误。原来我混淆了我的 clientCertificate 和我的服务证书。如果您已经尝试了以上所有方法,我会仔细检查您是否有这两个。一旦我这样做了,我的应用程序就成功地调用了 Web 服务。同样,只是一个健全的检查器。

于 2013-01-02T16:44:29.297 回答
0

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

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

于 2013-09-26T20:51:16.850 回答
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 -->

于 2018-04-02T02:30:51.553 回答
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

于 2019-08-27T04:42:23.483 回答
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.
于 2020-02-25T07:07:50.140 回答
0

这个问题很老,但它今天浮出水面,我所做的所有阅读都提到了许可,但我的情况并非如此。事实证明,我创建的新(Windows 服务)项目默认启用了此选项。属性--> 构建--> 首选 32 位。

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

希望这可以帮助那些问题与权限无关的人。

于 2021-11-17T00:23:38.747 回答
0

使用 SNK 数据签署文件时遇到此异常。诀窍是在 CspParameters 中将 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)

于 2021-12-23T12:31:57.710 回答