TCP guarantees a reliable byte stream. But that stream is plaintext. Any router, home gateway, or ISP along the packet’s path can read or alter its contents. The S in HTTPS, TLS (Transport Layer Security), builds a secure channel over this untrusted network.
A secure channel guarantees three things: confidentiality (no one can eavesdrop), integrity (tampering is detected), and authentication (the other side is not an impersonator). TLS secures these one at a time, through encryption, the handshake, and certificates. TLS is the successor to SSL (Secure Sockets Layer). The name changed when it was standardized after SSL 3.0, though many still call it SSL out of habit.
Symmetric and Asymmetric Encryption
Start with confidentiality. Encrypting data requires a key, and encryption schemes fall broadly into symmetric and asymmetric.
Symmetric encryption uses the same key to encrypt and decrypt. AES is the canonical example. It is fast and well suited to large volumes of data. The problem is key sharing. Sender and receiver must hold the same key, and the moment that key travels across the network it can be intercepted. It is a contradiction: the key meant to build a secure channel has to be sent over a channel that is not yet secure.
Asymmetric encryption uses a pair of keys, a public key and a private key. Data encrypted with the public key can only be decrypted with the matching private key. RSA and ECC belong here. The public key can be published, as its name says. Anyone can encrypt with it, but only the holder of the private key can read the result, which solves the key sharing problem. The trade-off is that the computation is far slower than symmetric encryption.
block-beta
columns 2
block:sym["Symmetric"]:1
columns 1
s1["Same key both ways"]
s2["Fast"]
s3["Key-sharing problem"]
end
block:asym["Asymmetric"]:1
columns 1
a1["Public / private pair"]
a2["Solves key sharing"]
a3["Slow"]
end
style sym fill:#E3F2FD
style asym fill:#E8F5E9
TLS combines the two. It uses asymmetric encryption to agree on a symmetric key safely, then exchanges the actual data with fast symmetric encryption. This hybrid approach takes both the key-sharing solution of asymmetric and the speed of symmetric. The process of agreeing on that symmetric key is the handshake.
The TLS 1.2 Handshake
The handshake agrees on a symmetric key and authenticates the other side. It runs on top of the connection, after the TCP 3-way handshake completes.
sequenceDiagram
participant C as Client
participant S as Server
C->>S: ClientHello (version, cipher suites, client random)
S->>C: ServerHello (chosen cipher suite, server random)
S->>C: Certificate (server public key)
S->>C: ServerKeyExchange (ECDHE public value + signature)
S->>C: ServerHelloDone
C->>S: ClientKeyExchange (ECDHE public value)
Note over C,S: Both derive the same symmetric key
C->>S: ChangeCipherSpec + Finished
S->>C: ChangeCipherSpec + Finished
Note over C,S: Encrypted application data
The client sends a ClientHello with its supported TLS versions, a list of cipher suites, and a client random value. The server responds with a ServerHello that picks one cipher suite, along with a server random value and its certificate. The certificate carries the server’s public key.
From here the way the symmetric key is agreed on splits into two paths. The handshake diagram above follows the ECDHE path.
RSA key exchange has the client generate a random value called the pre-master secret, encrypt it with the server’s public key, and send it. Only the server can decrypt it with its private key. Now that both sides hold the same pre-master secret, they mix in the client random and server random to derive the final symmetric key. There is a catch. If the server’s private key is ever leaked, an attacker can decrypt all past traffic they recorded in advance. A single private key unlocks the entire past.
ECDHE key exchange removes that weakness. ECDHE (Elliptic Curve Diffie-Hellman Ephemeral) has both sides generate a temporary key pair for each session, exchange only the public values, and each compute the same secret from the other’s public value and their own private value. The private value never leaves the machine and is discarded when the session ends. Even if the server’s long-term private key leaks later, the keys of past sessions cannot be recovered. This property is called forward secrecy.
At the end of the handshake both sides send a Finished message: a hash of every handshake message exchanged so far, encrypted with the key they just derived. If anyone tampered with a message in transit, the hash won’t match and the handshake fails. This step verifies the integrity of the key agreement itself.
Certificates and PKI
Confidentiality is now covered, but a gap remains. How does the client know that the public key it received actually belongs to the server it intended to reach? If a man-in-the-middle presents its own public key as if it were the server’s, the client establishes an encrypted channel with the attacker while believing it is safe. This is the authentication problem.
The certificate solves it. A certificate binds the server’s public key to an identity (a domain, among other fields) and is signed by a trusted third party, the CA (Certificate Authority). The CA signs the certificate with its own private key. The client verifies that signature with the CA’s public key, confirming that “this public key belongs to this domain.”
But then how does the client trust the CA’s public key? This is where the chain of trust comes in.
flowchart TD
R["Root CA certificate
bundled in OS · browser"] -->|signs| I["Intermediate CA certificate"]
I -->|signs| S["Server certificate
domain public key"]
C["Client"] -.verifies.-> S
S -.-> I
I -.-> R
The server certificate is signed by an intermediate CA, and the intermediate CA certificate is signed by a root CA. The root CA certificate is preinstalled in the operating system and browser. That bundled root is the trust anchor. Verification starts at the server certificate and walks up the signatures to the root, checking each step. Once it reaches the root, trust is established.
This whole structure is PKI (Public Key Infrastructure): a system that binds public keys to identities and vouches for those bindings through hierarchical signatures. With authentication in place, all three conditions of a secure channel are met.
Record Protection
Once the handshake finishes, both sides hold the same symmetric key. Application data is then split into records and encrypted with that key. Confidentiality and integrity are handled together here.
Modern TLS uses AEAD (Authenticated Encryption with Associated Data). AES-GCM and ChaCha20-Poly1305 are the common choices. AEAD produces an authentication tag while encrypting. The receiver verifies this tag as it decrypts, and if even a single bit was altered, the tag won’t match and the record is rejected. It merges into one step what used to be a separate MAC (Message Authentication Code) computed alongside encryption.
TLS 1.3
TLS 1.2 served for a long time but carried two burdens: the handshake took many round trips, and insecure options remained on the negotiation table. TLS 1.3, standardized in 2018, cleaned this up.
sequenceDiagram
participant C as Client
participant S as Server
C->>S: ClientHello (+ key share)
Note over S: Key agreement done
S->>C: ServerHello (+ key share)
S->>C: Encrypted {Certificate, Finished}
C->>S: Encrypted {Finished}
Note over C,S: Encrypted data after 1-RTT
The 1-RTT handshake reduced the round trips (RTT, round-trip time). TLS 1.2 needed two round trips for key exchange. TLS 1.3 puts the key exchange material right in the ClientHello. The server finishes key agreement in its first response and begins encrypting. The round trips drop to one, reducing connection latency.
It also removed the dangerous options. TLS 1.3 dropped RSA key exchange entirely. Key exchange always uses an ECDHE-family method, so every connection has forward secrecy by default. Cipher suites and options known to be weak were removed from the negotiation list too. Shrinking the choices removed the room for misconfiguration.
0-RTT was added as well. For a server the client has connected to before, TLS 1.3 can put data in the very first packet without waiting for a handshake round trip. Reconnection latency all but disappears. This data is exposed to replay attacks, though, so it needs careful handling. Session resumption, how 0-RTT works, and its risks are enough to fill a topic of their own.
Wrapping Up
The byte stream TCP provides is plaintext. On top of it, TLS secures confidentiality with symmetric/asymmetric hybrid encryption, integrity with the handshake and record protection, and authentication with certificates and PKI. When the three come together, a trustworthy channel stands over an untrusted network. Practical topics like session resumption, mutual authentication (mTLS), and automated certificate issuance build on this, but the starting point is always the handshake.
References
- TCP and UDP — the transport layer TLS runs on
- HTTP/1.1 and HTTP/2 — the HTTPS context and how QUIC/HTTP3 integrates TLS 1.3 into transport