OpenSSL commands

Here’s my notes of openssl commands for remembering (my own copy-pasting). There are other crypto/ssl/tls tools available (e.g., step, cfssl, certstrap etc) but openssl are the most widely used, at least that I know of.

If you don’t know what SSL/TLS/HTTPS is, or just want to learn more about it make sure to check out Julia Evans: What’s TLS and DNSimple’s comic: How HTTPS works. Both aweso

Create RSA key pair in PEM

When creating keys to test and dev environments. Size can be 1024, 2048, 4096

NOTE: Private key in PKCS1 and public key in SPKI format

openssl genrsa -out private.pem 2048 && openssl rsa -in private.pem -outform PEM -pubout -out public.pem

Create signature

Creates a base64 encoded signature. The default algorithm used is RSASSA-PKCS1-v1_5 and we’re setting SHA-256 as hash.

NOTE: -n option is easy to miss (it removes a trailing newline)

echo -n "hello world" | openssl dgst -sha256 -sign private.pem | base64

# Example with newlines in message
echo -n "hello\\nworld" | openssl dgst -sha256 -sign private.pem | base64

# Example with data from file.
# BEWARE: Removes trailing newline from `data.txt`
printf %s "$(cat data.txt)" | openssl dgst -sha256 -sign private.pem | base64

# Do not remove trailing newline
cat data.txt | openssl dgst -sha256 -sign private.pem | base64

# From file / to file
openssl dgst -sha256 -sign private.pem -out data.txt.sha256 data.txt

Verify signature

openssl dgst -sha256 -verify public.pem -signature data.txt.sha256 data.txt

Convert PEM to DER and then base64 it

To get rid of newlines and type header. This gives you a base64 key on one line

openssl rsa -pubin -inform PEM -in public.pem -outform DER | base64

Convert PKCS1 key to PKCS8 private key

Web browser crypto supports PKCS8 and openssl is using PKCS1 as default

openssl pkcs8 -topk8 -inform PEM -outform PEM -in private-pkcs1.pem -out private-pkcs8.pem -nocrypt

Create sha256 hash of public key

Outputs a HEX digest of the binary DER key

TODO: What are the use cases? Why not use fingerprint?

openssl rsa -in public.pem -pubin -outform der | openssl dgst -sha256
# step equivalent
step crypto hash digest <(openssl rsa -in public.pem -pubin -outform der)

Fetch remote x509 cert

This gets all information including the whole certificate chain and doesn’t decode certs

openssl s_client -showcerts -connect

This shortcut decodes the leaf certificate for you:

echo | openssl s_client -showcerts -connect | openssl x509 -noout -text

Decode x509 cert

When you get tired of staring at those base64 characters… Read it like a human instead!

openssl x509 -in cert.pem -noout -text

Inspect/decode keys

Often I want to see more than just base64 mumbo jumbo saying it’s a private or public key, or which program made the output, in the header.

openssl asn1parse -in key.pem

Here is a javascript website doing it:

Create self signed certificate

Creates a key and certificate it for localhost. Includes subjectAltName as well.

openssl req -x509 -out localhost.crt -keyout localhost.key \
  -newkey rsa:2048 -nodes -sha256 \
  -subj '/CN=localhost' -extensions EXT -config <( \
   printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")

Update macOS keychain to trust it

sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain localhost.crt

NOTE: Some applications don’t use the macOS keychain as CA store, they use their own. E.g., openssl, curl (if using openssl), nodejs, firefox etc.


Use minica or mkcert if you want to create a local root certificate and sign other’s with that, then you only need to trust that one root certificate. Which can be a good idea if you want to create multiple certificates.

Create random bytes

openssl has a built-in PRNG which can easily generate both binary, base64 and hex random output:

# Generating 32 random bytes in different formats
openssl rand 32
openssl rand -hex 32
openssl rand -base64 32

# Replace +/ with AB and remove padding (=) making it base62
openssl rand -base64 32 | tr "+/" "AB" | tr -d =

# Web safe base64
openssl rand -base64 32 | tr "+/" "-_" | tr -d =