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 private key, password protected (encrypted with DES), 4096 bits
openssl genrsa -des -out rootCA.key 4096
Generate self-signed CA certificate:
# Create CA cert, expires in 365 days, empty subj skips interactive DN prompts, you will be prompted for password of key if private key is DES encrypted
# sha256 is the default message digest algorithm since openssl 1.1
openssl req -x509 -new -key rootCA.key -sha256 -days 365 -out rootCA.crt -subj "/"
Create certificate signed with CA
Generate certificate signing request and private key. It's advisable to include the CN as SAN:
# openssl config file
cat <<- EOF > req.conf
[req]
default_bits = 4096
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn
[dn]
CN = test.nicktriller.com
[req_ext]
subjectAltName = @alt_names
[alt_names]
DNS.1 = test.nicktriller.com
DNS.2 = aaa.nicktriller.com
DNS.3 = bbb.nicktriller.com
IP.1 = 127.0.0.1
EOF
Generate private key and certificate signing request
# "nodes" = no DES (unencrypted, no password)
openssl req -nodes -new -config req.conf -keyout cert.key -out cert.csr
Create signed certificate:
# Generate signed certificate (you will be prompted for CA password)
openssl x509 -req -in cert.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out cert.crt -days 500 -sha256 -extensions req_ext -extfile req.conf
-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:
...
[req_ext]
subjectAltName = @alt_names
extendedKeyUsage = clientAuth
...
Create certificate chain bundle
End entity first, root CA last, intermediate CAs in between if applicable:
cat "cert.crt" "rootCA.crt" > "chain.crt"
Import a CA certificate in Debian based systems
sudo mkdir /usr/local/share/ca-certificates/extra
sudo cp rootCA.crt /usr/local/share/ca-certificates/extra/
sudo update-ca-certificates
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:
openssl req -noout -text -in cert.csr
Inspect certificate:
openssl x509 -noout -text -in cert.crt
Inspect key:
openssl rsa -noout -text -in cert.crt
Inspect all certificates in a chain bundle:
openssl crl2pkcs7 -nocrl -certfile chain.crt | openssl pkcs7 -print_certs -text -noout
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.
openssl x509 -noout -modulus -in cert.crt | tee /dev/tty | openssl md5
openssl rsa -noout -modulus -in cert.key | tee /dev/tty | openssl md5
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.
openssl s_client -connect nicktriller.com:443
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):
GET /blog/ HTTP/1.1
HOST: www.nicktriller.com
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/