0%

Chapter 10

HTTPS, Certificates, and Security Headers

What a Certificate Proves

Count the places where this course said “only over HTTPS”. The carries Secure, so a browser sends it over HTTPS and nowhere else. Its name starts with __Host-, which a browser accepts only from an HTTPS response. Basic credentials are the password in . A bearer token works for whoever holds it. Every one of these is safe only when nobody between the client and the server can read the request, and only when the server at the other end is the right one.

with Python showed that HTTPS is HTTP inside , and that a default TLS context checks the server’s and its name. This lesson asks what that check consists of. What does a client look at before it sends a password?

A name, a key, an issuer, and two dates

A server that speaks TLS presents a certificate. Here are five lines of the test certificate this chapter uses, as the openssl tool prints them:

Issuer: O=Python Land course tests, CN=TEST ONLY Python Land Web Security course authority
Not Before: Nov  1 00:00:00 2026 GMT
Not After : Nov  1 00:00:00 2046 GMT
Subject: O=Python Land course tests, CN=TEST ONLY reading
DNS:reading.example, DNS:app.reading.example, DNS:notes.reading.example, DNS:localhost, IP Address:127.0.0.1

The last line the names the certificate is for. The file also holds a public key, which is not shown here. So a certificate ties together four things: a name, a public key, an issuer who signed the statement, and the period in which it holds. This test file holds for twenty years. A certificate from a public issuer lasts about a year or less.

A certificate is public. The server sends it to every client that connects, and anyone can copy it. What an impostor lacks is the private key that belongs to the public key in the file. During the TLS handshake the server proves that it holds that private key, without revealing it. A copied certificate without the key proves nothing.

What does a certificate tie together?

Signed by someone you already trust

Anyone can write a file that says “this key belongs to reading.example”. A certificate counts because an issuer signed it. An issuer is also called a certificate authority; this lesson says issuer.

In Chapter 2 you protected a message with an tag. One key made the tag, and the same key checked it. That works when the two sides are the same party, or share a secret. It cannot work here. Every client in the world must be able to check a certificate, and whoever can check an HMAC tag can also make one.

An issuer’s signature is a different kind of signature, a public-key signature. The issuer signs with a private key that it never shares. Anyone can check the signature with the issuer’s public key, and checking gives no power to sign. This course does not build such signatures; it is enough to know which property they have that a keyed tag lacks.

That leaves one question: where does the client get the issuer’s public key? It starts with a list of issuers it trusts, installed with the or the browser. The check ends at that list. A certificate from an issuer that is not on it proves nothing to this client, however correct it looks.

Why does an issuer not protect a certificate with an HMAC tag, like the one you made in Chapter 2?

Three checks

Before a client sends a single byte of a request, it makes three checks on the certificate:

  1. Issuer. Was it signed by an issuer on my list?

  2. Name. Is it for the name I asked for?

  3. Date. Is today inside its period?

Here is a model of the three checks. It is a model: a real client checks signatures where this code compares names. Dates written year, month, day compare correctly as text, so the model keeps them as . Run it:

Try it

The first three calls print accepted, refused: wrong name, and refused: unknown issuer. Each refusal names one check. The name check is the one people forget: a trusted issuer signs certificates for millions of sites, so “signed by a trusted issuer” says nothing until the name matches too.

You connect to reading.example. The server presents a certificate that an issuer you trust made for other.example, valid today. Which check fails?

What does the fourth call in the block above print?

What a certificate does not say

A valid certificate tells you that you are talking to a server that holds the key for the name you asked for, and that an issuer you trust has confirmed it. It tells you nothing else. It does not say who runs the site, what the site does with a password, or whether its code is safe. For the usual kind of certificate, an issuer checks that the applicant controls the name, and that is all it checks. Some certificates also name an organization. A client does not look at that: it checks the name. A site that stores passwords as plain text can have a perfectly valid certificate.

One more limit, for recognition only. An issuer can withdraw a certificate before its end date, which is called revocation. Python’s default context does not check for that.

A site shows a valid certificate for the name you typed. What do you know?

You can now say what a client checks. Nothing in your project makes those checks yet. The next lesson builds the that does.