Source: Photo by Global Residence Index on Unsplash
TLS/SSL certificates are the fundamental source of trust on the web. Everyone
uses them every day, most without even knowing they exist. With modern
zero trust architecture,
developers have to deal with them even more.
I feel like many developers only learn the very basics to get along, which can
lead to dangerous mistakes.
Cryptographic Failures
is #2 on the OWASP Top 10 for a reason.
Developers do not have to be experts on TLS/SSL certificates, but know how to
handle them safely. Let’s go!
How can I trust someone on the web?
We visit a ridiculous number of websites every day, and we want to be sure that
the people and companies behind them are who they say they are.
In real life, we can ask strangers to show us their passports. We have learned
to judge the validity of a passport by checking features such as watermarks that
presumably could only be produced by a government’s passport office. So as long
as we trust the passport office, we can verify the identity.
On the web, certificates are the equivalent of passports. Every subject can get
a digital certificate from a certificate authority (CA), which takes the role
of the passport office. There is a list of trusted CAs built into our browsers
and operating systems by their developers that everyone is expected to trust.
Show me your passport!
Let’s check out the certificate of this blog. We are using
commands provided by
OpenSSL:
Terminal window
openssls_client-connectdrsys.de:443\
-servernamewww.drsys.de\
-showcerts\
</dev/null\
|opensslx509-text
# Pro tip: This shows the first certificate in the chain.
The hostname and DNS name can be set independently, which is handy for debugging
locally on a webserver (-connect localhost:443).
Common filename extensions are .pem, .cer and .crt.
Verify a passport
Let’s find out if we are dealing with a valid certificate:
Terminal window
openssls_client-connectdrsys.de:443\
-servernamewww.drsys.de\
-showcerts\
-verify_hostnamewww.drsys.de\
</dev/null
# Pro tip: This shows the whole certiciate chain.
If we see Verification: OK and Verified peername: www.drsys.de, we are good.
You could also set -connect localhost:443 for debugging locally on a
webserver. See the official docs for
more verification options.
Behind the scenes
The fascinating part is that your browser is actually able to verify the
certificates locally. This is possible using
public-key cryptography
with a digital signature.
First, let’s see how a certificate is requested from a certificate authority
(CA):
Create a key pair with a private and public key
Send the public key together with a domain name to the CA
this is called a Certificate Signing Request (CSR)
The CA verifies your identity (e.g. that you control the DNS entries)
The CA creates a certificate which includes the information from the CSR
and additional information like validity
The CA signs it (calculate a hash, encrypt it with it’s private key and add
it to the certificate)
encrypting with the private key is specific for
RSA and can be
different for other algorithms
The Verification of the certificate then goes like:
Check the validity and domain name
Check if we trust the issuer
Is the public key included in our local authorities list?
Hash the certificate, decrypt the signature with the CA’s public key and
compare the two
These steps usually have to be repeated multiple times, because it is common
to have hierarchies of CAs:
-----BEGIN CERTIFICATE-----
# Server certificate
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
# Intermediate CA certificate
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
# Root CA certificate
-----END CERTIFICATE-----
We will do all these steps ourselves in the
bonus section.
Get your own passport
Traditionally you would buy a TLS/SSL certificate from a company like DigiCert.
But since 2015, the non-profit organisation
Let’s Encrypt issues certificates for free through
an easy, fully automated process. Some webservers/reverse proxys like
Caddy and Traefik even obtain
and renew certificates automatically.
Another option is to create your own certificate authority and make your users’
browsers trust it. This is common for internal applications in enterprises.
Use your passport
Getting a TLS/SSL certificate from Let’s Encrypt is very easy if you have a
server with a public ip address.
For more use cases, like using Caddy as a reverse proxy, see the
official Caddy docs.
Bonus: Make your own passport
It’s totally possible to create your own CA, sign certificates and use them with
your server. We will also see how we can trust our CA and validate the result.
Run these commands:
Terminal window
# Create self-signed certificate for root CA
opensslreq-outmyRootCA.crt\
-newkeyrsa:4096\
-noenc\
-keyoutmyRootCA.key\
-x509\
-days365\
-subj"/CN=myRootCA"
# Create private key and CSR for localhost
opensslreq-outlocalhost.csr\
-new\
-newkeyrsa:4096\
-noenc\
-keyoutlocalhost.key\
-addext"subjectAltName = DNS:localhost"\
-subj"/CN=localhost"
# Sign the CSR
opensslx509-inlocalhost.csr\
-req\
-copy_extensionscopy\
-outlocalhost.crt\
-days365\
-CAmyRootCA.crt\
-CAkeymyRootCA.key
# Build certificate chain
catlocalhost.crtmyRootCA.crt>localhost-chain.crt
Check the files:
Terminal window
# View certificate
opensslx509-inlocalhost.crt-text
# Verify certificate by explicitly setting our root CA
Verify the served certificate by explicitly setting our root CA certificate
as trusted:
Terminal window
openssls_client-connectlocalhost:443\
-servernamelocalhost\
-showcerts\
-CAfilemyRootCA.crt\
-verify_hostnamelocalhost\
</dev/null
# Check: Verification: OK / Verified peername: localhost
FAQ
What do TLS and SSL stand for? Transport Layer Security and Secure
Sockets Layer.
How is SSL related to TLS? The now-deprecated SSL specification is the
predecessor of the TLS protocol. The term SSL is still widely used though, but
usually just refers to TLS.
How can I import TLS/SSL certificates to my operating system? For
Debian/Ubuntu Linux, save the files in the /usr/local/share/ca-certificates/
folder with suffix .crt and import them with
/usr/sbin/update-ca-certificates.
What happens if someone gets control of one of the CAs built into our browsers
and operating systems? This would be catastrophic because it would
allow them to fake any identity on the web.
How does Let’s Encrypt’s CA hierarchy look like? Let’s Encrypt has two
root CAs ISRG Root X1 and ISRG Root X2 and four intermediate CAs. For more
details see the
official “Chains of Trust” documentation.
The root certificates are already
available on our systems.
On Linux, you can analyse them with:
Terminal window
opensslx509-in/etc/ssl/certs/ISRG_Root_X1.pem\
-text
How can I see/verify SMTP server certificates? The default port for
secure connection is 587. If the SMTP server is still using STARTTLS, use the
-starttls smtp option.