Metadata-Version: 2.4
Name: qrbackup
Version: 0.1.0
Summary: Reliable paper backup using QR codes with optional erasure coding and Shamir's Secret Sharing
Project-URL: Homepage, https://git.mirus-tech.com/public/qrbackup
Project-URL: Repository, https://git.mirus-tech.com/public/qrbackup
Project-URL: Issues, https://git.mirus-tech.com/public/qrbackup/issues
Author-email: Jörg Ziefle <joerg@ziefle.org>
License-Expression: GPL-3.0-or-later
License-File: LICENSE
Keywords: archive,backup,encryption,erasure-coding,paper,pdf,qr-code
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: System :: Archiving :: Backup
Requires-Python: >=3.12
Requires-Dist: argon2-cffi>=23.1
Requires-Dist: numpy>=2.0
Requires-Dist: pillow>=10.4
Requires-Dist: pycryptodome>=3.20
Requires-Dist: pydantic>=2.9
Requires-Dist: pyeclib>=1.6.0
Requires-Dist: pymupdf>=1.24
Requires-Dist: pyzbar>=0.1.9
Requires-Dist: reportlab>=4.2
Requires-Dist: rich-click>=1.8
Requires-Dist: segno>=1.6
Requires-Dist: zstandard>=0.23
Provides-Extra: dev
Requires-Dist: hypothesis>=6.112; extra == 'dev'
Requires-Dist: mypy>=1.11; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest>=8.3; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Provides-Extra: qreader
Requires-Dist: qreader>=3.14; extra == 'qreader'
Description-Content-Type: text/markdown

# QRBackup

Reliable paper backup using QR codes with optional encryption, erasure coding, and Shamir's Secret Sharing.

## Why Paper Backups?

Digital storage fails. Hard drives crash, SSDs degrade, cloud services shut down, and file formats become obsolete. For truly critical data - encryption keys, cryptocurrency seeds, password vaults, or irreplaceable documents - you need a backup medium that:

- **Lasts decades** without power or maintenance
- **Survives disasters** (fire-resistant safes, bank vaults)
- **Remains readable** with commodity technology
- **Can be visually verified** for tampering

Paper, properly stored, meets all these criteria. QRBackup encodes your data into high-density QR codes that can be printed, stored, and later scanned to recover the original file.

## Key Features

- **High-Density Encoding**: Up to ~2.9 KB per QR code using Version 40 codes
- **Automatic Compression**: zstd compression reduces page count for compressible data
- **Strong Encryption**: AES-256-GCM with Argon2id key derivation (64MB memory-hard)
- **Erasure Coding**: Reed-Solomon coding recovers data even when QR codes are damaged or unreadable
- **Secret Sharing**: Shamir's Secret Sharing splits backups across multiple locations (K-of-N threshold)
- **Print-Ready PDFs**: Clean layouts with metadata headers, optimized for reliable scanning

## Example Output

![Sample QRBackup output](docs/sample-backup.png)

[Download sample PDF](docs/sample-backup.pdf)

## Installation

```bash
uv pip install -e .
```

### System Dependencies

- `zbar` library for QR code reading
- `liberasurecode` for erasure coding support

On macOS:
```bash
brew install zbar

# liberasurecode must be compiled from source
git clone https://github.com/openstack/liberasurecode.git
cd liberasurecode
./autogen.sh && ./configure --prefix=$HOME/.local && make && make install

# Add to your shell profile (.zshrc or .bashrc)
export DYLD_LIBRARY_PATH=$HOME/.local/lib
```

On Debian/Ubuntu:
```bash
apt-get install libzbar0 liberasurecode-dev
```

## Usage

### Basic encoding

```bash
qrbackup encode secret.txt -o backup.pdf
```

### With encryption (recommended for sensitive data)

```bash
qrbackup encode secret.txt -o backup.pdf --password
```

### With erasure coding (recommended for archival)

```bash
# 20% redundancy = can lose ~20% of QR codes and still recover
qrbackup encode data.bin -o backup.pdf --redundancy 20
```

### With secret sharing (for distributed trust)

```bash
# Creates 3 PDFs, any 2 can reconstruct the original
qrbackup encode keys.gpg -o backup.pdf --split 2-of-3
```

### Decoding

```bash
qrbackup decode backup.pdf -o recovered.txt

# Encrypted backup
qrbackup decode backup.pdf -o recovered.txt --password
```

