Signal for peers who do not share a server
The Signal Protocol was designed around a server that hands out prekey bundles and stores undelivered ciphertext. Glitr has no such server. Two people still need a classical handshake and a ratchet — the machinery that lets them agree on keys and keep advancing them so old messages stay gone if a key leaks later.
That layer in the cascade is Signal. It is the exception to Glitr’s closed product: you can inspect it.
It is a research-grade implementation. Treat it as not a substitute for a formal audit of the whole messenger. It is still the piece we are willing to put under lights.
What the library is
The classical handshake and ratchet: X3DH key agreement, the Double Ratchet, identity keys, signed prekeys, one-time prekeys, and AES-256-GCM message encryption. Rust core, compiled to WebAssembly, with TypeScript bindings.
Formal verification (hax/F*, Rocq, Lean, ProVerif) lives in that repository. Treat it as research-grade work on the handshake library, not an audit of the messenger. These implementations are spec-faithful and educational. They are not wire-compatible with the Signal app.
A second, local-only Dioxus gallery (signal-protocol-gallery) reuses the same chrome and calls the core directly. It does not replace the React deploy.
How Glitr uses it without a prekey server
Recipient encryption is three libraries composed into one cascade. signal-protocol is the classical handshake and ratchet. ml-kem is ML-KEM-1024. pqxdh combines those two toward Signal’s post-quantum extended Diffie–Hellman.
Your public profile holds an RSA public key and protocol bundles: the Signal, PQXDH, and ML-KEM public material a contact needs to encrypt the first message to you. Your profile secrets hold the matching private material. Those secrets are sealed at rest. A peer poll never reads them.
After a successful profile fetch, a contact row caches the peer’s public key and protocol bundles so later encrypts do not have to re-read their public profile.
Git cannot consume one-time prekeys off a peer repository the way a live prekey server would. The signed prekey is the last-resort path. That is a real difference from the Signal messenger’s deployment, and it is why we do not claim compatibility.
Git and live share one protocol session per contact so the ratchet does not fork. The session row is sealed. Later messages do not redo the handshake.
Where Signal sits in the product
The shipped recipient path is AES → Signal → PQXDH on the inside, then RSA hybrid → ML-KEM on the outside. Signal is one layer, not the whole story. A messaging app that only did today’s elliptic-curve handshake would be finished for 2016. The post-quantum wraps are the next essay.
Outbound, signaling, live chat bodies, and live file payloads share the same recipient encryption. Detection is by shape, not by folder name. The host should see ciphertext. The other person can open it because the cascade was addressed to them.
Open Signal is a trust anchor for the handshake, not a promise that every layer of the messenger is public. The rest of Glitr is not published as source.
How to try it
Run key exchange and a ratchet in the browser, then read the tests and the proofs in the repository if that is how you trust software.
The product try path is Signal Protocol. How it fits the cascade: Signal Protocol and the post-quantum path. Library detail: Cryptography.
