The most surprising thing about post-quantum cryptography is that the algorithms we’re adopting aren’t just "harder math problems," they’re fundamentally different kinds of math problems, often with roots in geometry and linear algebra, not number theory.
Let’s see ML-KEM (Module Learning With Errors Key Encapsulation) in action. Imagine Alice wants to send a secret key to Bob securely, knowing that a future quantum computer could break current RSA or ECC.
from pqcrypto import MLKEM_KEM, MLKEM_DEM
from pqcrypto.common import random_bytes
# Alice generates her key pair
pk, sk = MLKEM_KEM.generate_keypair()
# Alice wants to send a secret key (e.g., a symmetric encryption key) to Bob
# She uses Bob's public key (pk) to encapsulate a random secret
shared_secret_alice, ciphertext = MLKEM_KEM.encapsulate(pk)
# Alice now has a shared_secret_alice and a ciphertext
# She can use this shared_secret_alice with a deterministic encryption scheme (DEM)
# to encrypt her actual message (e.g., a session key for AES)
message_key = random_bytes(32) # A 32-byte (256-bit) key
encrypted_message_key = MLKEM_DEM.encrypt(shared_secret_alice, message_key)
# Alice sends the ciphertext and the encrypted_message_key to Bob
# Bob receives them
# Bob uses his secret key (sk) and the ciphertext to derive the same shared secret
shared_secret_bob = MLKEM_KEM.decapsulate(sk, ciphertext)
# Bob now has shared_secret_bob, which should be identical to shared_secret_alice
assert shared_secret_alice == shared_secret_bob
# Bob uses the shared secret to decrypt the message key
decrypted_message_key = MLKEM_DEM.decrypt(shared_secret_bob, encrypted_message_key)
# Bob now has the original message_key
assert message_key == decrypted_message_key
This process, called Key Encapsulation Mechanism (KEM), is how we’ll establish shared secrets for symmetric encryption in a post-quantum world. ML-KEM is the leading candidate for this. It’s based on the hardness of the Module Learning With Errors (MLWE) problem. Instead of factoring large numbers (RSA) or the discrete logarithm problem (ECC), ML-KEM relies on finding a small error vector in a system of linear equations over a ring.
The problem ML-KEM solves is establishing a shared secret without prior communication, in a way that’s resistant to quantum algorithms. The core idea is that it’s hard to recover a secret s given noisy linear equations of the form b = a*s + e, where a and b are public, s is the secret, and e is a small error term. If an attacker could easily find s, they could break the encryption. Quantum computers, while good at factoring and discrete logs, don’t offer a significant speedup for solving MLWE.
ML-DSA (Module Learning With Errors Digital Signature Algorithm), and its NIST standardized version SLH-DSA (Stateless Hash-to-Slice Learning With Errors Digital Signature Algorithm), are for digital signatures. Signatures are about proving authenticity: Alice signs a message, and Bob verifies it using Alice’s public key. If the signature is valid, Bob knows Alice (and only Alice) sent that message.
SLH-DSA operates on a similar principle of hardness as ML-KEM, but applied to the problem of creating signatures. It uses a cryptographic hash function and a technique called "stateless hash-to-slice" which is more efficient and easier to implement correctly than earlier LWE-based signature schemes. The core mechanism involves generating a secret key that allows the signer to compute a unique, short "message representative" (a value derived from the message and the secret key) that is hard for anyone else to forge without the private key.
The mental model for SLH-DSA is that you have a large, secret "random oracle" (a perfect hash function) that you can query using parts of your private key. The signature process involves carefully revealing just enough information about these oracle queries, combined with the message, such that the verifier can reconstruct a path back to the public key without being able to forge new paths. It’s like proving you know a secret password by showing you can unlock a specific door, without revealing the password itself. The "stateless" part means the verifier doesn’t need to maintain any secret state related to past signatures, simplifying deployment.
The actual parameters for these algorithms are quite specific. For instance, ML-KEM might use polynomial rings like Z_q[X] / (X^n + 1) with q being a prime modulus (e.g., 3329) and n being a power of 2 (e.g., 256). The dimensions of the modules (vectors of polynomials) also play a crucial role, impacting security and performance. For SLH-DSA, you’ll see parameters like SLH-DSA-SHA2-256 or SLH-DSA-SHA2-512, indicating the hash function and security level, with associated public key sizes and signature lengths.
A common misunderstanding is that these algorithms are all about "learning with errors." While MLWE is the foundation for ML-KEM and ML-DSA, SLH-DSA is technically a "Hash-to-Slice" scheme that uses MLWE principles in its construction to derive the underlying security. The "slice" refers to breaking down the problem into smaller, manageable parts that can be efficiently hashed and verified.
The next hurdle you’ll encounter is understanding the trade-offs between different parameter sets within these algorithms and how to choose the right ones for your specific application’s security and performance requirements.