PrivateKey threw an exception of type System.Security.Cryptography.CryptographicException

12,786

Solution 1

davidchristiansen Said:

What is a CNG Key? Certificates in Windows are stored using Storage Providers. Windows has two of these providers, that are not compatible. The old style “Cryptographic Service Providers” or CSP in short and the new style “Cryptography API: Next Generation” or CNG. The CNG providers have been around since Windows Vista, and although it is more secure and easier to use many facets of software are still not compatible with CNG providers. This appears to also include the .NET Framework.

A possible workaround to this may be to use CryptoAPI/CNG API directly to deal with CNG keys. But if we want an easier and pure .NET solution which understands CNG, we need to find another solution (details to follow!).

I followed the following post to convert to convert my certificate key from CNG to RSA. It works!

http://blog.davidchristiansen.com/2016/05/521/

Steps from blog:

  1. Extract your public key and full certificate chain from your PFX file
  2. Extract the CNG private key
  3. Convert the private key to RSA format
  4. Merge public keys with RSA private key to a new PFX file

After changing your application to use the new PFX you just created, you should find that your issues have been resolved.

Now let’s see how to carry out these steps using OpenSSL (Get OpenSSL for Windows from here)

  1. Extract your public key and full certificate chain from your PFX file

OpenSSL pkcs12 -in "yourcertificate.pfx" -nokeys -out "yourcertificate.cer" -passin "pass:myreallystrongpassword"

  1. Extract the CNG private key

OpenSSL pkcs12 -in "yourcertificate.pfx" -nocerts –out “yourcertificate.pem" -passin "pass:myreallystrongpassword" -passout "pass:myreallystrongpassword"

  1. Convert the private key to RSA format

OpenSSL rsa -inform PEM -in "yourcertificate.pem" -out "yourcertificate.rsa" -passin "pass:myreallystrongpassword" -passout "pass:myreallystrongpassword"

  1. Merge public keys with RSA private key to a new PFX file

OpenSSL pkcs12 -export -in "yourcertificate.cer" -inkey "yourcertificate.rsa" -out "yourcertificate-converted.pfx" -passin "pass:myreallystrongpassword" -passout "pass:myreallystrongpassword"

Solution 2

If you are debugging your application, try to open the Visual Studio as administrator. It solved the problem for me.

Solution 3

Sounds like your certificate uses CNG key storage to store the private key. In this case, PrivateKey property will throw this exception when attempting to access the property.

In order to access the key properly, you have to use extension methods to access the key: https://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2(v=vs.110).aspx#Extension Methods

Moreover, these extension methods are preferred when accessing any private key storage type, either legacy (CSP) or CNG. That is, do not access PrivateKey and PublicKey properties directly, instead, access them via these methods.

Solution 4

Running on IIS Express, the program uses your credentials to access the certificate, while on IIS the pool identity's credentials are used. You can easily check the certificate ACL to see who is allowed or not.

Follow these steps:

  1. Check what Application Pool your web site uses

Open Internet Information Services Manager, select Sites in the Connections tree on the left. Select your site in the middle panel and click Basic settings under Actions on the right panel.

  1. Check what identity the Application Pool uses

Select Application Pools in the Connections tree on the left and find the identity in the middle panel. It'll be probably "NETWORK SERVICE".

  1. Add read permissions for the identity used by Application Pool to your certificate

Open the Microsoft Management Console (mmc), add the Certificates snap-in for local Computer account and find your certificate under Personal certificates. Open its context menu, All Tasks and Manage Private Keys.... Click Add.., enter the identity ("NETWORK SERVICE") and click Check Names and OK. Under Permissions for allow only the Read permission.

You can read details in this question: How to give ASP.NET access to a private key in a certificate in the certificate store?

refer: Certificate private key throws CryptographicException under IIS Web Server

Share:
12,786
Anas Tina
Author by

Anas Tina

Updated on July 12, 2022

Comments

  • Anas Tina
    Anas Tina almost 2 years

    I'm trying to use self-signed certificate using the following code:

    X509Certificate2 cert = ToCertificate("CN=localhost");
    
    
    public static X509Certificate2 ToCertificate(this string subjectName,
                                                    StoreName name = StoreName.My,
                                                    StoreLocation location = StoreLocation.LocalMachine
                                                    )
        {
            X509Store store = new X509Store(name, location);
    
            store.Open(OpenFlags.ReadOnly);
    
            try
            {
                var cert = store.Certificates.OfType<X509Certificate2>().FirstOrDefault(c => c.Subject.Equals(subjectName, StringComparison.OrdinalIgnoreCase));
    
                return cert != null ? new X509Certificate2(cert) : null;
            }
            catch (Exception)
            {
    
                throw;
            }
            finally
            {
                store.Certificates.OfType<X509Certificate2>().ToList().ForEach(c => c.Reset());
                store.Close();
            }
        }
    

    I am getting the following exception:

    PrivateKey = 'cert.PrivateKey' threw an exception of type 'System.Security.Cryptography.CryptographicException'
    

    enter image description here

    I Tried this fix, and this fix

    But still having the problem!