Research preview Free to use, and not yet independently audited. Not yet audited. What that means →

What happens when you lock a message.

LatticeLink has two locks. A key lock scrambles a message with a key you hand over. A private link locks it for one browser, with post-quantum encryption. Both run on your device, and this page runs them live so you can check.

A key you hand over, or a browser that holds it.

Both locks are built from published standards that your browser already ships, plus one open-source library. Nothing is invented here.

Key lock

What the home page does when you press Lock message.

  1. Your browser draws a 256-bit key from its secure random number generator.
  2. HKDF-SHA-256 turns that key and a fresh random salt into a key for this one message.
  3. AES-256-GCM encrypts the message and adds a tag that gives away any change.
  4. The link carries the salt, a nonce and the scrambled message. The key travels separately, in your hands.

Key: 256 bits, written as 52 characters
A 100-letter message makes a link of about 220 characters

Private link

What happens when someone writes to a private link.

  1. The recipient’s browser makes an ML-KEM-768 key pair. The public half is their private link. The secret half stays in that browser.
  2. The sender’s browser encapsulates to the public half, which yields a fresh shared secret.
  3. HKDF-SHA-256 and AES-256-GCM seal the message with it, as the envelope further down shows.
  4. Only the browser holding the secret half can recover that secret and open the message.

Public key 1,184 bytes · KEM ciphertext 1,088 bytes
A key lock can go inside, for two locks

Built on NIST FIPS 203 (ML-KEM), RFC 5869 (HKDF), NIST SP 800-38D (AES-GCM), FIPS 180-4 (SHA-256) and the W3C Web Cryptography API. Read the specification

Watch it work.

Everything in this black panel is running in your browser right now. Nothing here is a recording, and every number is measured on your device.

On-device self-test

Running…

Two agents trading real messages, in this tab

A … ⇄ B …

Sealed
0
Verified
0
Tampered
0
Rejected
0
Self-test
running…
Median seal
—
Median open
—
Servers involved
0
    Every packet is a real envelope, sealed by one agent and opened by the other in this tab. One in five is altered in transit on purpose. The flight is animation; the sizes, bytes and timings are measured.

    Every operation, in the open.

    When this console scrolls into view, your browser generates a key, seals a message, opens it, then attacks it three ways, and prints what actually happened, with the time each step took.

    • Key generation and encapsulation from noble-post-quantum 0.7.1
    • HKDF and AES-256-GCM from your browser’s built-in WebCrypto
    • Three attacks, three refusals, and no plaintext released
    live trace · this tab waiting

      Timings measured in this tab · lines paced for reading

      Change one bit. Watch it fail.

      This is a real envelope, sealed a moment ago to a key that exists only inside a worker on this page. Click any byte to flip its lowest bit. The worker runs the real decryption on the altered copy.

      Ciphertext
      the encrypted message itself
      Tag
      16 bytes that authenticate everything
      Nonce
      12 random bytes, fresh per message
      KEM ciphertext
      1,088 bytes only the recipient can open

      Sealing a fresh envelope…

      Waiting for the envelope

      Every attempt starts from the untouched envelope.

      One open, versioned format.

      A strict JSON envelope with explicit algorithm identifiers. Every header field is bound into the AES-GCM tag as associated data, so changing any of it is detected.

      • Unknown fields, versions and algorithms are rejected before any cryptography runs
      • Canonical base64url only: exactly one valid encoding per envelope
      • A published test vector that reproduces byte for byte
      • An independent reference implementation, checked against the app in every build
      envelope.json sealed in this tab
      Sealing a live envelope…

      Sealed moments ago by the self-test, to a key that existed only inside a worker on this page.

      Stated plainly.

      Strong cryptography is necessary, not sufficient. This is exactly what a passing run demonstrates, and what it does not.

      A passing run shows

      • This implementation encrypts and decrypts your message with ML-KEM-768, HKDF-SHA-256 and AES-256-GCM, in your browser
      • Every tested alteration (a flipped bit, an edited header, a wrong key, a malformed envelope) is detected, with no plaintext released

      It does not show

      • That the system is secure in general, or free of side channels and untested bugs
      • That any quantum attack was attempted or defeated
      • Who sent a message. There is no sender authentication

      Audit status. ML-KEM is provided by noble-post-quantum 0.7.1, which states that it has not been independently audited (it was self-audited at version 0.6.1 in April 2026). LatticeLink’s own code has not been externally reviewed. It is a research preview, not an audited secure messenger.

      Read the security model
      Every build
      82 of 82 unit tests passed in this build
      Every visit
      Six-check self-test in your browser
      Implementations
      noble-post-quantum 0.7.1 + WebCrypto