QR CRYPT

The premise

Any device that has ever connected to a network may already be compromised.

So encrypt and decrypt on a device that stays fully offline. When a message is sent, the network carries only ciphertext that is unreadable without the key.

Keep reading

Where the network stops

On the QR transfer path, only light crosses this line — a QR code on one screen, a camera on the other. Removable media and the system clipboard are separate alternatives outside the app’s control.

What this is

Encrypt offline. Transfer by QR code.

QR Crypt is a small app that runs on a device you keep permanently offline. Enter a message, and the app encrypts it and displays the ciphertext as a QR code. Your everyday online device scans the code, converts it to text, and sends it through any messaging app. The recipient follows the same process in reverse. In the intended workflow, plaintext is handled only on the sender’s and recipient’s offline devices; the online devices relay ciphertext.

  • No accounts. No QR Crypt relay server. The app does not send plaintext or secret key material over a network.
  • Two devices per person: one offline and one online.
  • Open source under the Apache License 2.0; not independently audited.

Encryption

Two modes

Choose by who you write to and what you are willing to hand them.

Shared-key mode

For one-to-one messages

Encrypts a message with a secret the two of you shared in person. The data stays small, so a message travels in few QR codes. Each encryption derives a different AES-256-GCM key with HKDF.

Public-key mode

For several senders writing to one recipient

Establishes the message secret from the recipient's public key and verifies the sender's signature, so no sender has to hold a secret that can decrypt. It uses ML-KEM for the key establishment and ML-DSA to confirm the sender. The body itself is encrypted with AES-256-GCM, the same as shared-key mode; the signature and public-key data make the message larger.

Getting it

Two ways to install it

Route A

Verify the signed ZIP

This is the default route and the only one intended for high-assurance use. On a trusted computer, download the signed release and verify both its signature and checksum using verification values obtained through an independent channel. Independently rebuild the same commit, then compare the set of payload files and their hashes with the release. Cosign attests which workflow published the artifact; it does not prove that the binary corresponds to the source.

Transfer the archive to the offline device, extract it, and serve the folder with a static web server bound only to 127.0.0.1. Follow the bundled INSTALL.txt: use an audited static server obtained through an independent, trusted process and installed on the offline device in advance. Apply the bundled headers and redirect rules. Merely installing a server through a process labeled “trusted” does not provide equivalent assurance.

Do not open index.html directly from a file:// URL. In that context, browser storage isolation does not hold, so another local HTML file may be able to read your keys. The transfer medium—such as a USB drive or SD card—must also be trusted, because anyone who can modify it can modify the app. The repository contains the complete procedure.

Route B

Install it from the live origin

On the device you will keep offline, open this site, choose Install or Add to Home Screen, and then disconnect the device from every network. This route offers no integrity check that the user can perform. An attacker who controls the origin server, TLS endpoint, or CDN could deliver a modified bundle to a single target device without detection, and the service worker could keep that modified bundle installed. The app also remains associated with the live origin.

If the device reconnects, it sends a reachability probe to that origin. Wiping begins only after the sentinel responds, so the probe necessarily leaves the device before the wipe starts. Route A uses only 127.0.0.1; after the dedicated server is stopped and its reserved port is not reused, nothing is listening there. Never treat airplane mode alone as proof that a device is trustworthy.

QR code that opens qr-crypt.pages.dev
Scan this with the device you will keep offline.

Using it

How a message travels

Throughout all six steps, plaintext remains on the offline devices. Only ciphertext and the framing data needed to carry it cross the boundary. The key-exchange process depends on the method. A symmetric key is scanned in one direction only. With post-quantum identities, each person scans the other’s public identity even for one-way messages. The sender needs the recipient’s public encryption key, and the recipient needs the sender’s public signing key. The steps below show the post-quantum identity workflow.

  1. Each person creates their own key

    Create dialog

  2. Each person loads the other's key

    Import dialog

    Exchange keys face to face and compare the on-screen fingerprints. The app cannot determine whether a key actually belongs to the person you expect.

  3. The sender encrypts the message

    Encrypt page

    Encrypt the message with the recipient’s key. Every post-quantum message is signed with the sender’s key, and the recipient verifies its signature.

  4. The online device scans the QR code from the offline screen.

    Scan the QR code and send the text

    Online mode

  5. The recipient turns the text back into a QR code

    Online mode

  6. The offline device scans the QR code from the online screen.

    The recipient decrypts and reads it

    Decrypt page

    The plaintext never leaves this device.

Warnings

Read this before relying on QR Crypt

Once a device has been online, you can never fully trust it again

Airplane mode is only a setting. Software on a compromised device can make it appear offline when it is not. Treat a device as offline only after it has been permanently disconnected from every network.

If the offline device goes online, the app attempts to erase its stored data

The app attempts to delete its stored keys and data and reports any failed step. Logical deletion does not guarantee physical erasure, and recoverable remnants may remain on the storage medium. If the data must be made unrecoverable, sanitize the storage using a method appropriate to the medium, such as NIST SP 800-88 Rev. 2, or physically destroy the device.