CryptographicException“密钥集不存在”,但只能通过 WCF
我有一些代码可以调用使用 X.509 认证保护的第三方 Web 服务。
如果我直接调用代码(使用单元测试),它就可以正常工作。
部署后,将通过 WCF 服务调用此代码。 我添加了第二个调用 WCF 服务的单元测试,但是当我调用第三方方法时,此测试会失败,并出现 CryptographicException
、消息 “Keyset 不存在”
网络服务。
我认为这是因为我的 WCF 服务将尝试使用与我不同的用户来调用第三方 Web 服务。
任何人都可以对这个问题有更多的了解吗?
I have some code that makes a call to a third party web service that is secured using X.509 certification.
If I call the code directly (using a unit test) it works without any problems.
When deployed, this code will be called via a WCF Service. I have added a second unit test that calls the WCF Service, however this fails with a CryptographicException
, message "Keyset does not exist"
when I call a method on the third party web service.
I presume that this is because my WCF Service will be attempting to call the third party web service using a different user to myself.
Can anyone shed any additional light on this issue?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(25)
这很可能是因为 IIS 用户无权访问您的证书的私钥。 您可以按照以下步骤进行设置...
证书(本地计算机)→ 个人 → 证书
This is most likely because the IIS user doesn't have access to the private key for your certificate. You can set this by following these steps...
Certificates (Local Computer) → Personal → Certificates
这可能是证书上的权限问题。
运行单元测试时,您将在自己的用户上下文中执行这些测试,(取决于客户端证书所在的存储)将有权访问该证书的私钥。
但是,如果您的 WCF 服务托管在 IIS 下,或者作为 Windows 服务,则它可能会在服务帐户(网络服务、本地服务或其他一些受限帐户)下运行。
您需要对私钥设置适当的权限,以允许该服务帐户访问它。 MSDN 有详细信息
It will probably be a permissions problem on the certificate.
When running a unit test you are going to be executing those under your own user context, which (depending on what store the client certificate is in) will have access to that certificate's private key.
However if your WCF service is hosted under IIS, or as a Windows Service it's likely it will be running under a service account (Network Service, Local Service or some other restricted account).
You will need to set the appropriate permissions on the private key to allow that service account access to it. MSDN has the details
我昨晚也遇到了同样的问题。 私钥的权限设置正确,除了密钥集不存在错误之外,一切显然都很好。 最后发现证书先导入到当前用户存储,然后移动到本地机器存储。 但是 - 这并没有移动私钥,私钥仍然位于
C:\Documents 和 settngs\Administrator...
而不是
C:\Documents 和 settngs\All users...
尽管密钥的权限设置正确, ASPNET 无法访问它。 当我们重新导入证书以便将私钥放置在“所有用户”分支中时,问题就消失了。
I've had identical issue last night. Permissions on private key were set correctly, everything was apparently fine except the Keyset doesn't exist error. In the end it turned out that certificate was imported to the current user store first and then moved to local machine store. However - that didn't move the private key, which was still in the
C:\Documents and settngs\Administrator...
instead of
C:\Documents and settngs\All users...
Altough permissions on the key were set correctly, ASPNET couldn't access it. When we re-imported certificate so that private key is placed in the All users branch, the problem disappeared.
解决从IIS浏览时“Keyset不存在”的问题:
可能是私人权限
查看并授予权限:
要授予权限:
To solve the “Keyset does not exist” when browsing from IIS:
It may be for the private permission
To view and give the permission:
To give the permission:
尝试从 Visual Studio 运行 WCF 应用程序时遇到同样的问题。 通过以管理员身份运行 Visual Studio 解决了这个问题。
Had the same problem while trying to run WCF app from Visual Studio. Solved it by running Visual Studio as administrator.
我遇到过这个问题,我的证书有私钥,但我收到此错误(“密钥集不存在”)
原因:您的网站在“网络”下运行服务”帐户或权限较少。
解决方案:将应用程序池标识更改为“本地系统”,重置 IIS 并再次检查。
如果它开始工作,这是权限/较少权限问题,您也可以冒充然后使用其他帐户。
I have faced this issue, my certificates where having private key but i was getting this error("Keyset does not exist")
Cause: Your web site is running under "Network services" account or having less privileges.
Solution: Change Application pool identity to "Local System", reset IIS and check again.
If it starts working it is permission/Less privilege issue, you can impersonate then using other accounts too.
完全令人沮丧,我遇到了同样的问题并尝试了上述大部分方法。 导出的证书正确地具有读取 C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys 中的文件的权限,但事实证明它没有该文件夹的权限。 添加它并且它起作用了
Totally frustrating, I had the same issue and tried most of the above. The exported certificate correctly had permissions to read the file in
C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys
, however as it turns out it didn't have permission on the folder. Added it and it worked当我运行 MVC 应用程序时,出现错误: CryptographicException“密钥集不存在”。
解决方案是:向运行应用程序池的帐户授予对个人证书的访问权限。 就我而言,是添加 IIS_IUSRS 并选择正确的位置解决了这个问题。
I was getting the error : CryptographicException 'Keyset does not exist' when i run the MVC application.
Solution was : to give access to the personal certificates to the account that application pool is running under. In my case it was to add IIS_IUSRS and choosing the right location resolved this issue.
我也有完全相同的问题。
我使用了该命令,
结果显示私钥位于 c:\ProgramData 文件夹中,而不是 C:\Documents 和 settngs\All users 中。
当我从 c:\ProgramData 文件夹中删除密钥时,再次运行 findPrivatekey 命令没有成功。 IE。 它没有找到钥匙。
但是,如果我搜索先前命令返回的相同密钥,我仍然可以在
C:\Documents and settngs\All users 中找到该密钥。
所以据我了解,IIS 或托管的 WCF 没有从 C:\文档和设置\所有用户..
I have exactly similar problem too.
I have used the command
the result shows that the private key is in c:\ProgramData folder instead of C:\Documents and settngs\All users..
When I delete the key from c:\ProgramData folder, again run the findPrivatekey command does not succeed. ie. it does not find the key.
But if i search the same key returned by earlier command, i can still find the key in
C:\Documents and settngs\All users..
So to my understanding, IIS or the hosted WCF is not finding the private key from C:\Documents and settngs\All users..
Steve Sheldon 的答案为我解决了这个问题,但是,由于我在没有 GUI 的情况下编写证书权限脚本,因此我需要一个可编写脚本的解决方案。 我努力寻找我的私钥存储在哪里。 私钥不在 -C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys 中,最终我发现它实际上在
C:\ProgramData\Microsoft\Crypto\Keys
中代码>. 下面我描述了我是如何发现这一点的:我尝试了 FindPrivateKey 但它找不到私钥,并且使用 powershell 时 $cert.privatekey.cspkeycontainerinfo.uniquekeycontainername 为 null/空的。
幸运的是,
certutil -store my
列出了证书,并为我提供了编写解决方案所需的详细信息。然后,我扫描了
c\ProgramData\Microsoft\Crypto\
文件夹,并在以下位置找到了文件 8787033f8ccb5836115b87acb_ca96c65a-4b42-a145-eee62128a C:\ProgramData\Microsoft\Crypto\Keys 。授予我的服务帐户读取此文件的权限解决了我的问题
The Answer from Steve Sheldon fixed the problem for me, however, as I am scripting certificate permissions with out a gui, I needed a scriptable solution. I struggled to find where my private key was stored . The private key was not in
-C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys
, eventually I found that it was actually inC:\ProgramData\Microsoft\Crypto\Keys
. Below I describe how I found that out:I tried
FindPrivateKey
but it could not find the private key, and using powershell the$cert.privatekey.cspkeycontainerinfo.uniquekeycontainername
was null/empty.Luckily,
certutil -store my
listed the certificate and gave me the details I needed to script the solution.I then scanned
c\ProgramData\Microsoft\Crypto\
folder and found the file 8787033f8ccb5836115b87acb_ca96c65a-4b42-a145-eee62128a in C:\ProgramData\Microsoft\Crypto\Keys .Giving my service account read access this file fixed the issues for me
我在 PowerShell 脚本中遇到了同样的错误。 对我来说,解决方法只是以管理员身份运行脚本。 因此,请确保您正在运行的任何尝试检索证书的应用程序都以管理员身份运行。
I was getting this same error in my PowerShell scripts. The fix for me was simply to run the script as administrator. So make sure whatever app you're running that attempts to retrieve the certificate is running as admin.
这是 Azure 中的修复程序。
而不是摆弄不同的 KeyStorageFlags(它描述了如何在操作系统上存储私钥)和不同的 web.config 设置。
使用EphemeralKeySet,它将在内存中加载私钥(https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.x509keystorageflags?view=netframework-4.7 .2 )
测试一下,它每次都会工作:)
提示:如果您需要更多信息或其他方法,请阅读 https://github.com/projectkudu/kudu/wiki/Best-X509Certificate2-Practices
Here's the fix for in Azure.
Instead of fiddling with different KeyStorageFlags ( which describes how to store the private key on the OS) and different web.config settings.
Use EphemeralKeySet, which will load the private key in memory ( https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.x509keystorageflags?view=netframework-4.7.2 )
Test it out and it will work every time :)
Tip: If you need more info or other methods, read https://github.com/projectkudu/kudu/wiki/Best-X509Certificate2-Practices
我发现一些缺失的信息帮助我获得了具有消息级安全性的 WCF 服务,尽管我向互联网上的示例生成的所有密钥授予了权限,但我仍然遇到“密钥集不存在”的问题。
我最终将私钥导入到本地计算机上的受信任人员存储中,然后授予私钥正确的权限。
这填补了我的空白,最终让我能够实现具有消息级安全性的 WCF 服务。 我正在构建必须符合 HIPPA 要求的 WCF。
I found some missing information that helped me get my WCF service with Message level security past the "Keyset does not exist" that I kept running into despite granting permissions to all the keys generated from the examples on the internet.
I finally imported the private key into the trusted people store on local machine and then granted the private key the correct permissions.
This filled in the blanks for me and finally allowed me to implement the WCF service with Message level security. I am building a WCF that must be HIPPA compliant.
我刚刚在本地计算机中重新安装了我的证书,然后它工作正常
I just reinstalled my certificate in local machine and then it is working fine
就我而言,问题有所不同。
通过 MMC 添加任何权限不会改变任何内容。
我在 PowerShell 中运行此命令来找出此私钥文件的位置:
在这里,您应该将“YourCertThumbprint”更改为您自己的证书指纹。
这将返回您的密钥的唯一名称。 我在Windows中搜索了这个密钥,发现它存储在:“C:/ProgramData/Microsoft/Crypto/RSA/MachineKeys”现在,我右键单击这个文件,转到权限,然后中提琴,我没有看到我在 MMC 中为此文件授予的任何权限,因此这意味着 MMC 不起作用。 在我仅向该文件添加 IIS_IUSRS 权限后,它解决了该问题。
因此,您不应该总是指望 MMC 和 Microsoft Windows;而是应该这样做。 您应该始终检查该文件是否确实具有权限。
In my case, the issue was something different.
Adding any permission through MMC did not change anything.
I ran this in PowerShell to find out where this private key file is:
Here, you should change "YourCertThumbprint" to your own certificate thumbprint.
This returns the unique name of your key. I searched for this key in Windows and found out that it's stored in: "C:/ProgramData/Microsoft/Crypto/RSA/MachineKeys" Now, I right-click this file, go to permissions, and viola, I don't see any of the permissions I gave in MMC for this file, so it means MMC did not work. After I only added IIS_IUSRS permission to this file, it fixed the issue.
So, you should not always count on MMC and Microsoft Windows; you should always check that the file actually has permission.
如果您将 ApplicationPoolIdentity 用于应用程序池,则在注册表编辑器中为该“虚拟”用户指定权限时可能会遇到问题(系统中没有此类用户)。
因此,使用 subinacl - 启用设置注册表的命令行工具ACL,或者类似的东西。
If you use ApplicationPoolIdentity for your application pool, you may have problem with specifying permission for that "virtual" user in registry editor (there is not such user in system).
So, use subinacl - command-line tool that enables set registry ACL's, or something like this.
我只是想添加一个健全性检查答案。 即使将证书安装到计算机上的正确存储并为客户端拥有所有正确的安全权限后,我仍然遇到完全相同的错误。 结果我混淆了我的 clientCertificate 和我的服务证书。 如果您已经尝试了以上所有方法,我会仔细检查您是否有这两项。
完成此操作后,我的应用程序成功调用了 Web 服务。
再说一遍,只是一个健全性检查器。
I just wanted to add a sanity check answer. I was getting the exact same error even after installing the certificates to the right stores on my machines and having all the right security privileges for the client. Turns out I mixed up my clientCertificate and my Service Certificate. If you have tried all of the above, I would double check that you have those two straight.
Once I did that, my application successfully called the web service.
Again, just a sanity checker.
在 IIS7 上使用 openAM Fedlet 时收到此错误
更改默认网站的用户帐户解决了该问题。 理想情况下,您希望这是一个服务帐户。 也许甚至是 IUSR 帐户。 建议查找 IIS 强化方法以彻底解决问题。
Received this error while using the openAM Fedlet on IIS7
Changing the user account for the default website resolved the issue. Ideally, you would want this to be a service account. Perhaps even the IUSR account. Suggest looking up methods for IIS hardening to nail it down completely.
在用于对我们的密钥保管库进行身份验证的证书过期并轮换后,我在我的服务结构项目中遇到了这个问题,这改变了指纹。 我收到此错误是因为我错过了更新此块中的 applicationManifest.xml 文件中的指纹,该文件精确地执行了其他答案所建议的操作 - 授予 NETWORK SERVICE (我所有的 exes 都运行为 azure servicefabric 集群的标准配置)权限访问 LOCALMACHINE\MY 证书存储位置。
记下“X509FindValue”属性值。
I hit this in my service fabric project after the cert used to authenticate against our key vault expired and was rotated, which changed the thumbprint. I got this error because I had missed updating the thumbprint in the applicationManifest.xml file in this block which precisely does what other answers have suggested - to given NETWORK SERVICE (which all my exes run as, standard config for azure servicefabric cluster) permissions to access the LOCALMACHINE\MY cert store location.
Note the "X509FindValue" attribute value.
这是唯一对我有用的解决方案。
参考 1
参考2
This is the only solution worked for me.
Reference 1
Reference 2
这个问题很老了,但今天我才发现它,我所做的所有阅读都提到了许可,但我的情况并非如此。 原来我创建的新(Windows服务)项目默认启用了这个选项。
属性-->构建-->首选 32 位。
通过取消选中此选项并重新部署,此错误消失,一切正常。
希望这对问题与权限无关的人有所帮助。
This issue is old but it surfaced to me today and all the readings I did refer to permission, but that wasn't the case with me. It turned out that the new (Windows Service) project I created had this option enabled by default.
Properties-->Build-->Prefer 32-bit.
By unchecking this option and re-deploying this error went away and everything worked fine.
Hope this helps someone whose issue isn't permission-related.
我在使用 SNK 数据签署文件时遇到此异常。
诀窍是在 CspParameters 中将 KeyNumber 设置为 2(签名),例如:
I was having this exception when signing a file using SNK data.
The trick is to set the KeyNumber to 2 (Signature) in the CspParameters, e.g.:
我在竞争条件下遇到了这个异常。 我在并行进程(可能并行 50 个进程)中使用同一个 PFX 文件大约 10k 次,异常出现在大约 1% 的情况下。 我假设这些进程共享相同的私钥文件,并且句柄计数器有时计数错误或类似的情况,然后密钥文件被删除,尽管另一个进程仍然需要它。
捕获异常并重试使用相同的 X509Certificate2 对象没有帮助。 我暂时没有进一步调查,但我相信省略并行化会有所帮助。
I experienced this exception in a race condition. I used the same PFX file about 10k times in parallel processes (maybe 50 processes in parallel) and the exception appeared in about 1 % of the cases. I assume that the processes share the same private key file and the handle counter sometimes counts wrong or something the like, and then the key file is deleted although another process still needs it.
Catching the exception and retrying to use the same X509Certificate2 object didn't help. I didn't investigate further for now, but I believe it would help to leave out the parallelization.
我还建议此处讨论的解决方案。 正如那里所解释的:
因此,通过在将 PFX 文件加载到 X509Certificate2 之前删除 PFX 文件中的FriendlyName 属性来解决该问题。
这段代码对我有用:
I'd also suggest the solution discussed here. As explained there:
So, the problem was solved by removing the friendlyName attribute from the PFX file before loading it to X509Certificate2.
This code worked for me: