# SooSeF -- Soo Security Fieldkit **Offline-first security toolkit for journalists, NGOs, and at-risk organizations.** ![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) --- ## What is SooSeF? SooSeF combines steganography, provenance attestation, and field security tools into a single package designed for airgapped and resource-constrained environments. It lets you: - **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 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.