Friday, March 7, 2014

SSL Certs for IIS with PFX once and for all - SSL and IIS Explained

The problem is more common than dirt but the solutions provided are so often entirely incorrect and obscure and that's likely because the "Linux and Apache" folks are trying to use their standard approach with MS platforms that like to do their own thing.

Here's what you need to understand:

CSR - Certificate Signing Request: A CSR is how you ask for a certificate and provides things like your identify, the use, etc..

KEY - Private Key: When someone uses the public key that you share with the world (like that which your web server will give the client and they will use to encrypt traffic), your possession of the private key is how you prove (as a web site) that you are master. You encrypt using your private key and the client decrypts with your public key. ANYONE can have your public key and thus anyone can decrypt but since you are the only one with a private key, it is guaranteed (when you control that key correctly) that if the public key works, traffic must have come from you. Similarly, anything encrypted with your public key can ONLY be decrypted using your private key.

CER/CRT/CERT/CERTIFICATE - Public Key: See KEY explanation

PFX: Along comes microsoft and their proprietary way of doing things and the confusion that follows. IIS expects a PFX but the format has nothing to do with the standards world of PKI, keys and certs really. So how do you give them a PFX that includes the private key (needed to encrypted/decrypt your web traffic)? The intended way is for you to generate the CSR using IIS then give that CSR to your CA (internal or public) then get a key back based on the private key known by the creator of the CSR (IIS). This is where things are "all wrong" in the public CA business (from the perspective of us using IIS but really, they have it right). Most likely you created the CSR using your CA or the company reselling for them (cheapssl, gogetssl, etc..). When you do this, they give you a private key to keep safe and a public key to use but IIS/Windows has no concept of the private key so you're dead in the water from the start.


The solution:

Use IIS "Server Certificates" UI to "Generate Certificate Request" (the details of this request are out of the scope of this article but those details are critical). This will give you a CSR prepped for IIS. You then give that CSR to your CA and ask for a certificate. Then you take the CER/CRT file they give you, go back to IIS, "Complete Certificate Request" in the same place you generated the request. It may ask for a .CER and you might have a .CRT. They are the same thing. Just change the extension or use the *.* extension drop-down to select your .CRT. Now provide a proper "friendly name" (*.yourdomain.com, yourdomain.com, foo.yourdomain.com, etc..) THIS IS IMPORTANT! This MUST match what you setup the CSR for and what your CA provided you. If you asked for a wildcard, your CA must have approved and generated a wildcard and you must use the same. If your CSR was generated for foo.yourdomain.com, you MUST provide the same at this step.

Now select the PERSONAL store (No, not webhost). This will import your CRT in the personal store where it can be associated with the private key generated by IIS when it created the CSR. THIS IS WHERE ALL THE PROBLEMS COME FROM. This is what causes SO many headaches. The CRT you got from your CA and the KEY they gave you are useless here unless you do as others might suggest and go play around with other tools like openssl (which can work but why bother when you can do it the way IIS intended?)

Now you should see your cert in the server certificates list and if you open it, you should see something like, "You have a private key that corresponds to this certificate".

Now if you can use the Export function (IIS 8 provides this in the same place as the "request" and "complete request" links) or use the Certificate MMC then navigate to the personal store and export from there to the PFX format. You need to provide a strong password to protect this file because it will have the entire certificate chain AND your private key. In other words, this PFX has the keys to the entire "domain" (speaking figuratively).

Chances are that you don't even need the PFX now because you already have the certificate inside IIS but if you're using the centralized certificate store like I am, you do AND the file name is critical. For wildcard certs, the name MUST be _.yourdomain.com.pfx (assuming your request was for *.yourdomain.com). If you asked for www.somedomain.org, then the filename must be www.somedomain.org.pfx because this is how SNI and centralized SSL store will look for the right one.


In summary, the easy way to install an SSL cert into IIS:
  1. Generate your CSR using IIS
  2. Provide that CSR to your CA
  3. "Complete Request" using the CER/CRT you get back from the CA
  4. [optional] Export to PFX and protect with a strong password
  5. Live long and encrypt
Update (20191201): Even today, I am using this post as I have to renew SSL for a stack that lives both on IIS and Node.js. Because of this, I also need the private key file so if you've done step #4 above and need a .key also, the following might save you some googling. Be sure to protect your .key file when you do this though!

