A certificate is a small signed file that says which names a server may use, for which dates, and who vouches for it. When something breaks (a browser warning, a renewal that didn't take, a monitor that disagrees with you), the answer is almost always in five fields: the alternative names, the two dates, the issuer, the key, and the fingerprint. Here is how to read each of them.
A certificate read in the browser: whether it is in date first, then who it is for.
One command prints everything in the file:
openssl x509 -in cert.pem -noout -text
And this one prints only the fields that usually matter:
openssl x509 -in cert.pem -noout -subject -issuer -dates \
-ext subjectAltName -fingerprint -sha256
-noout stops it printing the certificate back at you. The rest of this guide
goes through what each line means. On a Mac, read the note below first: the
openssl that comes with macOS is older and has no -ext.
Get the certificate from a live site
If the certificate is on a server rather than in a file, ask the server for it.
s_client opens a TLS connection and prints what the server sends:
openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null
-servername matters: one IP address often serves many sites, and without it
you can get a different site's certificate. </dev/null closes the connection
as soon as the handshake is done. This is what example.com sent on 18 October
2026 (OpenSSL 3.5.7), trimmed to the summary lines:
Certificate chain
0 s:CN=example.com
i:C=US, O=SSL Corporation, CN=Cloudflare TLS Issuing ECC CA 3
a:PKEY: EC, (prime256v1); sigalg: ecdsa-with-SHA256
v:NotBefore: Sep 26 22:49:11 2026 GMT; NotAfter: Dec 25 22:56:35 2026 GMT
1 s:C=US, O=SSL Corporation, CN=Cloudflare TLS Issuing ECC CA 3
i:C=US, O=SSL Corporation, CN=SSL.com TLS Transit ECC CA R2
...
Verify return code: 0 (ok)
Each certificate's s: (subject) is the next one's i: (issuer). That is the
chain: the site's own certificate at 0, then the intermediates that vouch for
it. Verify return code: 0 (ok) means OpenSSL followed that chain to a root it
trusts. Any other code names what broke, and a missing intermediate is the
usual one.
To read only the site's own certificate, pipe it straight into x509:
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName
subject=CN=example.com
issuer=C=US, O=SSL Corporation, CN=Cloudflare TLS Issuing ECC CA 3
notBefore=Sep 26 22:49:11 2026 GMT
notAfter=Dec 25 22:56:35 2026 GMT
X509v3 Subject Alternative Name:
DNS:example.com, DNS:*.example.com
To keep the whole chain as a file, save the s_client -showcerts output and
cut out the certificate blocks:
openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null 2>/dev/null \
| awk '/BEGIN CERTIFICATE/,/END CERTIFICATE/' > chain.pem
For example.com that file held four certificates. Drop it on the SSL Certificate Viewer and each one gets its own card, in order.
A saved chain: one card per certificate, the site's own first.
What to read, and why
The names: subject alternative names, not the common name
openssl x509 -in cert.pem -noout -ext subjectAltName
X509v3 Subject Alternative Name:
DNS:fixture.browserbasedtools.test, DNS:www.fixture.browserbasedtools.test, IP Address:127.0.0.1, email:[email protected]
This list is what a browser checks the address against. The common name (CN=
in the subject) is ignored by browsers, so a certificate can have the right CN
and still fail. A wildcard covers one label only: *.example.com matches
www.example.com, not a.b.example.com and not example.com itself.
OpenSSL will check a name for you:
openssl x509 -in example-com.pem -noout -checkhost www.example.com
Hostname www.example.com does match certificate
For a.b.example.com the same command prints does NOT match and exits with 1.
The dates
openssl x509 -in cert.pem -noout -dates
notBefore=Sep 6 06:05:24 2026 GMT
notAfter=Sep 3 06:05:24 2036 GMT
Both are in UTC. Public certificates now last months, not years: the example.com
one above runs 90 days. To ask "does it expire within 30 days?" in a script, use
-checkend with seconds (30 × 86400 = 2592000):
openssl x509 -in cert.pem -noout -checkend 2592000
Certificate will not expire
It exits with 0 when the certificate outlasts the window and 1 when it doesn't,
so openssl x509 -in cert.pem -noout -checkend 2592000 || echo "renew it"
works as a cron check. Put the s_client pipe in front to check a live site
instead of a file.
The issuer
openssl x509 -in cert.pem -noout -subject -issuer
When the subject and the issuer are the same, the certificate is self-signed, as our test certificate is. That is normal for a root or an internal test server, and a browser warning on a public site. When they differ, the issuer is the next certificate up the chain, and the server has to send it too.
The key
openssl x509 -in cert.pem -noout -text | grep -E "Public Key Algorithm|Public-Key"
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
RSA 2048 or larger, or an elliptic curve key (id-ecPublicKey, Public-Key: (256 bit), NIST CURVE: P-256 for example.com). Both are fine today. The key
type matters when a client is old enough not to support EC, or when your
private key and certificate don't belong together.
The fingerprint
openssl x509 -in cert.pem -noout -fingerprint -sha256
sha256 Fingerprint=12:5C:41:9D:B3:66:57:4A:AC:B5:26:DE:E7:49:5F:F1:F9:AF:15:23:64:9E:62:4F:BA:E3:B0:08:69:ED:0C:B4
A hash of the whole certificate. Two files with the same SHA-256 fingerprint
are the same certificate, which is the quickest way to prove the server is
serving the one you installed. Leave out -sha256 and you get SHA-1, which is
a different string for the same certificate. The browser viewer shows both,
without the colons, and copies them as one unbroken run.
/usr/bin/openssl on macOS 26.5 is LibreSSL 3.3.6. It reads certificates fine
but has no -ext (unknown option -ext), needs -inform der for a DER file,
and -checkend prints nothing (the exit code still works). For the names, use
openssl x509 -in cert.pem -noout -text | grep -A1 "Subject Alternative Name",
or install OpenSSL 3 with Homebrew. To look without a terminal, select the file
in Finder and press Space: Quick Look has a certificate previewer built in.
Double-clicking the file hands it to Keychain Access, which is for adding
certificates to a keychain, more than you need to read one.
PEM, DER, .crt and .cer
The same certificate comes in two encodings. PEM is text, starting
-----BEGIN CERTIFICATE-----, and one file can hold a whole chain. DER is
the same bytes in binary, one certificate per file. The extensions .crt and
.cer are used for both, so open the file in a text editor to tell: readable
BEGIN line, PEM; gibberish, DER.
OpenSSL 3 detects DER on input by itself. With LibreSSL, or to be explicit, add
-inform der:
openssl x509 -in cert.der -inform der -noout -subject
To convert, name the output format. PEM to DER:
openssl x509 -in cert.pem -outform der -out cert.der
DER to PEM:
openssl x509 -in cert.der -inform der -out cert.pem
Our test certificate went from 1,692 bytes of PEM to 1,207 bytes of DER, and
back to a PEM file identical to the original (cmp found no difference).
openssl x509 converts only the first certificate in a file; for a chain, use
the browser converter, which converts every block.
Read one in the browser
- Open the SSL Certificate Viewer and
drop the
.pem,.crt,.ceror.derfile on it, or paste the PEM text into the Certificate box. - Click Read certificate.
- Read the chip at the top: Valid with the days left, Expires soon inside 30 days, Expired or Not valid yet. The dates under it are in UTC, the same as openssl prints.
- Check Subject alternative names for every hostname you need, then the Issuer, the Public key and the SHA-256 fingerprint. Copy puts a fingerprint on the clipboard without colons.
What it doesn't do, and says so on the page: it builds no chain, checks no
trust store, no revocation and no hostname. "Valid" means today falls between
the two dates, not that a browser would accept the certificate. For that, run
the s_client command above and read the verify code.
Which to use
- A live site:
openssl s_client ... | openssl x509 -noout -subject -issuer -dates -ext subjectAltName. It also tells you whether the chain verifies, which nothing that reads a file can. - Expiry in a script or a cron job:
-checkendand its exit code. - A file someone sent you, no OpenSSL to hand: the SSL Certificate Viewer. Every name, both dates in UTC, the key and both fingerprints, without uploading the file.
- A chain you need to sort into leaf, intermediate and root: save it as one PEM and drop it on the viewer; each card says its place in the file, and each subject is the issuer on the card above it.
When the SAN list covers your hostnames, the dates are in range and the
fingerprint matches what you installed, the certificate is the right one. If
the browser still complains, it is the chain or the server configuration, and
the s_client verify code is where to look next.