Agree on a secret that is never sent.
Alice publishes a public key. Bob uses it to create a ciphertext and a 32-byte secret. Alice uses her private key on that ciphertext and gets the same secret. This is X-Wing: ML-KEM-768 and X25519, combined so that both have to be broken.
What Establish does
- 01
Alice generates a 32-byte seed.
SHAKE256 stretches it into an ML-KEM-768 key and an X25519 key. The public key you will see is 1,216 bytes: 1,184 of lattice, then 32 of X25519.
- 02
Bob encapsulates to that public key.
He gets an ML-KEM ciphertext (1,088 bytes) and an X25519 ephemeral public key (32 bytes). Those 1,120 bytes are what he sends. The secret stays local.
- 03
Both sides run the same combiner.
SHA3-256 over the two shared secrets, Bob’s ephemeral key, Alice’s X25519 key, and a fixed label. If the digests match, the exchange worked.
Nothing has been exchanged yet.
Same call in Python
from qrclib.hybrid import generate_kem_keys, encapsulate, decapsulate alice = generate_kem_keys() ciphertext, bob = encapsulate(alice.public_key) alice_copy = decapsulate(alice.secret_key, ciphertext) assert alice_copy == bob