9

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!

Anas Tina
  • 329
  • 1
  • 2
  • 14
  • What is the message from the exception? – bartonjs Jul 11 '17 at 19:32
  • @bartonjs Message: "Invalid provider type specified.\r\n" Source: "mscorlib" – Anas Tina Jul 12 '17 at 08:28
  • Please run `certutil -store -silent -v my localhost` and share the results. (If you want to be selective, "Public Key Algorithm" and "CERT_KEY_PROV_INFO_PROP_ID(2):" are the important ones; but nothing it prints should be secret) – bartonjs Jul 12 '17 at 16:04

4 Answers4

10

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

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.

Crypt32
  • 12,850
  • 2
  • 41
  • 70
  • 1
    I upgrade the project to .net framework 4.6.1 where these extension methods are defined but still got the same error. – Anas Tina Jul 12 '17 at 08:31
3

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

Whyou126
  • 31
  • 2
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"

garethb
  • 3,951
  • 6
  • 32
  • 52
Anas Tina
  • 329
  • 1
  • 2
  • 14
  • 1
    Make sure to give the user the application is running under permission to access the certificates private key after changing the key from CNG to RSA (see @Whyou126 answer on how to do this) – garethb Jan 10 '19 at 23:40
  • @garethb, Is there any other option for certificates provided by customer and we have no control over them? – m_d_p29 Apr 08 '19 at 06:52