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

> How hostname matching really works: SAN versus CN, wildcard rules, IP SANs, key usage versus extended key usage, and the CA flag with pathLen.

Source: https://pkizerotohero.com/handbook/names-and-key-usage/ · Last reviewed: 2026-10-20

Part III: Certificates · Chapter 9

# Names and jobs: SANs, wildcards, key usage and the CA flag

**In one sentence:**

A certificate is valid only for the names in its Subject Alternative Name list, and only for the jobs that its key usage, extended key usage and CA flag allow.

## Who is this for

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

Level: **Practitioner**

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

## The idea

- Beginner

A certificate answers two questions for the software that checks it:

1. **Is this certificate for the name I asked for?** You typed `shop.example.com`. The certificate must say `shop.example.com`, or something that covers it.
2. **Is this key allowed to do this job?** A key that is meant to run a website should not be able to sign software or create new certificates.

The names live in a list inside the certificate called the [Subject Alternative Name](https://pkizerotohero.com/handbook/glossary/#subject-alternative-name) (SAN). A shop’s certificate might list `example.com` and `www.example.com`. If you visit `shop.example.com` with that certificate, your browser stops with a name error, even though everything else about the certificate is fine.

Older certificates also put a name in a field called the [Common Name](https://pkizerotohero.com/handbook/glossary/#common-name) (CN). Browsers no longer look at it for website names. Only the SAN list counts.

A [wildcard certificate](https://pkizerotohero.com/handbook/glossary/#wildcard-certificate) uses a star as a shortcut. `*.example.com` means “any one name directly under `example.com`”: `www.example.com` and `shop.example.com` both match. It does **not** cover `example.com` itself, and it does **not** cover `a.b.example.com`, which is two levels down.

The jobs are written in three places:

- [Key usage](https://pkizerotohero.com/handbook/glossary/#key-usage) says which basic operations the key may perform, such as creating signatures.
- [Extended key usage](https://pkizerotohero.com/handbook/glossary/#extended-key-usage) says for which purpose: a website server, a client logging in, code signing, and so on.
- [Basic constraints](https://pkizerotohero.com/handbook/glossary/#basic-constraints) says whether the certificate belongs to a certificate authority. Only a CA certificate may sign other certificates.

That last flag matters a great deal. If any website certificate could sign other certificates, every website owner could make a certificate for any other website, and the whole system would collapse.

In the game

In the game: the Name Registry

In Level 9, Ken works at the Name Registry. Every certificate is like a pass that lists exactly which doors it opens and which jobs its holder may do. A wildcard pass opens every door along one corridor, but not the corridor’s own entrance and not the doors in a side corridor.

Where the analogy stops being true: there is no guard who uses judgement. Software compares the text by strict rules, so “almost the right name” is simply wrong. And a pass with the right name only shows that a key belongs to that name. It does not show that the holder is honest.

## How it really works

- Developer
- Expert

### Where do the names live?

The SAN extension is defined in [RFC 5280 section 4.2.1.6](https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.6). It holds a list of typed names: `dNSName` for host names, `iPAddress` for IP addresses, and other types such as email addresses (`rfc822Name`) and URIs.

The rules for matching a server’s name are in RFC 9525. It is blunt about the Common Name: “The Common Name RDN MUST NOT be used to identify a service” ([section 2](https://www.rfc-editor.org/rfc/rfc9525#section-2)). Browsers acted on this long ago: since Chrome 58 (April 2017), Chrome ignores the Common Name and requires the hostname in the Subject Alternative Name.

The [Baseline Requirements](https://cabforum.org/working-groups/server/baseline-requirements/requirements/) for publicly trusted certificates say the same from the CA’s side: the SAN must be present and contain at least one DNS name or IP address, and the CN is “NOT RECOMMENDED”. If a CA includes a CN, it must repeat one of the SAN values (section 7.1.2.7).

Mainly for:

- Developer

**A trap for developers: library fallback.** Some libraries still look at the CN, but only when a certificate has **no DNS name in its SAN**, which in practice usually means no SAN at all. We tested a CN-only certificate for `intranet.example.com` in October 2026: OpenSSL’s `-checkhost`, Python 3.13 (whose `hostname_checks_common_name` setting defaults to `True`) and Node.js 23 all accepted it. They also accepted it when its SAN held only an IP address. Go has ignored the CN by default since [Go 1.15](https://go.dev/doc/go1.15), and browsers reject it. As soon as the SAN lists at least one DNS name, all of these clients ignore the CN for host names. So a CN-only certificate may pass your tests and still fail for real users. Always put every name in the SAN.

### How is a host name matched?

The client builds the name it expects, for example `shop.example.com`, and compares it with each `dNSName` in the SAN:

- The comparison ignores upper and lower case.
- Names are compared label by label. A label is one part between dots: `shop`, `example` and `com`.
- International names appear in their ASCII form, which starts with `xn--`.
- If no SAN entry matches, the connection fails. There is no partial credit.

### What exactly does a wildcard cover?

RFC 9525 [section 6.3](https://www.rfc-editor.org/rfc/rfc9525#section-6.3) sets three rules, and clients follow them closely:

1. The star must be “the complete content of the left-most label”. So `*.example.com` is valid, while `www.*.example.com` and `w*.example.com` are not.
2. “There is only one wildcard character.”
3. “A wildcard in a presented identifier can only match one label in a reference identifier.”

The third rule is why `*.example.com` covers neither `a.b.example.com` (two labels) nor `example.com` (no label at all where the star is). The Baseline Requirements define a wildcard name the same way: “\*.” followed by a fully qualified domain name. They also forbid public CAs from issuing wildcards directly under a public suffix, such as `*.co.uk`, unless the applicant controls that entire namespace (section 3.2.2.6).

Most organisations that want both put two entries in one certificate: `example.com` and `*.example.com`.

*Diagram: The wildcard name star dot example dot com on the left, with lines to four host names on the right. www.example.com: valid, marked with a tick, because the star covers exactly one label. shop.example.com: valid, tick. example.com: invalid, marked with a cross, because there is no label for the star. a.b.example.com: invalid, cross, because the star cannot cover two labels.*

A wildcard stands for exactly one label on the left. It never covers the bare domain or deeper names.

### What about IP addresses?

To connect to `https://10.0.0.5`, the certificate needs an `iPAddress` entry in its SAN. RFC 9525 [section 6.2](https://www.rfc-editor.org/rfc/rfc9525#section-6.2) says an IP address “MUST exactly match the value of an iPAddress entry in subjectAltName”. An IP address written in the CN, or as a `dNSName`, does not count. Java reports this case as [`No subject alternative names matching IP address … found`](https://pkizerotohero.com/errors/java-no-subject-alternative-names/).

Public CAs may issue certificates for public IP addresses they have validated, and Let’s Encrypt has offered certificates for IP addresses since 15 January 2026. For private addresses such as `10.0.0.5`, use a private CA ([chapter 22](https://pkizerotohero.com/handbook/private-ca/)).

### What is the difference between key usage and extended key usage?

**Key usage** ([RFC 5280 section 4.2.1.3](https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.3)) is a set of bits for low-level operations:

| Bit | Meaning | Typical certificate |
| --- | --- | --- |
| `digitalSignature` | The key may create signatures, such as the TLS 1.3 handshake signature | TLS server and client certificates |
| `keyEncipherment` | The key may encrypt other keys. Old TLS 1.2 RSA key exchange used it; TLS 1.3 does not | Older RSA server certificates |
| `keyCertSign` | The key may sign certificates | CA certificates only |
| `cRLSign` | The key may sign revocation lists | CA certificates |

**Extended key usage** (EKU, [section 4.2.1.12](https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.12)) names whole purposes, each with an OID:

| Purpose | OID | openssl prints |
| --- | --- | --- |
| `serverAuth` | 1.3.6.1.5.5.7.3.1 | TLS Web Server Authentication |
| `clientAuth` | 1.3.6.1.5.5.7.3.2 | TLS Web Client Authentication |
| `codeSigning` | 1.3.6.1.5.5.7.3.3 | Code Signing |
| `emailProtection` | 1.3.6.1.5.5.7.3.4 | E-mail Protection |

RFC 5280 is strict: “If the extension is present, then the certificate MUST only be used for one of the purposes indicated.” Both checks apply at the same time: a TLS server certificate needs a key usage that allows its handshake signature and an EKU that includes `serverAuth`.

Public TLS certificates are moving to a single purpose. Chrome's root program starts phasing out root hierarchies that are not dedicated to TLS server authentication (from 15 June 2026), and CAs are removing `clientAuth` from website certificates. If you use certificates to log machines in with mutual TLS, plan for a private CA ([chapter 23](https://pkizerotohero.com/handbook/mutual-tls/)).

### What does the CA flag do?

The basic constraints extension ([section 4.2.1.9](https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.9)) has two fields:

- **`cA`**: `TRUE` for a CA certificate, `FALSE` (or absent) for a leaf. A key may sign certificates only if its certificate has `cA` set to `TRUE` **and** its key usage includes `keyCertSign` ([section 4.2.1.3](https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.3)). CAs must mark this extension critical in CA certificates.
- **`pathLenConstraint`**: “the maximum number of non-self-issued intermediate certificates that may follow this certificate”. `pathlen:0` means the CA may sign leaf certificates but no further CAs.

A related extension, **name constraints** ([section 4.2.1.10](https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.10)), limits a CA to a namespace, for example only names under `corp.example.com`. It is mainly used for private and delegated CAs ([chapter 22](https://pkizerotohero.com/handbook/private-ca/)).

## At work

- Developer
- IT ops

### How do I see a certificate’s names and jobs?

Ask openssl for just these four extensions. This is the test certificate from [chapter 8](https://pkizerotohero.com/handbook/x509-certificates/):

```bash
openssl x509 -in www.crt -noout -ext subjectAltName,keyUsage,extendedKeyUsage,basicConstraints
```

```text
X509v3 Basic Constraints: critical
    CA:FALSE
X509v3 Key Usage: critical
    Digital Signature
X509v3 Extended Key Usage: 
    TLS Web Server Authentication
X509v3 Subject Alternative Name: 
    DNS:www.example.com, DNS:example.com
```

The issuing CA above it looks different. It may sign certificates, but no further CAs:

```text
X509v3 Basic Constraints: critical
    CA:TRUE, pathlen:0
X509v3 Key Usage: critical
    Certificate Sign, CRL Sign
```

### How do I test a host name before deploying?

`openssl x509 -checkhost` applies the matching rules for you. Here is a certificate whose only SAN entry is `*.example.com`:

```bash
for h in www.example.com shop.example.com a.b.example.com example.com; do
  openssl x509 -in wild.crt -noout -checkhost "$h"
done
```

```text
Hostname www.example.com does match certificate
Hostname shop.example.com does match certificate
Hostname a.b.example.com does NOT match certificate
Hostname example.com does NOT match certificate
```

For IP addresses, use `-checkip`. This certificate has the SAN `DNS:app.internal.example, IP Address:10.0.0.5`:

```text
$ openssl x509 -in ip.crt -noout -checkip 10.0.0.5
IP 10.0.0.5 does match certificate
$ openssl x509 -in ip.crt -noout -checkip 10.0.0.6
IP 10.0.0.6 does NOT match certificate
```

A certificate with `CN=10.0.0.5` and no SAN fails the same check: `IP 10.0.0.5 does NOT match certificate`.

### What does a name mismatch look like?

We served the `www.example.com` certificate from a local test server and connected to it as `shop.example.com`. Each client says the same thing in its own words:

```text
# Python 3.13
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: Hostname mismatch, certificate is not valid for 'shop.example.com'. (_ssl.c:1028)

# Node.js 23
ERR_TLS_CERT_ALTNAME_INVALID: Hostname/IP does not match certificate's altnames: Host: shop.example.com. is not in the cert's altnames: DNS:www.example.com, DNS:example.com
```

Browsers show [`NET::ERR_CERT_COMMON_NAME_INVALID`](https://pkizerotohero.com/errors/chrome-err-cert-common-name-invalid/) in Chrome and Edge, and [`SSL_ERROR_BAD_CERT_DOMAIN`](https://pkizerotohero.com/errors/firefox-ssl-error-bad-cert-domain/) in Firefox. The error pages for [Python](https://pkizerotohero.com/errors/python-hostname-mismatch/) and [Node.js](https://pkizerotohero.com/errors/node-err-tls-cert-altname-invalid/) walk through the fixes. In almost every case the fix is the same: issue a new certificate whose SAN lists the exact name that clients use, or point clients at a name that is already listed. Do not turn off hostname checking. Without it, any valid certificate for any name would be accepted, including one for an attacker’s own domain.

### How do I check what a CA flag prevents?

A quick experiment shows the CA flag at work. We used the `www.example.com` key, a leaf with `CA:FALSE`, to sign a certificate for another name, then asked OpenSSL to verify it:

```bash
openssl verify -CAfile root.crt -untrusted www-and-int.pem leaf-signed.crt
```

```text
C=BE, O=Example Shop, CN=www.example.com
error 79 at 1 depth lookup: invalid CA certificate
C=BE, O=Keystone Demo, CN=Keystone Demo Issuing CA 1
error 25 at 2 depth lookup: path length constraint exceeded
C=BE, O=Example Shop, CN=www.example.com
error 32 at 1 depth lookup: key usage does not include certificate signing
error leaf-signed.crt: verification failed
```

Three separate rules reject it: the leaf is not a CA, the issuing CA’s `pathlen:0` allows no CA below it, and the leaf’s key usage lacks `keyCertSign`.

### What should I ask for in a certificate request?

- List **every** name that clients will use in the SAN, including the bare domain if you need it.
- Prefer separate certificates per service over one huge wildcard, so that one stolen key does not expose everything.
- For internal services reached by IP address, add an `IP:` SAN entry.
- Leave key usage and EKU to the CA’s profile, unless you run the CA yourself.

[Chapter 10](https://pkizerotohero.com/handbook/csr/) shows how to put SAN entries into a CSR.

Try the hostname matcher with a wildcard certificate, then change the host name:

*Interactive tool: Hostname matcher (runs in the browser at [/tools/hostname/](https://pkizerotohero.com/tools/hostname/))*

Type a host name such as `example.com` or `a.b.example.com` and see which SAN entry matches, or why none does. The `leaf-cn-only` sample shows a certificate with no SAN at all.

## Common mistakes

- **“Browsers check the Common Name.”** They ignore it. Only the SAN counts for host names, as RFC 9525 requires.
- **“`*.example.com` covers `example.com`.”** It does not. The star must match exactly one label, and the bare domain has none there. Add `example.com` as a separate SAN entry.
- **“`*.example.com` covers `api.eu.example.com`.”** It does not. A wildcard covers exactly one label. You need `*.eu.example.com` or the exact name.
- **“Key usage and extended key usage are the same thing.”** Key usage lists low-level operations, such as signing. EKU lists purposes, such as server authentication. Clients check both.
- **“Any certificate can sign other certificates.”** Only a certificate with `CA:TRUE` and `keyCertSign` can. Every modern client checks this, along with `pathlen`.
- **“An IP address in the CN is enough.”** Modern clients need an `iPAddress` entry in the SAN.

## Why it matters to the business

- Leader

Why it matters to the business

Names decide which services can break together

Every name a service uses must be listed in its certificate, so a new domain, a renamed service or a forgotten bare domain becomes an outage. Wildcards save effort but put one key on many servers: if it leaks, every service under that name is exposed at once. Public certificates are also narrowing to one job, website authentication, so systems that use them to log machines in need a private CA. Decide who approves the names in each certificate, how far wildcards may be used, and whether machine-login certificates have a home.

## Check yourself

Check yourself

Your certificate's SAN lists only \*.example.com. Which address shows a certificate name error?

1. https://www.example.com
2. https://example.com
3. https://api.example.com

Show answer

Answer B https://example.com

What happened

example.com fails, while the other two match.

Why

A wildcard stands for exactly one label on the left. The bare domain example.com has no label in that position.

The rule

List the bare domain separately: example.com and \*.example.com.

Check yourself

A certificate has CN=portal.example.com and no SAN extension. Chrome shows a name error for https://portal.example.com. Why?

1. The CN is spelled in upper case
2. Chrome ignores the CN and finds no SAN to match
3. Chrome needs the organisation name as well

Show answer

Answer B Chrome ignores the CN and finds no SAN to match

What happened

Chrome ignores the Common Name, so the certificate has no usable name at all.

Why

RFC 9525 says the CN must not be used to identify a service, and Chrome stopped using it years ago.

The rule

Put every host name in the Subject Alternative Name extension.

Check yourself

Which certificate is allowed to sign other certificates?

1. Basic constraints CA:FALSE, key usage Digital Signature
2. Basic constraints CA:TRUE, key usage Certificate Sign
3. Extended key usage TLS Web Server Authentication

Show answer

Answer B Basic constraints CA:TRUE, key usage Certificate Sign

What happened

Only the certificate with CA:TRUE and the Certificate Sign key usage may sign certificates.

Why

RFC 5280 requires both the cA flag in basic constraints and the keyCertSign bit. EKU does not grant this power.

The rule

Leaf certificates carry CA:FALSE. Clients reject any chain where a non-CA certificate signs another.

## Go deeper

- [RFC 9525](https://www.rfc-editor.org/rfc/rfc9525): the current rules for matching server names, including wildcards and IP addresses.
- [RFC 5280, sections 4.2.1.3 to 4.2.1.12](https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.3): key usage, SAN, basic constraints, name constraints and extended key usage.
- [CA/Browser Forum Baseline Requirements](https://cabforum.org/working-groups/server/baseline-requirements/requirements/), sections 3.2.2.6 and 7.1.2.7: the wildcard and certificate profile rules for public CAs.
- [Chrome Platform Status: remove CN matching](https://chromestatus.com/feature/4981025180483584): Chrome’s own record of dropping the Common Name.
- [OpenSSL `x509` command](https://docs.openssl.org/master/man1/openssl-x509/): `-checkhost`, `-checkip` and `-ext`.
- [Python `ssl` module](https://docs.python.org/3/library/ssl.html): `check_hostname` and `hostname_checks_common_name`.

The crash course covers names and jobs in [lesson 5, Names, jobs and asking for a certificate](https://pkizerotohero.com/course/names-and-requests/).

**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/names-and-key-usage/).

Last reviewed 20 October 2026Edition 0.9

## Keep going

Crash course: [Lesson 5: Names, jobs and asking for a certificate](https://pkizerotohero.com/course/names-and-requests/)

### Error pages for this chapter

- [NET::ERR\_CERT\_COMMON\_NAME\_INVALID](https://pkizerotohero.com/errors/chrome-err-cert-common-name-invalid/)
- [SSL\_ERROR\_BAD\_CERT\_DOMAIN](https://pkizerotohero.com/errors/firefox-ssl-error-bad-cert-domain/)
- [ERR\_TLS\_CERT\_ALTNAME\_INVALID](https://pkizerotohero.com/errors/node-err-tls-cert-altname-invalid/)
- [certificate verify failed: Hostname mismatch, certificate is not valid for '…'](https://pkizerotohero.com/errors/python-hostname-mismatch/)
- [No subject alternative names matching IP address … found](https://pkizerotohero.com/errors/java-no-subject-alternative-names/)

### How-to guides

- [How to inspect a certificate with OpenSSL](https://pkizerotohero.com/guides/inspect-certificate-openssl/)
- [How to create a key and a CSR with OpenSSL (with SANs)](https://pkizerotohero.com/guides/create-csr-openssl/)
- [How to create a CSR on Windows (certreq and IIS)](https://pkizerotohero.com/guides/create-csr-windows/)
- [How to get a wildcard certificate with DNS-01](https://pkizerotohero.com/guides/wildcard-dns-01/)

### Tools

- [Hostname matcher](https://pkizerotohero.com/tools/hostname/): Test whether a name matches a certificate's SANs and wildcards.
- [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/)
