OpenSSL Keys, certs, TLS

Version 3.5.7 · source

Start here

openssl genpkey -algorithm ED25519 -out key.pem
New private key
openssl req -new -key key.pem -out req.csr
Certificate request
openssl req -x509 -newkey rsa:4096 -noenc -days 365 -keyout key.pem -out cert.pem
Self-signed cert
openssl x509 -in cert.pem -noout -text
Inspect a certificate
openssl s_client -connect <host>:443 -servername <host>
Test a TLS server
openssl dgst -sha256 <file>
Hash a file
openssl verify -CAfile ca.pem cert.pem
Check a chain
openssl rand -hex 32
Random bytes

Concepts

  1. Private key genpkey / req -newkey
  2. CSR request with public key
  3. Certificate x509 -text to inspect
  4. Bundle .p12 / fullchain.pem

Keys

openssl genpkey -algorithm ED25519 -out <key.pem>
Generate a private key
Other algorithms: RSA, EC, X25519
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out <key.pem>
RSA key with chosen size
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out <key.pem>
Elliptic curve key
openssl genpkey -aes-256-cbc -algorithm ED25519 -out <key.pem>
Key protected by a passphrase
openssl pkey -in <key.pem> -pubout -out <pub.pem>
Extract the public key
openssl pkey -in <key.pem> -text -noout
Show key components
openssl pkey -in <key.pem> -check -noout
Check key consistency
openssl pkey -in <key.pem> -aes-256-cbc -out <enc.pem>
Add a passphrase to a key
openssl pkey -in <enc.pem> -out <plain.pem>
Remove a passphrase
openssl pkey -in <key.pem> -outform DER -out <key.der>
Convert PEM key to DER
openssl pkey -pubin -in <pub.pem> -text -noout
Inspect a public key
openssl rand -base64 <num>
Random bytes as base64
openssl rand -hex <num>
Random bytes as hex

Requests and certificates

openssl req -new -key <key.pem> -out <req.csr>
CSR from an existing key
openssl req -new -newkey rsa:2048 -noenc -keyout <key.pem> -out <req.csr>
New key and CSR together
-noenc skips encrypting the key (older versions: -nodes)
openssl req -new -key <key.pem> -subj "/CN=<name>" -addext "subjectAltName=DNS:<name>" -out <req.csr>
CSR with name and SAN, no prompts
Browsers ignore CN and require a SAN
openssl req -in <req.csr> -noout -text
Read a CSR
openssl req -in <req.csr> -verify -noout
Verify CSR signature
openssl req -x509 -newkey rsa:4096 -noenc -days <num> -keyout <key.pem> -out <cert.pem>
Self-signed certificate
openssl req -x509 -key <key.pem> -days <num> -subj "/CN=<name>" -addext "subjectAltName=DNS:<name>" -out <cert.pem>
Self-signed cert from a key
openssl x509 -req -in <req.csr> -CA <ca.pem> -CAkey <ca.key> -days <num> -copy_extensions copy -out <cert.pem>
Sign a CSR with a CA
Add -CAcreateserial on the first run
openssl x509 -in <cert.pem> -pubkey -noout
Public key of a cert

Inspect certificates

openssl x509 -in <cert.pem> -noout -text
Full certificate details
openssl x509 -in <cert.pem> -noout -subject -issuer
Subject and issuer
openssl x509 -in <cert.pem> -noout -dates
Validity period
openssl x509 -in <cert.pem> -noout -enddate
Expiry date only
openssl x509 -in <cert.pem> -noout -checkend <secs>
Exit 1 if expiring within N seconds
86400 tests for expiry within a day
openssl x509 -in <cert.pem> -noout -ext subjectAltName
Show the SAN list
openssl x509 -in <cert.pem> -noout -fingerprint -sha256
SHA-256 fingerprint
openssl x509 -in <cert.pem> -noout -serial
Serial number
openssl verify -CAfile <ca.pem> <cert.pem>
Verify against a CA
openssl verify -CAfile <ca.pem> -untrusted <inter.pem> <cert.pem>
Verify with intermediates
openssl pkey -in <key.pem> -pubout | sha256sum
Hash of key public part
Compare with the cert's -pubkey output to check a key matches
openssl x509 -in <cert.pem> -pubkey -noout | sha256sum
Hash of cert public key