### Verification (without decoding)

```bash
qrbackup verify backup.pdf
```

## How It Works

### Encoding Pipeline

```
File → [Compress] → [Encrypt] → Chunk → Erasure Code → QR Codes → PDF
```

1. **Compression**: zstd compresses the input (skip with `--no-compress`)
2. **Encryption**: AES-256-GCM encrypts the compressed data (optional)
3. **Chunking**: Data is split into chunks sized for QR capacity
4. **Erasure Coding**: Reed-Solomon adds parity chunks for recovery (optional)
5. **QR Generation**: Each chunk becomes a QR code with a binary header
6. **PDF Layout**: QR codes are arranged on pages with metadata headers

### Chunk Format

Each QR code contains a 47-byte header followed by data:

| Field | Size | Description |
|-------|------|-------------|
| Magic | 4B | `QRB2` version identifier |
| Flags | 1B | Compressed, encrypted, parity chunk, etc. |
| Data chunks | 2B | Number of data chunks (N) |
| Parity chunks | 2B | Number of parity chunks (M) |
| Chunk index | 2B | This chunk's index (0..N+M-1) |
| SHA-256 | 32B | Hash of original uncompressed data |
| Original length | 4B | For padding removal |

### QR Code Sizes

| Size | QR Version | Capacity | Best For |
|------|------------|----------|----------|
| small | V18 (89 modules) | ~718 bytes | Large files, many codes per page |
| medium | V30 (137 modules) | ~1.7 KB | Most files, balanced density |
| large | V40 (177 modules) | ~2.9 KB | Small files, fewer large codes |
| xlarge | V18 (8px/module) | ~718 bytes | Maximum reliability, easy scanning |

### Erasure Coding

QRBackup uses Reed-Solomon erasure coding via liberasurecode. With `--redundancy 20`:

- Your data is split into N data chunks
- M parity chunks are generated (M ≈ 20% of N)
- **Any N chunks** (data or parity) can reconstruct the original
- You can lose up to M chunks and still recover

For large files exceeding the 32-fragment limit, data is automatically striped across multiple erasure groups.

### Encryption

When using `--password` or `--keyfile`:

- **Key Derivation**: Argon2id with 64MB memory, 3 iterations, 4 threads
- **Cipher**: AES-256-GCM (authenticated encryption)
- **Overhead**: 44 bytes (16B salt + 12B nonce + 16B auth tag)

Encryption happens before chunking, so the entire backup is protected. Erasure coding is automatically enabled (20% redundancy) for encrypted backups to prevent single-chunk failures from destroying the ciphertext.

## CLI Reference

### Encode options

| Option | Description |
|--------|-------------|
| `-o, --output` | Output PDF file path (required) |
| `--no-compress` | Disable zstd compression |
| `--qr-size` | QR size: small, medium, large, xlarge, auto (default: auto) |
| `--dpi` | Target print/scan DPI (default: 300) |
| `--pixels-per-module` | Pixels per QR module (default: 4) |
| `-r, --redundancy` | Erasure coding percentage (e.g., 20 for 20% parity) |
| `--split K-of-N` | Shamir's Secret Sharing (e.g., 2-of-3) |
| `--page-size` | Page size: A4, letter (default: A4) |
| `-p, --password` | Encrypt with password |
| `-k, --keyfile` | Encrypt with 256-bit key file |
| `--hint` | Password hint printed in PDF header |
| `-v, --verbose` | Verbose output |

### Decode options

| Option | Description |
|--------|-------------|
| `-o, --output` | Output file path (required) |
| `--combine K` | Number of SSSS shares being combined |
| `-p, --password` | Decrypt with password |
| `-k, --keyfile` | Decrypt with key file |
| `-v, --verbose` | Verbose output |

### Verify options

| Option | Description |
|--------|-------------|
| `-v, --verbose` | Verbose output |

## Best Practices

1. **Always use redundancy** for archival backups: `--redundancy 20` or higher
2. **Test your backup** by decoding it before storing
3. **Use encryption** for sensitive data: `--password` or `--keyfile`
4. **Print on acid-free paper** for longevity
5. **Store multiple copies** in different locations
6. **Consider secret sharing** for critical keys: `--split 2-of-3`

## Requirements

- Python 3.12+
- `zbar` library for QR code reading
- `liberasurecode` library for erasure coding

## License

QRBackup is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

See [LICENSE](LICENSE) for the full text.
