Protocol Simulations / MLS Group Messaging

What you will do: Run the MLS primitives with real keys — ML-DSA-65 credential signing, ML-KEM-768 TreeKEM updates, AES-128-GCM messages — and watch the ratchet tree change as members join.

Worked example: Alice and Bob start the group; add a third member and see which nodes on the direct path have to re-key.

Runtime and privacy: The cryptographic exercise runs in this browser. Review the site privacy terms before entering sensitive material; use synthetic inputs for learning and evaluation.

Browse all Crypto Lab tools · Learn with MLS — Group Messaging

For your role

Developer / Engineer
Run the three live primitives, the ML-DSA-65 credential signing, the ML-KEM-768 HPKE TreeKEM update and the AES-128-GCM message encryption, then Add a member to the ratchet tree: the nodes on the direct path that must re-key are the ones your client would update.
Security Architect
Use Add, Remove and Update on the TreeKEM ratchet tree to see how group size changes the number of re-keyed nodes; the How openmls_pqctoday_crypto wires OpenMLS to the HSM section shows where signature keys can be kept in custody.
Researcher / Academic
Enable HSM mode so the three primitives route through softhsmv3 (C_SignMessage, C_EncapsulateKey, C_EncryptInit) and compare the key material with the software path; the Authoritative references list the RFCs the invariants come from.
This tool is under active development — functionality may be incomplete or subject to change.

Live MLS crypto primitives

Three in-browser operations that underpin every MLS session. Run each step to see real key material and verify the cryptographic invariants. Enable HSM mode below to route all steps through softhsmv3 (PKCS#11 v3.2) — C_SignMessage, C_EncapsulateKey, and C_EncryptInit. All crypto executes client-side — no server contact.

Live HSM Mode Active

SoftHSM3 · PKCS#11 v3.2 · Rust · session open

1

Credential signing key — ML-DSA-65

Each MLS leaf node carries an identity credential. The leaf_node is signed with ML-DSA-65 before being committed to the tree.

2

TreeKEM node update — ML-KEM-768 HPKE

When a member commits, they HPKE-encapsulate a fresh path_secret for every ancestor node. Receivers recover the shared secret via decapsulation. Wrong keys get a distinct implicit-rejection value (RFC 9180 §6.1).

3

Application message encryption — AES-128-GCM

MLS derives a content key and nonce from the epoch key schedule (RFC 9420 §5.2). Messages are AES-GCM authenticated — the epoch number, group ID, and content type are bound as Additional Data.

TreeKEM ratchet tree

Watch which nodes get re-keyed on every Commit. Highlighted nodes are the committer's direct path — the only nodes touched by an O(log N) update.

Epoch: 0
Members: 2
Last op: initial state — 2-member group
rootAliBob
Re-keyed this Commit
Existing node
Blank / unoccupied

How openmls_pqctoday_crypto wires OpenMLS to the HSM

OpenMLS expects a single OpenMlsProvider trait combining crypto, randomness, and storage. Our provider routes each crypto trait method through PKCS#11 v3.2 against softhsmv3. The table below reflects the v0.2 implementation (Phase 1 + Phase 2 of the provider roadmap).

What this table describes: the real openmls_pqctoday_crypto Rust crate, which runs server-side. The workshop in this module is a JavaScript reimplementation of the same PKCS#11 calls against the same softhsmv3 engine — the crypto is genuinely HSM-backed either way, but the steps you run here are not literally this crate executing.

OpenMLS operationPKCS#11 mechanismHSM-residentNotes
hashCKM_SHA256 / SHA384 / SHA512 yesC_DigestInit + C_Digest
hmacCKM_SHA256_HMAC yesSession-only generic-secret key, destroyed after each MAC
hkdf_extract / hkdf_expandCKM_*_HMAC (RFC 5869 over HSM HMAC) yesEvery HMAC round executes in the token
aead_encrypt / aead_decryptCKM_AES_GCM yesSession-only AES key for each operation
signature_key_genCKM_EC_EDWARDS_KEY_PAIR_GEN / CKM_EC_KEY_PAIR_GEN yesToken object with CKA_SENSITIVE=TRUE, CKA_EXTRACTABLE=FALSE
sign / verify_signatureCKM_EDDSA / CKM_ECDSA_SHA* yesProvider returns an opaque HsmKeyHandle, not key material
HPKE (DhKem25519 + SHA-256 + AES-128-GCM)CKM_ECDH1_DERIVE + CKM_SHA256_HMAC + CKM_AES_GCM yesRFC 9180 reimplementation over PKCS#11 primitives
HPKE (other suites)hpke-rs-rust-crypto (fallback) Phase 2.1Phase 2.1 — generalise PKCS#11 path to P-256/P-384/P-521/ChaCha20

Signature key custody

When OpenMLS calls signature_key_gen(), our provider runs C_GenerateKeyPair with CKA_SENSITIVE=TRUE and CKA_EXTRACTABLE=FALSE. What we return to OpenMLS as the "private key" is an opaque, versioned handle blob.

HsmKeyHandle wire format
┌────────┬─────────┬──────────┬──────────────┬────────────┐
│ "PQTH" │ ver (1) │ sig sch. │ cka_id_len   │  cka_id    │
│  4 B   │   1 B   │   2 B    │     2 B      │   N bytes  │
└────────┴─────────┴──────────┴──────────────┴────────────┘

On every sign() call, the provider decodes the handle, looks up the token object via C_FindObjects{ CKA_CLASS=PRIVATE_KEY, CKA_ID=… }, and runs C_SignInit + C_Sign inside the HSM. Real key bytes never exist in process memory.

Authoritative references

The library entries that anchor this module's claims:

  • • RFC 9420
  • • RFC 9180
  • • draft-ietf-mls-pq-ciphersuites-06
  • • draft-ietf-mls-combiner-02
  • • draft-ietf-mls-extensions-09

Try it

Add a third member to the group. Which nodes re-key?

Next step

Turn it into a plan: Hybrid Transition Planner

This tool practises the MLS — Group Messaging module, phase 5 (Pilots & Migration); Hybrid Transition Planner produces a deliverable of that phase.

Next in Protocol Simulations