OpenSSL Cheat Sheet

Practical OpenSSL reference for keys, CSRs, certificates, TLS inspection, hashing, HMAC, symmetric crypto, and chain verification.

Security Tools
openssl
tls
cryptography

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.

bash
openssl version
openssl version -a
openssl help
openssl help genpkey
Table
ItemCommand
Full version + build infoopenssl version -a
List one subcommandopenssl help <command>
List all ciphers in a cipher suiteopenssl 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.

bash
# 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
Table
AlgorithmBest forKey file size (approx)
Ed25519Service identities, SSH, signing68 bytes signature, tiny key
ECDSA P-256TLS servers, JWT signing~250 bytes
RSA 3072Legacy 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.

bash
# 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.

bash
# 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"
Table
FlagPurpose
-x509Output a certificate instead of a CSR
-days NValidity period in days
-nodesSkip passphrase on the private key
-addextAppend an X.509 extension (e.g. SAN)
-newkey rsa:NLegacy 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.

bash
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
Table
FieldMeaning
SubjectDistinguished Name of the entity the cert names
IssuerDN of the signing CA
ValiditynotBefore / notAfter UTC timestamps
SANSubject Alternative Names — modern trust anchor
SerialUnique CA-issued identifier
Signature Algorithme.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.

bash
# 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.

bash
# 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
Table
ModeUse case
dgst -sha256Integrity check, content addressing
dgst -hmac KEYAuthenticated tag with shared secret
enc -aes-256-cbc -pbkdf2At-rest encryption with passphrase
enc -chacha20-poly1305Authenticated 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.

bash
# 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.

References