Certificates Mumbo Jumbo

5 minute read

Everybody hates PKI

Yeah, everybody hates Public Key Infrastructure (PKI) and I get that, it increases the complexity of a project and when you have to deal with SSL most of your troubleshooting options go down the drain.

No wonder there’s an old “MIT Curse” about casting PKI on an enemy team project, cause when you use it to solve a problem you’ll end up having many more.

Secure all the things

However, when done right, PKI is currently the best option for securing data exchanges over hostile environments (ex: internet, compromised networks).

So, why did I mention “done right” in the previous sentence?

Because most of the time this happens:

no idea

If you’re reading this post/rant you’re probably using client side SSL on your app, so…

Who can you trust?

Do you know which Certification Authorities you currently have on your truststore and what is the certification chain needed for the target certificate so it validates it successfuly?

If the answer is NO, you’re doing it wrong! You should only use Root Certification Authorities (CA) you trust and nothing else. Why maintain several CAs that you don’t care about and that could end up being compromised? Yeah, I’m talking about the standard Java cacerts file and this message is for all of you who use old Java versions and, with it, old cacerts truststores. Do yourself a favor and create your own truststores, specifically for your project.

Chaining things together

What da hell is a certificate chain and why should I care?

When you buy a digital certificate, usually it’s not signed directly by a Root CA. Instead, it’s signed by an intermediate CA, which by its turn is signed by a higher CA, and so on, until it reaches the Root one. This is called the certificate chain. Here’s an example:

ssl

As you can see, the wildcard certificate for google.com has two more intermediate CAs before the Root CA. So, answering the question above, if your truststore doesn’t have all the intermediate CAs you won’t be able build the certificate chain and the certificate won’t be successfully validated.

One in a million

How to guarantee that a certificate from a certain CA is exactly the one I’m expecting and not a random one from the same CA?

Well, a certificate has several fields that you can check against, for example, the fingerprint or the Common Name (CN). Be advised that when you use the fingerprint, if the certificate is renewed, you’ll need to update your validation scheme.

Check it out

How do I check if a certificate as been revoked by a CA?

There’re two mechanisms for that, Certificate Revocation Lists (CRL) and Online Certificate Status Protocol (OCSP):

  • CRL - File with a list of all revoked certificates issued by the CA. You can find a link to download it in the CA certificate.
  • OSCP - Service to check if a certain certificate is still valid. If implemented by the CA, you can just query if a certain certificate issued by that CA is still valid.

Bigger is not always better

A higher key size, like 4096 bits, is always better, right?

Security wise, definitely! But there’s a price to pay. It will have an impact in the performance of your server due to the cryptographic operations using that key. So, a key size of 2048 bits will be your best choice right now, lower than that it will be refused by some servers.

As a heads up…

Please keep in mind that you should never, ever, ever share your private key! I’ve heard the most ludicrous reasons for getting a hold on a private key, and the answer should always be: NO WAY IN HELL!

Command line primer

Time for some useful commands, but before proceeding any further check out the following definitions:

  • x509 - Public Key Infrastructure standards
  • .csr - Certificate Signing Request (also known as a pkcs10)
  • .der - Certificate container binary encoded
  • .pem - Certificate container base64 encoded
  • .key - It’s just a PEM encoded file containing only the private key
  • .p12 - May contain a certificate, a key and/or multiple certificates like CAs/chains (also known as .pfx or pkcs12)
  • .jks - Java keystore/trustore may contain a certificate, a key and/or multiple certificates like CAs/chains

Choose the Common Name

export DOMAIN="www.example.com"

Generate a .key

openssl genrsa -out $DOMAIN.key 2048

Generate a .csr

openssl req -new -key $DOMAIN.key -subj  "/C=PT/L=Porto/ST=Portugal/O=Epic Organization/OU=Department of Awesomeness/CN=$DOMAIN" -out $DOMAIN.csr

# show the .csr
openssl req -text -noout -verify -in $DOMAIN.csr

After sending the .csr to a CA so it may generate a new certificate, you’ll eventually receive a .pem or .der file.

openssl x509 -in $DOMAIN.pem -text

Convert .der to .pem

openssl x509 -in $DOMAIN.der -inform DER -out $DOMAIN.pem -outform PEM

Convert .pem to .der

openssl x509 -in $DOMAIN.pem -out $DOMAIN.der -outform DER

Check .key, .pem and .csr

# all must share the same hash
openssl rsa -noout -modulus -in $DOMAIN.key  | openssl md5
openssl x509 -noout -modulus -in $DOMAIN.pem | openssl md5
openssl req -noout -modulus -in $DOMAIN.csr  | openssl md5

Generate .p12

openssl pkcs12 -export -inkey $DOMAIN.key -in $DOMAIN.pem -out $DOMAIN.p12

Extract .key and .pem from .p12

# .pem
openssl pkcs12 -in $DOMAIN.p12 -out $DOMAIN.pem -nokeys -clcerts

# .key
openssl pkcs12 -in $DOMAIN.p12 -out $DOMAIN.key -nocerts

Convert .p12 to .jks

keytool -importkeystore -deststorepass "VeryStrongPass" -destkeypass "VeryStrongPass" -destkeystore $DOMAIN.jks -srckeystore $DOMAIN.p12 -srcstoretype PKCS12 -srcstorepass "VeryStrongPass" -alias 1

Convert .jks to .p12

keytool -importkeystore -srckeystore $DOMAIN.jks -destkeystore $DOMAIN.p12 -srcstoretype JKS -deststoretype PKCS12 -srcstorepass "VeryStrongPass" -deststorepass "VeryStrongPass" -srcalias 1 -destalias 1 -srckeypass "VeryStrongPass" -destkeypass "VeryStrongPass" -noprompt

List .p12 certificates

openssl pkcs12 -info -in $DOMAIN.p12

List .jks certificates

keytool -list -v -keystore $DOMAIN.jks

Get certificate chain from a webserver

openssl s_client -showcerts -connect $DOMAIN:443

Curl commands

Client side test

curl -v https://$DOMAIN --cert ./public.pem --key ./private.key

Specifying a truststore

# Add the Root CA to an empty file called trustore.pem
curl -v https://$DOMAIN --cacert trustore.pem

Bash functions

I’ve created a few helper functions that you might find useful, they’re available here.

May the PKI be with you

I’m just a Padawan on the ways of PKI and obviously this post is not “everything you wanted to know about PKI and were afraid to ask”, but I sincerely hope it kicks you down the rabbit hole.

Have fun!

Leave a comment