OpenSSL Cheatsheet
Inspecting Certificates
Use this OpenSSL reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
Full decode
x509 reads a certificate and prints whatever you ask for. -noout suppresses
the re-encoded PEM, which you almost always want.
openssl x509 -in cert.pem -noout -text # everything, human readable openssl x509 -in cert.pem -noout -text -certopt no_sigdump,no_pubkey openssl x509 -in cert.der -inform DER -noout -text
-certopt trims the noise. Useful values: no_sigdump (drop the signature
hex), no_pubkey (drop the key hex), no_header, no_version, no_serial,
no_validity, no_extensions, compatible (drop almost everything).
The one-field questions
Each of these is a single line of output, so they compose into scripts.
| Command | Prints |
|---|---|
-subject | subject=CN=example.com |
-issuer | issuer=C=US, O=Let's Encrypt, CN=R11 |
-dates | both notBefore= and notAfter= |
-startdate / -enddate | one date each |
-serial | serial=03A1... uppercase hex |
-fingerprint -sha256 | colon-separated SHA-256 of the DER |
-pubkey | the public key as PEM |
-modulus | Modulus=A747..., RSA only |
-purpose | which chain purposes this cert is valid for |
-subject_hash | the 8 hex digits CApath symlinks use |
-ext NAME | just the named extensions |
$ openssl x509 -in cert.pem -noout -dates notBefore=Sep 16 02:06:48 2026 GMT notAfter=Dec 15 02:06:47 2026 GMT $ openssl x509 -in cert.pem -noout -fingerprint -sha256 sha256 Fingerprint=76:AD:5E:60:37:4B:95:8F:31:9E:26:46:03:DF:AE:9D:...
Extensions
-ext takes a comma separated list of extension names and prints only those.
This is the fast way to answer "does it cover the hostname".
openssl x509 -in cert.pem -noout -ext subjectAltName openssl x509 -in cert.pem -noout -ext basicConstraints,keyUsage openssl x509 -in cert.pem -noout -ext extendedKeyUsage openssl x509 -in cert.pem -noout -ext authorityInfoAccess # OCSP and CA URLs openssl x509 -in cert.pem -noout -ext crlDistributionPoints
X509v3 Subject Alternative Name:
DNS:example.com, DNS:www.example.com, IP Address:10.0.0.5Expiry checks
-checkend N exits 0 if the certificate is still valid N seconds from now
and 1 if it is not, so it drops straight into a cron job or a health check.
openssl x509 -in cert.pem -noout -checkend 0 # expired right now? openssl x509 -in cert.pem -noout -checkend 2592000 # within 30 days? if ! openssl x509 -in cert.pem -noout -checkend 604800; then echo "cert expires within a week" fi
Straight off a live host, no file needed:
openssl s_client -connect example.com:443 -servername example.com \ </dev/null 2>/dev/null | openssl x509 -noout -subject -dates
Verify a chain
verify walks the chain and reports the first failure. -CAfile is the root
you trust, -untrusted holds the intermediates.
openssl verify -CAfile ca.crt cert.pem openssl verify -CAfile root.pem -untrusted intermediate.pem cert.pem openssl verify -CAfile ca.crt -show_chain cert.pem openssl verify -CAfile ca.crt -verify_hostname example.com cert.pem openssl verify -CAfile ca.crt -purpose sslserver cert.pem
cert.pem: OK
| Error text | Real cause |
|---|---|
unable to get local issuer certificate | Missing intermediate, pass -untrusted |
self-signed certificate | Leaf is self-signed, no CA above it |
self-signed certificate in certificate chain | Root not in -CAfile |
certificate has expired | notAfter is in the past |
certificate is not yet valid | Clock skew, or notBefore in the future |
unsupported certificate purpose | Missing serverAuth in EKU |
Hostname mismatch | Name is not in the SAN list |
A server-side chain file is leaf first, then intermediates, root omitted:
cat cert.pem intermediate.pem > fullchain.pem
openssl crl2pkcs7 -nocrl -certfile fullchain.pem |
openssl pkcs7 -print_certs -noout # list what is in a bundleDoes this key match this cert
Compare public key digests. This works for every algorithm, unlike the classic
-modulus trick, which is RSA only.
openssl x509 -in cert.pem -noout -pubkey | openssl sha256 openssl pkey -in key.pem -pubout | openssl sha256 openssl req -in req.csr -noout -pubkey | openssl sha256
Three identical digests means key, CSR, and certificate agree. The RSA-only version people still paste around:
openssl x509 -in cert.pem -noout -modulus | openssl md5 openssl rsa -in key.pem -noout -modulus | openssl md5
Gotchas
- -noout is not optional in scripts. Without it the PEM body lands in
your output and breaks whatever parses the line.
- verify still loads the system trust store unless you pass -no-CAfile
-no-CApath -no-CAstore. A cert can pass because a public root is trusted,
not because your -CAfile matched.
- verify checks the chain, not the hostname, unless you add
-verify_hostname. That is the mistake behind "openssl says OK but the
browser complains".
- Dates print in GMT in MMM D HH:MM:SS YYYY GMT form, which no date
parser likes. On GNU coreutils, date -d "$(openssl x509 ... -enddate |
cut -d= -f2)" normalizes it.
- -modulus on an EC certificate errors out. Use -pubkey.
- A certificate that is text-dumped and re-saved keeps only the PEM block.
Anything above -----BEGIN CERTIFICATE----- is ignored by OpenSSL but not by
every other parser, so strip it for portability.