System.Security.Cryptography.CryptographicException:密钥集不存在

Posted

技术标签:

【中文标题】System.Security.Cryptography.CryptographicException:密钥集不存在【英文标题】:System.Security.Cryptography.CryptographicException: keyset does not exist 【发布时间】:2012-08-19 19:37:44 【问题描述】:

当我制作 x509 证书来加密和解密消息时,我收到了一些错误信息,无法解决这个问题。有人能碰巧解决这个错误吗?谢谢。

说明:在执行当前 Web 请求期间发生未处理的异常。请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息。

异常详情:

System.Security.Cryptography.CryptographicException: 密钥集不存在。

来源错误:

第 53 行:使用 (RSACryptoServiceProvider rsaProviderDecrypt = (RSACryptoServiceProvider)cerDecrypt.PublicKey.Key) 第 54 行: 第 55 行:plainHashBytes = rsaProviderDecrypt.Decrypt(encryptedHashBytes, false);第 56 行: rsaProviderDecrypt.Clear();第 57 行: rsaProviderDecrypt.Dispose();

源文件: E:\PayUSite\PayMvcApp\Controllers\HashMessageController.cs 行:55

堆栈跟踪:

[CryptographicException:密钥集不存在。 ] System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 小时) +41 System.Security.Cryptography.RSACryptoServiceProvider.DecryptKey(SafeKeyHandle pKeyContext, Byte[] pbEncryptedKey, Int32 cbEncryptedKey, Boolean fOAEP, ObjectHandleOnStack ohRetDecryptedKey) +0 System.Security.Cryptography.RSACryptoServiceProvider.Decrypt(字节[] rgb, 布尔 fOAEP) +579

源代码:

string docFile = Server.MapPath("~/docx/DirectAccess_StepByStep.doc");
HashAlgorithm hash = HashAlgorithm.Create("SHA1");
byte[] hashedBytes;
using (FileStream fs = new FileStream(docFile, FileMode.Open))

    //compute message hash value
    hashedBytes = hash.ComputeHash(fs);
    hash.Dispose();
    fs.Close();

    
string hashedString = Convert.ToBase64String(hashedBytes);
    
//encrypt message digest
string priKeyFile = Server.MapPath("~/certificate/WosMiddle.pfx");
X509Certificate2 certEncrypt = new X509Certificate2(priKeyFile, "123456");
byte[] encryptedHashBytes;
using (RSACryptoServiceProvider rsaProviderEncrypt = (RSACryptoServiceProvider)certEncrypt.PrivateKey)

    encryptedHashBytes = rsaProviderEncrypt.Encrypt(hashedBytes, false);
    rsaProviderEncrypt.Dispose();

    
//decrypt message digest
string pubKeyFile = Server.MapPath("~/certificate/WosMiddle-pubkey.cer");
X509Certificate2 cerDecrypt = new X509Certificate2(pubKeyFile);
byte[] plainHashBytes;
using (RSACryptoServiceProvider rsaProviderDecrypt = (RSACryptoServiceProvider)cerDecrypt.PublicKey.Key)

    //***will throw error message here...***
    plainHashBytes = rsaProviderDecrypt.Decrypt(encryptedHashBytes, false);
    rsaProviderDecrypt.Dispose();

    
//verify message whether was modified
string docFile2 = Server.MapPath("~/docx/DirectAccess_StepByStep.doc");
HashAlgorithm hash2 = HashAlgorithm.Create("SHA1");
byte[] hashedBytes2;
using (FileStream fs2 = new FileStream(docFile2, FileMode.Open))

    //compute message hash value
    hashedBytes2 = hash.ComputeHash(fs2);
    fs2.Close();

    
//compare hash value
bool isEqual = plainHashBytes.SequenceEqual(hashedBytes2);

【问题讨论】:

CryptographicException 'Keyset does not exist', but only through WCF的可能重复 我以前见过这种情况。在Cryptographic Interoperability: Digital Signatures 搜索“密钥集不存在”。我认为打开了几个句柄。当它们被垃圾收集时,共享资源会被清理多次(这不起作用)。我会仔细查看certEncrypt.PrivateKey(加密通常使用公钥)和cerDecrypt.PublicKey(解密通常使用私钥)。我认为它们在离开using 块时已被清理干净。 【参考方案1】:

应用程序可能正在尝试写入以下文件夹路径:C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys

如果您的应用程序使用模拟或使用 IUSR_MACHINENAME 用户,则配置 MachineKeys 文件夹安全性并为用户提供读取和执行、列出文件夹内容、读取、写入。如果这不起作用,请尝试为 Everyone 用户授予相同的权限。

【讨论】:

我已尝试为“所有人”授予对 MachineKeys 目录的写入权限,但仍然显示相同的错误消息。 我的理解是上面提到的 MachineKeys 文件夹有一个很好的理由限制权限:它应该在操作系统的控制之下。您不应该能够直接访问它。【参考方案2】:

我相信在使用 Encrypt 和 Decrypt 时,它需要一个用于加密的公钥和一个用于解密的私钥。所以它失败了,因为你试图在没有私钥的情况下解密,这会导致异常。

