OpenSSL Practical Reference
openssl is the Swiss Army knife of cryptography on the command line. This note is a dense practical reference for the tasks you’ll actually run: inspecting certificates, testing TLS, generating keys, creating a local CA, and verifying file integrity.
Certificates - Inspection and Parsing
Section titled “Certificates - Inspection and Parsing”Inspect a Certificate File
Section titled “Inspect a Certificate File”# Full certificate dump (all fields)openssl x509 -in server.crt -text -noout
# Quick summary: subject, issuer, validity datesopenssl x509 -in server.crt -noout -subject -issuer -dates
# Extract just the serial numberopenssl x509 -in server.crt -noout -serial
# Show certificate fingerprint (SHA-256)openssl x509 -in server.crt -noout -fingerprint -sha256
# Verify certificate against a CA certopenssl verify -CAfile ca.crt server.crt
# Verify against a chain (intermediate + root)openssl verify -CAfile chain.pem server.crt
# Extract public key from certificateopenssl x509 -in server.crt -noout -pubkey > server-pubkey.pemInspect a Certificate from a Live Server
Section titled “Inspect a Certificate from a Live Server”# Connect and show the presented certificateopenssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \ | openssl x509 -text -noout
# Show just subject and issuer of live certopenssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \ | openssl x509 -noout -subject -issuer -dates
# See the full certificate chain presentedopenssl s_client -connect example.com:443 -showcerts </dev/null 2>&1 \ | grep -E "^(subject=|issuer=|-----)"
# Check a non-HTTPS TLS service (SMTP STARTTLS example)openssl s_client -connect mail.example.com:587 -starttls smtp </dev/null 2>/dev/null \ | openssl x509 -noout -subject -dates
# LDAPS (LDAP over TLS) - port 636openssl s_client -connect ldap.example.com:636 </dev/null 2>/dev/null \ | openssl x509 -noout -subject -dates
# Test with specific TLS versionopenssl s_client -connect example.com:443 -tls1_2 # force TLSv1.2openssl s_client -connect example.com:443 -tls1_3 # force TLSv1.3TLS Configuration Testing
Section titled “TLS Configuration Testing”# List which ciphers the server accepts (nmap is more comprehensive)nmap --script ssl-enum-ciphers -p 443 example.com
# Quick cipher test with openssl# Test if specific cipher is acceptedopenssl s_client -connect example.com:443 -cipher 'ECDHE-RSA-AES256-GCM-SHA384' </dev/null
# Check if old/weak protocols are accepted (should fail if server is hardened)openssl s_client -connect example.com:443 -ssl3 # SSLv3 - should failopenssl s_client -connect example.com:443 -tls1 # TLS 1.0 - should failopenssl s_client -connect example.com:443 -tls1_1 # TLS 1.1 - should fail
# Check OCSP stapling (certificate revocation)openssl s_client -connect example.com:443 -status </dev/null 2>&1 | grep "OCSP"# Look for "OCSP Response Status: successful" and "Cert Status: good"
# Full SSL/TLS assessment (use testssl.sh for comprehensive analysis)bash testssl.sh example.comGenerating Keys and Certificate Signing Requests (CSRs)
Section titled “Generating Keys and Certificate Signing Requests (CSRs)”Key Generation
Section titled “Key Generation”# Generate an RSA 4096-bit private key (encrypted with AES-256)openssl genrsa -aes256 -out server.key 4096# Remove passphrase (for web servers that need to start without prompt)openssl rsa -in server.key -out server.key.nopass
# Generate EC private key (P-256 curve - compact, fast)openssl ecparam -name prime256v1 -genkey -noout -out ec-server.key
# Generate EC key on P-384 (stronger)openssl ecparam -name secp384r1 -genkey -noout -out ec384-server.key
# Ed25519 key (modern; not supported everywhere yet)openssl genpkey -algorithm Ed25519 -out ed25519.key
# List available EC curvesopenssl ecparam -list_curves | grep -E "prime|secp384|X25519"Generate a Certificate Signing Request (CSR)
Section titled “Generate a Certificate Signing Request (CSR)”# Interactive CSR (prompts for CN, OU, O, etc.)openssl req -new -key server.key -out server.csr
# Non-interactive CSR with all fields specifiedopenssl req -new -key server.key -out server.csr \ -subj "/C=US/ST=California/L=San Francisco/O=ExampleCorp/OU=IT/CN=www.example.com"
# CSR with Subject Alternative Names (SANs) - required by modern browserscat > san.cnf <<EOF[req]distinguished_name = req_distinguished_namereq_extensions = v3_reqprompt = no
[req_distinguished_name]C = USST = CaliforniaO = ExampleCorpCN = www.example.com
[v3_req]subjectAltName = @alt_names
[alt_names]DNS.1 = www.example.comDNS.2 = example.comDNS.3 = api.example.comIP.1 = 203.0.113.5EOF
openssl req -new -key server.key -out server.csr -config san.cnf
# Verify the CSR contentsopenssl req -in server.csr -text -nooutCreate a Local Certificate Authority (CA)
Section titled “Create a Local Certificate Authority (CA)”A local CA is used for internal services, development HTTPS, mutual TLS (mTLS), and testing.
# 1. Generate the CA private key and self-signed root certificateopenssl genrsa -aes256 -out ca.key 4096openssl req -new -x509 -key ca.key -sha256 -days 3650 -out ca.crt \ -subj "/C=US/O=ExampleCorp Internal/CN=ExampleCorp Root CA"
# Inspect the CA certificateopenssl x509 -in ca.crt -text -noout | grep -E "Issuer|Subject|Not"
# 2. Generate server key and CSRopenssl genrsa -out server.key 4096openssl req -new -key server.key -out server.csr \ -subj "/C=US/O=ExampleCorp/CN=internal-api.example.com"
# 3. Sign the server certificate with the CA# Extension file for server certcat > server-ext.cnf <<EOFauthorityKeyIdentifier=keyid,issuerbasicConstraints=CA:FALSEkeyUsage = digitalSignature, keyEnciphermentextendedKeyUsage = serverAuthsubjectAltName = @alt_names
[alt_names]DNS.1 = internal-api.example.comDNS.2 = localhostIP.1 = 127.0.0.1IP.2 = 10.0.0.50EOF
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \ -CAcreateserial -out server.crt -days 365 -sha256 \ -extfile server-ext.cnf
# 4. Verify the chainopenssl verify -CAfile ca.crt server.crt # should output: server.crt: OK
# 5. Bundle into full chain (for web servers)cat server.crt ca.crt > fullchain.crt
# 6. Install the CA cert so your system trusts it (Ubuntu/Debian)sudo cp ca.crt /usr/local/share/ca-certificates/examplecorp-root-ca.crtsudo update-ca-certificates
# 7. Install CA cert in Firefox/Chrome (on Linux)# Firefox: Settings → Privacy → Certificates → Import# Chrome on Linux uses the OS cert store (after update-ca-certificates above)Generate Client Certificates (for mTLS)
Section titled “Generate Client Certificates (for mTLS)”# Client cert - identifies the client to the serveropenssl genrsa -out client.key 4096openssl req -new -key client.key -out client.csr \
cat > client-ext.cnf <<EOFauthorityKeyIdentifier=keyid,issuerbasicConstraints=CA:FALSEkeyUsage = digitalSignatureextendedKeyUsage = clientAuthEOF
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key \ -CAcreateserial -out client.crt -days 365 -sha256 \ -extfile client-ext.cnf
# Test mTLS connection with client certopenssl s_client -connect api.example.com:443 \ -cert client.crt -key client.key \ -CAfile ca.crtEncryption and Decryption
Section titled “Encryption and Decryption”Symmetric File Encryption
Section titled “Symmetric File Encryption”# Encrypt a file with AES-256-CBC (prompts for password)openssl enc -aes-256-cbc -pbkdf2 -salt -in plaintext.txt -out encrypted.bin
# Decryptopenssl enc -d -aes-256-cbc -pbkdf2 -in encrypted.bin -out decrypted.txt
# Encrypt with a specific key and IV (for scripting)KEY=$(openssl rand -hex 32) # 256-bit keyIV=$(openssl rand -hex 16) # 128-bit IVopenssl enc -aes-256-cbc -K "$KEY" -iv "$IV" -in file.txt -out file.encecho "KEY=$KEY IV=$IV" # store these securely!Asymmetric Encryption (RSA - for small data / key wrapping)
Section titled “Asymmetric Encryption (RSA - for small data / key wrapping)”# Extract public key from an RSA private keyopenssl rsa -in private.key -pubout -out public.pem
# Encrypt with recipient's public key (they decrypt with private key)openssl rsautl -encrypt -inkey public.pem -pubin -in secret.txt -out secret.enc
# Decrypt with private keyopenssl rsautl -decrypt -inkey private.key -in secret.enc -out secret.txt
# OAEP padding (more secure - use instead of default PKCS#1 v1.5)openssl rsautl -encrypt -oaep -inkey public.pem -pubin -in secret.txt -out secret.encopenssl rsautl -decrypt -oaep -inkey private.key -in secret.encHashing and Integrity Verification
Section titled “Hashing and Integrity Verification”# Compute file hashopenssl dgst -sha256 file.tar.gzopenssl dgst -sha512 file.tar.gzopenssl dgst -md5 file.tar.gz # MD5 - weak; only for legacy compatibility
# Verify against a known hashecho "abc3d5... file.tar.gz" | sha256sum -c -
# Compute HMAC (keyed hash - proves both integrity and authenticity)openssl dgst -sha256 -hmac "secretkey" file.tar.gz
# Generate random bytesopenssl rand -hex 32 # 32 random bytes as hex (e.g., for a secret key)openssl rand -base64 24 # 24 random bytes as base64 (e.g., for a token)openssl rand 16 > random.bin # raw binary
# Sign a file (proves the file came from the key holder)openssl dgst -sha256 -sign private.key -out file.sig file.tar.gz
# Verify a signatureopenssl dgst -sha256 -verify public.pem -signature file.sig file.tar.gz# Output: Verified OK (or "Verification Failure")Decoding and Format Conversion
Section titled “Decoding and Format Conversion”# Decode a JWT payload (base64url → JSON)echo "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c2VyMTIzIn0.xxx" \ | cut -d'.' -f2 \ | base64 -d 2>/dev/null | python3 -m json.tool
# Convert PEM to DER (binary format)openssl x509 -in server.crt -outform DER -out server.der
# Convert DER back to PEMopenssl x509 -in server.der -inform DER -outform PEM -out server.pem
# Convert PEM private key to PKCS#8 formatopenssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in private.key -out private-pkcs8.key
# Create PKCS#12 (.pfx) bundle (cert + key - used by Windows and Java)openssl pkcs12 -export -out bundle.pfx -inkey server.key -in server.crt -certfile ca.crt
# Extract from PKCS#12openssl pkcs12 -in bundle.pfx -nocerts -nodes -out extracted.key # private keyopenssl pkcs12 -in bundle.pfx -nokeys -out extracted.crt # certificates
# Decode a base64-encoded certificateecho "LS0t..." | base64 -d | openssl x509 -text -nooutOCSP - Certificate Revocation Checking
Section titled “OCSP - Certificate Revocation Checking”# Get the OCSP responder URL from a certificateopenssl x509 -in server.crt -noout -text | grep -A2 "OCSP"
# Manual OCSP check# 1. Extract issuer cert from chainopenssl s_client -connect example.com:443 -showcerts </dev/null 2>&1 > chain.pem# Extract individual certs from chain.pem (cert 0=server, cert 1=intermediate)
# 2. Get OCSP URIOCSP_URI=$(openssl x509 -in server.crt -noout -text | grep "OCSP" | awk -F'URI:' '{print $2}')
# 3. Check revocation statusopenssl ocsp -issuer issuer.crt -cert server.crt -url "$OCSP_URI" -resp_text
# Check revocation via CRL (Certificate Revocation List)# Get CRL distribution point from certopenssl x509 -in server.crt -noout -text | grep "CRL"# Download and inspect CRLcurl -s "https://crl.example.com/issuer.crl" | openssl crl -inform DER -text -nooutQuick Reference: Common Tasks
Section titled “Quick Reference: Common Tasks”# Generate a self-signed cert (dev/testing only)openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem \ -days 365 -nodes \ -subj "/CN=localhost" \ -addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
# Check cert expiry (exit 0 if valid, 1 if expired or within N days)openssl x509 -in server.crt -checkend 0 # expired?openssl x509 -in server.crt -checkend 2592000 # expires within 30 days? (2592000s)
# Check expiry of live server certecho | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \ | openssl x509 -noout -dates
# Monitor multiple certs for expiry (shell loop)for host in api.example.com www.example.com mail.example.com; do echo -n "$host: " echo | openssl s_client -connect "$host":443 -servername "$host" 2>/dev/null \ | openssl x509 -noout -enddate 2>/dev/null || echo "FAILED"done