Skip to content
ClientHello
step 1/5

Reading — step 1 of 5

Read

~1 min readTLS 1.3 Handshake

ClientHello

The handshake starts with the client sending:

struct ClientHello {
    legacy_version (always 0x0303 in TLS 1.3 — 1.2 wire compat)
    random (32 random bytes)
    legacy_session_id (often empty in 1.3)
    cipher_suites (list, e.g. TLS_AES_128_GCM_SHA256, TLS_CHACHA20_POLY1305_SHA256)
    legacy_compression_methods (always [0x00])
    extensions (extensible field — where most TLS 1.3 lives)
}

Critical extensions:

  • supported_versions: includes 0x0304 (TLS 1.3) — the REAL version negotiation.
  • key_share: client's DH public key(s), one per group it supports (e.g. X25519, secp256r1).
  • supported_groups: which DH groups client supports.
  • signature_algorithms: which sig algos client can verify (RSA-PSS-2048, Ed25519, ECDSA-P256, etc.).
  • server_name (SNI): which hostname client wants — server uses this to pick certificate.
  • psk_key_exchange_modes + pre_shared_key: for resumption.

The extension extensibility was vital: the entire 1.3 protocol was layered on top of 1.2 ClientHello format. Extensions = future-proofing.

Wire format:

byte 0..1   = 0x0303
byte 2..33  = random
byte 34     = session_id_length
byte 35..   = session_id
            = ciphers length (2 bytes)
            = cipher suite list
            = compression length (1 byte) + 0x00
            = extensions length (2 bytes) + extensions

Each extension:

ext_type (2)
ext_data_length (2)
ext_data (ext_data_length bytes)

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…