Secrets, PKI & CertificatesV · X.509 Certificates in DepthX509
Serial numbers, validity windows, signature algorithms and fingerprints
What you'll learn
- Explain the scope within which a certificate serial number is unique and what it is used for
- Apply the current maximum validity period for public TLS certificates and the way a day is counted
- Turn a validity window into a monitoring signal using the checkend exit status
- Choose between pinning a certificate fingerprint and pinning a public key digest
Prerequisites
Verified against OpenSSL 3.5.x teaching target; 3.0+ minimum · OpenSSH 10.x teaching target; 8.2+ minimum for certificate workflows · OpenBao 2.6.x · Smallstep step-ca 0.30.x · Certbot / Pebble Certbot current release; Pebble 2.10.x ACME test server · Kubernetes (cross-course target) 1.36.x · PostgreSQL 17.x · 2026-08-26
Four values from a certificate end up in tickets, monitoring rules and revocation requests: the serial, the validity window, the signature algorithm and the fingerprint. Each answers a different question, and confusing them produces confident wrong statements. The serial says which issuance this is. The validity says when it may be used. The signature algorithm says what the issuer committed to. The fingerprint says whether two copies are the same bytes.
The serial number identifies an issuance, not a service
A serial number is the issuing authority’s own identifier for one certificate. It is unique within that issuer and carries no meaning outside it, which is why “serial 42” is an incomplete statement and “serial 42 from the RunBook Lab Server Issuing CA” is a complete one. A revocation list is a list of serials published by a specific issuer for exactly this reason.
Two real serials from two different authorities make the point:
serial=21173B360D80F4A69A91164F1067F4F81A1B1B6E
serial=3DC74918D250C7E9
The first is from a private laboratory issuing CA, the second from an ACME test authority. They differ in length by more than a factor of two and both are perfectly valid, because there is no global format to conform to. What matters operationally is that the serial changes on every issuance. Renew a certificate for the same service, with the same key, from the same CA, and you get a new serial. That property is what makes the serial the right value to record in a change ticket and the right value to compare when you want to know whether a deployment actually replaced anything.
Validity is absolute, and the ceiling is falling
notBefore and notAfter are absolute instants in UTC. There is no
duration stored in the certificate and no relative interpretation. A
verifier compares its own clock against those two instants, so a host
whose clock is wrong will reject a good certificate or accept an expired
one, and neither outcome mentions the clock.
For public TLS certificates the maximum window is not a matter of preference. The CA/Browser Forum Baseline Requirements set a ceiling that steps down on fixed dates:
| Issued on or after | Issued before | Maximum validity |
|---|---|---|
| - | 2026-03-15 | 398 days |
| 2026-03-15 | 2027-03-15 | 200 days |
| 2027-03-15 | 2029-03-15 | 100 days |
| 2029-03-15 | - | 47 days |
For a certificate issued today the ceiling is 200 days, and the prose alongside the table sets a SHOULD NOT one day lower at each step, so 199 days is the recommended practical limit. The counting rule explains why that gap exists: a day is measured as exactly 86,400 seconds, and “any amount of time greater than this, including fractional seconds and/or leap seconds, shall represent an additional day”. A certificate cut for exactly the maximum can therefore land one day over the limit through nothing more than rounding, which is why the Requirements themselves advise against issuing for the maximum permissible time by default.
A separate definition moved on the same date. A short-lived subscriber certificate is now one with a validity period of at most 7 days, that is 604,800 seconds, where before 2026-03-15 the threshold was 10 days. The category matters because short-lived certificates are exempt from some revocation-infrastructure obligations, so a profile that drifts from six days to eight quietly changes which rules apply to it.
Private hierarchies are not bound by any of this. The laboratory certificate used throughout this part runs from 26 August to 24 November 2026, a 90-day window chosen by whoever built the CA. That freedom is real, and it is also how private estates end up with five-year certificates that nobody can rotate.
Turning a validity window into a signal
Reading dates by eye does not scale past a handful of hosts. OpenSSL exposes the comparison as an exit status, which is the primitive every certificate monitor is built on.
CERT=/etc/ssl/certs/app.lab.example.pem
openssl x509 -in "$CERT" -noout -checkend 0
openssl x509 -in "$CERT" -noout -checkend 7776000
The argument is a number of seconds into the future. The first call asks whether the certificate is expired right now and the second asks whether it will be expired in 90 days. Against a certificate with roughly three months left they produce:
Certificate will not expire
Certificate will expire
The messages are the least useful part. The exit status is what to script against: zero when the certificate survives the window, one when it does not. That single fact turns any host with OpenSSL on it into an expiry sensor, and it composes with the socket-reading approach from earlier in this part so that you can test what is being served rather than what is on disk.
flowchart LR
A["Renewal issues a new certificate"] --> B["New serial"]
A --> C["New fingerprint"]
A --> D["Same subject and SAN"]
A --> E["Key reused or replaced"]
C --> F["Certificate pin breaks"]
E -- "key reused" --> G["Public key pin survives"]
The diagram sets out what a renewal changes. The serial and the fingerprint are new every time. The names stay the same, because they are what the certificate is for. The key may or may not be reused, and that single choice decides whether anything that pinned the public key keeps working.
Signature algorithm, key type, and what the fingerprint covers
The signature algorithm appears twice in a certificate: once inside the signed body and once in the outer structure alongside the signature itself. A verifier compares them, because a mismatch would mean the value it used to choose a verification routine was not the value the issuer signed.
For public TLS the permitted choices are narrow. The Baseline Requirements allow RSA keys with a modulus of at least 2048 bits whose size in bits is evenly divisible by eight, or ECDSA keys on NIST P-256, P-384 or P-521, and state that “no other algorithms or key sizes are permitted”. A relevant date of 2026-09-15 sunsets all remaining use of SHA-1 in certificates and CRLs, so treat SHA-1 as gone rather than discouraged. None of this is advice about implementing cryptography; it is a compatibility boundary. A key type outside that set cannot be issued by a public CA at all, however well the algorithm performs.
A fingerprint is something different again. It is a hash over the entire DER encoding of the certificate, not over the body that was signed and not over the key.
CERT=/etc/ssl/certs/app.lab.example.pem
HOST=app.lab.example
FROM_FILE=$(openssl x509 -in "$CERT" -noout -fingerprint -sha256)
FROM_WIRE=$(openssl s_client -connect "$HOST:443" -servername "$HOST" </dev/null 2>/dev/null |
openssl x509 -noout -fingerprint -sha256)
if [ "$FROM_FILE" = "$FROM_WIRE" ]; then
echo "the served certificate is byte-identical to the file"
else
echo "the served certificate differs from the file"
fi
That comparison answers one question exactly: are these the same certificate? It is the fastest way to settle a dispute about which copy is deployed, to confirm that a file copied between hosts arrived intact, and to check an out-of-band value someone read to you over the phone.
Production discipline
- Record serial and issuer together. Every revocation and every audit trail depends on the pair. A serial alone is not an identifier.
- Alert on the exit status, not on parsed dates. Two
checkendthresholds, one warning far out and one paging close in, give a graded signal without any date arithmetic in your own code. - Do not issue at the ceiling. With days counted as 86,400 seconds and any excess rounding upwards, a certificate cut for the maximum can be rejected as one day too long. Leave margin deliberately.
- Pin public keys, never certificates. If something downstream must pin, give it the public key digest and a documented rotation plan, so that renewals are invisible and key changes are announced.
Cross-course references
- Observability for Production Sysadmins - Part LXIV (TLSMonitoring) covers expiry as a metric and the alerting built on top of it, which is where the two checkend thresholds in this lesson belong.
- Kubernetes for Production Sysadmins - Part LXXVI (Certs) covers cluster certificates issued with a fixed one-year expiry, where the same absolute validity semantics apply to control-plane components.
- Linux for Production Sysadmins - Part XXIV (Time) covers chrony and NTP fleet design, which is what keeps a host clock close enough for an absolute validity window to mean anything at all.
Quiz
Knowledge check · 4 questions
Q1. A mobile client pins the SHA-256 fingerprint of a production certificate. The certificate is renewed with the same key pair, the same names and the same issuer. What happens?
Q2. Certificate serial numbers are globally unique, so a serial alone identifies exactly one certificate anywhere in the world.
Q3. Which openssl x509 flag compares the validity window against a point in the future, what does its argument represent, and what does the exit status mean?
Q4. Decide whether an expiry alert is real, and describe the evidence that settles it.
At 06:20 UTC a monitoring probe reports that api.example.com has expired. The on-call engineer connects to the host, reads the certificate file, and finds notAfter set six weeks in the future. A second probe running from a different region reports the service as healthy. The affected probe host was rebuilt yesterday from a new image.
Passing score: 75%. Answers are checked in this browser.