你真的应该使用 SignData 用于创建签名的方法和VerifyData 用于验证。

【讨论】:

接收者太多,发送者最好提供公钥(给接收者)和私钥(给自己)。 你是对的,我修改了我的代码以使用 CreateSignature 而不是加密,这样可以运行并产生正确的结果。谢谢。:-)【参考方案3】:

这个问题很老,但是对于那些在继续使用 EncryptDecrypt 的同时寻找解决方案的人来说,这是我设法解决这个错误的方法:

基础是我的证书通过双击.pfx文件并选择商店以错误的方式安装。

证书安装方式错误

1. 双击证书:

2.向导打开,点击下一个按钮:

3. 向导显示证书位置,点击下一步按钮:

4.输入密码然后点击下一步:

5. 选择商店然后点击下一步:

6.向导显示证书信息,点击Finish按钮

7. 显示成功对话框:

所以此时我遇到了错误“密钥集不存在”


为了解决我是这样进行的(正确的方法)

1. 执行 Microsoft 管理控制台 (mmc.exe):

2. 一个空白的 MMC 实例显示:

3. 点击文件->添加/删除管理单元...

4. 选择证书管理单元并单击添加按钮:

5.选择计算机帐户然后点击下一步按钮:

6. 选择本地计算机然后点击完成按钮:

7. 证书管理单元现已添加,点击OK按钮:

8. 选择个人商店,然后右键单击并选择导入

9. 浏览证书,然后点击下一步:

10.输入密码,然后点击下一步按钮:

11.自动选择证书存储:

12.证书信息显示:

13. 成功对话框消息显示:

14. 刷新 MMConsole 以显示证书:

15. 右击证书,然后点击Manage Private Keys...

16. 添加池标识或 IIS 用户在我的情况下,我添加了 IIS_IUSRS:

17.用户已添加,点击OK按钮:

完成了,keyset现在确实存在了!!

【讨论】:

您可以通过说“用户没有私钥的权限,因此您需要授予它权限”来大大简化您的答案。该解决方案与您如何导入证书无关(没有“正确”或“错误”的导入方式)。感谢您在解决方案中的最后一步! 我也遇到了这个问题,设置证书权限正是问题所在!感谢您的出色回答;截图ftw! 这通常是权限问题。您需要向运行应用程序/服务的用户帐户授予读取权限。 就我而言,从 MMC 控制台安装证书是可行的。通过双击.PFX 没有安装。 订单项 15 和 16 很重要。【参考方案4】:

在尝试签署 SAML 响应时,我没有将证书中的 PrivateKey 加载到我的 signedXmlElement 的 SigningKey 中,因此遇到了这个错误。

signedElement.SigningKey = myCertificate.PrivateKey;

【讨论】:

【参考方案5】:

我收到与 OP 相同的错误: “System.Security.Cryptography.CryptographicException:密钥集不存在”

解决方案(对我而言)是: Visual Studio 需要(以管理员身份运行)

正如向我解释的(YMMV),VS 需要以管理员身份运行,以便从密钥库中提取证书私钥,以便与 keyvault 协商身份验证/握手。

【讨论】:

@PalleDue,您的应用程序不需要以管理员身份运行,它只需要在已在证书上授权的用户/服务帐户凭据下运行,否则您可能需要重新考虑您的应用程序身份验证架构。如果您在不以管理员身份运行 VS 的情况下对证书进行身份验证,此解决方案也可能有效,具体取决于证书的安装位置。【参考方案6】:

我确实遇到了同样的问题。该消息并不理想,在我的情况下,我的用户没有访问私钥的权限。您可以使用以下步骤解决此问题:

    打开mmc 添加证书管理单元 选择您要使用的证书 右键单击它并选择“所有任务”/“管理私钥...” 将您的用户添加到授权用户列表并允许“完全控制”

【讨论】:

【参考方案7】:

尝试以管理员身份运行 vs。为我工作

【讨论】:

【参考方案8】:

在我的情况下,私钥存储在 "C:\ProgramData\Microsoft\Crypto\Keys" 而不是 machinekeys 文件夹中 - 您可以使用 certutil 检查以找出将成为私钥的“唯一容器名称”。

我现在扫描加密目录以查找匹配项。通过该匹配,我可以在适当的文件上设置正确的 ACL

【讨论】:

【参考方案9】:

.Net 在此处创建临时证书文件“..\Microsoft\Crypto\RSA\MachineKeys”。 可能是证书文件仍然锁定了另一个进程。尝试重新启动应用程序然后PC。如果问题解决了,您需要手动创建 .pfx 文件,然后在您的电脑上加载证书应用程序。

【讨论】:

请在您的回答中提供更多详细信息。正如目前所写的那样,很难理解您的解决方案。 如果您有新问题,请点击 按钮提出问题。如果有助于提供上下文,请包含指向此问题的链接。

以上是关于System.Security.Cryptography.CryptographicException:密钥集不存在的主要内容,如果未能解决你的问题,请参考以下文章