https://github.com/flyingsurveyor/qrfs
QR FileSystem: a physical, offline, encrypted data transport and storage system based on QR
https://github.com/flyingsurveyor/qrfs
air-gapped archival encryption file flask optical python qrcode raspberry-pi termux
Last synced: about 1 month ago
JSON representation
QR FileSystem: a physical, offline, encrypted data transport and storage system based on QR
- Host: GitHub
- URL: https://github.com/flyingsurveyor/qrfs
- Owner: flyingsurveyor
- License: agpl-3.0
- Created: 2026-04-21T09:19:01.000Z (about 2 months ago)
- Default Branch: main
- Last Pushed: 2026-05-08T22:28:01.000Z (about 1 month ago)
- Last Synced: 2026-05-08T23:35:31.500Z (about 1 month ago)
- Topics: air-gapped, archival, encryption, file, flask, optical, python, qrcode, raspberry-pi, termux
- Language: Python
- Homepage:
- Size: 297 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# QRFS โ QR Filesystem
[](https://github.com/flyingsurveyor/qrfs/actions/workflows/ci.yml)
QRFS is an experimental system to encode encrypted data into printable QR code pages.
It is NOT a traditional filesystem.
It is a:
> **physical, offline, encrypted data transport and storage system**
---
## ๐ Specification
QRFS is independently re-implementable. The on-wire format (`QFSP v1`, `QFSC v6`, `QRC3`) is
fully documented in [`docs/SPEC-1.0.md`](docs/SPEC-1.0.md) โ an RFC-style specification that
any competent implementer can use to build a conforming QRFS encoder or decoder **without reading
a single line of Python code**. The Python package in this repository is the reference
implementation. Conformance test vectors are in `tests/vectors/`.
---
## ๐ง What QRFS Is
QRFS allows you to:
- take any file
- encrypt it securely
- split it into chunks
- encode it into QR codes
- print or display them
- reconstruct the file later from scans or photos
It works offline, including local encode/decode and the browser-based live scanner shipped in `qrfs/static/vendor/`.
---
## ๐ Core Features
- Password-based encryption (Argon2 + AEAD)
- Public key encryption (X25519 / SealedBox)
- Digital signatures (Ed25519)
- Chunking system
- FEC (XOR and Reed-Solomon, with explicit parity QR)
- Multi-page PDF generation
- Scan & reconstruct from images
---
## โ๏ธ What QRFS Is NOT
- Not a replacement for cloud storage
- Not efficient for large data
- Not a high-speed transfer system
---
## ๐ฅ Real Use Cases
### 1. Air-gapped data transfer
Move data between isolated systems without USB or network.
### 2. Field data exchange
Exchange data without connectivity using printed pages or phone images.
### 3. Physical encrypted archive
Store data in printed form, readable without digital infrastructure.
---
## ๐ง Long-term Archival / Time Capsule
QRFS can be used for **long-term data preservation**.
Concept:
- Store data on physical media (paper, metal, glass)
- Include:
- human-readable explanation
- decoding instructions
- format specification
- Encode actual data using QRFS
This creates a **self-describing archive**.
Even if all software is lost, the data can be reconstructed.
---
## ๐ง Key Insight
QRFS separates:
- **data transport (physical)**
- **data security (cryptography)**
---
## ๐ฆ Working with Multiple Files
QRFS operates on a single input file.
For multiple files or folders:
๐ Create a ZIP archive first, then encode it.
ZIP may optionally be password-protected as an additional layer.
---
## ๐งฉ FEC: XOR vs Reed-Solomon
QRFS can optionally add **extra parity QR codes** to improve recovery when some QR codes are missing or unreadable.
### XOR FEC
- adds **1 parity QR** for each group of `N` data QR
- can recover **at most 1 missing data chunk per group**
- simple, predictable, and easy to reason about
Example: with group size `5`, QRFS emits `5 data + 1 parity`.
If exactly one of those 5 data QR is missing, QRFS can reconstruct it.
If two data QR are missing from the same group, XOR is not enough.
### Reed-Solomon FEC
- adds `P` parity QR for each group of `N` data QR
- can recover up to `P` **known erasures per group**
- more flexible than XOR, but also denser and more demanding
Example: with group size `5` and parity `2`, QRFS emits `5 data + 2 parity`.
That group can survive up to 2 missing chunks in total inside the group.
### Important practical notes
- FEC helps with **missing or unreadable chunks**. It does **not** replace the QR code's own ECC level.
- Parity QR carry a small amount of extra metadata (chunk lengths), so they can be **slightly larger** than plain data QR.
- Dense presets plus FEC should always be tested on your **real printer / camera / scanner** path before relying on them.
- The internal **Testbench** page is useful for validating chunk loss scenarios before publishing or field use.
---
## โ ๏ธ Limitations
- Low data density compared to digital storage
- Requires reconstruction process
- Depends on image quality when scanning
- Physical media can degrade
---
## ๐ Security Model
Security relies on:
- strong password (with Argon2)
- or public/private key cryptography
- authenticated encryption
---
## ๐ Installation
QRFS binds to `127.0.0.1` (loopback only) by default, so a fresh
`python qrfs.py` is **not reachable from the network** unless you opt in.
- On the same device: `http://127.0.0.1:5000`
- From another device on the same LAN: `python qrfs.py --lan` โ `http://:5000`
Run `python qrfs.py --debug` only if you explicitly want Flask debug mode.
The default non-debug path uses Waitress when installed.
### Security defaults
**Loopback-only by default.**
A fresh `python qrfs.py` with no arguments binds to `127.0.0.1:5000` and is
reachable only from the same device. Use `--lan` (or `QRFS_LAN=1`) to expose
QRFS on the local network. Use `--host ` for full control.
**Optional self-signed HTTPS.**
Add `--https` to run the server over TLS. On first run QRFS auto-generates an
Ed25519 self-signed certificate under `data/tls/` (key stored with mode
`0o600`) and prints its SHA-256 fingerprint at startup. Subsequent runs reuse
the same certificate. Supply `--cert --key ` to use your own
certificate instead.
> **Note:** Self-signed TLS does not protect against active MITM unless you
> verify and pin the certificate fingerprint out-of-band on each remote device.
**KDF rate limiting.**
Password-based decode attempts (Argon2id) are rate-limited to **5 per IP per
60 seconds**. The 6th attempt within the window returns HTTP 429 with a
`Retry-After` header.
### Raspberry Pi / Debian / Ubuntu
#### 1. Install system packages
```bash
sudo apt update
sudo apt install -y \
git \
python3 \
python3-pip \
python3-venv \
poppler-utils \
libzbar0
```
If `pip install -r requirements.txt` needs to compile native packages, install these optional build dependencies too:
```bash
sudo apt install -y \
build-essential \
python3-dev \
pkg-config \
libjpeg-dev \
zlib1g-dev \
libpng-dev \
libffi-dev \
libssl-dev \
cargo
```
#### 2. Clone the repository
```bash
git clone https://github.com/flyingsurveyor/qrfs.git
cd qrfs
```
#### 3. Create a virtual environment and install Python dependencies
```bash
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
```
#### 4. Start QRFS
```bash
python qrfs.py
```
### Termux
#### 1. Install system packages
```bash
pkg update
pkg upgrade -y
pkg install -y \
git \
python \
zbar \
poppler \
libjpeg-turbo \
libpng
```
If `pip install -r requirements.txt` needs to compile native packages, install these optional build dependencies too:
```bash
pkg install -y \
clang \
make \
pkg-config \
ndk-sysroot \
rust
```
#### 2. Clone the repository
```bash
git clone https://github.com/flyingsurveyor/qrfs.git
cd qrfs
```
#### 3. Install Python dependencies
```bash
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
```
#### 4. Start QRFS
```bash
python qrfs.py
```
### Quick dependency check
```bash
which pdftoppm
python -c "from pyzbar.pyzbar import decode; print('OK')"
```
If `pdftoppm` is found and the Python command prints `OK`, the main decoding dependencies are in place.
---
## ๐ Future Directions
QRFS is still experimental, but its direction is becoming clearer.
The goal is not to turn it into a generic storage system or a novelty QR project.
The real direction is to make QRFS more reliable, more self-describing, and more useful in degraded, offline, hostile, or infrastructure-poor environments.
Possible future directions include:
- **Better scanning UX**
Faster and more reliable recovery from photos and scans, with clearer feedback about missing, duplicated, or damaged chunks.
- **Improved FEC strategies**
Smarter redundancy profiles, better real-world recovery behavior, and stronger resilience to partial page loss or poor image quality.
- **Standardization of the QRFS format**
A documented, versioned, implementation-independent format that can be decoded and reconstructed without relying on a single codebase.
- **Physical medium optimization**
Better support for paper, low-quality printers, difficult lighting, and more durable media such as metal, engraving, or other long-life physical substrates.
- **Time capsule / archival edition**
A more conservative and self-describing archival mode designed for long-term preservation, with human-readable recovery guidance and format documentation.
- **Paranoid Mode for politically harsh environments**
A minimal-disclosure mode that reduces metadata leakage, avoids unnecessary identifiers, and makes physical transport safer in hostile conditions.
- **Transport to and from Reticulum networks**
Using QRFS as a physical bridge for disconnected or delayed networks: exporting payloads from Reticulum, carrying them physically, and reinjecting them later.
- **Paper computing / executable capsules**
Exploring whether small scripts, bootstrap tools, configurations, and operational payloads can travel physically on paper as signed, inspectable, self-describing QRFS bundles.
- **Field-ready operational profiles**
Clear presets such as archive, rugged field, balanced, or dense mode, so QRFS can be tuned for real-world use instead of only lab conditions.
In the long term, QRFS may evolve from a simple encrypted QR transport tool into something broader:
> **a physical carrier for data, instructions, and minimal capabilities across disconnected worlds**
---
## ๐งญ Philosophy
QRFS is not about replacing modern systems.
It is about:
> **having an alternative when modern systems are unavailable**
---
## ๐ Development
To set up a development environment:
```bash
python3 -m venv .venv
source .venv/bin/activate
pip install -e .[dev]
```
Run the test suite:
```bash
pytest
```
Run the linter:
```bash
ruff check .
```
CI runs the same checks (`pytest`, `ruff check .`, and `bandit -r qrfs/core`) on every push to `main` and on every pull request, across Python 3.11, 3.12, and 3.13.
The on-wire format is pinned by reference vectors under `tests/vectors/` โ see `docs/FORMAT.md` ยง12.
---
## ๐ License
QRFS is released under the GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later).
---
Made with โค๏ธ for freedom
FlyingSurveyor ยท Italy