Agent Wranglers

SEC-108Recommended

Prepare your encryption for quantum computers

List every use of public-key cryptography, and offer hybrid ML-KEM key exchange on every TLS connection you control. Make each algorithm a setting you can change.

How to do it

A large quantum computer would break RSA and elliptic-curve keys. Traffic recorded today could be decrypted then, so data that must stay secret for years is at risk now. NIST published ML-KEM in FIPS 203 on 13 August 2024. RFC 10024, from August 2026, defines hybrid key exchange for TLS 1.3, and recommends X25519MLKEM768. The EU roadmap of 23 June 2025 asks for plans and pilots by the end of 2026. High-risk uses should move by the end of 2030, and medium-risk uses by the end of 2035. It recommends a cryptographic inventory in a standard format, such as a CBOM in CycloneDX. List every TLS endpoint, internal ones too, plus certificates, signing keys, token algorithms, SSH and stored encrypted data, with the library and algorithm of each. Name algorithms in settings, not in code. Store a key and algorithm version with every encrypted value and signature, so new data can move while old data still reads. AES-256 for stored data stays safe. Public TLS settings follow turn off old encryption, and the algorithms in use follow use only standard cryptography.

Examples

YAML example

# crypto-inventory.yaml
- asset: api.example.com
  use: public TLS
  library: OpenSSL 3.5
  key_exchange: [X25519MLKEM768, X25519]
  quantum_safe: true
- asset: orders database field encryption
  use: data at rest
  algorithm: AES-256-GCM
  key_version: k3
  quantum_safe: true
- asset: session tokens
  use: signature
  algorithm: ES256
  quantum_safe: false
  plan: move to ML-DSA once the token library supports it, by 2030

JavaScript example

import { createDecipheriv } from 'node:crypto';

const KEYS = { k2: oldKey, k3: currentKey };

export function open(sealed) {
  const { keyVersion, nonce, text, tag } = JSON.parse(sealed);
  const decipher = createDecipheriv('aes-256-gcm', KEYS[keyVersion], Buffer.from(nonce, 'base64'));
  decipher.setAuthTag(Buffer.from(tag, 'base64'));
  return Buffer.concat([decipher.update(Buffer.from(text, 'base64')), decipher.final()]);
}

Python example

import base64, json
from cryptography.hazmat.primitives.ciphers.aead import AESGCM

KEYS = {"k2": old_key, "k3": current_key}

def open_sealed(sealed: str) -> bytes:
    box = json.loads(sealed)
    nonce, text = base64.b64decode(box["nonce"]), base64.b64decode(box["text"])
    return AESGCM(KEYS[box["key_version"]]).decrypt(nonce, text, None)

How to check

A script compares the inventory with the TLS endpoints, keys and crypto calls in code and infrastructure. It fails on any use not listed. openssl s_client -groups X25519MLKEM768 -connect api.example.com:443 with OpenSSL 3.5 or later completes a handshake on every listed endpoint. A unit test changes the key version setting and still decrypts data sealed under the old one.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/adversarial-testing/data-and-secrets/post-quantum-readiness">Agent Wranglers adversarial testing playbook</a>. In code you write, add a comment next to it with the same link.