openssl x509 -in certificate.crt -noout -text The certificate cheat sheet
Every command you are likely to need for TLS certificates, on one page. 44 commands covering inspection, generation, format conversion, verification, live servers, key handling and running your own CA. Each one is executed against OpenSSL 3.5.7 on every build of this site, so nothing here is a copy of a guide that stopped working three major versions ago.
Inspect #
Read what is actually in a file, or on a server, before changing anything.
openssl x509 -in certificate.crt -noout -subject -issuer -dates openssl x509 -in certificate.crt -noout -ext subjectAltName The only field browsers match hostnames against.
openssl x509 -in certificate.crt -noout -enddate openssl x509 -in certificate.crt -noout -checkend 2592000 Exits 0 if yes, 1 if no. The form you want in monitoring.
openssl req -in request.csr -noout -text openssl pkey -in private.key -noout -text openssl x509 -in certificate.crt -noout -fingerprint -sha256 openssl crl2pkcs7 -nocrl -certfile fullchain.crt | openssl pkcs7 -print_certs -noout openssl pkcs12 -in certificate.pfx -info -noout Generate #
Keys, requests and self-signed certificates.
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out private.key openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out private.key Smaller and faster than RSA at equivalent strength.
openssl req -new -newkey rsa:2048 -nodes \
-keyout example.com.key -out example.com.csr \
-subj "/C=US/O=Example Inc/CN=example.com" \
-addext "subjectAltName=DNS:example.com,DNS:www.example.com" Omit the SANs and every browser rejects the certificate.
openssl req -new -key private.key -out request.csr \
-subj "/CN=example.com" -addext "subjectAltName=DNS:example.com" openssl req -x509 -newkey rsa:2048 -nodes \
-keyout private.key -out certificate.crt -days 365 \
-subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1" openssl pkey -in private.key -pubout -out public.pem Convert #
Between PEM, DER, PKCS#7, PKCS#12 and Java keystores.
openssl x509 -in certificate.pem -outform der -out certificate.der openssl x509 -inform der -in certificate.der -out certificate.pem openssl pkcs12 -export -out certificate.pfx \
-inkey private.key -in certificate.crt -certfile chain.crt Add -legacy if Windows or older Java rejects the result.
openssl pkcs12 -in certificate.pfx -nocerts -nodes -out private.key openssl pkcs12 -in certificate.pfx -clcerts -nokeys -out certificate.crt openssl pkcs12 -in certificate.pfx -cacerts -nokeys -out chain.crt openssl crl2pkcs7 -nocrl -certfile certificate.crt -certfile chain.crt -out bundle.p7b openssl pkcs7 -print_certs -in bundle.p7b -out certificates.pem openssl pkcs8 -topk8 -in pkcs1.key -out pkcs8.key -nocrypt Java and Go accept PKCS#8 only.
openssl rsa -in pkcs8.key -traditional -out pkcs1.key -traditional is required on OpenSSL 3.
keytool -importkeystore \
-srckeystore certificate.pfx -srcstoretype PKCS12 \
-destkeystore keystore.jks -deststoretype JKS Verify #
Prove things belong together before a deploy fails.
openssl pkey -in private.key -pubout | openssl sha256
openssl x509 -in certificate.crt -noout -pubkey | openssl sha256 Same hash means yes. Works for EC keys, unlike comparing moduli.
openssl req -in request.csr -noout -pubkey | openssl sha256
openssl pkey -in private.key -pubout | openssl sha256 openssl verify -CAfile root-ca.crt -untrusted intermediate.crt certificate.crt openssl req -in request.csr -noout -verify Live servers #
What a host is actually serving right now.
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates Without -servername you may inspect the wrong certificate.
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \
| grep "Verify return code" openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null 2>/dev/null \
| grep -c "BEGIN CERTIFICATE" 1 means the chain is incomplete.
openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null 2>/dev/null \
| sed -n '/BEGIN CERTIFICATE/,/END CERTIFICATE/p' > chain.pem openssl s_client -connect mail.example.com:587 -starttls smtp </dev/null Key handling #
Passphrases and formats.
openssl pkey -in encrypted.key -out plain.key openssl pkey -in plain.key -aes256 -out encrypted.key chmod 600 private.key Run your own CA #
Trust a root once instead of trusting certificates one at a time.
openssl req -x509 -new -key ca.key -out ca.crt -days 3650 -sha256 \
-subj "/CN=Example Internal Root CA" \
-addext "basicConstraints=critical,CA:TRUE" \
-addext "keyUsage=critical,keyCertSign,cRLSign" openssl x509 -req -in request.csr \
-CA ca.crt -CAkey ca.key -CAcreateserial \
-out certificate.crt -days 397 -sha256 -extfile ext.cnf Without -extfile or -copy_extensions the SANs are silently dropped.
cat certificate.crt intermediate.crt > fullchain.crt Leaf first. Do not append the root.
Decoding things without a terminal
The same operations, in your browser. Nothing you paste is uploaded — the tool pages block network requests with a Content Security Policy.