"System.Security.Cryptography.CryptographicException: Bad Key." for RSACryptoServiceProvider.Decrypt()
Asked Answered
Q

2

10

I'm playing with RSA encryption/decryption and certificates. Here specifically, I try to encrypt with the public key of a certificate, and then, when trying to decrypt with the private key corresponding to that certificate, get an error:

System.Security.Cryptography.CryptographicException: Bad Key.

   at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
   at System.Security.Cryptography.RSACryptoServiceProvider.DecryptKey(SafeKeyHandle pKeyContext, Byte[] pbEncryptedKey, Int3
2 cbEncryptedKey, Boolean fOAEP, ObjectHandleOnStack ohRetDecryptedKey)
   at System.Security.Cryptography.RSACryptoServiceProvider.Decrypt(Byte[] rgb, Boolean fOAEP)

Code is:

private void TestCertificates2()
{
    //////////////////////////////////////////////////////
    // SENDER CODE
    //////////////////////////////////////////////////////

    // get certificate
    var certSender = new X509Certificate2(@"C:\Test.cer");

    // encrypt with public key
    var providerSender = (RSACryptoServiceProvider)certSender.PublicKey.Key;
    var plainSender = Encoding.Default.GetBytes("this is plain text");
    var cipher = providerSender.Encrypt(plainSender, false);

    //////////////////////////////////////////////////////
    // RECEIVER CODE
    //////////////////////////////////////////////////////

    // get certificate
    var store = new X509Store("MY", StoreLocation.LocalMachine);
    store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
    var certReceiver = store.Certificates.Find(X509FindType.FindBySubjectName, "Test Subject", false)[0];

    // decrypt with private key
    var providerReceiver = (RSACryptoServiceProvider)certReceiver.PrivateKey;
    var plainReceiver = providerReceiver.Decrypt(cipher, false);

    // check they are same
    if (plainSender.Equals(plainReceiver))
    {
        Console.WriteLine("Same!");
    }
}

For reference, certificate was created and installed through

makecert.exe Test.cer -n "CN=Test Subject" -sr LocalMachine -ss My

Can someone spot what I am doing wrong? Thanks in advance!

Quadriplegia answered 11/1, 2011 at 19:16 Comment(1)
Side note: You really should use fOAEP=true.Crepitate
Q
8

Ok, found what the issue is: needed to tell makecert 1) that's certificate's subject key type is for "Exchange" 2) to mark private key as exportable

so makecert call looks like

makecert.exe Test.cer -r -n "CN=Test Subject" -sr LocalMachine -ss My -sky Exchange -pe
Quadriplegia answered 11/1, 2011 at 20:16 Comment(1)
adding "-sky Exchange" to makecert.exe command line call solved my problem. This marks key so that it can be also used for encryption/decryption.Burin
R
0

If you cannot generate the certificate yourself, ensure to import it via the command line which allows you to set the "key exchange" flag.

certutil -importPFX certificate.pfx AT_KEYEXCHANGE,NoExport

Importing via the GUI wizard will always use AT_SIGNATURE, and then you can only use the private key for signing, NOT for encryption!

Respondence answered 16/3, 2022 at 11:33 Comment(2)
Please don't post multiple identical answers across several questions. Your answers should be specific to each question, and if the questions are actually the same, then one should be closed as a duplicate of the other.Cloud
Ok feel free to close one duplicate then.Respondence

© 2022 - 2024 — McMap. All rights reserved.