Quantum-resistant on purpose
Glitr’s encryption story has two timescales: computers we have today, and computers we may have later. A messenger that only did today’s elliptic-curve handshake would be finished for 2016. The shipped cascade adds post-quantum key agreement on purpose: ML-KEM-1024 as a standalone hybrid envelope, and PQXDH so classical X25519 and the lattice KEM ride together.
These experiences are spec-faithful educational implementations. They are not a claim of wire compatibility with the Signal messenger app, and they are not a warranty about tomorrow’s cryptanalysis. They are the “we did not stop at 2016 curves” part of Glitr.
ML-KEM-1024
ml-kem is a pure-Rust ML-KEM-1024 (FIPS 203) wrapper for this stack. Signal alone does not meet a post-quantum requirement.
| Piece | Role |
|---|---|
ml-kem-core | Thin wrapper over libcrux-ml-kem 0.0.10 — the same crate and pin as libsignal — plus hybrid AES-256-GCM. |
ml-kem-wasm | wasm-bindgen façade. |
ml-kem-gallery | Dioxus demos on the same chrome the product uses. |
Lattice review lives in libcrux, not in this wrapper. The crate targets the 1024 parameter set (Signal PQXDH production): 1568-byte public key, 3168-byte expanded secret key, 1568-byte ciphertext, 32-byte shared secret. Secret keys are the expanded FIPS form.
Hybrid encrypt in core: encapsulate, HKDF-SHA256 with info ML-KEM-1024-AES-GCM, then AES-256-GCM. This is a different parameter set and key encoding from older ML-KEM-768 work.
You can press the buttons:
PQXDH
pqxdh is the composition step: signal-protocol-core (X25519 ECDH, HKDF-SHA-256, Ed25519, Double Ratchet) plus ml-kem-core (ML-KEM-1024), aimed at Signal PQXDH revision 3.
Classical hardness and post-quantum hardness are not substitutes for each other. X25519 stays hard against the computers we have. ML-KEM-1024 is expected to stay hard if large quantum computers arrive. PQXDH keeps both, so a break in one family does not automatically finish the handshake.
Documented deviations from the spec:
| Spec | This crate |
|---|---|
| XEdDSA on a single X25519 identity | Separate X25519 (DH) and Ed25519 (signatures) |
| SHA-256 or SHA-512 | HKDF-SHA-256 via signal-protocol-core |
| libsignal encodings / protobufs | Simple EncodeEC / EncodeKEM with type tags |
Parameters: curve X25519, hash SHA-256, info PQXDH-v1, pqkem ML-KEM-1024, AEAD AES-256-GCM. It is a spec-faithful educational implementation. It is not libsignal wire-compatible.
The gallery is public:
How the product stacks them
The shipped recipient path is AES → Signal → PQXDH on the inside, then RSA hybrid → ML-KEM on the outside. Stacking Signal + standalone ML-KEM + PQXDH is defense-in-depth. PQXDH already includes X25519, ML-KEM-1024, and a Double Ratchet. The extra Signal and ML-KEM layers are not a spec-recommended profile; they are extra independent wraps on the same payload.
Password sealing of your mailbox stays outside that cascade. The encryption password you type at connect derives a key (memory-hard hashing, then authenticated encryption) that seals documents in your mailbox. That is “the host should not read the file contents,” not “this is Signal,” and not “this is post-quantum.”
Your public profile publishes protocol bundles so a contact can encrypt the first message to you. After a fetch, the contact row caches those bundles. Git and live share one protocol session per contact so the ratchet does not fork.
What we will not claim
- Unaudited end-to-end forever against nation states.
- Compatible with the Signal app.
- The entire messenger is open source.
- A guarantee about tomorrow’s cryptanalysis.
Safe sentences: a post-quantum KEM and PQXDH are part of the shipped cascade, not only demos. Recipient payloads run AES → Signal → PQXDH, then RSA hybrid → ML-KEM.
The try path is Post-quantum. The user-level story is Signal Protocol and the post-quantum path. Library detail: Cryptography.

