C# import .pfx file to cert store and CryptographicException: Keyset does not exist

I had to add a .pfx file programmatically today but got an exception when accessing this file in code after importing . The simple demo code and the exception are as follows.

X509KeyStorageFlags.PersistKeySet);
X509Store certificateStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
certificateStore.Open(OpenFlags.ReadWrite);
certificateStore.Add(cert);

System.Security.Cryptography.CryptographicException: Keyset does not exist at System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer) at System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeP rovHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle) at System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair() at System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey()

I did a search and the top results took me to the direction of adding permission on the private key. There are two versions of code for this task.

http://www.codeproject.com/script/Forums/View.aspx?fid=1649&msg=2062983

private static void AddAccessToCertificate(X509Certificate2 cert)
{
  RSACryptoServiceProvider rsa = cert.PrivateKey as RSACryptoServiceProvider;
  if (rsa != null) {
    string keyfilepath = FindKeyLocation(rsa.CspKeyContainerInfo.UniqueKeyContainerName);
    FileInfo file = new FileInfo(keyfilepath + “\\” + rsa.CspKeyContainerInfo.UniqueKeyContainerName);
    FileSecurity fs = file.GetAccessControl();
    var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
    var everyone = (NTAccount)sid.Translate(typeof(NTAccount)); 
    fs.AddAccessRule(new FileSystemAccessRule(everyone, FileSystemRights.FullControl, AccessControlType.Allow));
    file.SetAccessControl(fs);
  }
}

http://stackoverflow.com/questions/425688/how-to-set-read-permission-on-the-private-key-file-of-x-509-certificate-from-ne

private static void AddAccessToCertificate(X509Certificate2 cert)
{
  RSACryptoServiceProvider rsa = cert.PrivateKey as RSACryptoServiceProvider;
  if (rsa != null) {
    var cspParams = new CspParameters(rsa.CspKeyContainerInfo.ProviderType, rsa.CspKeyContainerInfo.ProviderName, rsa.CspKeyContainerInfo.KeyContainerName)
  {
    Flags = CspProviderFlags.UseExistingKey | CspProviderFlags.UseMachineKeyStore, CryptoKeySecurity = rsa.CspKeyContainerInfo.CryptoKeySecurity};
   cspParams.CryptoKeySecurity.AddAccessRule(new CryptoKeyAccessRule(WindowsIdentity.GetCurrent().User,
   CryptoKeyRights.FullControl, AccessControlType.Allow));
   using (var rsa2 = new RSACryptoServiceProvider(cspParams))
   { // Only created to persist the rule change in the CryptoKeySecurity }
  } 
}

Unfortunately both solutions did not work for me. This code was just a part of my other code. Every time I had to change the code, build and re-run test case. It took me a couple of hours to prove that both solutions didn’t work. I think that it was time to try in differet direction. So I read more search liks. It turned out that the fix is simple. Just adding X509KeyStorageFlags.PersistKeySet in the constructor of X509Certificate2 made it work.

var cert = new X509Certificate2(certificatePath, password, X509KeyStorageFlags.PersistKeySet);
X509Store certificateStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
certificateStore.Open(OpenFlags.ReadWrite);
certificateStore.Add(cert);

The source of this solution is http://support.microsoft.com/kb/950090

Advertisements

One thought on “C# import .pfx file to cert store and CryptographicException: Keyset does not exist

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s