diff --git a/CLAUDE.md b/CLAUDE.md index e315524..9271874 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,16 +1,14 @@ # SooSeF — Claude Code Project Guide SooSeF (Soo Security Fieldkit) is an offline-first security toolkit for journalists, NGOs, -and at-risk organizations. Part of the Soo Suite alongside Stegasoo and Verisoo. +and at-risk organizations. Monorepo consolidating Stegasoo and Verisoo as subpackages. -Version 0.1.0 · Python >=3.11 · MIT License +Version 0.2.0 · Python >=3.11 · MIT License ## Quick commands ```bash -# Development install (requires stegasoo and verisoo installed first) -pip install -e /path/to/stegasoo[web,dct,audio] -pip install -e /path/to/verisoo[cli] +# Development install (single command — stegasoo and verisoo are inlined subpackages) pip install -e ".[dev]" pytest # Run tests @@ -19,19 +17,75 @@ ruff check src/ tests/ frontends/ --fix # Lint mypy src/ # Type check ``` +### Pip extras + +`stego-dct`, `stego-audio`, `stego-compression`, `attest`, `cli`, `web`, `api`, +`fieldkit`, `federation`, `rpi`, `all`, `dev` + ## Architecture ``` src/soosef/ Core library __init__.py Package init, __version__ + _availability.py Runtime checks for optional subpackages (has_stegasoo, has_verisoo) + api.py Optional unified FastAPI app (uvicorn soosef.api:app) + audit.py Audit logging + cli.py Click CLI entry point (soosef command) paths.py All ~/.soosef/* path constants (single source of truth) config.py Unified config loader exceptions.py SoosefError base exception - keystore/ Unified key management + + stegasoo/ Steganography engine (inlined from stegasoo) + encode.py / decode.py Core encode/decode API + generate.py Cover image generation + crypto.py AES-256-GCM encryption + channel.py Channel key derivation + steganography.py LSB steganography core + dct_steganography.py DCT-domain JPEG steganography + spread_steganography.py MDCT spread-spectrum audio steganography + audio_steganography.py Audio stego pipeline + video_steganography.py Video stego pipeline + backends/ Pluggable stego backend registry (lsb, dct, protocol) + batch.py Batch operations + compression.py Payload compression (zstd, lz4) + steganalysis.py Detection resistance analysis + validation.py Input validation + models.py Data models + constants.py Magic bytes, version constants + cli.py Stegasoo-specific CLI commands + api.py / api_auth.py Stegasoo REST API + auth + image_utils.py / audio_utils.py / video_utils.py + keygen.py / qr_utils.py / recovery.py / debug.py / utils.py + platform_presets.py Social-media-aware encoding presets + + verisoo/ Provenance attestation engine (inlined from verisoo) + attestation.py Core attestation creation + verification.py Attestation verification + crypto.py Ed25519 signing + hashing.py Perceptual + cryptographic hashing + embed.py Attestation embedding in images + merkle.py Merkle tree for batch attestation + binlog.py Binary attestation log + lmdb_store.py LMDB-backed trust store + storage.py Attestation storage abstraction + federation.py Federated attestation exchange + models.py Attestation, Verification dataclasses + exceptions.py Verisoo-specific exceptions + cli.py Verisoo-specific CLI commands + api.py Verisoo REST API + + federation/ Federated attestation chain system + chain.py Hash chain construction + entropy.py Entropy source for chain seeds + models.py ChainEntry, ChainState dataclasses + serialization.py CBOR chain serialization + export + + keystore/ Unified key management manager.py Owns all key material (channel keys + Ed25519 identity) models.py KeyBundle, IdentityBundle dataclasses export.py Encrypted key bundle export/import - fieldkit/ Field security features + + fieldkit/ Field security features killswitch.py Emergency data destruction deadman.py Dead man's switch tamper.py File integrity monitoring @@ -40,27 +94,30 @@ src/soosef/ Core library frontends/web/ Unified Flask web UI app.py App factory (create_app()) - auth.py SQLite3 multi-user auth (from stegasoo) + auth.py SQLite3 multi-user auth temp_storage.py File-based temp storage with expiry subprocess_stego.py Crash-safe subprocess isolation for stegasoo + stego_worker.py Background stego processing + stego_routes.py Stego route helpers ssl_utils.py Self-signed HTTPS cert generation blueprints/ - stego.py /encode, /decode, /generate (from stegasoo) - attest.py /attest, /verify (wraps verisoo) + stego.py /encode, /decode, /generate + attest.py /attest, /verify fieldkit.py /fieldkit/* (killswitch, deadman, status) keys.py /keys/* (unified key management) admin.py /admin/* (user management) -frontends/cli/ CLI entry point - main.py Click CLI wrapping stegasoo + verisoo + soosef commands +frontends/cli/ CLI package init (main entry point is src/soosef/cli.py) ``` ## Dependency model -Stegasoo and Verisoo are pip dependencies, not forks: -- `import stegasoo` for steganography -- `import verisoo` for provenance attestation -- SooSeF adds: unified web UI, key management, fieldkit features +Stegasoo and Verisoo are inlined subpackages, not separate pip packages: +- `from soosef.stegasoo import encode` for steganography +- `from soosef.verisoo import Attestation` for provenance attestation +- Never `import stegasoo` or `import verisoo` directly +- `_availability.py` provides `has_stegasoo()` / `has_verisoo()` for graceful degradation + when optional extras are not installed ## Key design decisions @@ -70,7 +127,11 @@ Stegasoo and Verisoo are pip dependencies, not forks: - **All state under ~/.soosef/** — one directory to back up, one to destroy - **Offline-first**: All static assets vendored, no CDN. pip wheels bundled for airgap install - **Flask blueprints**: stego, attest, fieldkit, keys, admin — clean route separation +- **Flask-WTF**: CSRF protection on all form endpoints +- **Waitress**: Production WSGI server (replaces dev-only Flask server) +- **FastAPI option**: `soosef.api` provides a REST API alternative to the Flask web UI +- **Pluggable backends**: Stego backends (LSB, DCT) registered via `backends/registry.py` ## Code conventions -Same as stegasoo: Black (100-char), Ruff, mypy, imperative commit messages. +Black (100-char), Ruff, mypy, imperative commit messages. diff --git a/README.md b/README.md index 6114267..8c9bf49 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,417 @@ -# SooSeF — Soo Security Fieldkit +# SooSeF -- Soo Security Fieldkit -Offline-first security toolkit for journalists, NGOs, and at-risk organizations. +**Offline-first security toolkit for journalists, NGOs, and at-risk organizations.** -Part of the **Soo Suite**: -- **Stegasoo** — hide encrypted messages in media (steganography) -- **Verisoo** — prove image provenance and authenticity (attestation) -- **SooSeF** — unified fieldkit with killswitch, dead man's switch, and key management + +![Version](https://img.shields.io/badge/version-0.2.0-blue) +![Python](https://img.shields.io/badge/python-%3E%3D3.11-blue) +![License](https://img.shields.io/badge/license-MIT-green) -## Status +--- -Pre-alpha. Phase 1 scaffolding complete. +## What is SooSeF? -## Install (development) +SooSeF combines steganography, provenance attestation, and field security tools into a +single package designed for airgapped and resource-constrained environments. It lets you: -```bash -pip install -e /path/to/stegasoo[web,dct,audio,cli] -pip install -e /path/to/verisoo[cli] -pip install -e ".[web,cli]" -``` +- **Hide messages** in images, audio, and video using multiple steganographic techniques +- **Prove authenticity** of photos and documents with Ed25519 signatures and Merkle trees +- **Protect data in the field** with a killswitch, dead man's switch, tamper detection, USB device whitelisting, and GPS geofencing +- **Manage cryptographic keys** with identity rotation, channel key generation, and encrypted key bundle export/import + +Stegasoo (steganography, v4.3.0) and Verisoo (attestation, v0.1.0) are included as +subpackages (`import soosef.stegasoo`, `import soosef.verisoo`). Everything ships as one +install: `pip install soosef`. + +--- ## Quick Start ```bash -soosef init # Generate identity + channel key, create ~/.soosef/ -soosef serve # Start the web UI +pip install "soosef[web,cli]" +soosef init +soosef serve ``` + +This creates the `~/.soosef/` directory structure, generates an Ed25519 identity and +channel key, writes a default config, and starts an HTTPS web UI on +`https://127.0.0.1:5000`. + +--- + +## Features + +### Steganography (Stegasoo) + +- **LSB encoding** -- bit-level message hiding in PNG images +- **DCT encoding** -- frequency-domain hiding in JPEG images (requires `stego-dct` extra) +- **Audio steganography** -- hide data in WAV/FLAC audio (requires `stego-audio` extra) +- **Video steganography** -- frame-level encoding +- AES-256-GCM encryption with Argon2id key derivation +- EXIF stripping on encode to prevent metadata leakage +- Compression support (zstandard, optional LZ4) + +### Attestation (Verisoo) + +- Ed25519 digital signatures for images and files +- Perceptual hashing (ImageHash) for tamper-evident photo attestation +- LMDB-backed attestation storage +- Append-only hash chain (CBOR-encoded) with Merkle tree verification +- Batch attestation for directories + +### Fieldkit + +- **Killswitch** -- emergency destruction of all data under `~/.soosef/` +- **Dead man's switch** -- automated purge if check-in is missed +- **Tamper detection** -- file integrity monitoring with baseline snapshots +- **USB whitelist** -- block or alert on unauthorized USB devices (Linux/pyudev) +- **Geofence** -- GPS boundary enforcement with configurable radius + +### Key Management + +- Two separate key domains: AES-256-GCM channel keys (stego) and Ed25519 identity keys (attestation) +- Key rotation for both identity and channel keys +- Encrypted key bundle export/import for secure backup and transfer +- QR code generation for key sharing + +--- + +## Installation + +### Basic install (core library only) + +```bash +pip install soosef +``` + +### With extras + +```bash +pip install "soosef[web,cli]" # Web UI + CLI (most common) +pip install "soosef[all]" # Everything except dev tools +pip install "soosef[dev]" # All + pytest, black, ruff, mypy +``` + +### Available extras + +| Extra | What it adds | +|---|---| +| `stego-dct` | DCT steganography (numpy, scipy, jpeglib, reedsolo) | +| `stego-audio` | Audio steganography (pydub, soundfile, reedsolo) | +| `stego-compression` | LZ4 compression support | +| `attest` | Attestation features (imagehash, lmdb, exifread) | +| `cli` | Click CLI with rich output and QR code support | +| `web` | Flask web UI with Waitress/Gunicorn, includes attest + stego-dct | +| `api` | FastAPI REST API with uvicorn, includes stego-dct | +| `fieldkit` | Tamper monitoring (watchdog) and USB whitelist (pyudev) | +| `federation` | Peer-to-peer attestation federation (aiohttp) | +| `rpi` | Raspberry Pi deployment (web + cli + fieldkit + gpiozero) | +| `all` | All of the above | +| `dev` | All + pytest, pytest-cov, black, ruff, mypy | + +### Airgapped / Raspberry Pi install + +Bundle wheels on a networked machine, then install offline: + +```bash +# On networked machine +pip download "soosef[rpi]" -d ./wheels + +# Transfer ./wheels to target via USB +# On airgapped machine +pip install --no-index --find-links=./wheels "soosef[rpi]" +soosef init +soosef serve --host 0.0.0.0 +``` + +--- + +## CLI Reference + +All commands accept `--data-dir PATH` to override the default `~/.soosef` directory, +and `--json` for machine-readable output. + +``` +soosef [--data-dir PATH] [--json] COMMAND +``` + +### Core commands + +| Command | Description | +|---|---| +| `soosef init` | Create directory structure, generate identity + channel key, write default config | +| `soosef serve` | Start the web UI (default: `https://127.0.0.1:5000`) | +| `soosef status` | Show instance status: identity, keys, chain, fieldkit, config | + +### `soosef serve` options + +| Option | Default | Description | +|---|---|---| +| `--host` | `127.0.0.1` | Bind address | +| `--port` | `5000` | Bind port | +| `--no-https` | off | Disable HTTPS (use HTTP) | +| `--debug` | off | Use Flask dev server instead of Waitress | +| `--workers` | `4` | Number of Waitress/Gunicorn worker threads | + +### Steganography commands (`soosef stego`) + +```bash +soosef stego encode -i cover.png -m "secret message" -o output.png +soosef stego decode -i output.png +``` + +### Attestation commands (`soosef attest`) + +```bash +soosef attest sign -i photo.jpg # Sign a file +soosef attest verify -i photo.jpg # Verify attestation +soosef attest batch ./photos/ --caption "Field report" +``` + +### Fieldkit commands (`soosef fieldkit`) + +```bash +soosef fieldkit status # Show fieldkit state +soosef fieldkit checkin # Reset dead man's switch timer +soosef fieldkit check-deadman # Check if deadman timer has expired +soosef fieldkit purge --confirm # Activate killswitch (destroys all data) +soosef fieldkit geofence set --lat 48.8566 --lon 2.3522 --radius 1000 +soosef fieldkit geofence check --lat 48.8600 --lon 2.3500 +soosef fieldkit geofence clear +soosef fieldkit usb snapshot # Snapshot current USB devices as whitelist +soosef fieldkit usb check # Check for unauthorized USB devices +``` + +### Key management commands (`soosef keys`) + +```bash +soosef keys show # Display current key info +soosef keys export -o backup.enc # Export encrypted key bundle +soosef keys import -b backup.enc # Import key bundle +soosef keys rotate-identity # Generate new Ed25519 identity +soosef keys rotate-channel # Generate new channel key +``` + +### Chain commands (`soosef chain`) + +```bash +soosef chain status # Show chain head, length, integrity +soosef chain verify # Verify entire chain integrity +soosef chain show INDEX # Show a specific chain record +soosef chain log --count 20 # Show recent chain entries +soosef chain backfill # Backfill existing attestations into chain +soosef chain export --start 0 --end 100 -o chain.cbor +``` + +--- + +## Web UI + +Start with `soosef serve`. The web UI provides authenticated access to all features +through Flask blueprints. + +### Routes + +| Blueprint | Routes | Description | +|---|---|---| +| stego | `/encode`, `/decode`, `/generate` | Steganography operations | +| attest | `/attest`, `/verify` | Attestation signing and verification | +| fieldkit | `/fieldkit/*` | Killswitch, dead man's switch, status dashboard | +| keys | `/keys/*` | Key management, rotation, export/import | +| admin | `/admin/*` | User management (multi-user auth via SQLite) | +| health | `/health` | Capability reporting endpoint (see API section) | + + + +--- + +## Configuration + +SooSeF loads configuration from `~/.soosef/config.json`. All fields have sensible defaults. +`soosef init` writes the default config file. + +### Config fields + +| Field | Type | Default | Description | +|---|---|---|---| +| `host` | string | `127.0.0.1` | Web UI bind address | +| `port` | int | `5000` | Web UI bind port | +| `https_enabled` | bool | `true` | Enable HTTPS with self-signed cert | +| `auth_enabled` | bool | `true` | Require login for web UI | +| `max_upload_mb` | int | `50` | Maximum upload size in MB | +| `session_timeout_minutes` | int | `15` | Session expiry | +| `login_lockout_attempts` | int | `5` | Failed logins before lockout | +| `login_lockout_minutes` | int | `15` | Lockout duration | +| `default_embed_mode` | string | `auto` | Stegasoo encoding mode | +| `killswitch_enabled` | bool | `false` | Enable killswitch functionality | +| `deadman_enabled` | bool | `false` | Enable dead man's switch | +| `deadman_interval_hours` | int | `24` | Check-in interval | +| `deadman_grace_hours` | int | `2` | Grace period after missed check-in | +| `deadman_warning_webhook` | string | `""` | URL to POST warning before auto-purge | +| `usb_monitoring_enabled` | bool | `false` | Enable USB device whitelist enforcement | +| `tamper_monitoring_enabled` | bool | `false` | Enable file integrity monitoring | +| `chain_enabled` | bool | `true` | Enable attestation hash chain | +| `chain_auto_wrap` | bool | `true` | Auto-wrap attestations in chain records | +| `backup_reminder_days` | int | `7` | Days before backup reminder | +| `gpio_killswitch_pin` | int | `17` | Raspberry Pi GPIO pin for hardware killswitch | +| `gpio_killswitch_hold_seconds` | float | `5.0` | Hold duration to trigger hardware killswitch | + +### Environment variables + +| Variable | Description | +|---|---| +| `SOOSEF_DATA_DIR` | Override the data directory (default: `~/.soosef`) | + +--- + +## Architecture + +### Source layout + +``` +src/soosef/ + __init__.py Package init, __version__ + cli.py Click CLI (entry point: soosef) + paths.py All path constants (single source of truth) + config.py Unified config loader (dataclass + JSON) + exceptions.py SoosefError base exception + stegasoo/ Steganography engine (subpackage) + verisoo/ Attestation engine (subpackage) + keystore/ + manager.py Key material management (channel + identity) + models.py KeyBundle, IdentityBundle dataclasses + export.py Encrypted key bundle export/import + fieldkit/ + killswitch.py Emergency data destruction + deadman.py Dead man's switch + tamper.py File integrity monitoring + usb_monitor.py USB device whitelist (Linux/pyudev) + geofence.py GPS boundary enforcement + +frontends/web/ + app.py Flask app factory (create_app()) + auth.py SQLite3 multi-user auth + temp_storage.py File-based temp storage with expiry + subprocess_stego.py Crash-safe subprocess isolation + ssl_utils.py Self-signed HTTPS cert generation + blueprints/ + stego.py /encode, /decode, /generate + attest.py /attest, /verify + fieldkit.py /fieldkit/* + keys.py /keys/* + admin.py /admin/* +``` + +### Data directory (`~/.soosef/`) + +``` +~/.soosef/ + config.json Unified configuration + audit.jsonl Append-only audit trail + identity/ Ed25519 keypair (private.pem, public.pem, identity.meta.json) + stegasoo/ Channel key (channel.key) + attestations/ Verisoo attestation store (log.bin, index/, peers.json) + chain/ Hash chain (chain.bin, state.cbor) + auth/ Web UI auth database (soosef.db) + certs/ Self-signed TLS certificates + fieldkit/ Fieldkit state (deadman.json, tamper/, usb/, geofence.json) + temp/ Ephemeral file storage + instance/ Flask instance (sessions, secret key) +``` + +Sensitive directories (`identity/`, `auth/`, `certs/`, and the root) are created with +`0700` permissions. + +--- + +## Security Model + +**Two key domains, never merged.** Stegasoo uses AES-256-GCM with keys derived via +Argon2id from user-supplied factors. Verisoo uses Ed25519 for signing. These serve +different security purposes and are kept strictly separate. + +**Killswitch priority.** The killswitch destroys all data under `~/.soosef/`, including +the audit log. This is intentional -- in a field compromise scenario, data destruction +takes precedence over audit trail preservation. + +**Offline-first.** All static assets are vendored (no CDN calls). Pip wheels can be +bundled for fully airgapped installation. No network access is required for any core +functionality. + +**Web UI hardening:** +- CSRF protection via Flask-WTF +- Session timeout (default: 15 minutes) +- Login rate limiting with lockout (5 attempts, 15-minute lockout) +- HTTPS by default with auto-generated self-signed certificates +- EXIF stripping on steganographic encode to prevent metadata leakage + +**Subprocess isolation.** Steganographic operations run in a subprocess boundary +(`subprocess_stego.py`) to contain crashes and prevent memory corruption from affecting +the main web server process. + +--- + +## API + +### `/health` endpoint + +The web UI exposes a `/health` endpoint that reports installed capabilities: + +```json +{ + "status": "ok", + "version": "0.2.0", + "capabilities": ["stego-lsb", "stego-dct", "attest", "fieldkit", "chain"] +} +``` + +Useful for monitoring and for clients to discover which extras are installed. + +### FastAPI (optional) + +Install the `api` extra for a standalone FastAPI REST interface: + +```bash +pip install "soosef[api]" +``` + +This provides `soosef.api` with a FastAPI application served by uvicorn, suitable for +programmatic integration. + +--- + +## Development + +### Setup + +```bash +git clone https://github.com/alee/soosef.git +cd soosef +pip install -e ".[dev]" +``` + +### Commands + +```bash +pytest # Run tests with coverage +black src/ tests/ frontends/ # Format (100-char line length) +ruff check src/ tests/ frontends/ --fix # Lint +mypy src/ # Type check +``` + +### Code style + +- Black with 100-character line length +- Ruff with E, F, I, N, W, UP rule sets +- mypy strict mode with missing imports ignored +- Imperative commit messages (e.g., "Add killswitch purge confirmation") + +### Python support + +Python 3.11, 3.12, 3.13, and 3.14. + +--- + +## License + +MIT License. See [LICENSE](LICENSE) for details. diff --git a/docs/deployment.md b/docs/deployment.md new file mode 100644 index 0000000..4cce815 --- /dev/null +++ b/docs/deployment.md @@ -0,0 +1,638 @@ +# SooSeF Deployment Guide + +Deploying SooSeF on a Raspberry Pi for airgapped LAN use. + +This guide is for field deployers: IT staff at NGOs, technically competent journalists, +and anyone setting up a shared SooSeF instance on a local network with no internet access. + +--- + +## 1. Hardware Requirements + +**Minimum:** + +- Raspberry Pi 4 Model B, 2 GB RAM (4 GB recommended) +- 32 GB microSD card (Class 10 / A2 recommended) +- USB-C power supply (5V 3A, official RPi PSU recommended) +- Ethernet cable or pre-configured Wi-Fi for LAN + +**Optional:** + +- USB GPS module (e.g., VK-162) for geofencing +- Momentary push button + 10k pull-down resistor on GPIO pin 17 for hardware killswitch +- USB drive for airgap package transfer and key backups +- Case with passive cooling (no fan noise in sensitive environments) + +If you plan to use the hardware killswitch button, wire it between GPIO 17 and 3.3V with +a 10k pull-down to GND. The default requires a 5-second hold to trigger (configurable via +`gpio_killswitch_hold_seconds` in config). + +--- + +## 2. OS Setup + +Install **Raspberry Pi OS Lite (64-bit, Bookworm or later)**. The desktop environment is +unnecessary and wastes resources. + +After first boot: + +```bash +# Set hostname +sudo hostnamectl set-hostname soosef-node + +# Create a dedicated service user +sudo useradd -m -s /bin/bash soosef +sudo passwd soosef + +# Enable SSH (if not already) +sudo systemctl enable --now ssh + +# Update system packages (do this before going airgapped) +sudo apt update && sudo apt upgrade -y +``` + +Set a strong password. If possible, use SSH key authentication and disable password login +in `/etc/ssh/sshd_config` (`PasswordAuthentication no`). + +--- + +## 3. Security Hardening + +### 3.1 Disable or encrypt swap + +Python does not zero memory when objects are garbage-collected. Cryptographic keys, +passwords, and plaintext can persist in swap long after the process exits. On an SD card, +this data may survive even after the swap file is deleted (wear leveling). + +**Option A: Disable swap entirely (recommended if you have 4 GB+ RAM)** + +```bash +sudo dphys-swapfile swapoff +sudo systemctl disable dphys-swapfile +sudo rm /var/swap +``` + +**Option B: Encrypted swap (if you need swap on 2 GB models)** + +```bash +sudo dphys-swapfile swapoff +sudo systemctl disable dphys-swapfile + +# Use dm-crypt with a random key (regenerated each boot) +echo "swap /dev/mmcblk0p3 /dev/urandom swap,cipher=aes-xts-plain64,size=256" | sudo tee -a /etc/crypttab +echo "/dev/mapper/swap none swap sw 0 0" | sudo tee -a /etc/fstab +``` + +Adjust the device path to match your partition layout. + +### 3.2 Disable core dumps + +A core dump from the SooSeF process would contain key material in plaintext. + +```bash +echo "* hard core 0" | sudo tee -a /etc/security/limits.conf +echo "kernel.core_pattern=/dev/null" | sudo tee -a /etc/sysctl.d/99-soosef.conf +sudo sysctl -p /etc/sysctl.d/99-soosef.conf +``` + +### 3.3 Firewall + +```bash +sudo apt install -y ufw +sudo ufw default deny incoming +sudo ufw default allow outgoing +sudo ufw allow ssh +sudo ufw allow 5000/tcp # SooSeF web UI +sudo ufw enable +``` + +If running fully airgapped, also deny outgoing: + +```bash +sudo ufw default deny outgoing +``` + +### 3.4 Disable unnecessary services + +```bash +sudo systemctl disable bluetooth +sudo systemctl disable avahi-daemon +sudo systemctl disable triggerhappy +``` + +--- + +## 4. Installation + +### 4.1 System dependencies + +```bash +sudo apt install -y \ + python3 python3-pip python3-venv python3-dev \ + libjpeg-dev libjpeg62-turbo-dev zlib1g-dev \ + libffi-dev libssl-dev \ + shred coreutils +``` + +`libjpeg-dev` is required for Pillow and jpeglib (DCT steganography). `libffi-dev` is +required for argon2-cffi. + +### 4.2 Create virtual environment + +```bash +sudo -u soosef -i # Switch to the soosef user + +python3 -m venv ~/soosef-env +source ~/soosef-env/bin/activate +pip install --upgrade pip wheel +``` + +### 4.3 Install SooSeF + +**If the Pi has internet access (pre-deployment):** + +```bash +pip install "soosef[web,cli,fieldkit]" +``` + +For hardware killswitch support via GPIO: + +```bash +pip install "soosef[rpi]" +``` + +The `rpi` extra includes `web`, `cli`, `fieldkit`, and `gpiozero`. + +**For airgapped install (no internet on the Pi):** + +On an internet-connected machine with the same architecture (aarch64 for RPi 4): + +```bash +mkdir soosef-wheels +pip download "soosef[rpi]" -d soosef-wheels/ +``` + +Copy the `soosef-wheels/` directory to a USB drive, then on the Pi: + +```bash +pip install --no-index --find-links /media/usb/soosef-wheels/ "soosef[rpi]" +``` + +### 4.4 Verify installation + +```bash +soosef --version +``` + +--- + +## 5. Initial Setup + +### 5.1 Initialize SooSeF + +```bash +soosef init +``` + +This creates the `~/.soosef/` directory structure: + +``` +~/.soosef/ + config.json Unified configuration + identity/ Ed25519 signing keypair (verisoo) + private.pem + public.pem + identity.meta.json + stegasoo/ Stegasoo state + channel.key AES-256-GCM channel key + attestations/ Verisoo attestation log and index + chain/ Hash chain data + auth/ Web UI user database (SQLite) + certs/ Self-signed TLS certificates + fieldkit/ Killswitch, deadman, tamper, USB, geofence state + temp/ Ephemeral upload/processing files + instance/ Flask session data + audit.jsonl Append-only audit trail +``` + +The `identity/` and `auth/` directories are created with mode 0700. + +`soosef init` generates: + +- An Ed25519 identity keypair (for signing attestations) +- A channel key (for steganographic encoding) +- A default `config.json` + +### 5.2 First user setup + +Start the server and create the first admin user through the web UI: + +```bash +soosef serve --host 0.0.0.0 --no-https +``` + +Navigate to `http://:5000` from a device on the same LAN. The web UI will prompt +you to create the first user account. + +After creating the admin account, stop the server (Ctrl+C) and restart with HTTPS +(see Section 6). + +--- + +## 6. Running + +### 6.1 Basic usage + +```bash +# LAN-only, no HTTPS (acceptable if the network is physically isolated) +soosef serve --host 0.0.0.0 --no-https + +# With self-signed HTTPS (recommended) +soosef serve --host 0.0.0.0 + +# Custom port +soosef serve --host 0.0.0.0 --port 8443 +``` + +On first HTTPS start, SooSeF auto-generates a self-signed certificate at +`~/.soosef/certs/cert.pem`. Browsers will show a certificate warning -- this is expected +for self-signed certs. Instruct users to accept the warning or distribute the cert file +to client devices. + +SooSeF uses Waitress (pure Python, no C dependencies) as its production server with 4 +worker threads by default. Adjust with `--workers`. + +### 6.2 systemd service + +Create `/etc/systemd/system/soosef.service`: + +```ini +[Unit] +Description=SooSeF Security Fieldkit +After=network.target + +[Service] +Type=simple +User=soosef +Group=soosef +WorkingDirectory=/home/soosef +Environment="PATH=/home/soosef/soosef-env/bin:/usr/bin" +ExecStart=/home/soosef/soosef-env/bin/soosef serve --host 0.0.0.0 --workers 4 +Restart=on-failure +RestartSec=5 + +# Hardening +NoNewPrivileges=yes +ProtectSystem=strict +ProtectHome=read-only +ReadWritePaths=/home/soosef/.soosef +PrivateTmp=yes + +[Install] +WantedBy=multi-user.target +``` + +Enable and start: + +```bash +sudo systemctl daemon-reload +sudo systemctl enable --now soosef +sudo journalctl -u soosef -f # Watch logs +``` + +Add `--no-https` to `ExecStart` if running on a physically isolated LAN where TLS is +unnecessary. + +--- + +## 7. Configuration + +Configuration lives at `~/.soosef/config.json`. Edit it directly or use the web admin +panel. All fields have sensible defaults -- you only need to set what you want to change. + +| Field | Default | Description | +|---|---|---| +| `host` | `127.0.0.1` | Bind address. Set to `0.0.0.0` for LAN access. | +| `port` | `5000` | TCP port for the web UI. | +| `https_enabled` | `true` | Enable self-signed HTTPS. | +| `auth_enabled` | `true` | Require login. Do not disable this. | +| `max_upload_mb` | `50` | Maximum file upload size in MB. | +| `session_timeout_minutes` | `15` | Idle session expiry. Lower is safer. | +| `login_lockout_attempts` | `5` | Failed logins before lockout. | +| `login_lockout_minutes` | `15` | Lockout duration. | +| `killswitch_enabled` | `false` | Enable software killswitch. | +| `deadman_enabled` | `false` | Enable dead man's switch. | +| `deadman_interval_hours` | `24` | Hours between required check-ins. | +| `deadman_grace_hours` | `2` | Grace period after missed check-in before purge. | +| `deadman_warning_webhook` | `""` | URL to POST a JSON warning when check-in is overdue. Must be a public URL (SSRF protection blocks private IPs). | +| `usb_monitoring_enabled` | `false` | Monitor for unauthorized USB devices. | +| `tamper_monitoring_enabled` | `false` | File integrity monitoring. | +| `chain_enabled` | `true` | Wrap attestations in a hash chain. | +| `chain_auto_wrap` | `true` | Automatically chain verisoo attestations. | +| `backup_reminder_days` | `7` | Warn if no backup in this many days. | +| `gpio_killswitch_pin` | `17` | GPIO pin for hardware killswitch button. | +| `gpio_killswitch_hold_seconds` | `5.0` | Required hold time to trigger hardware killswitch. | + +Example minimal config for a field deployment: + +```json +{ + "host": "0.0.0.0", + "port": 5000, + "https_enabled": true, + "session_timeout_minutes": 10, + "deadman_enabled": true, + "deadman_interval_hours": 12, + "deadman_grace_hours": 1, + "killswitch_enabled": true, + "backup_reminder_days": 3 +} +``` + +--- + +## 8. Fieldkit Setup + +### 8.1 Dead man's switch + +The dead man's switch requires periodic check-ins. If you miss a check-in, SooSeF sends +a warning during the grace period. If the grace period expires without a check-in, the +killswitch fires automatically and destroys all key material and data. + +Arm it: + +```bash +soosef fieldkit deadman arm --interval 12 --grace 1 +``` + +This requires a check-in every 12 hours, with a 1-hour grace period. + +Check in: + +```bash +soosef fieldkit checkin +``` + +You can also check in through the web UI at `/fieldkit`. + +Check status: + +```bash +soosef status +``` + +The dead man's switch enforcement loop runs as a background thread inside `soosef serve`, +checking every 60 seconds. It will send a webhook warning (if configured) during the grace +period, then execute a full purge if the grace period expires. + +Disarm: + +```bash +soosef fieldkit deadman disarm +``` + +### 8.2 Geofence + +If you have a USB GPS module, you can set a geographic boundary. SooSeF will trigger the +killswitch if the device moves outside the fence. + +```bash +soosef fieldkit geofence set --lat 50.4501 --lon 30.5234 --radius 5000 +``` + +Coordinates are in decimal degrees, radius in meters. + +### 8.3 USB whitelist + +Record currently connected USB devices as the trusted baseline: + +```bash +soosef fieldkit usb learn +``` + +When monitoring is enabled, SooSeF will alert (or trigger killswitch, depending on config) +if an unknown USB device is connected. + +### 8.4 Tamper baseline + +Record file integrity baselines for critical files: + +```bash +soosef fieldkit tamper baseline +``` + +SooSeF monitors for unexpected changes to tracked files when tamper monitoring is enabled. + +--- + +## 9. Key Management + +SooSeF manages two separate key domains: + +- **Ed25519 identity key** (`~/.soosef/identity/`) -- used for signing attestations. + This is your provenance identity. +- **AES-256-GCM channel key** (`~/.soosef/stegasoo/channel.key`) -- used for + steganographic encoding/decoding. Shared with anyone who needs to read your + stego messages. + +These are separate security concerns and are never merged. + +### 9.1 Backup + +Back up keys regularly. SooSeF warns if no backup has been taken within the +`backup_reminder_days` window (default: 7 days). + +```bash +soosef keys backup --output /media/usb/soosef-backup.enc +``` + +This creates an encrypted bundle. You will be prompted for a passphrase. Store the USB +drive physically separate from the Pi. + +### 9.2 Restore + +```bash +soosef keys restore --input /media/usb/soosef-backup.enc +``` + +### 9.3 Key rotation + +Generate a new channel key (the old one is overwritten): + +```bash +soosef init --no-identity +``` + +Generate a new identity (the old one is overwritten -- all previous attestations will +reference the old fingerprint): + +```bash +soosef init --no-channel +``` + +After rotating keys, take a fresh backup immediately. + +### 9.4 Trusting collaborator keys + +Import a collaborator's public key so you can verify their attestations: + +```bash +soosef keys trust --import /media/usb/collaborator-pubkey.pem +``` + +Verify the fingerprint out-of-band (in person, over a secure channel) before trusting. + +--- + +## 10. Operational Security Notes + +SooSeF is a tool, not a shield. Understand what it cannot do. + +### What SooSeF does not protect against + +- **Physical coercion.** If someone forces you to unlock the device or reveal passwords, + no software can help. The killswitch is for situations where you can act before + interception, not during. +- **Social engineering.** SooSeF cannot prevent users from being tricked into revealing + credentials or disabling security features. +- **Leaving the browser open.** The session timeout helps, but if someone walks up to an + unlocked browser session, they have access. Train users to close the browser or lock the + screen. +- **Compromised client devices.** SooSeF secures the server. If a user's laptop has + malware, their browser session is compromised regardless of what the server does. + +### Shred limitations on flash storage + +The killswitch uses `shred` on Linux (3-pass overwrite + zero). On spinning disks, this +is effective. On SD cards and SSDs, **it is not reliable** because: + +- Flash translation layers remap physical blocks. Overwritten data may persist on + remapped blocks. +- Wear leveling distributes writes across the flash, meaning the original block may be + preserved. + +SooSeF's defense against this is **cryptographic erasure**: destroy the keys first, then +the data. Even if fragments of encrypted data survive on flash, they are useless without +the keys. The killswitch destroys keys before anything else, and keys are small enough to +fit in a single flash block. + +This is why full-disk encryption matters -- see below. + +### Full-disk encryption (LUKS) + +For serious deployments, encrypt the entire SD card (or at least the data partition) with +LUKS. This way, even if the SD card is physically seized: + +- All data at rest is encrypted +- Shred limitations are irrelevant because the underlying storage is encrypted +- Power-off = data inaccessible (assuming the LUKS passphrase is strong) + +Setting up LUKS on Raspberry Pi OS is beyond the scope of this guide, but the short +version is: create an encrypted partition, mount it at `/home/soosef/.soosef`, and +configure auto-unlock via a keyfile on a separate USB (remove the USB after boot in +hostile environments). + +### Memory considerations + +Python does not securely zero memory. Key material, passwords, and plaintext may persist +in process memory and swap. The mitigations in Section 3 (disable swap, disable core +dumps) reduce the window, but a memory dump of the running process would expose secrets. +This is a fundamental limitation of Python-based security tools. + +--- + +## 11. Troubleshooting + +### Health check + +SooSeF exposes a `/health` endpoint on the web UI. Hit it from the LAN to verify the +server is running: + +```bash +curl -k https://:5000/health +``` + +The `-k` flag skips certificate verification for self-signed certs. + +### System status + +```bash +soosef status +``` + +This checks identity key, channel key, trusted keys, dead man's switch state, geofence, +chain status, and backup status. + +### Common issues + +**scipy fails to build on Raspberry Pi** + +scipy requires Fortran and BLAS libraries. On Raspberry Pi OS: + +```bash +sudo apt install -y gfortran libopenblas-dev +``` + +If the build still fails (common on low-memory Pis), increase swap temporarily during +install, then disable it again: + +```bash +sudo dphys-swapfile swapon +pip install scipy +sudo dphys-swapfile swapoff +``` + +Or use pre-built wheels: + +```bash +pip install --prefer-binary scipy +``` + +**Argon2 OOM on low-memory Pi (2 GB)** + +Argon2 password hashing is memory-intensive by design. If the server crashes during login +on a 2 GB Pi with other services running, either: + +- Free memory by disabling unnecessary services +- Reduce Argon2 memory cost (not recommended -- weakens password hashing) + +The default Argon2 parameters use ~64 MB per hash operation. With 2 GB total RAM and a +running server, this is tight but workable if nothing else is competing for memory. + +**Web UI unreachable from LAN** + +1. Check that `host` is set to `0.0.0.0` in config, not `127.0.0.1` +2. Check firewall: `sudo ufw status` -- port 5000 must be allowed +3. Check the service is running: `sudo systemctl status soosef` +4. Check the Pi's IP: `ip addr show` + +**Certificate warnings in browser** + +Expected with self-signed certificates. Users must click through the warning. To avoid +this, distribute `~/.soosef/certs/cert.pem` to client devices and install it as a +trusted certificate. + +**Dead man's switch fires unexpectedly** + +The switch checks every 60 seconds. If the Pi loses power or the service crashes and +does not restart within `interval_hours + grace_hours`, the switch will fire on the next +start. Make sure the systemd service is set to `Restart=on-failure` and the Pi has +reliable power. + +If you need to perform maintenance, disarm the switch first: + +```bash +soosef fieldkit deadman disarm +``` + +Re-arm when maintenance is complete. + +**Permission errors on ~/.soosef/** + +The `identity/`, `auth/`, and `certs/` directories are mode 0700. If running under a +different user than the one who ran `soosef init`, you will get permission denied errors. +Always run SooSeF as the same user. + +```bash +ls -la ~/.soosef/ +```