Create an intermediate certificate authority
To create an intermediate CA, generate a key and CSR for it, then sign that CSR with your root using extensions that mark the result as a CA — `basicConstraints=critical,CA:TRUE,pathlen:0` and `keyUsage=critical,keyCertSign,cRLSign`. The `pathlen:0` constraint means the intermediate may issue end-entity certificates but may not create further CAs beneath itself, which limits the damage if its key is exposed. Once it exists, the root key can go back offline and the intermediate does all day-to-day signing.
Step 1 — the intermediate’s key #
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -aes-256-cbc -out intermediate.key chmod 400 intermediate.key Step 2 — a CSR for it #
openssl req -new -key intermediate.key -out intermediate.csr \
-subj "/C=US/O=Example Inc/CN=Example Inc Intermediate CA" Step 3 — the CA extensions #
Signing an intermediate is signing a CA, so the extensions differ from a server certificate:
basicConstraints = critical,CA:TRUE,pathlen:0
keyUsage = critical,digitalSignature,keyCertSign,cRLSign
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer Replace these values
| Placeholder | What to put there |
|---|---|
CA:TRUE | This certificate may sign other certificates. |
pathlen:0 | It may not create further CAs beneath itself. |
keyCertSign, cRLSign | Permits signing certificates and revocation lists. |
authorityKeyIdentifier | Links back to the root so clients can build the chain. |
Step 4 — sign it with the root #
openssl x509 -req -in intermediate.csr \
-CA root-ca.crt -CAkey root-ca.key -CAcreateserial \
-out intermediate.crt -days 1825 -sha256 \
-extfile intermediate-ext.cnf Step 5 — verify #
openssl verify -CAfile root-ca.crt intermediate.crt Expected output
intermediate.crt: OK
openssl x509 -in intermediate.crt -noout -subject -issuer -ext basicConstraints -ext keyUsage Expected output
subject=C = US, O = Example Inc, CN = Example Inc Intermediate CA issuer=C = US, O = Example Inc, CN = Example Inc Root CA X509v3 Basic Constraints: critical CA:TRUE, pathlen:0 X509v3 Key Usage: critical Digital Signature, Certificate Sign, CRL Sign
Step 6 — issue from the intermediate #
openssl x509 -req -in server.csr \
-CA intermediate.crt -CAkey intermediate.key -CAcreateserial \
-out server.crt -days 397 -sha256 \
-extfile server-ext.cnf Then verify the full path, with the root as anchor and the intermediate as an untrusted link:
openssl verify -CAfile root-ca.crt -untrusted intermediate.crt server.crt Expected output
server.crt: OK
Step 7 — the chain file #
cat server.crt intermediate.crt > fullchain.crt Leaf first, intermediate second, root omitted. See certificate chains.
Constraining the intermediate to your own domains #
Worth doing. Without it, a leaked intermediate can issue a certificate for any hostname, and every machine trusting your root will accept it:
nameConstraints = critical,permitted;DNS:.example.com,permitted;DNS:.internal Frequently asked questions
- What does pathlen:0 do?
- It caps how many further CA certificates may appear below this one.
pathlen:0means none — the intermediate can issue server and client certificates but cannot create another CA. It limits the blast radius if the intermediate key is exposed. - Do I need an intermediate for an internal CA?
- Only if you will actually keep the root offline. The entire benefit is that the root key is not on a running machine. If the root key is going to sit on the same server anyway, the extra layer adds complexity and buys nothing.
- Which certificates does the server send?
- The leaf and the intermediate. Not the root — clients that trust your CA already have it installed.
- Can an intermediate issue a certificate for a name outside my organisation?
- By default yes, which is why
nameConstraintsexists. AddingnameConstraints=critical,permitted;DNS:.example.comrestricts it to your own domains, so a leaked intermediate cannot be used to impersonate anyone else.
References
- openssl-ca(1) — the CA command and its configuration file
- RFC 5280: X.509 and CRL profile — the specification every field on a certificate comes from