<!-- https://pkizerotohero.com/handbook/x509-certificates/ | Markdown mirror of the HTML page | PKI Zero to Hero, by Duyutech BV -->

> What is inside an X.509 certificate: version, serial, issuer, dates, subject, public key, extensions and signature, shown with real openssl output.

Source: https://pkizerotohero.com/handbook/x509-certificates/ · Last reviewed: 2026-10-20

Part III: Certificates · Chapter 8

# Anatomy of an X.509 certificate

**In one sentence:**

An X.509 certificate is a public, signed record that ties one public key to names for a fixed period, and you can read every field with openssl.

## Who is this for

- [Developer](https://pkizerotohero.com/start/#developer)
- [IT ops](https://pkizerotohero.com/start/#itops)
- [Beginner](https://pkizerotohero.com/start/#beginner)
- [Expert](https://pkizerotohero.com/start/#expert)
- [Leader](https://pkizerotohero.com/start/#leader)

Level: **Practitioner**

- [New to this? Start with The idea](https://pkizerotohero.com/handbook/x509-certificates/#the-idea)
- [Developer? Jump to How it really works](https://pkizerotohero.com/handbook/x509-certificates/#how-it-really-works)
- [IT ops? At work](https://pkizerotohero.com/handbook/x509-certificates/#at-work)
- [Leader? Why it matters](https://pkizerotohero.com/handbook/x509-certificates/#why-it-matters-to-the-business)

## The idea

- Beginner

In [chapter 7](https://pkizerotohero.com/handbook/binding-identity/) you met the weak spot of public keys: a public key is just a long number, and nothing on it says whose it is. Mallory can pin her own key on the noticeboard and label it “Rosa’s key”. You need someone you already trust to vouch that a key belongs to a name.

A [certificate](https://pkizerotohero.com/handbook/glossary/#certificate) is that vouching, written down. It is a small file that says, in effect: “This public key belongs to `www.example.com`. This is true from 19 October 2026 until 17 January 2027. Signed, Keystone Demo Issuing CA 1.” The signer is a [certificate authority](https://pkizerotohero.com/handbook/glossary/#certificate-authority) (CA). The format that almost all software uses is called [X.509](https://pkizerotohero.com/handbook/glossary/#x509).

Every certificate carries the same handful of parts:

- **Subject**: who the certificate is about, for example a website.
- **Public key**: the subject’s public key, the thing being vouched for.
- **Issuer**: the CA that signed it.
- **Validity**: a start date and an end date.
- **Serial number**: a number the CA uses to tell its certificates apart.
- **Extensions**: extra rules, such as which names the certificate covers and what the key may be used for.
- **Signature**: the issuer’s [digital signature](https://pkizerotohero.com/handbook/glossary/#digital-signature) over everything above.

The signature makes the rest believable. If anyone changes a single character, for example the name or the end date, the signature no longer checks out and software rejects the certificate.

Three things surprise most people:

1. **A certificate is public.** Every website sends its certificate to every visitor, and anyone can save a copy.
2. **A certificate does not contain the private key.** The [private key](https://pkizerotohero.com/handbook/glossary/#private-key) stays with the owner. Only the owner can use it to prove that they are the name in the certificate, so holding a copy of someone’s certificate proves nothing.
3. **A certificate does not encrypt anything.** It answers one question, “whose public key is this?”, so that your connection is set up with the right party.

In the game

In the game: Lord Notarius signs an ID card

In Level 8, Lord Notarius, the Royal Notary, issues Rosa’s first certificate: a card with her name, her public key and his signature. A certificate works like an ID card signed by an office.

Where the analogy stops being true: you keep an ID card in your pocket, but a certificate is public and anyone can hold a copy. What proves you are the name is your private key, not the card. And a certificate only says that a key belongs to a name. It says nothing about whether the holder is honest.

## How it really works

- Developer
- Expert

The internet profile of X.509, which browsers, CAs and libraries follow, is RFC 5280. Its [section 4.1](https://www.rfc-editor.org/rfc/rfc5280#section-4.1) splits a certificate into three parts:

1. `tbsCertificate`, the “to be signed” part that holds every field;
2. `signatureAlgorithm`, which says how the CA signed;
3. `signatureValue`, the signature itself.

*Diagram: A certificate drawn as one large box with two parts. The upper part, labelled tbsCertificate, lists version, serial number, signature algorithm, issuer, validity, subject, subject public key info and extensions. The lower part holds the signature algorithm and the signature value. An arrow from the issuer's private key points to the signature value, labelled: signs the exact bytes of tbsCertificate. A note says that changing any field breaks the signature.*

Everything a client relies on sits in the signed part. The signature covers its exact bytes.

### Which fields are in the signed part?

| Field | What it holds | RFC 5280 |
| --- | --- | --- |
| `version` | Version 3 for every modern certificate, stored as the number 2. Only version 3 can carry extensions. | [4.1.2.1](https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.1) |
| `serialNumber` | A positive integer, unique per CA, at most 20 bytes. Public TLS CAs must put at least 64 random bits in it ([Baseline Requirements](https://cabforum.org/working-groups/server/baseline-requirements/requirements/), section 7.1). | [4.1.2.2](https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.2) |
| `signature` | The signature algorithm, for example `ecdsa-with-SHA256`. It must match the outer `signatureAlgorithm`. | [4.1.2.3](https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.3) |
| `issuer` | The name of the CA that signed it. | [4.1.2.4](https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.4) |
| `validity` | `notBefore` and `notAfter`. The certificate is valid from the first through the second, inclusive. | [4.1.2.5](https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.5) |
| `subject` | The name of the owner. For websites, the names that count live in an extension instead ([chapter 9](https://pkizerotohero.com/handbook/names-and-key-usage/)). | [4.1.2.6](https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.6) |
| `subjectPublicKeyInfo` | The key’s algorithm (RSA, or an elliptic curve such as P-256) and the public key itself. | [4.1.2.7](https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.7) |
| `extensions` | A list of extensions. Each has an identifier (an OID), a critical flag and a value. | [4.1.2.9](https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.9), [4.2](https://www.rfc-editor.org/rfc/rfc5280#section-4.2) |

The issuer and subject are each a [distinguished name](https://pkizerotohero.com/handbook/glossary/#distinguished-name) (DN): a list of attributes such as country (`C`), organisation (`O`) and [common name](https://pkizerotohero.com/handbook/glossary/#common-name) (`CN`). The `issuer` of a certificate must equal the `subject` of the CA certificate that signed it. That is one way software links certificates into a chain ([chapter 13](https://pkizerotohero.com/handbook/certificate-chains/)).

Dates up to 2049 are stored as `UTCTime` with a two-digit year, and dates from 2050 onwards as `GeneralizedTime`. All of them are in UTC, which is why openssl prints “GMT”.

### What does the signature cover?

The CA takes the exact bytes of the `tbsCertificate`, hashes them, and signs the hash with its private key ([section 4.1.1.3](https://www.rfc-editor.org/rfc/rfc5280#section-4.1.1.3)). A verifier hashes the same bytes and checks the signature with the CA’s public key, which it finds in the CA’s own certificate. That is signature verification, not decryption ([chapter 6](https://pkizerotohero.com/handbook/digital-signatures/) explains the difference).

Everything in the signed part is protected: the names, the dates, the extensions and the subject’s public key. The outer `signatureAlgorithm` sits outside the signed part, which is why the inner `signature` field repeats it and the two must match.

### What are ASN.1, DER and PEM?

[ASN.1](https://pkizerotohero.com/handbook/glossary/#asn1) is the notation that describes the structure: a sequence of fields, each with a type. [DER](https://pkizerotohero.com/handbook/glossary/#der) is the single exact way to turn that structure into bytes. Each item is written as a tag (its type), a length and a value. DER allows only one encoding for each value, so the same certificate always has the same bytes, and a signature over those bytes stays checkable.

The first bytes of our test certificate show the pattern:

```text
30 82 02 6e 30 82 02 14 a0 03 02 01 02 02 14 7d
```

- `30 82 02 6e`: a SEQUENCE (the whole certificate) whose content is 0x26e, or 622, bytes long.
- `30 82 02 14`: the next SEQUENCE, the 532-byte `tbsCertificate`.
- `a0 03 02 01 02`: the version field, holding the integer 2, which means version 3.
- `02 14 7d …`: an INTEGER of 0x14, or 20, bytes, the serial number.

[PEM](https://pkizerotohero.com/handbook/glossary/#pem) is DER encoded as Base64 text between `-----BEGIN CERTIFICATE-----` and `-----END CERTIFICATE-----` lines ([RFC 7468](https://www.rfc-editor.org/rfc/rfc7468)). Almost every PEM certificate starts with `MII`, because that is the Base64 form of the bytes `30 82`. A file extension such as `.crt` or `.cer` does not reliably tell you whether a file is PEM or DER. The [file formats appendix](https://pkizerotohero.com/handbook/file-formats/) covers PEM, DER and PKCS #12.

### Which extensions matter most?

- **Subject Alternative Name (SAN)**: the DNS names and IP addresses the certificate is valid for ([chapter 9](https://pkizerotohero.com/handbook/names-and-key-usage/)).
- **Key Usage and Extended Key Usage**: what the key may do, for example create signatures or authenticate a TLS server (chapter 9).
- **Basic Constraints**: whether this certificate belongs to a CA (chapter 9).
- **Subject and Authority Key Identifiers (SKI, AKI)**: short identifiers of this key and of the issuer’s key, used to build chains ([chapter 13](https://pkizerotohero.com/handbook/certificate-chains/)).
- **Authority Information Access (AIA)**: where to download the issuer’s certificate, and sometimes an OCSP address (chapters 13 and [16](https://pkizerotohero.com/handbook/revocation/)).
- **CRL Distribution Points**: where the CA publishes its revocation list (chapter 16).
- **Certificate Policies**: the rules the CA followed. The value `2.23.140.1.2.1` means “domain validated” ([chapter 11](https://pkizerotohero.com/handbook/domain-validation/)).
- **Signed Certificate Timestamps (SCTs)**: proof that the certificate was logged publicly ([chapter 17](https://pkizerotohero.com/handbook/certificate-transparency/)).

An extension marked **critical** must be understood: software that meets a critical extension it does not recognise must reject the certificate ([section 4.2](https://www.rfc-editor.org/rfc/rfc5280#section-4.2)). Unknown non-critical extensions may be ignored.

### What does a client check?

When software receives a certificate, it checks at least these things ([RFC 5280 section 6](https://www.rfc-editor.org/rfc/rfc5280#section-6) and [RFC 9525](https://www.rfc-editor.org/rfc/rfc9525)):

1. the signature, using the issuer’s public key;
2. the dates, against **its own clock**;
3. that the chain of issuers ends at a root in its [trust store](https://pkizerotohero.com/handbook/glossary/#trust-store) ([chapter 12](https://pkizerotohero.com/handbook/trust-stores/));
4. the constraints and usages along the chain;
5. for TLS, that the name it wanted appears in the SAN.

Revocation checks come on top, and clients differ a lot there ([chapter 16](https://pkizerotohero.com/handbook/revocation/)). Note point 2: a device with a wrong clock sees perfectly good certificates as “not yet valid” or “expired”.

## At work

- Developer
- IT ops

### How do I read a certificate?

`openssl x509` decodes any PEM certificate. We created a small test hierarchy with OpenSSL 3.2 (a root CA, an issuing CA and one website certificate for `www.example.com`) and printed the website certificate:

```bash
openssl x509 -in www.crt -noout -text
```

```text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            7d:de:28:b9:6f:0e:60:ba:ec:77:61:c1:2e:d0:d8:c1:40:0b:c5:7c
        Signature Algorithm: ecdsa-with-SHA256
        Issuer: C=BE, O=Keystone Demo, CN=Keystone Demo Issuing CA 1
        Validity
            Not Before: Oct 19 21:58:14 2026 GMT
            Not After : Jan 17 21:58:14 2027 GMT
        Subject: C=BE, O=Example Shop, CN=www.example.com
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:de:97:84:56:68:98:87:ab:13:b6:9e:ec:e1:43:
                    (4 more lines of the public key)
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Key Usage: critical
                Digital Signature
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication
            X509v3 Subject Key Identifier: 
                B4:7C:08:25:AE:9F:2B:4F:E1:A8:22:B3:72:02:AA:61:47:BC:34:7E
            X509v3 Authority Key Identifier: 
                73:25:6F:04:13:C8:DA:28:C5:70:88:FA:DB:29:21:C8:1B:DC:B6:8B
            X509v3 Subject Alternative Name: 
                DNS:www.example.com, DNS:example.com
            Authority Information Access: 
                CA Issuers - URI:http://ca.example.com/issuing-ca-1.crt
    Signature Algorithm: ecdsa-with-SHA256
    Signature Value:
        30:45:02:20:72:20:70:13:35:54:4a:30:20:52:28:17:9b:99:
        (3 more lines of the signature)
```

Read it from top to bottom:

- **`Version: 3 (0x2)`**: version 3, stored as 2.
- **`Serial Number`**: 20 random bytes.
- **`Issuer` and `Subject`** differ, so this certificate was signed by someone else. In a self-signed root they are identical.
- **`Validity`**: 90 days, always printed in GMT.
- **`Public-Key: (256 bit)`**: the subject’s elliptic-curve public key. The private key is nowhere in this output.
- **`CA:FALSE`**: this is a leaf, not a CA. **`Digital Signature`** and **`TLS Web Server Authentication`**: the key may sign TLS handshakes for a server.
- **`Subject Alternative Name`**: the two names that browsers will check.
- **`Authority Key Identifier`**: matches the Subject Key Identifier in the issuing CA’s certificate.
- **`Signature Value`**: the issuing CA’s ECDSA signature over everything under `Data`.

### How do I answer one question quickly?

Ask openssl for only the fields you need:

```bash
openssl x509 -in www.crt -noout -subject -issuer -dates -serial -fingerprint -sha256
```

```text
subject=C=BE, O=Example Shop, CN=www.example.com
issuer=C=BE, O=Keystone Demo, CN=Keystone Demo Issuing CA 1
notBefore=Oct 19 21:58:14 2026 GMT
notAfter=Jan 17 21:58:14 2027 GMT
serial=7DDE28B96F0E60BAEC7761C12ED0D8C1400BC57C
sha256 Fingerprint=F4:8B:F4:C9:DB:9A:74:F5:EF:E1:24:2C:DB:34:9E:53:52:FF:2F:85:12:82:26:C9:1A:A0:4D:8B:53:32:19:08
```

The fingerprint is not stored in the certificate. Your tool computes it as a hash of the whole DER file. Use it to compare two copies of a certificate, for example in a ticket or on the phone.

To read the certificate a live server sends, pipe `openssl s_client` into `openssl x509`:

```bash
openssl s_client -connect letsencrypt.org:443 -servername letsencrypt.org </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates -ext subjectAltName
```

```text
subject=CN=letsencrypt.org
issuer=C=US, O=Let's Encrypt, CN=YE2
notBefore=Sep  4 14:34:32 2026 GMT
notAfter=Dec  3 14:34:31 2026 GMT
X509v3 Subject Alternative Name: 
    DNS:cp.letsencrypt.org, DNS:cp.root-x1.letsencrypt.org, DNS:cps.letsencrypt.org, DNS:cps.root-x1.letsencrypt.org, DNS:lencr.org, DNS:letsencrypt.com, DNS:letsencrypt.org, DNS:www.lencr.org, DNS:www.letsencrypt.com, DNS:www.letsencrypt.org
```

This real certificate, fetched in October 2026, covers ten names. Its subject holds only a CN, because browsers use the SAN list, not the subject.

On Windows, `certutil -dump www.crt` prints the same fields. Note that certutil shows the dates in your **local** time zone, while openssl shows GMT:

```text
X509 Certificate:
Version: 3
Serial Number: 7dde28b96f0e60baec7761c12ed0d8c1400bc57c
Signature Algorithm:
    Algorithm ObjectId: 1.2.840.10045.4.3.2 sha256ECDSA
...
 NotBefore: 2026-10-19 11:58 PM
 NotAfter: 2027-01-17 11:58 PM
```

### How do I catch expiry before users do?

`-checkend` takes a number of seconds and tells you whether the certificate expires within that time. The exit code makes it easy to use in monitoring:

```bash
openssl x509 -in www.crt -noout -checkend 2592000   # 30 days
openssl x509 -in www.crt -noout -checkend 8640000   # 100 days
```

```text
Certificate will not expire
Certificate will expire
```

The first command exits with 0 and the second with 1. Inventory and renewal at scale are the subject of [chapter 19](https://pkizerotohero.com/handbook/certificate-lifecycle/).

### What breaks?

Date problems are the most common certificate failure:

- **Expired**: OpenSSL says [`verify error:num=10:certificate has expired`](https://pkizerotohero.com/errors/openssl-certificate-has-expired/), and Chrome and Edge show [`NET::ERR_CERT_DATE_INVALID`](https://pkizerotohero.com/errors/chrome-err-cert-date-invalid/).
- **Not yet valid**: the same browser error appears when the client’s clock is behind `notBefore`, for example on a device whose clock was reset.
- **Wrong clock on the client**: if every site fails on one machine only, check that machine’s date and time first.

Try the decoder below. It reads a certificate in your browser; nothing is uploaded.

*Interactive tool: Certificate decoder (runs in the browser at [/tools/decoder/](https://pkizerotohero.com/tools/decoder/))*

Paste any PEM certificate, starting with `-----BEGIN CERTIFICATE-----`. Certificates are public, so this is safe. Never paste a private key into any website.

## Common mistakes

- **“The certificate contains the private key.”** It contains only the public key. A `.pfx` or `.p12` file can bundle a certificate together with its private key, but that bundle is not the certificate.
- **“Certificates encrypt the traffic.”** They do not. In TLS 1.3 the traffic keys come from a fresh key exchange, and the certificate’s key only signs the handshake ([chapter 15](https://pkizerotohero.com/handbook/tls-handshake/)).
- **“A certificate is secret.”** It is public. Every server sends it to every client, and publicly trusted certificates are also published in Certificate Transparency logs.
- **“The CA signs by encrypting the hash with its private key.”** A signature is not encryption. Signing and verifying are their own operations ([chapter 6](https://pkizerotohero.com/handbook/digital-signatures/)).
- **“`.crt` means PEM and `.cer` means DER.”** The extension is only a habit. Look at the content: PEM starts with `-----BEGIN`, DER is binary.
- **“Validity is checked against the server’s clock.”** It is checked against the client’s clock, so a client with a wrong clock rejects good certificates.

## Why it matters to the business

- Leader

Why it matters to the business

Every certificate has an end date

A certificate is valid only between two dates written inside it, and nobody can extend it afterwards. Publicly trusted TLS certificates are now limited to 200 days, and from 15 March 2029 the limit falls to 47 days. When a certificate expires, the service behind it fails for every client at once, which makes expiry one of the most common causes of avoidable outages. The decisions to make: who owns the list of your certificates, and is renewal automated rather than left to a calendar reminder?

## Check yourself

Check yourself

A colleague accidentally posts your website's certificate file in a public chat. What can a stranger do with it?

1. Run a fake copy of your website that browsers trust
2. Nothing harmful, because certificates are public and a fake site would also need your private key
3. Decrypt traffic between your website and its visitors

Show answer

Answer B Nothing harmful, because certificates are public and a fake site would also need your private key

What happened

Nothing harmful happens: the certificate is already public, because your server sends it to every visitor.

Why

To use a certificate, a server must prove during the handshake that it holds the matching private key. The certificate file does not contain that key.

The rule

Certificates are public. Protect the private key, not the certificate.

Check yourself

Someone edits the notAfter date inside a certificate with a hex editor to make it valid for one more year. What happens?

1. Clients accept the new date
2. The signature no longer verifies, so clients reject the certificate
3. Only browsers notice; command-line tools accept it

Show answer

Answer B The signature no longer verifies, so clients reject the certificate

What happened

Every client rejects the edited certificate.

Why

The CA's signature covers the exact bytes of the signed part, including the dates. Any change breaks the signature.

The rule

Only the CA can produce a certificate with new dates, by issuing a new certificate.

Check yourself

One laptop shows a certificate date error on every HTTPS website, while colleagues on the same network have no problems. What is the most likely cause?

1. All the websites forgot to renew at the same time
2. The laptop's clock is wrong
3. The laptop's trust store is full

Show answer

Answer B The laptop's clock is wrong

What happened

The laptop's date or time is wrong.

Why

Clients compare notBefore and notAfter with their own clock. A wrong clock makes good certificates look not yet valid or expired.

The rule

When every site fails on one device only, check that device's clock first.

## Go deeper

- [RFC 5280, section 4](https://www.rfc-editor.org/rfc/rfc5280#section-4): every certificate field and the standard extensions.
- [RFC 5280, section 6](https://www.rfc-editor.org/rfc/rfc5280#section-6): the path validation algorithm that clients run.
- [RFC 7468](https://www.rfc-editor.org/rfc/rfc7468): the PEM text format and its labels.
- [CA/Browser Forum Baseline Requirements](https://cabforum.org/working-groups/server/baseline-requirements/requirements/), section 7.1: the exact profile of publicly trusted TLS certificates.
- [OpenSSL `x509` command](https://docs.openssl.org/master/man1/openssl-x509/): every option for printing, converting and checking certificates.
- [Microsoft `certutil`](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/certutil): decoding and managing certificates on Windows.

The crash course covers certificates in [lesson 4, Whose key is it?](https://pkizerotohero.com/course/whose-key-is-it/).

**Early edition.** Checked against the standards; an independent expert review is in progress. Found a mistake? [Tell us](https://pkizerotohero.com/contact/?topic=content-error&page=/handbook/x509-certificates/).

Last reviewed 20 October 2026Edition 0.9

## Keep going

Crash course: [Lesson 4: Whose key is it?](https://pkizerotohero.com/course/whose-key-is-it/)

### Error pages for this chapter

- [verify error:num=10:certificate has expired](https://pkizerotohero.com/errors/openssl-certificate-has-expired/)
- [NET::ERR\_CERT\_DATE\_INVALID](https://pkizerotohero.com/errors/chrome-err-cert-date-invalid/)

### How-to guides

- [How to inspect a certificate with OpenSSL](https://pkizerotohero.com/guides/inspect-certificate-openssl/)
- [How to check when a certificate expires, and monitor it](https://pkizerotohero.com/guides/check-certificate-expiry/)
- [How to check that a private key matches a certificate](https://pkizerotohero.com/guides/check-key-matches-certificate/)
- [How to convert between DER and PEM](https://pkizerotohero.com/guides/convert-der-pem/)
- [How to install a certificate in nginx](https://pkizerotohero.com/guides/install-certificate-nginx/)
- [How to install a certificate in Apache httpd](https://pkizerotohero.com/guides/install-certificate-apache/)

### Tools

- [Certificate decoder](https://pkizerotohero.com/tools/decoder/): Paste a PEM certificate and read every field in plain words.

### Topics

- [Certificates](https://pkizerotohero.com/topics/certificates/)
