Home / Alt manpages / openssl-verification-options(1ssl)

  • openssl-verification-options(1ssl)
  • OpenSSL command
  • linux

Verify X.509 Chains with OpenSSL Without Losing the Trust Boundary

You will use openssl verify to check a certificate against a trust store, add an intermediate certificate without trusting it, test a hostname, and investigate time or policy failures. The examples are read-only and should take about 10 minutes if you already have a PEM certificate and, where needed, its CA files.

Before you start

You need OpenSSL and a target certificate in PEM format. You may also need a CA bundle and one or more intermediate certificates. Verification does not prove that a private key is protected or that a server is reachable. It answers a narrower question: can this certificate chain be built and accepted under the options you supplied?

Check which executable and manpage you are using:

command -v openssl
openssl version
man openssl-verification-options

On the system used for this guide, the installed Ubuntu package is OpenSSL 3.0.13, while the executable on PATH reports 3.6.1. The option names below are present in the local openssl verify -help output, but check your own command if the versions differ.

1. Run the baseline check

Start with the default trust configuration. Replace the path with the certificate you are checking:

openssl verify /path/to/server.pem

A successful result names the certificate and ends with OK:

/path/to/server.pem: OK

OpenSSL may load a system default CA file, directory, or store. The manpage warns that OpenSSL itself does not provide a universal set of trust anchors; distributions normally configure one. If this command fails, do not immediately disable checks. First identify which trust material is missing or unsuitable.

2. Make the trust source explicit

Use -CAfile when you have a PEM bundle containing trusted CA certificates:

openssl verify \
  -CAfile /path/to/trust-bundle.pem \
  /path/to/server.pem

Use -CApath for a hashed directory of CA certificates. The filenames must use the X.509 subject-name hash, so an ordinary directory of randomly named PEM files may not work. Use openssl rehash when you maintain that directory.

openssl verify \
  -CApath /path/to/hashed-ca-directory \
  /path/to/server.pem

For a narrow test, -trusted supplies the only trust anchors and implies -no-CAfile, -no-CApath, and -no-CAstore. That is useful for repeatable tests, but it changes the trust boundary. Do not confuse -untrusted with -trusted: the former supplies intermediates for chain building, not roots that may terminate trust.

3. Add intermediates without trusting them

When the target certificate does not contain its intermediate CA, provide a file containing one or more intermediate certificates:

openssl verify \
  -CAfile /path/to/root-bundle.pem \
  -untrusted /path/to/intermediates.pem \
  /path/to/server.pem

Ask OpenSSL to show the chain it built:

openssl verify \
  -show_chain \
  -CAfile /path/to/root-bundle.pem \
  -untrusted /path/to/intermediates.pem \
  /path/to/server.pem

Read the result as a chain-building problem. The trust file contains certificates allowed to anchor the result. The untrusted file contains candidates that can link the leaf to an anchor. Since trusted certificates are searched first by default, a locally supplied anchor can affect which valid path is selected.

4. Check the identity and intended use

A valid chain is not automatically valid for a particular peer. Use -verify_hostname for a DNS name, -verify_ip for an IP address, or -verify_email for an email identity:

openssl verify \
  -verify_hostname example.test \
  -CAfile /path/to/trust-bundle.pem \
  /path/to/server.pem

Use -purpose sslserver when checking a certificate for a TLS server, or -purpose sslclient for a TLS client. Purpose checks examine extensions such as basic constraints, key usage, and extended key usage. If an EKU extension is present, it limits the permitted uses rather than adding a second independent approval.

openssl verify \
  -purpose sslserver \
  -verify_hostname example.test \
  -CAfile /path/to/trust-bundle.pem \
  /path/to/server.pem

5. Reproduce time and strength failures

Certificate validity is checked against the current system time. To reproduce a historical result, pass a Unix timestamp with -attime:

openssl verify \
  -attime 1704067200 \
  -CAfile /path/to/trust-bundle.pem \
  /path/to/server.pem

-no_check_time suppresses validity-period checks, but it is a diagnostic escape hatch, not a repair. Never use it to claim that an expired certificate is acceptable.

-auth_level applies a certificate-chain security level. The manpage describes level 1 as broadly interoperable and as rejecting, for example, MD5 signatures or RSA keys shorter than 1024 bits. Raising the level can expose weak legacy material; lowering checks can hide it. Record the chosen level in tests and configuration so a later operator does not mistake it for a default.

6. Tighten checks deliberately

Use -x509_strict to disable compatibility workarounds for certificates that do not comply with RFC 5280. It can reject certificates with issues such as a non-critical CA basic-constraints extension or missing required key usage. This is useful for acceptance testing and migration work, but it can expose certificates that older software accepted.

openssl verify \
  -x509_strict \
  -CAfile /path/to/trust-bundle.pem \
  /path/to/server.pem

Use -crl_check or -crl_check_all only when the required CRLs are available. The first checks the end-entity certificate; the second checks every certificate in the chain. A missing usable CRL is an error, so these options do not fetch or invent revocation data for you.

Common traps and recovery

  • Unknown issuer: confirm the correct root is in -CAfile or -CApath, then provide the missing intermediate with -untrusted.
  • Hostname failure: inspect the certificate SAN with openssl x509 -in /path/to/server.pem -noout -subject -ext subjectAltName. Fix the name or certificate; do not remove hostname checking.
  • Unexpected trust: use -trusted with -no-CAfile -no-CApath -no-CAstore to isolate the test to named anchors.
  • Changed results after a CA update: run the same command with an explicit trust file and record its checksum. Trust stores are inputs, not neutral background.

The options above do not modify certificates or trust stores. If you do run openssl rehash, keep a backup of the directory and remove only the generated hash links to undo that directory change. Do not replace a system CA bundle during troubleshooting.

Done means

  • The baseline check returns OK, or the failure has a named cause.
  • The trust anchor is explicit for any repeatable or security-sensitive test.
  • Intermediates are supplied with -untrusted, not silently promoted to trust anchors.
  • Hostname, IP, email, purpose, time, revocation, and strictness checks match the question you are asking.
  • You recorded the OpenSSL executable version and the trust-store inputs.