logo

Cheatsheets - openssl

How to generate a cert?

# generate a private key foo.key of 2048-bit
# => foo.key (public/private key pair)
$ openssl genrsa -out foo.key 2048

# show content of the private key
$ openssl rsa -text -in foo.key -noout

# extract public key (the private key file contains both the private key and the public key).
# foo.key => foo_public.key
$ openssl rsa -in foo.key -pubout -out foo_public.key

# create a certificate signing request (CSR); public key will be included.
# foo.key => foo.csr
$ openssl req -new -key foo.key -out foo.csr

# verify csr
$ openssl req -text -in foo.csr -noout -verify

# option 1: send csr to CA and get the cert; CA signs the cert with their own private key.
# foo.csr => (CA) => foo.crt

# option 2: create a self-signed cert
# foo.key + foo.csr => foo.crt
$ openssl x509 -req -days 365 -in foo.csr -signkey foo.key -out foo.crt

# option 3: create your CA, then create the cert
$ openssl req -x509 -days 365 -newkey rsa:4096 -sha256 -nodes -out ca.crt -keyout ca.key -outform PEM
$ openssl x509 -req -days 365 -in foo.csr -CA ca.crt -CAkey ca.key -out foo.crt

# view cert
$ openssl x509 -text -in foo.crt -noout

# check the purposes of the cert
$ openssl x509 -purpose -in foo.crt -inform PEM

Generate a hash of each file's public key, they should match:

$ openssl pkey -pubout -in foo.key | openssl sha256
$ openssl req -pubkey -in foo.csr -noout | openssl sha256
$ openssl x509 -pubkey -in foo.crt -noout | openssl sha256

How to Verify?

Check content of the cert

# Parse a cert from a file
$ openssl x509 -in /path/to/cert -text -noout

# Parse a cert from a k8s secret
$ kubectl get secret mysecret -n foo-system -o jsonpath='{.data.ca-cert}' | base64 -d | openssl x509 -noout -text

# Extract the public key from root.crt.
$ openssl x509 -in root.crt -noout -pubkey > root.key
  • -in filename
  • -text print out full detailed
  • -issuer print the issuer name
  • -noout do not print anything NOT specified

Verify a cert using CA cert

$ openssl verify -CAfile ca.crt foo.crt

Verify if a certificate is self-signed

Check if the subject and the issuer are the same entity.

$ openssl x509 -in foo.crt -noout -subject -issuer

Verify if is CA

Check if CA:TRUE is included in the X509v3 Basic Constraints.

$ openssl x509 -in foo.crt -noout -text | grep "CA:TRUE"

Or verify by cert-manager. If you are issuing a certificate using cert-manager, and the issuer only has the SelfSigned stanza in the spec (selfSigned: {}), then you are using an arbitrary CA.

Verify Keypair

To verify that a private key corresponds to the public key from a certificate or a CSR, print out their modulus and compare the resulting hash-values.

For an ECDSA key pair/certificate:

$ openssl req -in ${CSR_FILE} -noout -pubkey | openssl dgst -sha256
$ openssl ec -in ${KEY_FILE} -pubout | openssl dgst -sha256
$ openssl x509 -in ${CERT_FILE} -noout -pubkey | openssl dgst -sha256

For a RSA key pair/certificate:

$ openssl req -noout -modulus -in ${CSR_FILE} | openssl sha256
$ openssl rsa -noout -modulus -in ${KEY_FILE} | openssl sha256
$ openssl x509 -noout -modulus -in ${CERT_FILE} | openssl sha256

How to check exponents and modulus?

$ openssl rsa -in foo.key -pubout -noout -text

The result looks like this:

modulus: ...
publicExponent: 65537 (0x10001)
privateExponent: ...
prime1: ...
prime2: ...
exponent1: ...
exponent2: ...
coefficient: ...

Note that publicExponent is almost always 65537 (0x10001).

Check Kubernetes Certs

Kubernetes stores config files in /etc/kubernetes, to check the cert content (e.g. of the kube-scheduler):

$ cat /etc/kubernetes/scheduler.conf | yq .users[].user.client-certificate-data | base64 -d | openssl x509 -text

# Result:
Issuer: CN = kubernetes
...
Subject: CN = system:kube-scheduler

Conversions

By default, OpenSSL generates keys and CSRs using the PEM format.

Between PEM and PKCS#12:

# PEM to PKCS#12
$ openssl pkcs12 -export -name "foo-digicert-(expiration date)" \
-out foo.pfx -inkey foo.key -in foo.crt

# PKCS#12 to PEM; PKCS#12 format contains both the certificate and private key
# extract private key
$ openssl pkcs12 -in foo.pfx -nocerts -out foo.key -nodes

# extract cert
$ openssl pkcs12 -in foo.pfx -nokeys -clcerts -out foo.crt

Between PEM and DER: The DER format uses ASN.1 encoding to store certificate or key information. Similar to the PEM format, DER stores key and certificate information in two separate files. The file extension .der was used in the below examples for clarity.

# convert a PEM encoded certificate into a DER encoded certificate:
$ openssl x509 -inform PEM -in foo.crt -outform DER -out foo.der

# convert a PEM encoded private key into a DER encoded private key:
$ openssl rsa -inform PEM -in foo.key -outform DER -out foo_key.der

# convert a DER encoded certificate into a PEM encoded certificate:
$ openssl x509 -inform DER -in foo.der -outform PEM -out foo.crt

# convert a DER encoded private key into a PEM encoded private key:
$ openssl rsa -inform DER -in foo_key.der -outform PEM -out foo.key
# Check a PEM certificate (`.crt` or `.pem`)
$ openssl x509 -text -noout -in cert.pem

# Check a Certificate Signing Request (CSR)
$ openssl req -text -noout -verify -in CSR.csr

# Check a private key
$ openssl rsa -check -in cert.key

$ cat << EOF > csr.cnf
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no

[req_distinguished_name]
CN = example.com

[v3_req]
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1 = example.com
DNS.2 = www.example.com
EOF
openssl req -newkey rsa:2048 -out csr.pem -keyout key.pem -config csr.cnf

openssl config

Config file: /etc/ssl/openssl.cnf

Also:

$ openssl version -d
OPENSSLDIR: "/usr/lib/ssl"

How to generate random strings:

$ openssl rand -base64 10
129udXpYaQJZeg==

How to test a TLS connection?

Check if an endpoint you are connecting to or listening at uses TLS by running the following command:

$ openssl s_client -connect HOST:PORT

# e.g.
$ openssl s_client -connect google.com:443 -showcerts < /dev/null

It shows Certificate chain, server certificate, etc.

The s_client command implements a generic SSL/TLS client which connects to a remote host using SSL/TLS.

How to check the details of a server cert?

openssl s_client result can be directly sent to openssel x509:

$ openssl s_client -connect google.com:443 | openssl x509 -text -noout

What is -showcerts flag?

The showcerts flag appended onto the openssl s_client connect command shows the entire certificate chain in PEM format; without -showcerts flag, it shows only the end entity certificate.

Why openssl s_client does not terminate?

This is because OpenSSL is still connected to the server and waiting for further commands. You can add < /dev/null to terminate it.

OpenSSL vs BoringSSL

BoringSSL is a much lighter-weight version of OpenSSL with no guarantees of API or ABI stability since Google requires far less legacy application support.

Private key

$ openssl genrsa -out foo.key 4096
-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----

Private key => Certificate

$ openssl req -x509 -new -nodes -sha512 -days 3650 \
 -subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=yourdomain.com" \
 -key foo.key \
 -out foo.crt

Generated cert:

-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----

Read more