2
votes

I'm trying to get this external REST webservice that requires both a server-side certificate and a private key (both of which I got from the publisher as *.pem files of that service).

For my testing, I googled and found a way to combine these two pieces into a *.pfx file - and loading a X509Certificate2 instance from that binary file on disk works just fine.

Now I was trying to put this into the Cert Store on my production Windows Server 2008.

I can get the X509Certificate2 from the cert store in my C# code - no problem:

X509Store store = new X509Store(StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);

X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindBySerialNumber, "serial-number-here", false);

if (certs.Count > 0)
{
    X509Certificate2 cert = certs[0];

    // set the certificate on the RestClient to call my REST service
    _restClient.ClientCertificates.Add(cert);
}

store.Close();

But when I do this, then the web service barfs at me, claiming it needs a "SSL certificate"...

Also: when I was loading the X509Certificate2 from disk, from that *.pfx file, I had to provide a password - nothing needs to be provided here, when loading from the cert store.... odd....

It seems that even though I imported the *.pfx which contains both the server-side certificate and our private key, somehow I cannot get both back from the cert store...

Any idea how I can get this to work? Do I need to load the private key from the cert store in a second step? How?

These certificates still remain mainly a big voodoo-like mystery to me ..... can anyone enlighten me?

2

2 Answers

4
votes

The first thing to check is to see whether the certificate store does have the private key.

  1. Open up the certificate management snappin and find your certificate, double click it and make sure it has the red highlighted section like in the image below: enter image description here

Next, if the private key is in the store then maybe the account accessing the certificate does not have permissions on the private key. There are two ways to check this:

  1. In the certificate management snappin, right click the certificate > All tasks > Manage private keys. (You should be able to check and edit permissions here)
  2. In your code you could access the PrivateKey property (i.e. Do var privateKey = cert.PrivateKey and see whether you get it back).
0
votes

You did not write how is the web service implemented.

  1. if it is deployed on IIS
  2. if it is self hosted

Your code to get certificate from store is correct. The question is where did you import the pfx - CurrentUser or LocalMachine store. You are using CurrentUser store in the code example. If you imported the certificate to LocalMachine store it will not be found. Also, please specify the store name - StoreName.My (in MMC or certmgr.msc it means Personal) in the constructor of X509Store (it might be default, but who knows all the defaults anyway :) )

But when I do this, then the web service barfs at me, claiming it needs a "SSL certificate"...

You need to ensure you have Client Authentication in the extended key usage of the certificate.

Also: when I was loading the X509Certificate2 from disk, from that *.pfx file, I had to provide a password - nothing needs to be provided here, when loading from the cert store.... odd....

It's how it works. When you have a pfx then the private key in it is secured/encrypted with password (password can be an empty string). When you import pfx to certificate store then the private key is secured/encrypted with other key (not exactly sure what key it is). However you can add another level of protection to the private key by specifying strong protection when importing pfx to the store (I do not recommend it when used with ASP.NET, or web services or anything that does not have a desktop). But when it is your personal certificate to sign emails then it might be good to enable it. Windows will then popup a window whenever an application will try to use the private key.

@DanL might be right about the rights to the private key and his

1) - set rights on private key and

2) - accessing private key in X509Certificate2

are written OK. I would just add to 1) that you are trying to connect to the REST service from a ASP.NET application or another web service on IIS then the name of the account that you need to add permission for is IIS APPPOOL\name_of_the_apppool_your_app_runs_under