You’re asked to update the SSL certificate for movingpackets.net on a load balancer. The requestor (me, in this case) gives you the certificate file. I don’t need to give you the intermediate certificate bundle because you’re going to use the checkcert tool to sort that out. I also tell you to use the same private key as for the last certificate. How do you know that the old private key works with the new public certificate?
Checking SSL Certificates and Keys
My good friend OpenSSL can help us match a certificate and key. The basic premise is that the modulus of both the key and the cert file should be the same. The openssl commands to do this are:
# openssl x509 -noout -modulus -in microsoft.com.crt Modulus=B788D872FFB6C827EF5656A0535CC1E36343D6A29F1824564238793737BB2C17EAB7FF6A2032AB95174FDA4A24AFF438DFB23B85746E7B37D657F5EB3E3580291218CA66AC8CF872C2A62FD1A7F1DB85C554E4DE803E3F9397D251C8A283FA0EF4314210BFF88AE0AF656C5953A71A8D6A4C2A4476B6AD1EADE1920D1CEEEB8E0C16583698CC735861FA98D63DA3EB5632968751D099AAB7D22321920AE962B065100FFEA7BC5EF7E3DC1398935F3C6F8C43DC689BC290DAACEEDD487ECD81795BC7CA702B20369029CE6F7527D0E16CD9CC603671B05940433D49590EB15C6768DF0A326AEE7AE77084BCCC4707D1AE2694E6E0477C038598F5552B46D04C95 # openssl rsa -noout -modulus -in microsoft.com.key Modulus=B788D872FFB6C827EF5656A0535CC1E36343D6A29F1824564238793737BB2C17EAB7FF6A2032AB95174FDA4A24AFF438DFB23B85746E7B37D657F5EB3E3580291218CA66AC8CF872C2A62FD1A7F1DB85C554E4DE803E3F9397D251C8A283FA0EF4314210BFF88AE0AF656C5953A71A8D6A4C2A4476B6AD1EADE1920D1CEEEB8E0C16583698CC735861FA98D63DA3EB5632968751D099AAB7D22321920AE962B065100FFEA7BC5EF7E3DC1398935F3C6F8C43DC689BC290DAACEEDD487ECD81795BC7CA702B20369029CE6F7527D0E16CD9CC603671B05940433D49590EB15C6768DF0A326AEE7AE77084BCCC4707D1AE2694E6E0477C038598F5552B46D04C95
Are they the same? Did you check every byte? The lazy way to do this, then, is to take an md5 hash of the output and compare those instead; it’s little easier and while there’s a remote chance that two non-equal moduli could have the same md5 hash, it’s pretty unlikely. And so:
# openssl x509 -noout -modulus -in microsoft.com.crt | openssl md5 9c67051f3732cc4a78e6053892641dd9 # openssl rsa -noout -modulus -in microsoft.com.key | openssl md5 9c67051f3732cc4a78e6053892641dd9
Thats easier, though still quite a long string to work with.
Here is the operational annoyance. This is easy stuff to do, but remembering the commands is irritating and fiddly. I suppose I could write a couple of shell aliases or a shell script that would do something similar, but why do it the simple way when you can make things more difficult for yourself?
As with checkcert I began to wonder whether this too would not benefit from a neat little wrapper that takes the guesswork out of things. To make things more resilient, I wanted a tool that would do error checking, confirm that the files are indeed a cert and a key, assume that given just a .crt filename, the key has the same name but with a .key extension (unless you specify it), then would do the modulus check for you and give you a really clear yes/no kind of answer.
Since this is yet another ‘quick and dirty’ script born of laziness, I find myself once more using Perl to do my dirty work, in turn calling openssl to do the truly difficult stuff. The script is called “checkkey.”
Give checkkey a certificate filename (and, optionally, a key filename), and it does all the things I wanted:
# ./checkkey.pl microsoft.com.crt checkkey: Modulus Certificate: 9c67051f3732cc4a78e6053892641dd9 (microsoft.com.crt) Key: 9c67051f3732cc4a78e6053892641dd9 (microsoft.com.key) RESULT: Yeah, baby! It's a match made in heaven!
Easy, right? It’s not about how complicated it is (because as I demonstrated above, it’s fairly simple), but it takes a task that requires some silly syntax and turns it into a one step process. That works nicely for me.
Looking at the wider picture of process automation, the script could also be used as part of my fictional web portal where certificate updates are submitted. Upload the certificate and key, and now we have a simple tool to call on the server-side that will validate that the uploaded files are correct before they even get sent to an engineer for processing. In fact, now we have valid files, we can run them immediately through checkcert to create the configuration. By jove, I think we’re getting somewhere!
Making things easier doesn’t have to take a huge amount of effort, and the end result can far outweigh the nominal up front cost of doing so. More to the point, I’m trying to build an environment where, prior to my magical web portal existing, I can encourage the engineering team to make some basic checks on certificates and keys before trying them in production and finding out there’s a problem. After the certificate/key switch, mind you, we will still need to validate that everything went well; and that’s a subject for another post.
Yes, but I need some time to sanitize it first. Hang in there; your laughter can wait a little.
I would certainly try something like `diff <(openssl rsa -noout -modulus -in microsoft.com.crt) <(openssl rsa -noout -modulus -in microsoft.com.key)` — but that’s mostly because it’s easier to remember for me when I rarely perform this sort of function.