Use openssl to individually verify components of a certificate chain

I've more-or-less solved my problem as follows:

There is an option to verify called -partial_chain that allows verify to output OK without finding a chain that lands at self-signed trusted root cert. However, -partial_chain doesn't exist on the version of OpenSSL that I have, nor in any later version of 1.0.1. Here's the run-down:

  • OpenSSL 1.0.1f -- This is the latest for Ubuntu 14.04; it has the heartbleed fix
  • OpenSSL 1.0.1s -- This is the latest in the 1.0.1 line, and likely to be the last; must be installed by hand in Ubuntu 14.04
  • OpenSSL 1.0.2g -- Currently the latest in the 1.0.2 line; this does support -partial_chain
  • OpenSSL 1.1 -- This is currently in alpha and has even more options, but I didn't explore it

So, with 1.0.2g or later, one can do the following:

$ openssl verify -CApath /dev/null -partial_chain -trusted g1 g0
g0: OK
$ openssl verify -CApath /dev/null -partial_chain -trusted g2 g1
g1: OK
$ openssl verify -CApath /dev/null -trusted /etc/ssl/certs/EquiFax_Secure_CA.pem g2
g2: OK

(Note that -partial_chain was not needed in the last command since the Equifax root cert is self-signed.)

This satisfies my question, but requires a version of OpenSSL that is not yet available on some distros unless you hand-install. If you are stuck with a pre-1.0.2 version, you probably have to use @Anthony Geoghegan's method.

Note: There is an option listed in the verify docs called -no-CApath which purportedly obviates the need for -CApath /dev/null, but it's not available on 1.0.2g or earlier, based on my tests. I assume it is available in 1.1.


The OpenSSL verify command builds up a complete certificate chain (until it reaches a self-signed CA certificate) in order to verify a certificate. From its man page:

Firstly a certificate chain is built up starting from the supplied certificate and ending in the root CA. It is an error if the whole chain cannot be built up.

It only returns a positive result if it can verify the complete chain.

If any operation fails then the certificate is not valid.

However, the following command results provide enough information to show that the g0 certificate is signed by the g1 certificate.

$ openssl verify -CApath /dev/null -CAfile g1 g0
g1.crt: C = US, O = Google Inc, CN = Google Internet Authority G2
error 2 at 1 depth lookup:unable to get issuer certificate

Error 2 indicates that one of the certificates in the chain could not be found.

2 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: unable to get issuer certificate

the issuer certificate of a looked up certificate could not be found. This normally means the list of trusted certificates is not complete.

The important thing here is that the depth is 1. This indicates that the certificate being checked was verified at the first level, depth 0 (by the g1 certificate).

If the g1 certificate was not used to sign the g0 certificate, the error would be at the first stage, depth 0 and you would instead receive Error 20:

error 20 at 0 depth lookup:unable to get local issuer certificate

20 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: unable to get local issuer certificate

the issuer certificate could not be found: this occurs if the issuer certificate of an untrusted certificate cannot be found.