The TLS 1.3 handshake record by record — the key agreement, the certificate and every check a browser or curl makes on it — then the Basic-auth password inside the encrypted connection, with an eavesdropper under the wire showing what a copy of each record reveals. Self-signed, expired, wrongly named and stolen certificates, curl's -k and --cacert, and the browser's Proceed.
TLS is what turns the password of
Basic HTTP Authentication
from readable text into ciphertext. Before any HTTP is sent, the client and the server agree on a secret
that nobody on the path can compute, and the server proves that it holds the private key of a
certificate issued for the name the client typed. The simulator shows every record of that handshake as
the two ends see it, and as an eavesdropper copying the wire sees it.
TLS Concepts
comes before it: how the server gets its certificate, how
the browser follows the chain to a root it trusts, and why only the server proves who it is, with keys
and stamps instead of bytes. This page is the same handshake record by record, with the same two CAs.
The simulator's layout The client on the left is a browser window or a curl command line, both asking for
https://shop.example/orders with alice's password in a Basic Authorization header. The browser's
address bar picks the scheme and the name; curl adds -v, -k and --cacert self.crt, as in the
course lab. Below them: the client's half of the key agreement, its checks of the certificate, and its
trust store.The server on the right picks the certificate it presents, from a CA-issued one to the real
certificate in the hands of an impostor without its private key.The wire in the middle shows the last record whole; the lines marked 🔒 are encrypted. Clicking a
line says what it does.The eavesdropper under the wire shows its copy of the same record, and keeps a list of everything
the copies have told it so far.Step and Prev move one record at a time; the client's own work, computing the keys and checking
the certificate, is a step of its own.The TLS 1.3 handshake The handshake takes one round trip: the client sends one flight, the server answers with one, and the
client's Finished closes it.
ClientHello , in plain text: the versions and cipher suites the client offers, a fresh key share,
and the name of the site (SNI).ServerHello , in plain text: the server's choice and its own key share. Both sides now compute the
same secret, and every record after this one is encrypted.EncryptedExtensions : the rest of the answer, such as http/1.1 from the client's ALPN list.Certificate : the server's certificate and the intermediate CA's.CertificateVerify : a signature over the whole handshake, made with the private key of the
certificate.Finished : a MAC over the handshake, proving the server saw the same messages the client did.The client's checks, then its Finished , or a fatal alert that ends the connection.The steps of TLS Concepts are these records under other names:
TLS Concepts The record here Say hello to shop.example ClientHello Send your key share ServerHello Diffie-Hellman: compute the shared session key both sides, right after ServerHello Send your certificate Certificate, with the intermediate's certificate Sign this handshake CertificateVerify Check who answered the client's checks Send the password the request, in an application_data record
EncryptedExtensions and the two Finished messages have no step there: they carry no idea of their own,
only the answer's details and a proof that both ends saw the same handshake.
HTTP starts after the client's Finished: the request is the same text as on the Basic auth page, inside
an application_data record. The example Two pages on one connection shows that a browser keeps the
connection and sends its next request with no handshake at all, while curl opens a new connection every
time it runs.
The key agreement: ephemeral Diffie-Hellman The key exchange is Diffie-Hellman on the x25519 curve, with key pairs that each side makes for this
connection alone: ECDHE, the name cipher lists and openssl use. The key shares are their public halves.
Combining one side's private half with the other side's public half gives the same number on both sides,
and the private halves never leave their machines:
The eavesdropper copies both public halves and still cannot compute the secret.The keys of every record from ServerHello on are derived from that secret.Forward secrecy follows from the key pairs being fresh: the server's long-lived private key only
signs, so stealing it later decrypts none of the connections recorded before.What the eavesdropper sees A copy of TLS 1.3 traffic tells the eavesdropper which site, which cipher, and how big each record is,
and nothing else:
The site's name travels in plain text in the ClientHello's server_name, because the server needs
it to choose a certificate before anything is encrypted.Every encrypted record is labelled application_data , whatever it carries. The length stays
visible: an encrypted record is 17 bytes longer than its contents, one byte for the real type and a
16-byte tag that fails to verify if a single bit is changed.The certificate is encrypted in TLS 1.3, so the eavesdropper sees a record the size of one, not
which one it is.Over plain http:// it reads everything: the example The same request over plain http shows
the Authorization header decoding to alice:secret123.The client's checks of the certificate The client checks what the server sent in a fixed order, and the first failure ends the handshake with
an alert:
Check Fails when Alert curl says Chrome says The chain ends at a root in the trust store the certificate is self-signed, or --cacert left out its root unknown_ca (48)(60) SSL certificate problem: self-signed certificate / unable to get local issuer certificateNET::ERR_CERT_AUTHORITY_INVALIDToday is between the dates the certificate expired certificate_expired (45)(60) SSL certificate problem: certificate has expiredNET::ERR_CERT_DATE_INVALIDThe name typed is in the SAN list the certificate is for another name bad_certificate (42)(60) SSL: no alternative certificate subject name matches target hostnameNET::ERR_CERT_COMMON_NAME_INVALIDCertificateVerify matches the certificate's key the sender does not hold the private key decrypt_error (51)(35) error:0A00007B:SSL routines::bad signatureERR_SSL_PROTOCOL_ERROR
The name is matched exactly. The certificate lists shop.example and www.shop.example, so the
example The names on the certificate loads the second and is refused on api.shop.example.curl checks the name itself, after the handshake. OpenSSL does the other checks during the
handshake, so for a wrong name curl completes it, then closes the connection before sending the
request; the example curl checks the name after the handshake shows it.The signature is the check that stops an impostor. A certificate is public, and anyone can send
the real one. The example An impostor with the real certificate passes the chain, the dates and the
name, and fails on CertificateVerify, because the private key never left the real server.curl's -k and --cacert The course lab serves self.crt, a certificate that signs itself, and gets past curl's refusal in two
ways; the example curl and self.crt runs all three commands:
-k skips the checks of the certificate: the trust, the dates and the name. The connection is
encrypted, to whoever answered. The example What -k lets through shows the one check it keeps: an
impostor holding only the real certificate still fails on the signature, and an impostor that makes a
self-signed certificate of its own gets through.--cacert self.crt names the root to trust for this command. A self-signed certificate is its own
root, so curl checks everything and accepts it. The file replaces the system's CAs instead of adding to
them, so the same flag refuses the site's real, CA-issued certificate: the example --cacert replaces
the trust store .The browser's Proceed (unsafe) The browser's warning page is its plain curl: the same refusal, shown as a page. Proceed is its -k
for one certificate on one site: the browser keeps an exception, opens a new connection, and accepts
that certificate from then on, with Not secure in the address bar. The warning for a failed signature
offers no Proceed at all, since the server behind it cannot be told from an impostor.
Simplifications in the simulator The TCP connection under TLS is not shown, and neither are the compatibility ChangeCipherSpec records
that real TLS 1.3 clients and servers send. The key shares, randoms, signatures and ciphertext are seeded fake bytes of realistic length; the
record lengths are computed from the contents, the certificate sizes are typical ones. Only x25519 is offered, where current browsers also offer a post-quantum hybrid share. The browser remembers alice's Basic credentials from the start, so the first request already carries
them. The server answers plain http:// with the page; a real site would redirect it to https://, after the
first request has already crossed in plain text. The chain is one intermediate, Example Trust R1, under the root, Example Trust Root CA; TLS Concepts
shows how each got its certificate. Revocation, a CA withdrawing a certificate before its end date, is
not shown. The course
Authentication and Secrets
runs the same handshake
against nginx in its chapter TLS , with curl -v, openssl s_client and a self-signed certificate.
← Previous TLS Concepts who proves what, played one role at a time, with an impostor trying to get past the browser