OpenSSL is the Swiss Army knife for SSL/TLS certificates. Every other article on this site references OpenSSL commands — this page collects them all in one place.
Check a certificate
View certificate details (remote server)
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -text
Check expiry date
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -enddate
Check subject and SANs
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -subject -ext subjectAltName
Check issuer (which CA)
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -issuer
Check a local certificate file
openssl x509 -in cert.pem -noout -text
openssl x509 -in cert.pem -noout -dates # Just the dates
openssl x509 -in cert.pem -noout -subject # Just the subject
openssl x509 -in cert.pem -noout -ext subjectAltName # Just the SANs
Verify the certificate chain
Check chain completeness (remote)
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null
# Look for:
# Verify return code: 0 (ok) ← Chain is complete
# Verify return code: 21 (unable to verify) ← Chain is incomplete
Verify a certificate against a chain file
openssl verify -CAfile chain.pem cert.pem
# Expected: cert.pem: OK
Check if certificate and key match
# These two hashes must be identical
openssl x509 -noout -modulus -in cert.pem | openssl md5
openssl rsa -noout -modulus -in privkey.pem | openssl md5
# For ECDSA keys:
openssl ec -in privkey.pem -pubout 2>/dev/null | openssl md5
openssl x509 -in cert.pem -pubkey -noout | openssl md5
Generate keys
ECDSA P-256 (recommended)
openssl ecparam -genkey -name prime256v1 -noout -out privkey.pem
RSA 2048
openssl genrsa -out privkey.pem 2048
RSA 4096
openssl genrsa -out privkey.pem 4096
Generate a CSR
ECDSA
openssl req -new -key privkey.pem -out csr.pem -subj "/CN=example.com"
With SANs (multi-domain)
openssl req -new -key privkey.pem -out csr.pem \
-subj "/CN=example.com" \
-addext "subjectAltName=DNS:example.com,DNS:www.example.com"
Inspect a CSR
openssl req -in csr.pem -noout -text
Convert between formats
PEM → PFX (for Windows/IIS)
openssl pkcs12 -export -out cert.pfx -inkey privkey.pem -in cert.pem -certfile chain.pem
PFX → PEM
openssl pkcs12 -in cert.pfx -clcerts -nokeys -out cert.pem
openssl pkcs12 -in cert.pfx -nocerts -nodes -out privkey.pem
openssl pkcs12 -in cert.pfx -cacerts -nokeys -out chain.pem
PEM → DER
openssl x509 -in cert.pem -outform DER -out cert.der
DER → PEM
openssl x509 -in cert.der -inform DER -outform PEM -out cert.pem
Certificate formats explained →
Debug TLS connections
Test which TLS version is negotiated
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | grep "Protocol"
Test a specific TLS version
# Test TLS 1.2
echo | openssl s_client -connect example.com:443 -servername example.com -tls1_2 2>/dev/null | grep "Protocol"
# Test TLS 1.3
echo | openssl s_client -connect example.com:443 -servername example.com -tls1_3 2>/dev/null | grep "Protocol"
Show the full handshake
openssl s_client -connect example.com:443 -servername example.com -msg
Check supported cipher suites
# List all ciphers the server accepts
nmap --script ssl-enum-ciphers -p 443 example.com
Generate a self-signed certificate (development only)
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 \
-keyout key.pem -out cert.pem -days 365 -nodes \
-subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
For trusted localhost HTTPS, use mkcert instead.
Create fullchain.pem from separate files
cat cert.pem chain.pem > fullchain.pem
Order matters: your certificate first, then the intermediate(s).
Frequently asked questions
How do I install OpenSSL?
Most Linux distributions include it. On macOS: brew install openssl. On Windows: install via Git for Windows (includes OpenSSL) or Chocolatey (choco install openssl).
What’s the difference between openssl x509 and openssl s_client?
x509 reads a local certificate file. s_client connects to a remote server and retrieves its certificate. Use s_client to check a live server; use x509 to inspect a file on disk.
Why do my commands show “unable to load certificate”?
The file is probably DER-encoded (binary), not PEM (text). Add -inform DER to the command:
openssl x509 -in cert.der -inform DER -noout -text