◇ OpenCyber Academy
Technologist · Chapter 14 · English

Chapter 14 — Quantum and post-quantum security: methods I

Open, free learning for anyone who wants to protect people and technology. No account is required to read this text or its worked answers.

Chapter 14 — Quantum and post-quantum security: methods I

Lesson map

Lesson 14 published. Map, example, EX027.

flowchart TD
  N0["Learning outcomes"]
  N1["14.1 Combining secrets"]
  N2["14.2 Practical activity — Lab C"]
  N3["14.3 X25519MLKEM768 in TLS 1.3"]
  N4["14.4 Configuring a lab server"]
  N5["14.7 Client-side configuration"]
  N6["Synthesis"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6
  N6 --> EX["Worked example"]
  EX --> Q["Exercise EX027"]

Logical drawing

flowchart LR
  N0["Learning outcomes"]
  N1["14.1 Combining secrets"]
  N2["14.2 Practical activity — Lab C"]
  N3["14.3 X25519MLKEM768 in TLS 1.3"]
  N4["14.4 Configuring a lab server"]
  N5["14.7 Client-side configuration"]
  N6["Synthesis"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> Q["EX027"]
[Learning outcomes]
    |
    v
[14.1 Combining secrets]
    |
    v
[14.2 Practical activity — Lab C]
    |
    v
[14.3 X25519MLKEM768 in TLS 1.3]
    |
    v
[14.4 Configuring a lab server]
    |
    v
[14.7 Client-side configuration]
    |
    v
[Synthesis]
    |
    v
[Worked example] --> [Exercise EX027]

Learning outcomes

You will (1) explain how hybrid key exchange combines secrets; (2) run a toy combiner and interpret it; (3) describe how TLS 1.3 integrates X25519MLKEM768; and (4) configure hybrid groups in a lab server.

14.1 Combining secrets

In a hybrid, both components produce shared secrets; a key-derivation step combines them with context so the result is secure if either component is. SP 800-227 discusses KEM combination; TLS concatenates the secrets and feeds them into its HKDF-based key schedule.

Lab C makes the property visible: change either secret alone and the output changes completely, so an attacker who breaks only X25519 or only ML-KEM still lacks the key. Binding the transcript prevents the same secrets producing the same key in another handshake.

14.2 Practical activity — Lab C

# Lab C (ch 14): a hybrid key combiner. The session key depends on BOTH shared secrets.
import hashlib, hmac
def hkdf_extract(salt, ikm): return hmac.new(salt, ikm, hashlib.sha256).digest()
def combine(ss_pq, ss_trad, context):
    # Concatenate secrets (PQ first, as in X25519MLKEM768), bind the transcript/context, then extract.
    return hkdf_extract(b"\x00" * 32, ss_pq + ss_trad + context).hex()[:16]
pq, trad, ctx = b"P" * 32, b"T" * 32, b"handshake-transcript-hash"
print("baseline              ", combine(pq, trad, ctx))
print("PQ secret changed     ", combine(b"Q" * 32, trad, ctx))
print("traditional changed   ", combine(pq, b"U" * 32, ctx))
print("context changed       ", combine(pq, trad, b"other-transcript"))

Expected output:

baseline               d48e982e8c06ca60
PQ secret changed      d4c36ea2d90b2e9c
traditional changed    8dcefa12ded3d99c
context changed        af06eca8abcd45a9

Read the four lines as a test of the combiner's three inputs. The baseline key d48e982e8c06ca60 changes when the post-quantum secret changes, when the traditional secret changes and when only the context changes, and none of the changed outputs resembles the baseline. That is what "secure if either component is" requires: an attacker who recovers the X25519 secret still faces an unknown ML-KEM secret, and the output gives no hint which input was altered. The lab's 16-hex-digit truncation is for display only; TLS uses the full HKDF output.

14.3 X25519MLKEM768 in TLS 1.3

RFC 10024 defines the group: the client sends an ML-KEM-768 encapsulation key followed by an X25519 public key (1,216 bytes); the server returns an ML-KEM ciphertext followed by its X25519 share (1,120 bytes); the shared secret is the ML-KEM secret concatenated with the X25519 secret. If a client sends only classical shares, a server that prefers hybrid may answer with HelloRetryRequest asking for the hybrid share, adding a round trip; tune client key-share predictions accordingly.

The order inside the share matters for implementers reading captures: the ML-KEM part comes first in both directions, unlike some earlier draft hybrids. KLS's lab parser checks the share length, 1,216 or 1,120 bytes, to classify a captured handshake as hybrid.

14.4 Configuring a lab server

In OpenSSL-based servers the group list is configurable, for example Groups = X25519MLKEM768:X25519:secp256r1 in an OpenSSL configuration file or an ssl_ecdh_curve-style directive in a web server. Order matters: the server's preference decides the outcome when the client offers several. OpenSSL 3.5's default keyshares include X25519MLKEM768 (OpenSSL 3.5 NEWS). Check your product's documentation for exact syntax.

For KLS's NGINX ingress the setting is ssl_ecdh_curve X25519MLKEM768:X25519;, which only works if the image's OpenSSL knows the group name; on an older library NGINX refuses to start, which is a useful failure in staging. Product syntax varies, so KLS keeps one tested snippet per product in the central profile repository.

14.5 Worked example

KLS staging ingress: groups set to X25519MLKEM768:X25519. Test client A (OpenSSL 3.5) negotiates the hybrid; test client B (older library) negotiates X25519. A misordered list X25519:X25519MLKEM768 caused both to choose X25519 — offered, never selected.

The misordered case is the instructive one. Both clients supported the hybrid group, the server listed it, and nothing failed; the server's preference simply chose X25519. Only a check of the negotiated group, not of the configured list, revealed it. KLS's Lab T rule "hybrid offered but not preferred" exists because of this run.

14.6 Common errors and limits

The first error is the portal case that Lab T in Chapter 17 detects: hybrid present, never chosen. The second shows up as latency: a client predicting only X25519 meets a hybrid-preferring server and pays an extra round trip, visible at the 99th percentile on mobile paths. The third bit KLS when a blog's group name for a draft hybrid was copied into a production profile; the library rejected it and the ingress failed to start in staging. Each is caught by checking negotiation, timing and version, not by reading configuration.

14.7 Client-side configuration

Servers are only half of the negotiation. Clients choose which key shares to send first, and a wrong prediction costs the extra round trip described in Section 14.3. Modern browsers and current libraries send the hybrid share by default. For KLS's own SDKs and internal clients, set the group list explicitly in code or configuration, test against the staging gateway, and record the library version in the release notes so customers know which SDK versions negotiate hybrid key exchange. KLS's Go SDK, for example, sets the group list in its own TLS configuration, so a customer who upgrades the SDK gets the hybrid share without changing any code.

Exercises

Synthesis

Hybrid key exchange concatenates and derives secrets so either component protects the session. In TLS 1.3 it is one configurable group; order and client support decide whether it is used.

Continue studying — chapter 14 of 30

← Chapter 13 (draft) · Course chapter index · Chapter 15 (draft) →