Lattice Lattice

Specifications.

Long. ~25 minutes if you read every link.

This page exists for researchers, journalists, and anyone who wants to verify our claims by reading the actual standards. Every protocol Lattice uses, every RFC we conform to, every NIST publication we follow, every ISO/IEC reference. No shortcuts.

If something on this page looks wrong, please tell us in our Matrix room. We'd rather correct an error than have it sit.


1. The stack at a glance.

   ┌──────────────────────────────────────────────────────────┐
   │ Application                                              │
   │   ChatStore, GroupChat, IntroductionBundle, BurnCommand  │
   ├──────────────────────────────────────────────────────────┤
   │ Group security                                           │
   │   MLS (RFC 9420) via openmls 0.8                         │
   ├──────────────────────────────────────────────────────────┤
   │ Session security                                         │
   │   Noise XX (Curve25519+ChaCha20-Poly1305+SHA-256)        │
   │   Hybrid post-quantum: ML-KEM-768 (FIPS 203)             │
   ├──────────────────────────────────────────────────────────┤
   │ Mesh routing                                             │
   │   Cluster-bounded gossip + Bloom dedupe + onion (3-hop)  │
   ├──────────────────────────────────────────────────────────┤
   │ Wire format                                              │
   │   Sealed-sender packet, padding buckets {256,512,1024,   │
   │   2048}, ChaCha20-Poly1305 IETF AEAD per packet          │
   ├──────────────────────────────────────────────────────────┤
   │ Transport (any of)                                       │
   │   Bluetooth LE (5.0+, GATT + L2CAP CoC)                  │
   │   Wi-Fi Aware (NAN v4, IEEE 802.11)                      │
   │   Tor v3 onion (opt-in, internet-bridged)                │
   ├──────────────────────────────────────────────────────────┤
   │ Identity / key derivation                                │
   │   BIP-39 mnemonic → PBKDF2-HMAC-SHA512 → HKDF-SHA-512    │
   │   Per-persona: X25519, Ed25519, ML-KEM-768, AES-256-GCM  │
   ├──────────────────────────────────────────────────────────┤
   │ Storage                                                  │
   │   SQLite (file-format) + ChaCha20-Poly1305 per-cell      │
   │   AEAD; key wrapped by Secure Enclave / StrongBox        │
   ├──────────────────────────────────────────────────────────┤
   │ Hardware key storage                                     │
   │   iOS: Apple Secure Enclave (NIST P-256 wrap)            │
   │   Android: StrongBox (StrongBox Keymaster) / TEE         │
   └──────────────────────────────────────────────────────────┘
  

2. Cryptographic primitives.

2.1 Symmetric encryption

2.2 Hash functions

2.3 Key derivation

2.4 Asymmetric primitives — classical

2.5 Asymmetric primitives — post-quantum

The hybrid choice is deliberate. Pure post-quantum is premature; the algorithms are new and have less analytic history. Pure classical is dead in the long term against any quantum adversary. Hybrid is the standard cautious approach taken by Apple iMessage's PQ3, Signal's PQXDH, and OpenSSH.

3. Identity and onboarding.

3.1 Mnemonic

3.2 Persona derivation tree

   seed (64 B from BIP-39)
        │
        │  HKDF-SHA-512 with salt "Lattice/v1"
        ▼
   master_secret (64 B)
        │
        │  HKDF-Expand info = "persona/" || u32_be(persona_index)
        ▼
   persona_root (64 B)
        │
        ├── HKDF-Expand "noise_x25519"   → 32 B → X25519 secret
        ├── HKDF-Expand "kem_ml_kem_768" → 32 B (placeholder; full KEM key
        │                                       generated separately at M4
        │                                       since FIPS 203 keys are
        │                                       not deterministic from a
        │                                       small seed)
        ├── HKDF-Expand "sig_ed25519"    → 32 B → Ed25519 secret
        ├── HKDF-Expand "intro_ed25519"  → 32 B → Ed25519 intro key
        └── HKDF-Expand "storage_wrap"   → 32 B → ChaCha20-Poly1305 key
                                                   for the local SQLite vault
  

3.3 Bullet ID

4. Session security — Noise XX hybrid.

The Noise XX pattern, specified in The Noise Protocol Framework revision 34. We extend it with ML-KEM-768 mixing per the Hybrid Forward Secrecy "hfs" pattern (work-in-progress draft adopted with documentation).

   Pattern: Noise_XXhfs_25519+Kyber768_ChaChaPoly_SHA256

   message 1 (initiator → responder):
     -> e            X25519 ephemeral pubkey
                     ML-KEM-768 ciphertext (initiator-encapsulated to
                     responder's static KEM key, but XX has no static yet,
                     so this ciphertext is to a *transient* KEM key — see
                     RFC-0011 §3 for the precise mixing)

   message 2 (responder → initiator):
     <- e, ee, s, es Both DH and KEM outputs mixed into the symmetric state.

   message 3 (initiator → responder):
     -> s, se        Identity revealed. Final mixing.

   At completion, both sides have:
     - a confirmed handshake hash (transcript binding)
     - a 32-byte send key, a 32-byte receive key
     - a counter for nonce uniqueness, replay-protection sliding window 64
  

The hybrid mixing is forward-secure under the standard Noise security analysis even if one of {X25519, ML-KEM-768} is broken. Internal property tests at core/crates/lattice-crypto/tests/property_tests.rs verify: round-trip on random plaintexts, tampered AEAD rejected at any byte position, ML-KEM-768 implicit rejection (FO-transform), distinct sessions yield non-interchangeable keys.

