CryptographicException“密钥集不存在”,但只能通过 WCF

发布于 2024-07-14 13:14:10 字数 312 浏览 6 评论 0原文

我有一些代码可以调用使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(25

南烟 2024-07-21 13:14:10

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

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

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

  1. Start → Run → MMC
  2. File → Add/Remove Snapin
  3. Add the Certificates Snap In
  4. Select Computer Account, then hit next
  5. Select Local Computer (the default), then click Finish
  6. On the left panel from Console Root, navigate to
    Certificates (Local Computer) → Personal → Certificates
  7. Your certificate will most likely be here.
  8. Right click on your certificate → All Tasks → Manage Private Keys
  9. Set your private key settings here.
北风几吹夏 2024-07-21 13:14:10

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

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

但是,如果您的 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

污味仙女 2024-07-21 13:14:10

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

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.

几味少女 2024-07-21 13:14:10

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

查看并授予权限:

  1. 运行>mmc>是单击
  2. 文件
  3. 单击添加/删除管理单元...
  4. 双击证书
  5. 计算机帐户
  6. 下一步
  7. 完成
  8. 确定
  9. 单击证书(本地计算机)
  10. 单击个人
  11. 单击证书

要授予权限:

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

To solve the “Keyset does not exist” when browsing from IIS:
It may be for the private permission

To view and give the permission:

  1. Run>mmc>yes
  2. click on file
  3. Click on Add/remove snap-in…
  4. Double click on certificate
  5. Computer Account
  6. Next
  7. Finish
  8. Ok
  9. Click on Certificates(Local Computer)
  10. Click on Personal
  11. Click Certificates

To give the permission:

  1. Right Click on the name of certificate
  2. All Tasks>Manage Private Keys…
  3. Add and give the privilege( adding IIS_IUSRS and giving it the privilege works for me )
幸福%小乖 2024-07-21 13:14:10

尝试从 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.

韶华倾负 2024-07-21 13:14:10

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

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

解决方案:将应用程序池标识更改为“本地系统”,重置 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.

风轻花落早 2024-07-21 13:14:10

完全令人沮丧,我遇到了同样的问题并尝试了上述大部分方法。 导出的证书正确地具有读取 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

紫南 2024-07-21 13:14:10

当我运行 MVC 应用程序时,出现错误: CryptographicException“密钥集不存在”。

解决方案是:向运行应用程序池的帐户授予对个人证书的访问权限。 就我而言,是添加 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. 

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.

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. 
草莓味的萝莉 2024-07-21 13:14:10

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

findprivatekey root localmachine -n "CN="CertName" 

结果显示私钥位于 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

findprivatekey root localmachine -n "CN="CertName" 

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

老子叫无熙 2024-07-21 13:14:10

Steve Sheldon 的答案为我解决了这个问题,但是,由于我在没有 GUI 的情况下编写证书权限脚本,因此我需要一个可编写脚本的解决方案。 我努力寻找我的私钥存储在哪里。 私钥不在 -C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys 中,最终我发现它实际上在 C:\ProgramData\Microsoft\Crypto\Keys 中代码>. 下面我描述了我是如何发现这一点的:

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

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

<代码>================ 证书 1 ================
序列号:162f1b54fe78c7c8fa9df09
发行人:CN=*.internal.xxxxxxx.net
之前:23/08/2019 14:04
不之后: 23/02/2020 14:24
主题:CN=*.xxxxxxxnet
签名与公钥匹配
根证书:主题与颁发者匹配
证书哈希(sha1):xxxxa5f0e9f0ac8b7dd634xx
密钥容器 = {407EC7EF-8701-42BF-993F-CDEF8328DD}
唯一容器名称:8787033f8ccb5836115b87acb_ca96c65a-4b42-a145-eee62128a
#* ^-- 私钥文件名*##
提供商 = Microsoft 软件密钥存储提供商
私钥不可以纯文本形式导出
加密测试通过
CertUtil:-store 命令成功完成。

然后,我扫描了 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 in C:\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.

================ 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.

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

原来是傀儡 2024-07-21 13:14:10

我在 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.

不语却知心 2024-07-21 13:14:10

这是 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

小女人ら 2024-07-21 13:14:10

我发现一些缺失的信息帮助我获得了具有消息级安全性的 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.

酒浓于脸红 2024-07-21 13:14:10

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

I just reinstalled my certificate in local machine and then it is working fine

星軌x 2024-07-21 13:14:10

就我而言,问题有所不同。
通过 MMC 添加任何权限不会改变任何内容。
我在 PowerShell 中运行此命令来找出此私钥文件的位置:

[System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey((Get-ChildItem $certStorePath | Where thumbprint -eq <YourCertThumbprint>)).key.UniqueName

在这里,您应该将“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:

[System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey((Get-ChildItem $certStorePath | Where thumbprint -eq <YourCertThumbprint>)).key.UniqueName

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.

寄风 2024-07-21 13:14:10

如果您将 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.

不必在意 2024-07-21 13:14:10

我只是想添加一个健全性检查答案。 即使将证书安装到计算机上的正确存储并为客户端拥有所有正确的安全权限后,我仍然遇到完全相同的错误。 结果我混淆了我的 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.

胡渣熟男 2024-07-21 13:14:10

在 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.

奢欲 2024-07-21 13:14:10

在用于对我们的密钥保管库进行身份验证的证书过期并轮换后,我在我的服务结构项目中遇到了这个问题,这改变了指纹。 我收到此错误是因为我错过了更新此块中的 applicationManifest.xml 文件中的指纹,该文件精确地执行了其他答案所建议的操作 - 授予 NETWORK SERVICE (我所有的 exes 都运行为 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 -->

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.

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

ぺ禁宫浮华殁 2024-07-21 13:14:10

这是唯一对我有用的解决方案。

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

This is the only solution worked for me.

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

我们只是彼此的过ke 2024-07-21 13:14:10
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.
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.
白馒头 2024-07-21 13:14:10

这个问题很老了,但今天我才发现它,我所做的所有阅读都提到了许可,但我的情况并非如此。 原来我创建的新(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.

人生戏 2024-07-21 13:14:10

我在使用 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)

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.:

$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)

作死小能手 2024-07-21 13:14:10

我在竞争条件下遇到了这个异常。 我在并行进程(可能并行 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.

心头的小情儿 2024-07-21 13:14:10

我还建议此处讨论的解决方案。 正如那里所解释的:

PFX 的密钥具有amiliesName 属性。 Windows PFXImportCertStore 存在竞争条件,即并行打开两个具有相同FriendlyName 值的PFX(包括“相同的PFX”)可能会导致两个对象相互链接,删除一个对象会从另一个对象下删除密钥。

因此,通过在将 PFX 文件加载到 X509Certificate2 之前删除 PFX 文件中的FriendlyName 属性来解决该问题。

这段代码对我有用:

 public static void Foo( byte[] certificate, string pin)
    {
        using (X509Certificate2 cert = new X509Certificate2(certificate, pin,
                X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable))
        {
            if (!string.IsNullOrEmpty(cert.FriendlyName))
            {
                cert.FriendlyName = null;
                var bytesCert = cert.Export(X509ContentType.Pkcs12, pin);
                Foo(bytesCert , pin); //To reopen the certificate without the FriendlyName
                return;
            }
            cert.GetRSAPrivateKey() //It works!
        }
    }

I'd also suggest the solution discussed here. As explained there:

The PFX has the friendlyName attribute on the key. Windows PFXImportCertStore has a race condition where opening two PFXes (including "the same PFX") that have identical friendlyName values in parallel may result in the two objects becoming inter-linked, and deleting one deletes the key out from under the other.

So, the problem was solved by removing the friendlyName attribute from the PFX file before loading it to X509Certificate2.

This code worked for me:

 public static void Foo( byte[] certificate, string pin)
    {
        using (X509Certificate2 cert = new X509Certificate2(certificate, pin,
                X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable))
        {
            if (!string.IsNullOrEmpty(cert.FriendlyName))
            {
                cert.FriendlyName = null;
                var bytesCert = cert.Export(X509ContentType.Pkcs12, pin);
                Foo(bytesCert , pin); //To reopen the certificate without the FriendlyName
                return;
            }
            cert.GetRSAPrivateKey() //It works!
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文