OpenSSL Cheat Sheet
Practical OpenSSL reference for keys, CSRs, certificates, TLS inspection, hashing, HMAC, symmetric crypto, and chain verification.
OpenSSL is the de facto toolkit for X.509 certificates, TLS handshakes, and general-purpose cryptography. Use genpkey instead of the deprecated genrsa, prefer PBKDF2-derived keys for password-based encryption, and always inspect certificates before trusting them.
Version and help
Start every script by checking the OpenSSL version because command syntax shifts between major releases. Modern OpenSSL 3.x has stricter defaults than 1.1.x and deprecates several legacy commands.
openssl version
openssl version -a
openssl help
openssl help genpkey
| Item | Command |
|---|---|
| Full version + build info | openssl version -a |
| List one subcommand | openssl help <command> |
| List all ciphers in a cipher suite | openssl ciphers -v 'TLS_AES_256_GCM_SHA384' |
Key generation
Always prefer genpkey for new code. genrsa, dhparam (legacy form), and ecparam without -genkey are considered legacy and may be removed.
# RSA 3072-bit private key
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out rsa.pem
# Ed25519 private key (fast, modern, recommended for new systems)
openssl genpkey -algorithm ED25519 -out ed25519.pem
# ECDSA P-256 private key
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out ec.pem
# Encrypt the key with AES-256 (will prompt for passphrase)
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -aes-256-cbc -out rsa-enc.pem
| Algorithm | Best for | Key file size (approx) |
|---|---|---|
| Ed25519 | Service identities, SSH, signing | 68 bytes signature, tiny key |
| ECDSA P-256 | TLS servers, JWT signing | ~250 bytes |
| RSA 3072 | Legacy interoperability | ~1.6 KB |
Certificate Signing Requests
A CSR carries the public key and identifying subject that a CA signs. The -subj flag skips the interactive prompts and is safe to use in scripts when you control the values.
# Build a CSR from an existing key
openssl req -new -key rsa.pem -out server.csr \
-subj "/C=US/ST=California/L=San Francisco/O=Acme/OU=Platform/CN=api.example.com"
# Include Subject Alternative Names via an extensions file
cat > san.cnf <<'EOF'
subjectAltName = DNS:api.example.com,DNS:www.example.com
EOF
openssl req -new -key rsa.pem -out server.csr -subj "/CN=api.example.com" -config <(echo "[req]"; echo "x509_extensions = v3_req"; echo "[v3_req]"; cat san.cnf)
The CN is deprecated by modern browsers; always include SAN entries. CAs reject CSRs without them.
Self-signed certificates
Self-signed certs are fine for development, internal services, and tests, but never for public trust. -nodes skips passphrase encryption on the key — useful for automation, dangerous for production.
# One-shot self-signed cert with Ed25519 (no intermediate key file)
openssl req -x509 -newkey ed25519 -keyout key.pem -out cert.pem \
-days 365 -nodes -subj "/CN=localhost"
# RSA 2048 with SAN
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem \
-days 365 -nodes -subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
| Flag | Purpose |
|---|---|
-x509 | Output a certificate instead of a CSR |
-days N | Validity period in days |
-nodes | Skip passphrase on the private key |
-addext | Append an X.509 extension (e.g. SAN) |
-newkey rsa:N | Legacy combined key + cert flow |
Inspecting certificates and CSRs
-text -noout produces the human-readable dump that every auditor wants; pipe it through a pager when it scrolls past a screen.
openssl x509 -in cert.pem -text -noout
openssl x509 -in cert.pem -noout -subject -issuer -dates -fingerprint -sha256
openssl req -in server.csr -text -noout
openssl pkcs12 -in bundle.pfx -info -nokeys
openssl pkey -in rsa.pem -text -noout
| Field | Meaning |
|---|---|
| Subject | Distinguished Name of the entity the cert names |
| Issuer | DN of the signing CA |
| Validity | notBefore / notAfter UTC timestamps |
| SAN | Subject Alternative Names — modern trust anchor |
| Serial | Unique CA-issued identifier |
| Signature Algorithm | e.g. sha256WithRSAEncryption, ed25519 |
TLS connections
s_client opens a TCP connection, performs the TLS handshake, and prints the negotiated certificate chain. Always pass -servername when a host serves multiple SNI names — without it, you hit the default vhost and may see the wrong cert.
# Quick handshake check
echo | openssl s_client -connect example.com:443 -servername example.com
# Full chain + protocol negotiation
openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null
# Force TLS 1.3 only
openssl s_client -tls1_3 -connect example.com:443 -servername example.com </dev/null
# Show cipher suites actually offered
openssl s_client -connect example.com:443 -tls1_2 -cipher 'ECDHE+AESGCM' </dev/null
Hashing, HMAC, and symmetric crypto
sha256sum is fine for file checksums. For HMAC and symmetric encryption, prefer openssl dgst and openssl enc with -pbkdf2. The old -k flag uses a weak EVP_BytesToKey derivation and is deprecated.
# File digest
sha256sum release.tar.gz
openssl dgst -sha256 release.tar.gz
# HMAC-SHA256 (e.g. webhook signature)
openssl dgst -sha256 -hmac "shared-secret" payload.json
# Symmetric encryption with PBKDF2 (modern)
openssl enc -aes-256-cbc -salt -pbkdf2 -iter 100000 -in plain.txt -out secret.enc
openssl enc -d -aes-256-cbc -pbkdf2 -iter 100000 -in secret.enc -out plain.txt
| Mode | Use case |
|---|---|
dgst -sha256 | Integrity check, content addressing |
dgst -hmac KEY | Authenticated tag with shared secret |
enc -aes-256-cbc -pbkdf2 | At-rest encryption with passphrase |
enc -chacha20-poly1305 | Authenticated encryption for streaming |
Verifying certificate chains
openssl verify checks a leaf against a trust anchor bundle. Always pass the complete CA chain when intermediates are involved — many handshakes fail only because the bundle lacks the intermediate.
# Verify a leaf against a CA bundle
openssl verify -CAfile ca-bundle.pem cert.pem
# Verify with a chain (leaf, intermediate, root)
cat intermediate.pem cert.pem > chain.pem
openssl verify -CAfile root.pem chain.pem
# Check expiration programmatically
openssl x509 -in cert.pem -noout -checkend 86400 && echo "valid >24h" || echo "expiring"
If verification fails, dump the chain with openssl s_client -showcerts and confirm each certificate's issuer matches the next subject up.