Test a TLS server

openssl s_client -connect <host>:443 -servername <host>
Open a TLS connection
-servername sets SNI; needed for virtual hosts
openssl s_client -connect <host>:443 -brief </dev/null
Short connection summary
openssl s_client -connect <host>:443 -showcerts </dev/null
Show the full chain sent
openssl s_client -connect <host>:443 -tls1_3 </dev/null
Force TLS 1.3
openssl s_client -connect <host>:443 -alpn h2 </dev/null
Offer an ALPN protocol
openssl s_client -connect <host>:443 -verify_hostname <host> -CAfile <ca.pem> </dev/null
Verify name and CA
openssl s_client -connect <host>:587 -starttls smtp
Upgrade SMTP to TLS
Also imap, pop3, ftp and others
openssl s_client -connect <host>:443 -cert <c.pem> -key <k.pem>
Present a client certificate
openssl s_client -connect <host>:443 </dev/null | openssl x509 -noout -dates
Check remote cert expiry
openssl s_client -connect <host>:443 </dev/null | openssl x509 -out <cert.pem>
Save the server cert

Digests and encryption

openssl dgst -sha256 <file>
SHA-256 of a file
openssl dgst -sha256 -hmac <secret> <file>
HMAC of a file
openssl dgst -sha256 -sign <key.pem> -out <sig> <file>
Sign a file
RSA/EC keys only; Ed25519 rejects a digest: use pkeyutl -rawin
openssl dgst -sha256 -verify <pub.pem> -signature <sig> <file>
Verify a signature
openssl dgst -list
List supported digests
openssl enc -aes-256-cbc -pbkdf2 -salt -in <file> -out <file.enc>
Encrypt a file with a password
Always add -pbkdf2; the default key derivation is weak
openssl enc -d -aes-256-cbc -pbkdf2 -in <file.enc> -out <file>
Decrypt it
openssl enc -base64 -in <file>
Base64 encode
openssl passwd -6 <password>
Crypt-style password hash

Convert formats

openssl x509 -in <cert.pem> -outform DER -out <cert.der>
PEM cert to DER
openssl x509 -inform DER -in <cert.der> -out <cert.pem>
DER cert to PEM
openssl pkcs12 -export -inkey <key.pem> -in <cert.pem> -certfile <chain.pem> -out <bundle.p12>
Bundle key and cert as PKCS#12
openssl pkcs12 -in <bundle.p12> -nokeys -out <cert.pem>
Extract certificates
openssl pkcs12 -in <bundle.p12> -nodes -out <all.pem>
Extract everything unencrypted
openssl pkcs12 -in <bundle.p12> -legacy -info -noout
Read an old PKCS#12
openssl asn1parse -in <file.pem>
Dump the ASN.1 structure
openssl crl2pkcs7 -nocrl -certfile <chain.pem> -out <chain.p7b>
Chain to PKCS#7
openssl ciphers -v
List cipher suites
openssl version -a
Version and build info

Recipes

Local dev cert with SAN
openssl req -x509 -newkey rsa:2048 -noenc -days 365 \  -keyout dev.key -out dev.crt -subj "/CN=localhost" \  -addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
Does this key match this cert?
openssl pkey -in key.pem -pubout | sha256sumopenssl x509 -in cert.pem -pubkey -noout | sha256sum# the two hashes must be identical
Expiry check for a monitor
echo | openssl s_client -connect <host>:443 -servername <host> 2>/dev/null \  | openssl x509 -noout -checkend 1209600 \  && echo ok || echo "expires within 14 days"
Share a secret file
openssl enc -aes-256-cbc -pbkdf2 -salt -in secret.txt -out secret.encopenssl enc -d -aes-256-cbc -pbkdf2 -in secret.enc