For many developers certificates are a black box: It is old tech with terrible documentation and the underlying encryption is complex and hard to understand. This practical guide to TLS/SSL certificates will help you navigate these hazardous waters.
In this guide you will learn:
- Reasons why a certificate may be invalid
- All about self signed certificates
- Certificate formats
- Components of a certificate
Why you should care about TLS/SSL certificates
Certificates play a central role in IT and cloud security. Failure to understand them and handle them correctly can result in serious damage to business:
- Certificates can expire causing outages - it happened to Microsoft
- Private keys could be exposed if handled incorrectly - Atlassian made that mistake
- Creating self-signed certificates that are unsafe
- Man-in-the-middle attack to retrieve passwords - not easily detectable
- Bad actors authenicating themselves with certificates - the NSA posed as Google
Certificate vs. public key vs. private key vs. CSR
When using TLS certificates you will be working with different parts that work together in different use cases:
Key pairs consist of private and public keys that belong together and are used for asymmetric encryption:
- Private key
- must be kept secret (not part of a certificate)
- decrypt messages encrypted with the respective public key
- sign messages
- Public key
- shared with others (included with a certificate)
- encrypt messages for the holder of the respective private key
- verify messages were signed by the respective private key
Certificate signing requests (CSR) are basically unsigned certificates. They contain all information required for creating a certificate including the public key (but not the private key). They're presented to a certificate authority (e.g. a well-known certificate issuer) which can then validate that everything is in order (e.g. if someone requests a certificate for example.com the certificate issuer should ensure that the requestor actually controls that domain), and use its own private key to create a signed certificate from the information contained in the CSR.
Think CSR = certificate - issuer signature.
A certificate contains many pieces of information with the following being of most practical importance:
- Subject: Who is the owner of the certificate?
- Subject Public key: Used for communicating with the certificate owner.
- Issuer: Who signed this certificate?
Certificates are usually not secret since they contain no private information, however, they're sometimes bundled together with their private keys, so care must be taken.
TLS certificates contain different pieces of information, you can look at the contents of a certificate using
openssl. When working with certificates it's very likely that you will encounter the following parts:
Information about the certificate subject, who does this certificate belong to?
The Common Name (or CN) is the most basic piece of identifying information about the subject of a certificate and you may well encounter certificates that provide only CNs and no further subject information. Previously the common name was used to verify that a certificate was used for the correct host, so in most cases, certificates still use a hostname for the common name (as seen above).
CN validation may still work with legacy applications but current browsers and libraries are no longer using the common name for validation, instead, they use the Subject Alternative Name (or SAN).
Using SAN has the added benefit of working with a list of domain names and that you may also include IP addresses.
Issuer information about the certificate issuer, which authority signed this certificate?
$ openssl x509 -in example.com.pem -noout -text | grep 'Issuer:' Issuer: C = US, O = DigiCert Inc, CN = DigiCert TLS RSA SHA256 2020 CA1
It also contains the Authority Key Identifier which allows you to identify the key pair used for signing this certificate.
$ openssl x509 -in example.com.pem -noout -text | grep -A1 'Authority Key Identifier' X509v3 Authority Key Identifier: keyid:B7:6B:A2:EA:A8:AA:84:8C:79:EA:B4:DA:0F:98:B2:C5:95:76:B9:F4
Formats of certificates
Common formats for TLS certificates are
- DER encoded binary data (
- PEM: Base64 encoded DER (
.pembut also often
.crt), files begin and end with
-----END CERTIFICATE-----. Used by most *nix applications/libraries.
- PKCS12: Binary data, may include private key, optionally password protected (
Reasons why a certificate may be invalid
As a developer, you're most likely to get into certificates when something doesn't work. Usually, this is because a certificate can't be validated. Here are some of the most likely reasons why a certificate is invalid.
Expired or not yet valid
Certificates are only valid for a specific time window, so not only can they expire they may also be not valid yet.
# Lookup certificate validity for a local certificate. $ openssl x509 -in example.com.pem -noout -text | grep -A2 'Validity' Validity Not Before: Nov 24 00:00:00 2020 GMT Not After : Dec 25 23:59:59 2021 GMT
Some clients may also reject certificates that are valid for too long periods (typically 1 or 2 years), e.g. Safari does not trust certificates that are valid for more than 1 year plus a grace period of 30 days.
Let's Encrypt certificates are also only valid for 90 days which is why they provide tools for automated renewals.
Name validation fails
TLS certificates are only valid for a specific set of domains/addresses which are specified in a certificate's Subject Alternate Name (SAN) field.
# Looking up SAN of a local certificate $ openssl x509 -in example.com.pem -noout -text | grep -A1 'Subject Alternative Name:' X509v3 Subject Alternative Name: DNS:www.example.org, DNS:example.com, DNS:example.edu, DNS:example.net, DNS:example.org, DNS:www.example.com, DNS:www.example.edu, DNS:www.example.net
The field contains a list of DNS names and/or IP addresses that this certificate is valid for. DNS names may also contain wildcards like
*.example.com but note that this does not cover additional subdomains like
foo.bar.example.com or the naked domain name
Since SAN was not always present in certificates you may encounter legacy applications that still rely on validating against the Common Name (CN) of a certificate, which is why this is usually set to the domain name as well.
# Looking at the subject information of a local certificate $ openssl x509 -in example.com.pem -noout -text | grep 'Subject:' Subject: C = US, ST = California, L = Los Angeles, O = Internet Corporation for Assigned Names and Numbers, CN = www.example.org
When working with recent applications and libraries setting the common name is not enough and you definitely need to specify SAN.
Certificates are not trusted automatically but rely on a big bundle of trusted certificate authorities (CA) that are usually distributed as part of an operating system or firmware. Your operating system or device is configured to trust all certificates signed by these CAs. If you encounter a certificate that is signed by a different CA it will be rejected.
Applications may also decide to use their own sets of trusted certificates, e.g. the Java Keystore.
If a certificate is not trusted even though it has been issued by a well-trusted issuer there may be missing intermediate certificates.
Consider the following example: a trusted CA A has issued a certificate to another CA B which allows them to issue certificates of their own. The certificate you're seeing has been issued by B and since B is not included in your trusted certificates the certificate is rejected. To avoid this issue everyone using certificates issued by B should also include the certificate which verifies that B may issue certificates (issued by A). This is an intermediate certificate that allows clients to verify that there is an intact chain of trust from A to B to the certificate they're actually concerned with.
It's of course also possible to encounter certificates from CAs that are simply not trusted e.g. because they're only used for private or internal purposes. If you are certain that such a CA should be trusted you can of course add them to your locally trusted CAs.
Certificates can be restricted in their usage, e.g. when you receive a signed certificate from a well-known issuer you're not allowed to sign other certificates, i.e. you may not act as a CA yourself because then you could sign any certificates you wanted to without oversight.
# Checking allowed usage $ openssl x509 -in example.com.pem -noout -text | grep -A1 'Usage' X509v3 Key Usage: critical Digital Signature, Key Encipherment X509v3 Extended Key Usage: TLS Web Server Authentication, TLS Web Client Authentication
Above you see the typical set of allowed usages for a TLS certificate used for HTTPS, note that certificate signing is not included.
Self-signed certificates are frequently used for testing purposes or in ad-hoc situations. They're signed by the same key that is used for the certificate itself. This implies that the certificate metadata has not been verified by an external entity which is why they're considered not trustworthy.