Inspect and verify a TLS certificate with OpenSSL (2026)
OpenSSL reads X.509 certificates so you can check the subject, SANs, issuer, and expiry — and confirm a cert matches the private key it's paired with. Includes the s_client trick for inspecting what a live HTTPS server is really serving.
TL;DR — openssl x509 -in cert.crt -noout -text dumps a certificate in readable form. Compare -modulus | openssl md5 of the cert and the key to confirm they match. Use openssl s_client -connect host:443 to see what a live server serves.
Two short 2009 notes (“view x509 details” and “verify a cert matches a key”), merged and refreshed into one. Companion to reading a CSR and removing a key passphrase.
View a certificate
openssl x509 -in filename.crt -noout -text
filename is the X.509 file — typically .crt, .cert, .pem. -noout skips re-printing the encoded blob; -text gives the human-readable view: subject, issuer, validity dates, key, and extensions.
Pull out just the fields you care about:
openssl x509 -in cert.crt -noout -subject -issuer -dates
openssl x509 -in cert.crt -noout -ext subjectAltName # the SANs
openssl x509 -in cert.crt -noout -fingerprint -sha256
The SANs are the part that matters most now — browsers ignore the CN and only trust the Subject Alternative Names, so confirm every hostname is listed.
Verify a certificate matches a private key
The classic cutover failure: the cert and key don’t belong together, and TLS refuses to start. The certificate, key (and CSR) share the same public modulus — compare hashes:
(openssl x509 -noout -modulus -in server.crt | openssl md5; \
openssl rsa -noout -modulus -in server.key | openssl md5) | uniq
One line of output → they match. Two lines → they don’t (uniq collapses identical hashes). For an EC key, compare the public keys instead:
diff <(openssl x509 -in server.crt -noout -pubkey) \
<(openssl ec -in server.key -pubout)
No diff → they match.
Inspect what a live server is serving
To see the certificate an HTTPS host actually presents (expiry, chain, SANs):
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName
-servername sends SNI, so you get the right cert on a multi-site host. Quick expiry check:
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -enddate
Other formats
openssl x509 -in cert.der -inform der -noout -text # DER (binary)
openssl pkcs12 -in cert.pfx -info -nodes # inspect a .pfx/.p12 bundle
FAQ
“No certificate matches private key” — what now?
The cert and key are from different keypairs. Run the modulus check above; if the hashes differ, find the key that was used to generate this cert’s CSR (or reissue the cert from the key you have).
How do I check the full chain?
openssl verify -untrusted intermediate.crt server.crt, or inspect what s_client returns with -showcerts to see every cert the server sends.
When does this cert expire, across many hosts?
Script the s_client … -enddate one-liner over a host list — it’s the no-dependencies way to monitor expiry.
Summary
- View:
openssl x509 -in cert.crt -noout -text(and-subject -dates -ext subjectAltName). - Match cert↔key: compare
-modulus | openssl md5— one line = match. - Live server:
openssl s_client -connect host:443 -servername host.