Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CryptographicException "Key not valid for use in specified state." while trying to export RSAParameters of a X509 private key

I am staring at this for quite a while and thanks to the MSDN documentation I cannot really figure out what's going. Basically I am loading a PFX file from the disc into a X509Certificate2 and trying to encrypt a string using the public key and decrypt using the private key.

Why am I puzzled: the encryption/decryption works when I pass the reference to the RSACryptoServiceProvider itself:

byte[] ed1 = EncryptRSA("foo1", x.PublicKey.Key as RSACryptoServiceProvider); string foo1 = DecryptRSA(ed1, x.PrivateKey as RSACryptoServiceProvider); 

But if the export and pass around the RSAParameter:

byte[] ed = EncryptRSA("foo", (x.PublicKey.Key as RSACryptoServiceProvider).ExportParameters(false)); string foo = DecryptRSA(ed, (x.PrivateKey as RSACryptoServiceProvider).ExportParameters(true)); 

...it throws a "Key not valid for use in specified state." exception while trying to export the private key to RSAParameter. Please note that the cert the PFX is generated from is marked exportable (i.e. I used the pe flag while creating the cert). Any idea what is causing the exception?

static void Main(string[] args) {     X509Certificate2 x = new X509Certificate2(@"C:\temp\certs\1\test.pfx", "test");     x.FriendlyName = "My test Cert";          X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);     store.Open(OpenFlags.ReadWrite);     try     {         store.Add(x);     }     finally     {         store.Close();     }      byte[] ed1 = EncryptRSA("foo1", x.PublicKey.Key as RSACryptoServiceProvider);     string foo1 = DecryptRSA(ed1, x.PrivateKey as RSACryptoServiceProvider);      byte[] ed = EncryptRSA("foo", (x.PublicKey.Key as RSACryptoServiceProvider).ExportParameters(false));     string foo = DecryptRSA(ed, (x.PrivateKey as RSACryptoServiceProvider).ExportParameters(true)); }  private static byte[] EncryptRSA(string data, RSAParameters rsaParameters) {     UnicodeEncoding bytConvertor = new UnicodeEncoding();     byte[] plainData = bytConvertor.GetBytes(data);      RSACryptoServiceProvider publicKey = new RSACryptoServiceProvider();     publicKey.ImportParameters(rsaParameters);     return publicKey.Encrypt(plainData, true); }  private static string DecryptRSA(byte[] data, RSAParameters rsaParameters) {     UnicodeEncoding bytConvertor = new UnicodeEncoding();      RSACryptoServiceProvider privateKey = new RSACryptoServiceProvider();     privateKey.ImportParameters(rsaParameters);      byte[] deData = privateKey.Decrypt(data, true);     return bytConvertor.GetString(deData); }  private static byte[] EncryptRSA(string data, RSACryptoServiceProvider publicKey) {     UnicodeEncoding bytConvertor = new UnicodeEncoding();     byte[] plainData = bytConvertor.GetBytes(data);      return publicKey.Encrypt(plainData, true); }  private static string DecryptRSA(byte[] data, RSACryptoServiceProvider privateKey) {     UnicodeEncoding bytConvertor = new UnicodeEncoding();      byte[] deData = privateKey.Decrypt(data, true);     return bytConvertor.GetString(deData); } 

Just to clarify in the code above the bold part is throwing: string foo = DecryptRSA(ed, (x.PrivateKey as RSACryptoServiceProvider)**.ExportParameters(true)**);

like image 530
kalrashi Avatar asked Feb 20 '12 08:02

kalrashi


2 Answers

I believe that the issue may be that the key is not marked as exportable. There is another constructor for X509Certificate2 that takes an X509KeyStorageFlags enum. Try replacing the line:

X509Certificate2 x = new X509Certificate2(@"C:\temp\certs\1\test.pfx", "test"); 

With this:

X509Certificate2 x = new X509Certificate2(@"C:\temp\certs\1\test.pfx", "test", X509KeyStorageFlags.Exportable); 
like image 109
Iridium Avatar answered Sep 21 '22 01:09

Iridium


For the issue I encountered a code change was not an option as the same library was installed and working elsewhere.

Iridium's answer lead me to look making the key exportable and I was able to this as part of the MMC Certificate Import Wizard.

Hope this helps someone else. Thanks heaps

Cert import wizard

like image 21
will webster Avatar answered Sep 19 '22 01:09

will webster