Looking at Certificates
The single most useful OpenSSL habit is
reading a certificate before you deploy it,
renew it, or blame it. The reader is
openssl x509, and the rule of thumb is:
-in <file> -noout plus the questions you
want answered. -noout says "don't reprint
the certificate itself"; without it every
answer arrives with the whole PEM block
attached.
Everything below runs against the lab's
server certificate. Build the lab first
(examples/lab-setup.sh in an empty
directory), then, from inside it:
$ openssl x509 -in server.cert.pem -noout -subject -issuer -dates
subject=CN = server.example.test, O = Example Lab
issuer=CN = Mere Mortals Intermediate CA, O = Example Lab
notBefore=Oct 18 17:39:13 2026 GMT
notAfter=Oct 18 17:39:13 2027 GMT
Three of the four first questions answered in
one line each. Subject — the name the
certificate claims. Issuer — who signed
it; here the intermediate, not the root. A
-subject equal to -issuer means
self-signed, and the lab's root shows exactly
that:
$ openssl x509 -in root/root.cert.pem -noout -subject -issuer
subject=CN = Mere Mortals Root CA, O = Example Lab
issuer=CN = Mere Mortals Root CA, O = Example Lab
Dates are in GMT, always — certificates
do not do time zones, and "it expired at
midnight" incidents are usually this fact
wearing a coat. The usual follow-up, "how
long has it got?", is -enddate alone paired
with your own calendar, or -checkend 0,
which exits quietly if the certificate is
still valid and says so if it isn't.
The parts that decide things
The subject's CN is tradition; what modern
clients actually check is the Subject
Alternative Name extension — the list of
names the certificate covers:
$ openssl x509 -in server.cert.pem -noout -ext subjectAltName
X509v3 Subject Alternative Name:
DNS:server.example.test, IP Address:127.0.0.1
-ext <name> prints one extension. A
certificate asked for with the wrong SAN list
is the hostname-mismatch failure of chapter
11, pre-loaded. Other switches worth knowing:
-serial (the issuer's number for this
certificate — the lab's CA started numbering
at 1000, hex, printed as serial=1000),
and -purpose, which lists what OpenSSL
considers the certificate good for, given its
extensions.
Fingerprint: the certificate's name for humans
$ openssl x509 -in server.cert.pem -noout -fingerprint -sha256
sha256 Fingerprint=91:11:B6:F1:60:A2:3C:9C:17:99:40:6F:CB:38:F4:EE:0A:2B:E4:4C:6F:3F:12:C0:98:4D:DA:A3:EB:64:10:1A
Fingerprints are how you compare two files
without reading either. Same fingerprint,
same certificate — chapter 10 leans on this
to prove a converted file survived. (Use
-sha256; bare -fingerprint defaults to
SHA-1, fine for identification, and both are
identification only — a fingerprint is a
name, not a signature check.)
The whole document
When the specific questions run out, -text
prints everything OpenSSL knows how to say
about the certificate. The head of the lab
server certificate's report, trimmed:
$ openssl x509 -in server.cert.pem -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 4096 (0x1000)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = Mere Mortals Intermediate CA, O = Example Lab
Validity
Not Before: Oct 18 17:39:13 2026 GMT
Not After : Oct 18 17:39:13 2027 GMT
Subject: CN = server.example.test, O = Example Lab
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:d9:bc:bf:6c:5e:26:02:71:68:bc:4c:7f:42:5b:
[...]
Note the serial again: 4096 (0x1000) — the
same number -serial printed as hex. The
rest of the report is the extensions (where
you'll find the SAN again, the key-usage
limits, and CA:FALSE in the basic
constraints — this certificate may not sign
others) and the signature itself. Nobody
reads the modulus bytes; they exist for the
next trick.
The modulus trick: does this key belong to this certificate?
A server needs a key and a certificate that match. The files rarely say so. The classic proof compares the public modulus inside the certificate with the modulus of the key:
$ openssl x509 -in server.cert.pem -noout -modulus | cut -c1-60
Modulus=D9BCBF6C5E26027168BC4C7F425B098070E64856BF1217625064
$ openssl rsa -in server.key.pem -noout -modulus | cut -c1-60
Modulus=D9BCBF6C5E26027168BC4C7F425B098070E64856BF1217625064
Same number: same key pair. (In practice you
compare hashes — pipe both through
openssl md5 — rather than eyeballing hex;
the heads are shown here because they match,
which is the point.) A mismatch is the
"key values mismatch" failure every web
server eventually serves someone; finding it
with two commands beats finding it in a log
at deploy time. For EC keys the equivalent
comparison is the public key text from
openssl x509 -pubkey against
openssl pkey -pubout.
Check: pick any certificate in the lab;
-subject, -issuer and -dates agree with
the story the file's name tells, and the
modulus of server.cert.pem and
server.key.pem match. If they do, you can
read a certificate. The next chapter makes
the keys themselves.