5. Group security — MLS.

6. Mesh routing.

6.1 Wire format

   Outer packet (clear, AAD'd):
   ┌─────────────────────────────────────────────────────────────────┐
   │ version (1 B) │ flags (1 B) │ ttl (1 B) │ kind (1 B)            │
   │ epoch (2 B BE) │ recipient_tag (16 B)                            │
   │ packet_id (8 B BE) │ ct_len (2 B BE) │ reserved (4 B = 0)        │
   ├─────────────────────────────────────────────────────────────────┤
   │ ciphertext (ct_len bytes) — ChaCha20-Poly1305(key, nonce,        │
   │   payload, AAD = outer_header)                                   │
   ├─────────────────────────────────────────────────────────────────┤
   │ ciphertext continued + 16 B Poly1305 tag                        │
   └─────────────────────────────────────────────────────────────────┘
   Total padded to one of: 256, 512, 1024, or 2048 bytes.

   Padding bucket selected to fit body+overhead; remainder PKCS#7-ish.
  

Padding to bucket sizes is the standard traffic-analysis defence: a packet on the wire is always one of four sizes, so an observer cannot infer the size of your message body from the packet length.

6.2 Sealed-sender recipient tags

The 16-byte recipient_tag is HKDF-derived from a (shared_secret, epoch) pair, where epoch is a 30-minute increment from a 2026-01-01 anchor. Only the legitimate recipient can derive their tag for the current epoch — relays cannot tell who a packet is for, just that it is for somebody.

6.3 Cluster-bounded gossip

   Each phone maintains an "active neighbour set" — the small bounded
   group of peers it actually exchanges traffic with. Capacity per
   density class:

       Sparse  (few neighbours)       cap = 12
       Normal  (handful of neighbours) cap = 8
       Dense   (a stadium row)         cap = 6
       Crowd   (festival pocket)       cap = 6

   Score per visible peer:
     score = signal_quality × route_utility × freshness × diversity

   Promotion / demotion rate-limited to ≤ 1 swap per 30 s to prevent
   thrash.

   On packet receipt:
     1. Bloom-dedupe against a time-windowed filter (10k packets / 10 min).
     2. Decrement TTL (max 16).
     3. For each active neighbour ≠ source, forward with probability
        p = 0.5 * ttl_term + 0.3 * battery_term + 0.2 * link_quality_term
        clamped to [0, 1].
  

Detailed analysis with the three reference environments (supermarket, airport, Glastonbury festival) in WP-04 — Density and Crowd Behaviour.

6.4 Onion wrapping (optional)

For high-threat send paths the user can enable 3-layer onion routing through the mesh. Each hop has its own ephemeral X25519 keypair and ChaCha20-Poly1305 layer; each relay sees only the previous and next hops. Implementation in core/crates/lattice-mesh/src/onion.rs with property tests covering hop isolation and tamper rejection.

7. Transport layer.

7.1 Bluetooth LE

7.2 Wi-Fi Aware (NAN)

7.3 Tor (optional bridged)

8. Storage at rest.

9. Hardware-backed key storage.

9.1 iOS — Secure Enclave

9.2 Android — StrongBox / TEE

10. Notifications.

11. Threat-model summary.

Three tiers of adversary, with explicit defences and explicit limits at each. The full table with citations to specific code paths is in WP-01.

12. Compliance and accessibility.

13. Build provenance and reproducibility.

14. Audits and disclosure.

14a. Key rotation.

Three independent rotation regimes:

   What rotates                 When                              How
   ──────────────────────────────────────────────────────────────────────
   Per-invite ephemeral         Every Lattice Invite generated    Fresh
     X25519 keypair             (single-use, rejected on re-use). X25519
                                Default 24h expiry, max 7d.       gen.

   Per-handshake Noise XX       Every new session.                Standard
     ephemeral                                                    Noise
                                                                  XX e/ee/se.

   Per-message nonce            Every encrypted packet.           Counter +
                                                                  IV per RFC 8439.

   MLS group epoch keys         Every Add / Remove / Update /     RFC 9420
                                Commit on the group.              tree update.

   What does NOT rotate         Why                               Mitigation
   ──────────────────────────────────────────────────────────────────────
   Long-term identity           Wallet model: the seed phrase IS  If a long-term
     keys (X25519 static,       the user's identity. A rotation   key is suspected
     Ed25519 sig, Ed25519       mechanism is something an         compromised, the
     intro, ML-KEM static)      attacker can attack — phish the   user burns the
                                user, social-engineer, etc. We    identity (T-M8-08
                                chose the wallet model            remote burn) and
                                deliberately so there is no       onboards a new
                                such surface to attack.           one. Contacts
                                                                  re-add via the
                                                                  fresh Bullet ID.

   Bullet ID                    Same — it's a SHA-256 of the      Same.
                                long-term key bundle.
  

Forward secrecy follows from the per-handshake and per-message rotation: an attacker who obtains today's session key cannot read yesterday's traffic, and an attacker who later breaks one of {X25519, ML-KEM-768} still can't read past traffic because both were mixed.

15. Source.


If you want to verify a specific claim on this page, the table of contents in the source's docs/ directory cross-references every claim back to a source file or test. Ask if anything is unclear.