The TLS Handshake and Certificates

Topics Covered

What TLS Actually Guarantees

The three properties, and their order

What TLS does not provide

The record layer, underneath everything

The handshake and the data phase are different problems

Cipher suites, and what they stopped meaning

Forward secrecy, and why it is non-negotiable now

Who you are trusting, concretely

Where versions stand, and what to turn off

TLS is the layer everyone depends on and few can describe, and the gap matters because most TLS incidents come from a misunderstanding of what the protocol promises rather than from cryptography. Starting with the guarantees, stated exactly, makes the rest of the lesson follow.

The three properties, and their order

TLS provides confidentiality, integrity and authentication, and the order they are established in is the opposite of the order people list them.

Authentication comes first in importance because without it the other two are worthless: an encrypted channel to an attacker is no better than a plaintext channel to the right server. The handshake authenticates the server by proving it holds the private key for a certificate that a trusted authority says belongs to the name you asked for. Integrity comes next, provided per record by an authenticated encryption construction, so any modification in flight is detected and the connection fails rather than delivering altered data. Confidentiality is the property people name first and is in a sense the easiest, following from the shared key the handshake establishes.

Each of these is worth testing against a real question. If a client skips certificate verification, which happens routinely in internal tooling, it keeps confidentiality and integrity against a passive observer and loses everything against an active one. That is why verify=False is not "slightly less secure"; it removes the property the other two rest on.

What TLS does not provide

The list of non-guarantees is as useful as the guarantees, because each item is a design decision somebody has mistakenly delegated to TLS.

TLS does not provide authorization. A valid certificate proves identity, not permission, and a client presenting a certificate issued by your internal authority is authenticated as whoever that certificate names, which may be any service in the organisation. Authorization is a separate decision on top.

TLS does not hide traffic patterns. An observer sees the destination address, the size and timing of every record, and in most deployments the server name in plaintext in the handshake. Those are frequently enough to identify what a user is doing.

TLS does not protect data at rest, does not protect you from a compromised endpoint, and does not provide availability: an attacker who can drop packets can prevent the connection entirely, and integrity checking converts tampering into a failed connection rather than a working one.

Authentication is the load-bearing property: confidentiality and integrity to the wrong peer are worthless. Everything on the right needs a different mechanism.

The record layer, underneath everything

Above the handshake, TLS presents a reliable byte stream to the application and below it splits that stream into records, each encrypted and authenticated independently with a maximum size of 16 KB.

This structure explains several observable behaviours. A record must be received completely before any of its plaintext can be used, because the authentication tag covers the whole record, so a large record adds latency for a client that wants to start processing early. This is why serving HTML with small initial records, sometimes called TLS record size optimisation, measurably improves time to first render, and why a server writing one 16 KB record per response can be slower than one writing several small ones even though it sends fewer bytes.

It also explains why TLS requires a reliable transport underneath: records arriving out of order cannot be decrypted, since the sequence number is part of the construction. QUIC solves this differently by handling encryption per packet, which is what allows independent streams.

The handshake and the data phase are different problems

It helps to treat TLS as two protocols sharing a name, because almost every operational concern belongs cleanly to one or the other.

The handshake is a negotiation and an authentication: it is expensive, it involves asymmetric cryptography and certificate verification, it is where version and cipher compatibility is decided, and it is where nearly all failures occur. Its cost is paid per connection, which is why connection reuse is the dominant performance lever.

The data phase is a stream cipher with authentication: it is cheap, it almost never fails, and its only interesting property for an operator is record size. Once a connection is established, TLS essentially disappears as a concern.

Keeping these separate avoids two common confusions. It explains why a service can have a high TLS failure rate and no performance problem, since failures are handshake events. And it explains why throughput measurements show TLS costing nothing while latency measurements show it costing a great deal, because the two are measuring different phases.

Cipher suites, and what they stopped meaning

A cipher suite names the algorithms for the connection, and the significant change in TLS 1.3 is how much smaller that name became.

In TLS 1.2 a suite named four things: the key exchange, the authentication algorithm, the bulk cipher and the MAC, giving names like ECDHE-RSA-AES128-GCM-SHA256. The combinatorial space was enormous and included many insecure combinations that remained negotiable for compatibility, which is the origin of a long series of protocol attacks.

In TLS 1.3 the suite names only the AEAD cipher and the hash, such as TLS_AES_128_GCM_SHA256, because the key exchange is negotiated separately and the authentication method is determined by the certificate. Insecure options were not deprecated, they were removed: no static RSA key exchange, no CBC mode, no renegotiation, no compression. The result is a protocol where a misconfiguration is far harder to express.

Forward secrecy, and why it is non-negotiable now

Forward secrecy means that compromising a server's long-term private key does not let an attacker decrypt past recorded sessions. It is achieved by deriving each session's keys from an ephemeral Diffie-Hellman exchange, with the certificate's key used only to sign, never to encrypt the session key.

The alternative, static RSA key exchange, had the client encrypt a session secret with the server's public key, which means anyone who later obtained that private key could decrypt every session ever recorded. That property made large-scale retrospective decryption possible and is why TLS 1.3 removed the mechanism entirely.

In practice this means ECDHE key exchange on every connection, and it means a server's private key is a signing key whose compromise is serious but bounded in time rather than retroactive. It also means that passive interception appliances which worked by holding a copy of the server key no longer function, which is the reason some enterprises resisted TLS 1.3.

Who you are trusting, concretely

The trust decision in TLS is easy to state abstractly and worth making concrete, because the abstraction hides the size of the set.

When a client verifies a server certificate, it accepts any certificate chaining to any root in its trust store, which on a typical system is well over a hundred authorities operated by organisations in many jurisdictions. Any one of them can issue a certificate for any name, so the security of the connection rests on all of them behaving correctly, which is a far weaker statement than "I trust my certificate authority".

Three mechanisms narrow that. CAA records in DNS state which authorities may issue for a name, which an authority is obliged to check. Certificate Transparency makes any issuance publicly visible, turning prevention into detection. And for an internal system, a private trust store containing only your own authority removes the public set entirely, which is why internal mutual TLS should verify against a specific issuer rather than the default store.

The reason to understand this precisely is that it changes what defences are worth configuring, and all three of the above are cheap and frequently absent.

Where versions stand, and what to turn off

TLS 1.0 and 1.1 are deprecated and removed from browsers. TLS 1.2 remains widespread and is secure when configured carefully, which is the operative caveat: it permits weak choices that must be explicitly excluded. TLS 1.3 is the default for new deployments and is safe without careful configuration, which is its main practical benefit.

SSL, the predecessor, is dead in every version, and the fact that the word persists in library names, configuration directives and conversation is a source of confusion worth resisting. When someone says SSL they mean TLS.

The configuration stance that holds up is to offer TLS 1.3 and 1.2 only, restrict TLS 1.2 to ECDHE suites with AEAD ciphers, and treat any requirement for older versions as a specific exception with an expiry date attached.

Common Pitfall

Disabling certificate verification removes the one property the others depend on, and it is the most common security defect in internal tooling because it makes an error message go away. A client with verification off has no idea who it is talking to, so the encryption protects the conversation with whoever intercepted it. When a certificate error blocks you, the correct fixes are to add the internal authority to the trust store, correct the name on the certificate, or fix the chain the server sends. None of them is verify=False.