The document
The protocol, written down.
A summary of the Asgard Protocol: the four layers, the primitives each one uses, and the standards they come from. It is written to be checked. Where something is specified and has not been built yet, the page says so.
- Protocol
- Asgard
- Group extensions
- intouch_hybrid_v1
- Standards basis
- CRYSTALS round 3 · RFC 9420
- Custom cryptography
- None
Four layers, and every one of them hybrid
Each layer runs a classical primitive and a post-quantum one together, and both contribute to the same derived secret. Breaking a layer means breaking both of them, and breaking one layer does not open the layer above it.
- 01
Identity
Ed25519 + CRYSTALS-Dilithium
Every account, person or agent, holds two signing keys. Both are generated on the device and neither is ever sent to the server. Every operation that proves who you are has to carry both signatures, so forging an identity means forging both.
- 02
Session
Hybrid X3DH · root = HKDF(DH₁‖DH₂‖DH₃‖DH₄‖SS_pq)
Opening a conversation runs the four Diffie-Hellman exchanges X3DH specifies and one CRYSTALS-Kyber encapsulation against a one-time post-quantum pre-key. All five feed the same derivation. The other person can be offline while it happens, because their published bundle already carries the post-quantum material.
- 03
Message
Double Ratchet · new root = HKDF(DH_ratchet ‖ KEM_ratchet)
Every asymmetric ratchet step performs an X25519 exchange and a fresh CRYSTALS-Kyber encapsulation. This is the step most implementations leave classical. Recording the traffic and breaking the handshake years later buys an attacker one epoch, because the next ratchet step rebuilds post-quantum secrecy out of new material.
- 04
Groups
MLS (RFC 9420) + intouch_hybrid_v1
Groups run on MLS, so adding or removing somebody costs one path update in a tree instead of a message to everybody. Each leaf is bound to the member's CRYSTALS-Dilithium key, epoch secrets take both classical and post-quantum material, and an account with no post-quantum keys cannot join at all.
Every primitive is somebody else's
There is no custom cryptography in the protocol. Each of these is a published standard with a specification you can go and read, and Asgard composes them instead of inventing anything.
- Symmetric encryption
- AlgorithmAES-256-GCM
- StandardNIST
- Strength256-bit
- Key exchange
- AlgorithmX25519
- StandardRFC 7748
- Strength~128-bit classical
- Signatures
- AlgorithmEd25519
- StandardRFC 8032
- Strength~128-bit classical
- Post-quantum KEM
- AlgorithmCRYSTALS-Kyber1024
- StandardCRYSTALS round 3
- StrengthNIST level 5
- Post-quantum signatures
- AlgorithmCRYSTALS-Dilithium5
- StandardCRYSTALS round 3
- StrengthNIST level 5
- Key derivation
- AlgorithmHKDF-SHA-512
- StandardRFC 5869
- Strength256-bit
- Group protocol
- AlgorithmMLS
- StandardRFC 9420
- Strength—
What the server holds
The server is a relay. On the left is the whole of what it has. On the right is what it cannot reach, with root on every machine and the database in front of it.
Held
- Account identifiers, about as private as an email address
- Public pre-key bundles
- Queued ciphertext, until it is collected
- The transparency log, which is meant to be public
- Key backups, encrypted on the device before they arrive
Out of reach
- Message content
- Message type: a text and a payment request are the same ciphertext
- Who sent a message, which travels inside the envelope
- The social graph, because no sender-and-recipient log is kept
- Private keys, which are made on the device and stay there
What this does not protect
Metadata is reduced and not removed. The server can see that something was delivered to somebody and roughly when, and without padding switched on, roughly how large it was. A compromised device is a compromised device: nothing here helps against somebody holding an unlocked phone. And a protocol is not a policy. This page says what InTouch cannot do; it says nothing about what an organisation running InTouch decides to keep. The post-quantum layer runs at the level-5 parameter sets, Dilithium5 and Kyber1024, from the CRYSTALS round-3 submissions rather than the FIPS-standardised ML-DSA and ML-KEM. The strength is the same; the encoding is not, so a signature from this relay will not verify against a FIPS-conformant library.
Specified, not shipped yet
Private contact discovery, which blinds every identifier before it leaves the device so the server never sees a raw one, is written into the specification and has not shipped. Until it does, finding contacts is not covered by anything on this page.
How to check any of it
Three things that need nothing from us.
- 01
Read the source
The library that does the encrypting is open and written in Rust, under a policy of no unsafe code. The interesting part is small enough to read in an afternoon.
- 02
Watch the transparency log
Signed tree heads are published. An auditor that collects them, checks that the log only ever grows and compares notes with other auditors will catch a server showing two different histories to two different people.
- 03
Compare a safety number
Ten seconds, in person, with somebody you already trust. It is the check the transparency log exists to save you from having to make, and it is the one that still works if the log is lying.
This is the shape of it, and not the whole of it.
The complete document, with the wire formats and the proofs, is being prepared for publication alongside the first independent audit. What is on this page is what the protocol does today.