QS QR-Stream

Data that travels
as light

Move a file from a machine with no network onto a phone, using nothing but a screen and a camera. No radio, no cable, no cloud โ€” just a stream of QR codes and something pointed at it.

๐ŸŒŠ

Rateless by design

The sender never repeats itself. It emits an endless fountain of coded frames, and any sufficiently large handful of them rebuilds the file. Miss a frame, look away, walk in halfway through โ€” none of it matters.

๐Ÿ“ฆ

Files, not just text

Arbitrary binary, with the filename and media type carried along. Payloads are compressed when compression actually helps, and every transfer ends with a CRC-32 check against what the sender said it was sending.

๐Ÿ”Œ

No dependencies at runtime

The QR encoder is written from scratch here; the decoder is vendored, unminified, and auditable. Once the page has loaded it makes no network requests at all โ€” which is the only way an air-gap tool makes sense.

๐Ÿ”ฌ

Provable, not just plausible

Every QR version and error correction level is round-tripped against an independent decoder in CI, and full transfers are tested through real pixels at up to 50% frame loss.

How it works

Three ideas, and the third is the one that matters.

The payload is compressed, then cut into k equal blocks sized to fill one QR symbol exactly. A manifest frame describes the whole transfer โ€” length, checksum, name, block geometry โ€” and is re-sent every twelfth frame so a late arrival can catch up.

Each outgoing frame carries the XOR of a pseudo-randomly chosen set of blocks, labelled only with the 32-bit seed that chose them. The first k frames are a plain uncoded pass, so a clean run costs nothing extra.

The receiver collects whatever it sees. Any frame combining exactly one unknown block reveals it, which may in turn reduce other frames to one unknown, cascading until the payload falls out. Typically about 1.1ร— k frames is enough.

The version of this project from a year ago looped over chunks 1..N forever. That works, but it makes the receiver responsible for catching one specific frame โ€” and a camera that periodically drops frames can miss the same chunk on every pass and never finish. Rateless coding removes the problem rather than mitigating it.

What it is good for

And, just as importantly, what it is not.

Getting a key, a config file, a seed phrase or a signed transaction off a machine that is deliberately not on any network. Optical transfer is slow โ€” expect a few kilobytes per second โ€” so this is for the small, valuable things.

QR-Stream provides no confidentiality of its own. Anything on the screen is readable by anything that can see the screen, including a camera you did not notice. Encrypt sensitive payloads before sending them, and think about who else is in the room.