Skip to content
 

Check certificate chain file

Sometimes when configuring a server that uses SSL (or actually, more likely these days, TLS), the server certificate is signed by a CA that is not directly recognized by clients, but instead you have a certificate chain of two or three certificates leading to a well-known CA (the so-called "intermediate CA chain" or similar term). In those cases, chances are you have to install a certificate chain file, containing all the certificates in the chain. This seems to be the case more and more recently, and apparently it is for some good reasons.

When an intermediate CA chain file is needed, sometimes that file is available for download from the website of the CA from which you got the server certificate; if that is not available, you can create it manually by just concatenating the relevant PEM-encoded certificates, as in

$ cat cert1.pem cert2.pem cert3.pem > chain.pem

Depending on the application that will use it, the chain file may or may not have to include the server certificate itself. The documentation for the application that is going to use the chain file should specify which configuration applies to it. For example, Apache requires separate files, and the two files must be referenced in the configuration using the SSLCertificateFile and SSLCertificateChainFile directives respectively.
Whatever you do, the certificates MUST be ordered, with each certificate immediately following the certificate it signed, and the final well-known root CA certificate must thus be last.

Here is a quick and dirty hack to check that "you've got it right" and the certificates are in the right order. What it does is walk the chain of certificates in the chain file, and for each certificate output the subject and the issuer. So to confirm that the ordering is right, you just need to check that the subject line in a certificate matches the issuer line for the previous certificate (except the first, of course). You'll also probably see that the last certificate in the chain is self-signed, ie the subject and the issuer are the same.

Code (all on a single line, though Perl isn't really picky about that):

# here the chain file includes the server certificate
$ perl -n0777e 'map { print "---\n"; open(CMD, "| openssl x509 -noout -subject -issuer"); 
print CMD; close(CMD) } /^-----BEGIN.*?^-----END.*?\n/gsm' chain.pem
---
subject= /C=GB/ST=Sussex/L=Some cool place/O=Your organization/CN=www.example.com
issuer= /C=GB/ST=Greater Manchester/L=Salford/O=Comodo CA Limited/CN=PositiveSSL CA
---
subject= /C=GB/ST=Greater Manchester/L=Salford/O=Comodo CA Limited/CN=PositiveSSL CA
issuer= /C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware
---
subject= /C=US/ST=UT/L=Salt Lake City/O=The USERTRUST Network/OU=http://www.usertrust.com/CN=UTN-USERFirst-Hardware
issuer= /C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
---
subject= /C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
issuer= /C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root

Once the correct ordering has been verified, the actual signature verification can be performed:

$ openssl verify chain.pem
chain.pem: OK
# or, using GnuTLS
$ certtool -e --infile chain.pem
Certificate[0]: C=GB,ST=Sussex,L=Some cool place,O=Your organization,CN=www.example.com
	Issued by: C=GB,ST=Greater Manchester,L=Salford,O=Comodo CA Limited,CN=PositiveSSL CA
        Verifying against certificate[1].
	Verification output: Verified.

Certificate[1]: C=GB,ST=Greater Manchester,L=Salford,O=Comodo CA Limited,CN=PositiveSSL CA
	Issued by: C=US,ST=UT,L=Salt Lake City,O=The USERTRUST Network,OU=http://www.usertrust.com,CN=UTN-USERFirst-Hardware
	Verifying against certificate[2].
	Verification output: Verified.

Certificate[2]: C=US,ST=UT,L=Salt Lake City,O=The USERTRUST Network,OU=http://www.usertrust.com,CN=UTN-USERFirst-Hardware
	Issued by: C=SE,O=AddTrust AB,OU=AddTrust External TTP Network,CN=AddTrust External CA Root
	Verifying against certificate[3].
	Verification output: Verified.

Certificate[3]: C=SE,O=AddTrust AB,OU=AddTrust External TTP Network,CN=AddTrust External CA Root
	Issued by: C=SE,O=AddTrust AB,OU=AddTrust External TTP Network,CN=AddTrust External CA Root
	Verification output: Verified.

Chain verification output: Verified.

In this case, the certificate chain seems to be correct. Clients will receive the whole chain when connecting, and they will use each certificate in the chain in turn to verify the previous one, until they reach a certificate they trust because it's built-in in the client.