OpenSSL version note: Commands below target OpenSSL 3.x. Some flags differ in 1.x — noted inline where relevant.
List all available ciphers with details:
openssl ciphers -vList TLS 1.3 ciphersuites (these are separate from TLS 1.2 and below):
openssl ciphers -v 'TLSv1.3'List unique cipher algorithms:
openssl list -cipher-algorithmsopenssl pkey -inform DER -outform PEM -in privatekey.der -out privatekey.pem
openssl pkeyis preferred overopenssl rsain OpenSSL 3.x — it works for RSA, EC, and Ed25519 keys. Theopenssl rsasubcommand still works but is key-type specific.
openssl pkey -in privatekey.pem -out privatekey_nopass.pemopenssl pkey -inform PEM -outform DER -in privatekey.pem -out privatekey.deropenssl x509 -inform DER -outform PEM -in certificate.der -out certificate.pemopenssl x509 -inform PEM -outform DER -in certificate.pem -out certificate.deropenssl x509 -in certificate.pem -out certificate.crtopenssl crl2pkcs7 -nocrl -certfile certificate.pem -out certificate.p7bopenssl pkcs7 -print_certs -in certificate.p7b -out certificate.pem-
Extract the certificates:
openssl pkcs7 -print_certs -in certificate.p7b -out certificate.pem
-
Combine with the private key to create a PFX file:
openssl pkcs12 -export -in certificate.pem -inkey privatekey.key \ -out certificate.pfx -certfile CACert.pem
openssl pkcs12 -in certificate.pfx -out certificate.pem -noencChanged from
-nodes— that flag was deprecated in OpenSSL 3.x. Use-noencinstead. Both do the same thing (output unencrypted private key) but-nodeswill generate a deprecation warning in OpenSSL 3.x.
Legacy compatibility: If the PFX was created with an older tool (e.g., Windows, Java keystores pre-JDK 9) and you get a MAC or decryption error, add the
-legacyflag:openssl pkcs12 -in certificate.pfx -out certificate.pem -noenc -legacy
openssl pkcs12 -export -out certificate.pfx \
-inkey privatekey.key \
-in certificate.crt \
-certfile CACert.crtopenssl genpkey -algorithm RSA -out privatekey.pem -pkeyopt rsa_keygen_bits:4096Why 4096 instead of 2048? NIST SP 800-131A recommends 3072-bit RSA as the minimum for security past 2030. 4096-bit is the safe default for new long-lived keys. 2048-bit is still technically valid today but is approaching end-of-life guidance.
P-384 (NIST curve, conservative choice):
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-384 -out eckey.pemP-256 (still secure, widely supported):
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out eckey.pemopenssl genpkey -algorithm Ed25519 -out ed25519key.pemEd25519 is a modern signature algorithm with strong security properties and no parameter choices to get wrong. Preferred over RSA and ECDSA for new systems where compatibility with very old clients isn't a concern.
Basic CSR:
openssl req -new -key privatekey.pem -out request.csr -sha256CSR with Subject Alternative Names (recommended):
openssl req -new -key privatekey.pem -out request.csr -sha256 \
-subj "/CN=example.com/O=Your Org/C=US" \
-addext "subjectAltName=DNS:example.com,DNS:www.example.com"Why SANs? All major browsers and RFC 2818 require Subject Alternative Names for hostname verification. A CSR with only a Common Name (CN) will result in certificates rejected by modern clients. Always include at least one
DNS:SAN matching your hostname.
Note for Ed25519 CSRs: Drop
-sha256— Ed25519 uses its own digest internally and doesn't accept a separate hash flag:openssl req -new -key ed25519key.pem -out request.csr \ -subj "/CN=example.com" \ -addext "subjectAltName=DNS:example.com"
openssl x509 -in certificate.pem -text -nooutopenssl x509 -in certificate.pem -noout -datesCheck a live server's certificate expiry directly:
openssl s_client -connect example.com:443 </dev/null 2>/dev/null \
| openssl x509 -noout -datesopenssl x509 -noout -modulus -in certificate.pem | openssl sha256
openssl pkey -noout -modulus -in privatekey.pem | openssl sha256Changed from MD5 — the original used
openssl md5which is a broken hash algorithm. Both commands must produce the same SHA-256 hash for the key and certificate to match.For Ed25519/EC keys, check with the public key fingerprint instead:
openssl pkey -in privatekey.pem -pubout | openssl sha256 openssl x509 -in certificate.pem -pubkey -noout | openssl sha256
openssl verify -CAfile ca-bundle.pem certificate.pemopenssl s_client -connect example.com:443openssl s_client -connect example.com:443 -tls1_3openssl s_client -connect example.com:443 -tls1_2Connections using TLS 1.0 or TLS 1.1 should be refused. Both protocols are deprecated by RFC 8996 (March 2021). If a server only accepts TLS 1.0/1.1, that's a finding.
openssl s_client -connect example.com:443 -servername example.comopenssl s_client -connect example.com:443 -status </dev/null 2>/dev/null \
| grep -A 10 "OCSP response"openssl s_client -connect example.com:443 -showcerts </dev/null 2>/dev/null \
| openssl x509 -noout -text