Dev Learning Lab

The labs on this site need JavaScript to run. The same content is written out below.

Learn › Networking › Secure connections

TLS handshake

What happens before the https padlock locks

HTTPS is HTTP wrapped in TLS. Before any data is sent, the browser and the server check that "the other side really is that server" and create "an encryption key that only the two of them know".

Checked against real execution · Checked by making real TLS 1.3 connections with openssl

Concepts in this lab

HTTPS and TLS
HTTPS is HTTP communication encrypted with TLS. TLS keeps third parties from seeing the content (confidentiality), keeps it from being changed on the way (integrity), and uses a certificate to check that the server you connected to is the real one (authentication). SSL is the protocol that came before TLS. It is now deprecated and only TLS is actually used, but the name SSL is still used alongside it by habit.
TLS handshake and certificates
The TLS handshake is the process, before encrypted communication starts, in which the client and the server agree on the cryptographic algorithms to use, verify the identity of the server, and agree on the keys that will encrypt the data. A certificate is a document that contains the server's public key and domain information and is signed and vouched for by a trusted certificate authority (CA). The client validates it to confirm that the server it connected to is the real one.
Symmetric-key cryptography and public-key cryptography
Symmetric-key cryptography uses the same key to encrypt and to decrypt. It is fast, but it has the problem that the key must be shared safely with the other party (AES). Public-key cryptography uses a pair of keys, a public key and a private key. Data encrypted with the public key can be decrypted only with the private key, so there is no key-sharing problem, but it is slow (RSA). In practice, public-key cryptography is used to exchange a symmetric key safely, and then the symmetric key encrypts the data.
HMAC and digital signatures
Techniques for confirming that a message was not changed on the way and that the legitimate party sent it. HMAC hashes the message together with a secret key that both sides share to produce an authentication code. With a digital signature, the sender signs with a private key and the receiver verifies with the public key. Only the signer can create the signature, so the sender cannot deny having sent the message.

Try these

Running with the default settings

  1. The browser connects to https://shop.example. After the TCP connection is established, it sends the list of cipher suites it can use and a public value (key share) to be used for the key exchange. This message is not encrypted.
  2. The server picks one cipher suite and sends its own public value for the key exchange. Each side combines the other side's public value with its own secret value and computes the same result. Someone who only watched the public values in the middle cannot compute this result.
  3. Each side derives a symmetric key from this result. The key itself was never sent over the network. The handshake messages from here on are encrypted.
  4. The server sends its certificate. The certificate contains the domain name, the server's public key, the validity period, and a signature that a certificate authority (CA) made over this content with its own private key.
  5. The browser validates the certificate. The signature comes from a trusted certificate authority, the certificate is within its validity period, and the domain matches shop.example. You can trust that this public key belongs to the real shop.example.
  6. The server signs everything exchanged so far with its private key and sends the signature. The browser checks this signature with the public key in the certificate. Anyone can copy a certificate, but only the real server that holds the matching private key can create the signature.
  7. Both sides exchange a verification value over the entire handshake, to check that no one changed a message in the middle.
  8. Now the HTTP request and the response travel encrypted with the agreed symmetric key. Someone watching in the middle can see only roughly which server you are talking to, and cannot see the content (the path of the address, the headers, cookies, and the body).

Result of this run

Code

# application.yml (server-side settings)
server:
  port: 443
  ssl:
    enabled: true
    key-store: classpath:shop.p12       # certificate + private key
    key-store-password: ********
    protocol: TLS
    enabled-protocols: TLSv1.3

# In production, a load balancer or nginx in front usually handles TLS,
# and the application server receives plain HTTP behind it

Assumptions of this model

This simplifies the basic TLS 1.3 handshake (in a real handshake, several of the server's reply messages are sent bundled together). The key exchange is the kind in which both sides exchange public values and compute the same secret (ECDHE); it does not encrypt a symmetric key with the server's public key and send it, as the older method did. The certificate checks follow the standard procedure of TLS and the web PKI. On the PC used to write this lab, openssl was used to create a test certificate authority and four kinds of certificate, and real TLS 1.3 connections were made with them to check. The valid certificate passed validation, and each of the others was rejected with the error certificate has expired, hostname mismatch, or self-signed certificate. It was also confirmed that the handshake messages are exchanged in the order ClientHello, ServerHello, EncryptedExtensions, Certificate, CertificateVerify, Finished.

Previous lab: Polling, SSE, and WebSocket · Next lab: Load balancers and scale out

Concepts in this lab

What this lab shows

Settings

Code


      
    

Diagram

Run comparison

Try these