How to Create and Use Custom CAs with OpenSSL
Sometimes I need to create certificates for testing purposes. For example, I setup an etcd cluster by hand recently. This happens rarely enough that I need to look up the openssl syntax every time.
This is my personal openssl cheat sheet with the commands that are most relevant to me. Examples use options that I need often (e. g. DNS and IP SANs in certificate signing requests). All commands were tested on Ubuntu 20.04.1 LTS with OpenSSL 1.1.1f  31 Mar 2020.
Create a CA
Generate private key:
|
|
Generate self-signed CA certificate:
|
|
Create certificate signed with CA
Generate certificate signing request and private key. It’s advisable to include the CN as SAN:
|
|
Generate private key and certificate signing request
|
|
Create signed certificate:
|
|
-extensions
defines the config section that configures x509 extensions.
-days
defines the number of days after which the certificate expires.
-CAcreateserial
makes OpenSSL create a new file for serial tracking if it’s missing. The default filename consists of the CA certificate file base name with “.srl” appended, e. g. “mycacert.srl”.
-extfile
defines the file containing the extensions.
Create certificates for client and server authentication
The openssl config file from the section “Create certificate signed with CA” can be augmented with serverAuth / clientAuth extensions:
|
|
Create certificate chain bundle
End entity first, root CA last, intermediate CAs in between if applicable:
|
|
Import a CA certificate in Debian based systems
|
|
Inspecting CSRs, certificates and keys
The “-noout” flag suppresses printing the encoded input material to stdout. With the “-text” flag, openssl outputs the decoded input material.
Inspect CSR:
|
|
Inspect certificate:
|
|
Inspect key:
|
|
Inspect all certificates in a chain bundle:
|
|
Check if certificate and key match
Validate a certificate and key belong to each other. The “tee” ensures error messages are visible. Otherwise, the md5 digest would appear to match when both commands output the same error message. Hashing the modulus produces a shorter output that’s easier to compare.
|
|
If both message digests are the same, the modulus of key and cert match, therefore the certificate and key belong together.
Using secure client
s_client is a generic TLS client and is highly useful for debugging and inspecting  certificates used by an endpoint.
|
|
stdin stays open when the above command is executed. Whatever is entered will be transfered to the target by s_client. For example, you could send an HTTP request by hand like this (don’t miss the trailing newline):
|
|
Alternative to OpenSSL
Cloudflare’s cfssl is a fine alternative to the openssl cli tool for the creation and signing of certificates.
Further reading
A detailed OpenSSL guide that also describes creation of intermediate CAs can be found here: https://jamielinux.com/docs/openssl-certificate-authority/