TLS Handshake and Certificate Chain Quiz
A 4-question reference set on TLS 1.3: the handshake flights, certificate chain validation, SNI privacy, and mTLS rotation. Covers the practical knobs that show up at staff-level networking interviews.
By CodeSnatch
April 3, 2026
·
Updated August 10, 2026
241 views
8
4.3 (14)
Walk through the TLS 1.3 handshake step by step. What does each side send, and at what point can the client start sending encrypted application data?
Examples
Example 1:
Input: Client opens a fresh TLS 1.3 connection to example.com
Output: 1-RTT before application data: ClientHello (with key share) -> ServerHello + cert + Finished -> Client Finished -> data
Explanation: TLS 1.3 reduces handshake to a single round trip vs TLS 1.2's two.Example 2:
Input: Resumed session with PSK (pre-shared key) from a recent connection
Output: 0-RTT: client can send application data in the very first flight
Explanation: 0-RTT trades replay resistance for latency and is opt-in per server policy.import ssl
import socket
def fetch_with_tls13(host: str, port: int = 443) -> bytes:
context = ssl.create_default_context()
context.minimum_version = ssl.TLSVersion.TLSv1_3
with socket.create_connection((host, port), timeout=5) as raw:
with context.wrap_socket(raw, server_hostname=host) as tls:
tls.sendall(f"GET / HTTP/1.0\r\nHost: {host}\r\n\r\n".encode())
chunks = []
while True:
data = tls.recv(4096)
if not data:
break
chunks.append(data)
return b"".join(chunks)What does a certificate chain validation actually verify? Trace the signature checks from a leaf cert up to a trusted root.
Examples
Example 1:
Input: Client receives leaf cert (example.com) + intermediate (R3) from server; root (ISRG X1) in local trust store
Output: Verify chain: R3.sign(leaf) matches leaf.signature; X1.sign(R3) matches R3.signature; X1 in trust store -> ok
Explanation: Each cert is signed by the next one up; the root is self-signed and present in the OS trust store.Example 2:
Input: Server sends only the leaf cert, intermediate omitted
Output: Validation fails: client cannot link leaf signature to any root in its trust store
Explanation: Servers must send the full chain (minus the root); a missing intermediate breaks validation on first-touch clients.from cryptography import x509
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
def verify_signature(child_cert: x509.Certificate, parent_cert: x509.Certificate) -> bool:
parent_pub = parent_cert.public_key()
try:
parent_pub.verify(
child_cert.signature,
child_cert.tbs_certificate_bytes,
padding.PKCS1v15(),
child_cert.signature_hash_algorithm,
)
return True
except Exception:
return False
def chain_links(leaf: x509.Certificate, intermediates: list, roots: list) -> bool:
current = leaf
for parent in intermediates:
if not verify_signature(current, parent):
return False
current = parent
for root in roots:
if verify_signature(current, root):
return True
return FalseSNI (Server Name Indication) ships the requested hostname in the ClientHello. Why is it required for shared-IP hosting, and what privacy problem does it introduce?
Examples
Example 1:
Input: One IP hosts example.com and other-site.com under separate certificates
Output: Without SNI the server cannot pick the right cert; with SNI it sees 'example.com' and chooses correctly
Explanation: SNI was the protocol fix for IPv4 exhaustion that let many hostnames share one IP.Example 2:
Input: A passive network observer watches a TLS handshake
Output: Observer sees the SNI hostname in cleartext even though the rest of the handshake is encrypted
Explanation: SNI leaks the requested hostname; ECH (Encrypted Client Hello) is the in-progress fix.import socket
import ssl
def fetch_with_sni(host: str, ip: str, port: int = 443) -> int:
context = ssl.create_default_context()
with socket.create_connection((ip, port), timeout=5) as raw:
with context.wrap_socket(raw, server_hostname=host) as tls:
tls.sendall(f"HEAD / HTTP/1.0\r\nHost: {host}\r\n\r\n".encode())
response = tls.recv(4096).decode("latin-1", errors="replace")
status_line = response.splitlines()[0]
return int(status_line.split()[1])Mutual TLS (mTLS) requires both sides to present a certificate. What does the server validate on the client cert, and where does mTLS typically fail in production?
Examples
Example 1:
Input: Service mesh routes traffic between pods; both sides have certs from the mesh CA
Output: Each side validates the other's chain back to the mesh CA + checks the SPIFFE ID in SAN matches policy
Explanation: mTLS in a mesh provides authenticated identity for both endpoints, not just the server.Example 2:
Input: Client cert expires at midnight in a CD pipeline
Output: All outbound calls fail at 00:00 with 'certificate expired'; clock skew across nodes makes the failure look intermittent
Explanation: Cert rotation, not cryptography, is the dominant mTLS failure mode in production.import ssl
import socket
def mtls_client(host: str, port: int, ca_file: str, client_cert: str, client_key: str) -> bytes:
context = ssl.create_default_context(cafile=ca_file)
context.load_cert_chain(certfile=client_cert, keyfile=client_key)
context.verify_mode = ssl.CERT_REQUIRED
with socket.create_connection((host, port), timeout=5) as raw:
with context.wrap_socket(raw, server_hostname=host) as tls:
tls.sendall(b"GET / HTTP/1.0\r\nHost: " + host.encode() + b"\r\n\r\n")
chunks = []
while True:
data = tls.recv(4096)
if not data:
break
chunks.append(data)
return b"".join(chunks)