`openssl pkcs12 -in exported.pfx -nocerts -out key.pem -nodes`
then
`openssl rsa -in key.pem -out server.key`

Now you you can use server.key and the cer/crt you were provided.

17 comments :

Mike said...

Hi Michael,
This article is absolutely superb I am so glad I found it before I embarked on any of the posted alternatives. They make such hard work of it. I also now understand what's going on.
Many thanks for taking the time to write this up - Genius.
Mike Annesley

Unknown said...

Hi Michael,

Am I correct in saying:

1) If you receive for example a .CER/.CRT file and the CSR was generated using IIS on the server, you can simply import the certificate using "Complete Certificate Request"
2) If you receive for a example a .CER/.CRT file and the CSR was NOT generated using IIS (i.e. third party generator), you have to combine the .CER, (optional - intermediate certificates) AND the private key into a PFX file so that you can import it?

Cheers,

Michael

Fredrik said...

Thank you for this article!

dude said...

thanks a lot for your info.

BlogOn said...

Hi Michael,

I am not sure if you still blog on this article, can you let me know How to generate a CSR using IIS that supports SHA-256 ?

Your steps are clear if we don't need sha256. How can we do the steps if we need sha256.

rainabba said...

BlogOn,

As I understand it, SHA2 is only used to create the hash for the request, to be even more sure the request itself isn't tampered with though I'm not 100% sure on that. I do think the following will help you get there though: https://myexchangelync.wordpress.com/2014/12/14/create-a-csr-with-sha256-signature-algorithm/ That's the best I've got.

IIS-Certificate-Insanity said...

While this did help, I found that there was still an additional step missing. I had to repair the cert I received from my CA as it was missing the private key, like so:

certutil –repairstore my “thumbprint”

where the thumbprint is from the certificate.

kalpesh said...

Thanks for the blog. :)

Unknown said...

This is what you need when you search about an argument. Clear, concise and comprehensive

Vijayaraghavan TV a.k.a Vijay TV said...

I have a wild card SSL (*.mydomain.net) from GoDaddy and I have the exact same issue; and I did the steps exactly as you have done. But I am not able to Export the CRT with the Private Key from the MMC. The Option to export with the private key is disabled. Neither I am able to associate this Certificate in IIS for https binding. It is giving an error "The logon session does not exist...blah blah". I tried to explain GoDaddy Tech support on the issue, but I their Tech Support team is pathetic to even understand the issue and they keep repeating the SOP they have like a textbook definition. I tried using OpenSSL as I do not have any other option to convert, but OpenSSL also doesn't work. Kindly suggest / help.

Vijayaraghavan TV a.k.a Vijay TV said...

Forgot to mention one more aspect. If I try to Export the certificate from MMC, it doesn't allow to export with the private key. However, if I see the property of the certificate, it says 'you have a private key corresponding to this certificate'. Wonder what prevents from exporting with private key.

Thanks

rainabba said...

@Vijayaraghavan When a cert is imported to Windows and it has a private key, there is an option to make it exportable (with key) or not. It sounds like the one in your system was done without that switch enabled. The following may prove useful though:

https://goo.gl/photos/9rUNYe7eQ8bWt25D8

https://support.microsoft.com/en-au/help/232154/iis-export-private-key-option-is-grayed-when-exporting-a-server-certif

RF said...

Kudos!

Anonymous said...

I have 1 CSR of one of my appliance I need to convert it into pkcs#7 (Webserver template) and again convert that PKCS#7 to PEM.
Manually I can do it. My question is how to automate this task. Is there any way, if yes please help me. Thanks!

Unknown said...

This is the best explanation I have seen. Thank you very much. :)

Unknown said...

Question: My hosting provider (WinHost) generated a CSR for me. I used that CSR at ZeroSSL to generate a certificate. That certificate is being rejected with the error message that the certificate does not match the common name of the request. I tried it three times (and now have run out of cert attempts), and all three fail.

In generating the CSR, I used my full domain name - e.g. www.mydomain.com. I noted that ZeroSSL listed both www.mydomain.com and mydomain.com to generate the cert. Is that where the mismatch comes from?

Since I'm out of attempts with ZeroSSL, is there somewhere else I can generate a Cert with my CSR?

Unknown said...

at yet again, resolved. Thank you

Post a Comment

Followers