This is still the header! Main site

Self Signed Certs

2021/05/01

... they're called "self-signed" for a reason. (... and here is how to do it in 3 lines.)

Although "self-signed" kinda sounds like "I signed it myself, so it's not that trustworthy", in fact the word "self" is referring to the fact that we actually sign the cert about the key with the key itself.

At some point, I might end up writing a somewhat longer article about certificates; this one is really only about demonstrating how simple it is to play around with them. You can create one with

# Generating a brand new RSA key
openssl genrsa -out our_rsa_key.key 4096
It's an RSA key, and 4096 bits aren't too bad. (You can also generate other, fancier, quantum-resistant kinds; RSA ones still work well for the time being though.) If we have this file, we have the entire public-private keypair.

To actually use this, we need a certificate; this is essentially the public key, together with some claims on what it can be used for, signed by someone. Fun fact: that someone doesn't really ever need to see our private key! We generate a request:

# Creating a request for certificate signing
openssl req -new -sha256 -key our_rsa_key.key -out the_signing_request.csr

This will ask a bunch of questions, who you are, what the expected usage of this is, etc. (It will also utilize OpenSSL's config file for default settings.) The answers will be signed together with the public key, by someone who our target audience already knows something about. (E.g. if we want a key for a website, that's e.g. Let's Encrypt whose certs are already known by browsers.)

We send this out, and then they sign it by:

# Signing a request with the Certificate Authority key
openssl x509 -req -in the_signing_request.csr \
   -signkey lets_encrypt_super_secret_private.key \
   -CAcreateserial -out the_signed_cert.crt \
   -days 90 -sha256

... well okay this is probably not the exact way they're signing it, but this is how you can sign CSRs anyway.

And here is the point where we come back to what "self-signed" means. Well, if we're going to just distribute our public keys anyway, by directly talking to whoever is supposed to be using them, there is no real need for fancy signatures. However, it's still good to have said public keys sit in a certificate (e.g. so that it has an expiry date, and some data on its intended usage), so we need to sign it with something. Given how we do have a key itself already at hand... let's use it to sign the cert, too!

# Signing a request with the same key it was created from (self-signed)
openssl x509 -req -in the_signing_request.csr \
   -signkey our_rsa_key.key \
   -CAcreateserial -out the_signed_cert.crt \
   -days 90 -sha256

That is, we used our key twice: to generate the signing request (so the cert will be about this key), and to sign it (so that the cert will be signed by this key, too).

This has the additional benefit that if we add this cert to the trusted set of certs (e.g. in our browser), if a website uses this very same certificate, we'll trust it even if our check looks like "is this cert signed by someone we trust?" (as opposed to "do we trust this or its signer?").

This is post no. 8 for Kev Quirk's #100DaysToOffload challenge.

... comments welcome, either in email or on the (eventual) Mastodon post on Fosstodon.