OpenSSL is a robust software library that provides a rich collection of secure communications functionalities via the Secure Sockets Layer (SSL) and Transport Layer Security (TLS) protocols. In this post, we will focus on OpenSSL’s capabilities related to SSL/TLS certificates: validation, retrieval, and handling of certificate chains including intermediate certificates.

Inspecting and Validating a Certificate

Printing a certificate shows what it claims; verification checks its signature and chain against trust anchors. For inspection:

openssl x509 -in cert.pem -noout -subject -issuer -dates -ext subjectAltName

To verify the validity of an SSL/TLS certificate, you can use the openssl verify command:

openssl verify -purpose sslserver -verify_hostname some-domain.com cert.pem

This command will attempt to validate the certificate stored in cert.pem. If the root certificate authority (CA) certificate is unknown to your system, you may encounter an error:

cert.pem: C = Country, ST = State, O = Organization, CN = FQDN
error 20 at 0 depth lookup:unable to get local issuer certificate

This error message indicates that the root Certificate Authority (CA) that issued the certificate is unknown to your system, and as such, the certificate chain cannot be validated.

To find out who the issuing CA is for the certificate, use the following command:

$ openssl x509 -in cert.pem -noout -issuer

This will display the Common Name (CN) of the CA that issued the certificate in cert.pem. If the CA is an intermediate CA, we will need to follow the certificate chain to find the root CA.

Checking Certificate Chains

You can confirm that you have the correct root CA certificate by matching the subject of the root CA certificate with the issuer of the server certificate.

Here’s how to retrieve the subject of the root CA certificate:

$ openssl x509 -noout -subject -in ca.pem

The subject of the root CA certificate should match the issuer of the server certificate. If they don’t, there might be intermediate certificates to consider. You can verify the certificate chain by using the root CA certificate file:

$ openssl verify -CAfile ca.pem -purpose sslserver \
    -verify_hostname some-domain.com cert.pem

This should return cert.pem: OK if the chain, server purpose, and host name are correct. OpenSSL verify documentation

Working with Intermediate Certificates

If you still encounter errors or mismatches, you may need to include an intermediate certificate. Let’s assume we have an intermediate certificate in intermediate.pem. We can confirm its subject and issuer using similar commands as above:

$ openssl x509 -in intermediate.pem -noout -subject
$ openssl x509 -in intermediate.pem -noout -issuer

These should respectively match with the issuer of the server certificate and the subject of the root CA certificate.

To verify the server certificate with an intermediate certificate, use the openssl verify -CAfile ca.pem -untrusted intermediate.pem cert.pem command.

Ordering Certificates

Applications usually require the complete certificate chain in a single file, with the server certificate first, followed by the intermediate certificates. Here’s how you can create the chain:

openssl crl2pkcs7 -nocrl -certfile chain.pem | openssl pkcs7 -print_certs -noout

This command will output the chain of certificates, each with its subject and issuer.

Real World Verification

In a real-world situation, a server certificate may not be directly issued by a root CA but instead by an intermediate CA. To validate such certificates, OpenSSL provides a way to specify both the root and intermediate certificates.

Let’s take the following command as an example:

openssl verify -CAfile rootCA.crt -untrusted intermediateCA1.crt -untrusted intermediateCA2.crt some-domain-com.crt

In this command:

  • openssl verify: The verify command in OpenSSL is used to validate certificates and certificate chains.
  • -CAfile rootCA.crt: This argument specifies the root Certificate Authority (CA) certificate file. The root CA is the top of the certificate chain and is trusted implicitly.
  • -untrusted intermediateCA1.crt and -untrusted intermediateCA2.crt: The -untrusted argument specifies intermediate CA certificates. These certificates are used to form a chain of trust from the server certificate to the root CA.
  • some-domain-com.crt: This is the end-entity certificate you are verifying. It could be a server certificate or a client certificate, in this example for some-domain.com.

Validating a Certificate Matches a Private Key

I compare fingerprints of the public keys. This works for RSA, EC, and other key types:

openssl x509 -in server.crt -pubkey -noout | openssl pkey -pubin -outform DER | openssl sha256
openssl pkey -in server.key -pubout -outform DER | openssl sha256

The two SHA-256 values must match. My old modulus comparison remains an RSA-only shortcut:

openssl x509 -in server.crt -noout -modulus | openssl sha256
openssl rsa -in server.key -noout -modulus | openssl sha256

Checking the Server’s Certificate Chain

To check the certificate chain of a server, you can use:

openssl s_client -connect some-domain.com:443 -servername some-domain.com \
  -showcerts -verify_hostname some-domain.com -verify_return_error

This connects with SNI, prints the chain, and returns verification errors instead of merely displaying them. Add -CAfile /path/to/ca-bundle.pem when the configured default CA store is not the one I need. OpenSSL s_client documentation

Using Server Name Indication (SNI) with OpenSSL

When a server hosts multiple TLS-protected websites, it may present different certificates depending on the hostname the client is connecting to. To specify the hostname, use the -servername option:

openssl s_client -connect some-domain.com:443 -showcerts -servername some-domain.com

In this command, OpenSSL connects to the server and requests the certificate for some-domain.com.

Retrieving a Certificate from a Server

To fetch the SSL/TLS certificate from a server, use the openssl s_client command:

echo | openssl s_client -servername domain.com -connect domain.com:8443 |\
  sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > certificate.crt

This command will save the SSL/TLS certificate of domain.com running on port 8443 to certificate.crt.

That last command retrieves the certificate the endpoint presented; it does not by itself prove that the endpoint or certificate is trusted. I run the verification command above on the saved certificate and its chain when trust is the question.

OpenSSL provides a variety of functionalities that are crucial for handling SSL/TLS certificates, from validation and verification to retrieval. With OpenSSL, you can ensure that your secure communications are truly secure, with the right certificates in place and correctly configured.



Buy Me a Coffee