Build a two-tier certificate chain and break it on purpose
Task
Build a root CA, an intermediate, and a server certificate on your own lab VM, verify the chain, then break it in two different ways and observe how the failures differ. Chain problems are the commonest certificate incident there is, and they are much clearer once you have caused them.
Steps
- Make a working directory and a root: generate a key and a self-signed root certificate with
openssl req -x509 -newkey rsa:2048 -nodes -keyout root.key -out root.crt -subj '/CN=Lab Root CA' -days 365. - Generate an intermediate key
intermediate.keyand a CSR, then sign the CSR with the root intointermediate.crt, settingbasicConstraints=CA:TRUE,pathlen:0via an extension file so it is genuinely a CA certificate. - Generate a server key
server.keyand a CSRserver.csrforlab.internal, and sign it with the INTERMEDIATE, not the root, intoserver.crt. Keep all of these: the hashing capstone signs a release withserver.key. - Verify the full chain:
openssl verify -CAfile root.crt -untrusted intermediate.crt server.crt. - Break it the first way: verify
server.crtagainst the root alone, without supplying the intermediate. Note the error text. - Break it the second way, without touching
server.crt: issue a second certificate from the same CSR that lives for one day --openssl x509 -req -in server.csr -CA intermediate.crt -CAkey intermediate.key -CAcreateserial -days 1 -out shortlived.crt-- and verify it as it will stand two days from now:openssl verify -attime $(( $(date +%s) + 2*86400 )) -CAfile root.crt -untrusted intermediate.crt shortlived.crt. Note that the error is different, and write both messages into/tmp/chain.md. (Backdating with-days -1is refused by current OpenSSL: "end date before start date".)
Verify
openssl verify -CAfile root.crt -untrusted intermediate.crt server.crt
openssl x509 -in server.crt -noout -issuer -subject -dates
openssl verify -CAfile root.crt server.crt 2>&1 | grep -ci "unable to get local issuer"
openssl verify -attime $(( $(date +%s) + 2*86400 )) -CAfile root.crt -untrusted intermediate.crt shortlived.crt 2>&1 | grep -ci "certificate has expired"
grep -ciE "expired|issuer" /tmp/chain.md
The first must print server.crt: OK for the good certificate. The second must show the issuer is the intermediate and the subject is your invented name. The third must be non-zero — that specific message is what a missing intermediate looks like, and recognising it saves an afternoon. The fourth must be non-zero too, and it is a different message: an expired certificate is a renewal problem, a missing intermediate is a server configuration problem. The fifth confirms you recorded both failure modes, because they are different findings with different fixes.
Notes
The missing-intermediate failure is the one that reaches production, because it works in the browser of whoever tested it — their browser had already cached the intermediate from another site. The server must send the chain; relying on the client to have it is how a certificate works for you and fails for your customers.
This is an independent study companion for CompTIA Security+ SY0-801 and is not produced by or endorsed by CompTIA.