简体   繁体   中英

System.Security.Cryptography.CryptographicException: keyset does not exist

When I make an x509 certificate to encrypt and decrypt messages, I got some error information and could not able to fix this problem. Could someone ever happen to solve this bug? thanks.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details:

System.Security.Cryptography.CryptographicException: keyset does not exist。

Source Error:

Line 53: using (RSACryptoServiceProvider rsaProviderDecrypt = (RSACryptoServiceProvider)cerDecrypt.PublicKey.Key) Line 54:
{ Line 55: plainHashBytes = rsaProviderDecrypt.Decrypt(encryptedHashBytes, false); Line 56:
rsaProviderDecrypt.Clear(); Line 57:
rsaProviderDecrypt.Dispose();

Source File: E:\PayUSite\PayMvcApp\Controllers\HashMessageController.cs Line: 55

Stack Trace:

[CryptographicException: keyset does not exist. ]
System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr) +41
System.Security.Cryptography.RSACryptoServiceProvider.DecryptKey(SafeKeyHandle pKeyContext, Byte[] pbEncryptedKey, Int32 cbEncryptedKey, Boolean fOAEP, ObjectHandleOnStack ohRetDecryptedKey) +0
System.Security.Cryptography.RSACryptoServiceProvider.Decrypt(Byte[] rgb, Boolean fOAEP) +579

source code:

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

This question is old but for someone looking for the solution while continuing to use Encrypt and Decrypt here is how I manage to solve this error:

The base is my certificate have been installed the wrong way by double-clicking the .pfx file and selecting the store.

The wrong way to install the certificate

1. Double click the certificate:

证书文件

2. The wizard opens, click in the next button:

向导 0

3. The wizard show the certificates location, click in the next button:

向导 1

4. Enter the password then click next:

向导 2

5. Select the store then click next:

巫师 3

6. The wizard show the certificate information, click in Finish button

向导 4

7. Succes dialog is showed:

巫师 5

So at this point I had the error "Keyset does not exist" .


To solve that I proceeded this way (the correct way)

1. Execute Microsoft Management Console (mmc.exe):

执行mmc

2. A blank MMC instance showed:

mmc 显示

3. Click in File->Add/Remove Snap-in...

添加管理单元

4. Select certificate snap-in an click in Add button:

添加证书管理单元

5. Select Computer account then click in Next button:

选择电脑账户

6. Select Local computer then click in Finish button:

选择本地计算机

7. The certificate snap-in is now added, click in OK button:

证书管理单元显示

8. Select the personal store, then right click and select Import :

选择个人商店并导入

9. Browse the certificate, and click next:

浏览证书

10. Enter the password, then click in Next button:

在此处输入图片说明

11. Automatically select the certificate store:

自动选择商店

12. The certificate information shows:

证书信息

13. Success dialog message shows:

在此处输入图片说明

14. Refresh the MMConsole to show the certificate:

刷新mmc

15. Right click on the certificate, then click in Manage Private Keys... :

管理私钥

16. Add the pool identity or the IIS user in my case I added IIS_IUSRS:

添加 iis_iusrs

17. The user has been added, click on OK button:

用户添加

And it is finished the keyset does exist now!!

I received same error as OP: "System.Security.Cryptography.CryptographicException: keyset does not exist"

The resolution (for me) was: Visual Studio needs to be (run as Admin)

As was explained to me(YMMV), VS needs to be run as Admin in order to extract the certificates private key from the key store, in order to negotiate auth/handshake with keyvault.

The application might be trying to write to the following folder path: C:\\Documents and Settings\\All Users\\Application Data\\Microsoft\\Crypto\\RSA\\MachineKeys

If your application is using impersonation or using the IUSR_MACHINENAME user, then configure the MachineKeys folder sercurities and give the user Read & Execute, List Folder Contents, Read, Write. If that doesn't work, try giving the Everyone user the same permissions.

I did run into the same problem. The message is not ideal and in my case my user did not have permission to access the private key. You can fix this using these steps:

  1. Open mmc
  2. Add certificate snap-in
  3. select the certificate you want to use
  4. right click on it and select 'All Tasks' / 'Manage Private Keys...'
  5. Add your user to the list of authorized users and allow 'Full Control'

Try running vs as Administrator. Worked for me

I believe when using Encrypt and Decrypt it expects a public key for encrypt and a private key for decrypt. So it is failing because you are trying to decrypt without the private key and that causes the exception.

You should really be using SignData method for creating the signature and VerifyData for the verification.

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

signedElement.SigningKey = myCertificate.PrivateKey;

.Net create temp certificate file here "..\Microsoft\Crypto\RSA\MachineKeys". May be the certificate file still locked an other process. Try restart app then pc. If the problem solved, you need to create manuelly.pfx file then load certificate app your pc.

In my case the private key was stored in "C:\\ProgramData\\Microsoft\\Crypto\\Keys" and not machinekeys folder - you can check using certutil to find out the "Unique container name" that will be the private key.

I now scan through the crypto directory to find the match. WIth that match I can set the correct ACL on the appropriate file

If you are facing this issue while running code from visual studio then running visual studio as administrator will solve the probelm or if you are facing this issue after publishing on IIS then following steps will solve the problem:

1. Open IIS and Right click on API/website and click Manage Application => Advanced Settings to find which application pool is being used

在此处输入图像描述

在此处输入图像描述

2. Click Application Pool

在此处输入图像描述

3. Right click on the Application Pool used by your API and then select "Advanced Settings"

在此处输入图像描述

4. Change "Identity" to "Local System" and press Ok button

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM