diff --git a/PLAN-4.1.0.md b/PLAN-4.1.0.md deleted file mode 100644 index 8bde36b..0000000 --- a/PLAN-4.1.0.md +++ /dev/null @@ -1,538 +0,0 @@ -# Stegasoo 4.1.0 Plan - -## Overview - -Version 4.1.0 is a feature release focusing on small-group deployment improvements and new utilities. - -## Goals - -1. ~~**Multi-User Support** - Admin can create up to 16 users for shared deployments~~ ✅ DONE -2. **Channel Key QR** - Easy visual sharing of channel keys via QR codes -3. ~~**CLI Channel Commands** - Manage channel keys from command line~~ ✅ DONE -4. **Advanced Tools** - Image/stego utilities (TBD) - ---- - -## Feature 1: Multi-User Support ✅ COMPLETED - -> Implemented in commit 7b33501. All requirements met. - -### Requirements - -- 16 users + 1 admin maximum (17 total) -- First user created at setup is always admin -- Admin can add/delete users, reset passwords -- Regular users can only change their own password -- No self-registration (admin-invite only) - -### Database Changes - -**Update User model in `frontends/web/models.py`:** - -```python -class User(db.Model): - id = Column(Integer, primary_key=True) - username = Column(String(80), unique=True, nullable=False) - password_hash = Column(String(255), nullable=False) - role = Column(String(20), default='user') # 'admin' or 'user' - created_at = Column(DateTime, default=datetime.utcnow) -``` - -**Migration:** Add `role` and `created_at` columns. Existing users get `role='admin'`. - -### New Routes - -| Route | Method | Access | Description | -|-------|--------|--------|-------------| -| `/admin/users` | GET | admin | List all users | -| `/admin/users/new` | GET, POST | admin | Create user form | -| `/admin/users//delete` | POST | admin | Delete user | -| `/admin/users//reset-password` | POST | admin | Generate temp password | - -### New Decorator - -```python -# auth.py -def admin_required(f): - @wraps(f) - def decorated(*args, **kwargs): - if not current_user.is_authenticated: - return redirect(url_for('login')) - if current_user.role != 'admin': - flash('Admin access required', 'error') - return redirect(url_for('index')) - return f(*args, **kwargs) - return decorated -``` - -### UI Changes - -**Navigation (for admin users):** -- Add "Users" link in navbar (visible only to admin) - -**Account page (`/account`):** -- Admin sees link to user management -- All users see their own password change form - -**New template: `templates/admin/users.html`:** -- Table: Username | Role | Created | Actions -- Actions: Reset Password, Delete (disabled for self) -- "Add User" button (disabled if at 16 user limit) -- Show count: "3 of 16 users" - -**New template: `templates/admin/user_new.html`:** -- Username field (email-style allowed) -- Password field (auto-populated with random 8-char, admin can override) -- Submit → confirmation page shows password once with copy button - -### Validation - -- Username: 3-80 chars, alphanumeric + underscore/hyphen + @/. for email-style -- Password: 8+ chars (same as current) -- Can't delete yourself -- Can't demote the last admin -- Deleting user immediately invalidates their sessions - ---- - -## Feature 2: Channel Key QR - -### Web UI - -**About page additions:** - -If `STEGASOO_CHANNEL_KEY` environment variable is set: - -``` -┌─────────────────────────────────────────┐ -│ Channel Key │ -│ │ -│ ██████████████ Your server uses a │ -│ ██ ██ private channel key. │ -│ ██ ██████ ██ Share this QR with │ -│ ██ ██████ ██ others to join. │ -│ ██ ██ │ -│ ██████████████ [Copy Key] [Download]│ -│ │ -│ Key: abc123...xyz │ -└─────────────────────────────────────────┘ -``` - -- QR generated server-side using `qrcode` library -- "Copy Key" copies text to clipboard -- "Download QR" saves as PNG - -**Implementation:** - -```python -# about route addition -@app.route('/about') -def about(): - channel_key = os.environ.get('STEGASOO_CHANNEL_KEY', '') - channel_qr_b64 = None - if channel_key: - # Generate QR as base64 PNG - qr = qrcode.make(channel_key) - buffer = BytesIO() - qr.save(buffer, format='PNG') - channel_qr_b64 = base64.b64encode(buffer.getvalue()).decode() - return render_template('about.html', - channel_key=channel_key, - channel_qr=channel_qr_b64) -``` - -### CLI Commands - -**New command group: `stegasoo channel`** - -```bash -# Generate a new channel key -stegasoo channel generate -# Output: -# Channel Key: stg_abc123...xyz789 -# -# ██████████████████ -# ██ ██ -# ██ ██████████ ██ -# ... -# -# Set in environment: export STEGASOO_CHANNEL_KEY="stg_abc123..." - -# Show current key (from env or argument) -stegasoo channel show -# Output: -# Channel Key: stg_abc123...xyz789 - -# Display QR in terminal (ASCII) -stegasoo channel qr -# Output: ASCII QR code - -# Save QR as PNG -stegasoo channel qr -o channel-key.png -# Output: Saved to channel-key.png - -# Explicit format selection -stegasoo channel qr --format ascii # Terminal (default) -stegasoo channel qr --format png -o - # PNG to stdout -``` - -**Implementation notes:** - -- Use `qrcode[pil]` for PNG output -- Use `qrcode` with `print_ascii()` for terminal -- Read key from `--key` argument or `STEGASOO_CHANNEL_KEY` env var -- `generate` uses existing `generate_channel_key()` from `stegasoo.channel` - ---- - -## File Changes Summary - -### New Files - -| File | Description | -|------|-------------| -| `frontends/web/templates/admin/users.html` | User management page | -| `frontends/web/templates/admin/user_new.html` | Add user form | - -### Modified Files - -| File | Changes | -|------|---------| -| `frontends/web/models.py` | Add `role`, `created_at` to User | -| `frontends/web/auth.py` | Add `@admin_required`, user management routes | -| `frontends/web/templates/base.html` | Add Users link for admins | -| `frontends/web/templates/account.html` | Add admin link | -| `frontends/web/templates/about.html` | Add channel key QR section | -| `src/stegasoo/cli.py` | Add `channel` command group | - ---- - -## Testing Plan - -### Multi-User - -1. Fresh install → first user is admin -2. Admin can create users up to limit (16) -3. Admin can't create 17th user (shows error) -4. Regular user can log in, encode/decode -5. Regular user can't access `/admin/users` -6. Admin can reset user password -7. Admin can delete user -8. Admin can't delete self -9. Existing 4.0.2 databases upgrade correctly (single user becomes admin) - -### Channel Key QR - -1. About page shows nothing if no channel key -2. About page shows QR + key if channel key set -3. Copy button works -4. Download gives valid PNG -5. QR scans correctly to key value - -### CLI - -1. `channel generate` creates valid key + shows QR -2. `channel show` displays current key -3. `channel qr` outputs ASCII to terminal -4. `channel qr -o file.png` saves PNG -5. Commands work with `--key` override -6. Commands read from env var - ---- - -## Feature 3: Advanced Tools - -### Included Tools - -| Tool | Web | CLI | Description | -|------|-----|-----|-------------| -| **Capacity Calculator** | ✓ | ✓ | Upload image → show DCT/LSB capacity | -| **Metadata Stripper** | ✓ | ✓ | Remove EXIF/metadata from image | -| **Stego Detector** | ✓ | ✓ | Analyze image for signs of hidden data | -| **Image Compare** | ✓ | - | Side-by-side before/after diff | -| **Header Peek** | ✓ | ✓ | Check for Stegasoo header without decrypting | -| **Batch Mode** | - | ✓ | Encode/decode multiple files | - -### Web UI: `/tools` Page - -New page with card-based layout: - -``` -┌─────────────────────────────────────────────────────────────┐ -│ 🛠️ Advanced Tools │ -├─────────────────────────────────────────────────────────────┤ -│ │ -│ ┌─────────────────┐ ┌─────────────────┐ │ -│ │ 📏 Capacity │ │ 🧹 Metadata │ │ -│ │ Calculator │ │ Stripper │ │ -│ │ │ │ │ │ -│ │ Check how much │ │ Remove EXIF │ │ -│ │ data fits │ │ before encoding │ │ -│ └─────────────────┘ └─────────────────┘ │ -│ │ -│ ┌─────────────────┐ ┌─────────────────┐ │ -│ │ 🔍 Stego │ │ 🔎 Header │ │ -│ │ Detector │ │ Peek │ │ -│ │ │ │ │ │ -│ │ Analyze image │ │ Check for │ │ -│ │ for hidden data │ │ Stegasoo data │ │ -│ └─────────────────┘ └─────────────────┘ │ -│ │ -│ ┌─────────────────┐ │ -│ │ ⚖️ Image │ │ -│ │ Compare │ │ -│ │ │ │ -│ │ Before/after │ │ -│ │ diff view │ │ -│ └─────────────────┘ │ -│ │ -└─────────────────────────────────────────────────────────────┘ -``` - -Each card opens a modal or expands inline for the tool interface. - -### CLI Structure - -```bash -# Capacity calculator -stegasoo capacity image.jpg -stegasoo capacity image.jpg --format json - -# Metadata stripper -stegasoo strip image.jpg # Output to image_stripped.jpg -stegasoo strip image.jpg -o clean.jpg # Custom output -stegasoo strip image.jpg --in-place # Overwrite original - -# Stego detector -stegasoo detect image.jpg -stegasoo detect image.jpg --verbose # Detailed analysis - -# Header peek -stegasoo peek image.jpg -# Output: "Stegasoo DCT header detected" or "No Stegasoo header found" - -# Batch mode -stegasoo encode --batch manifest.json # JSON with files + credentials -stegasoo decode --batch input_dir/ --out output_dir/ -``` - -### Tool Details - -#### Capacity Calculator -- Input: Image file -- Output: Dimensions, megapixels, DCT capacity, LSB capacity -- Web: Upload zone + results panel -- CLI: Table or JSON output - -#### Metadata Stripper -- Input: Image file -- Output: Clean image (EXIF/metadata removed) -- Show what was removed (camera model, GPS, etc.) -- Preserve image quality - -#### Stego Detector -- Input: Image file -- Analysis: - - Chi-square analysis (LSB detection) - - DCT coefficient histogram analysis - - Visual inspection hints -- Output: Likelihood score + findings -- Note: Detection is probabilistic, not definitive - -#### Image Compare -- Input: Two images (original + stego) -- Output: - - Side-by-side view - - Difference overlay (amplified) - - Pixel-level stats (PSNR, SSIM) -- Web only (visual tool) - -#### Header Peek -- Input: Image file -- Output: Header found (yes/no), mode (DCT/LSB), embedded size estimate -- Does NOT decrypt - just checks for valid header structure -- Useful for "is this a stego image?" without credentials - -#### Batch Mode -- CLI only -- Manifest file (JSON) or directory-based -- Progress bar for multiple files -- Error handling per-file (continue on failure) - ---- - -## Migration Notes - -### Database Migration - -For existing 4.0.2 installations: - -```python -# migrations/add_user_role.py -def upgrade(): - # Add columns with defaults - op.add_column('user', sa.Column('role', sa.String(20), default='user')) - op.add_column('user', sa.Column('created_at', sa.DateTime)) - - # Set existing users as admin (they were the first user) - op.execute("UPDATE user SET role = 'admin' WHERE role IS NULL") - op.execute("UPDATE user SET created_at = datetime('now') WHERE created_at IS NULL") -``` - -Or simpler: detect on startup, update schema automatically (current pattern). - ---- - -## Out of Scope - -- Per-user channel keys -- User groups/teams -- API authentication tokens -- User activity logging -- Password complexity rules beyond length - ---- - -## Estimated Effort - -| Component | Complexity | -|-----------|------------| -| Database schema change | Low | -| Admin routes + templates | Medium | -| Access control decorator | Low | -| About page QR | Low | -| CLI channel commands | Medium | -| Advanced Tools (TBD) | Medium-High | -| Testing | Medium | - ---- - -## Decisions - -1. **Temp password flow:** Password field auto-populates with random 8-char password. Admin can override if desired. Show password once on confirmation page. - -2. **Session handling:** Yes - deleting a user immediately invalidates their active sessions (ban hammer). - -3. **Username rules:** Sane requirements, email-style allowed. Validation: 3-80 chars, alphanumeric, underscore, hyphen, @ and . for email-style. - ---- - -## Approval - -- [x] Plan reviewed -- [x] Questions resolved -- [x] Ready to implement - -## Progress - -- [x] Multi-User Support (commit 7b33501) -- [x] Channel Key QR (Web UI) - added QR generator on About page -- [x] CLI Channel Commands -- [x] Saved Channel Keys (Web UI) - users can save/manage channel keys -- [x] Advanced Tools - Image Security Toolkit - - [x] CLI: `stegasoo tools capacity/strip/peek/exif` - - [x] API: `/api/tools/capacity`, `/api/tools/peek`, `/api/tools/exif/*` - - [x] WebUI: Tools page with tabbed interface - - [x] EXIF Editor with inline editing, clear all, save/download - ---- - -## Architectural Improvements (4.1.0) - -### Consolidated Channel Key Resolution - -Moved `resolve_channel_key()` from 3 duplicate implementations to single source of truth in `src/stegasoo/channel.py`: - -```python -# Library: src/stegasoo/channel.py -def resolve_channel_key(value, *, file_path=None, no_channel=False) -> str | None: - """Unified channel key resolution - returns None (auto), "" (public), or key.""" - -def get_channel_response_info(channel_key) -> dict: - """Get channel info dict for API/WebUI responses.""" -``` - -Frontends now use thin wrappers that translate exceptions to their context (Click/HTTP). - -### DCT Payload Pre-Check - -Added `will_fit_by_mode()` pre-check to WebUI encode to fail fast with helpful error message instead of cryptic exception deep in DCT processing. - -### EXIF Tools (Library Layer) - -Added to `src/stegasoo/utils.py`: -- `read_image_exif(image_data)` - Read EXIF metadata as dict -- `write_image_exif(image_data, updates)` - Update EXIF fields (JPEG only) - -Dependencies added: `piexif>=1.1.0` - ---- - -## Action Item: Architectural Review ✅ DONE - -Reviewed modules for consistency with Library → CLI → API → WebUI pattern: - -| Module | Library | CLI | API | WebUI | Status | -|--------|---------|-----|-----|-------|--------| -| encode | ✓ | ✓ | ✓ | ✓ | Consistent | -| decode | ✓ | ✓ | ✓ | ✓ | Consistent | -| channel | ✓ | ✓ | ✓ | ✓ | Consolidated resolve_channel_key | -| tools | ✓ | ✓ | ✓ | ✓ | Complete | -| generate | ✓ | ✓ | - | ✓ | CLI has `stegasoo generate` | - -Priority order: Developer/CLI → API integrator → WebUI end-user - ---- - -## Admin Recovery System (4.1.0) ✅ DONE - -Password reset capability for locked-out admins with multiple backup options. - -### Library Layer (`src/stegasoo/recovery.py`) - -```python -# Key generation and validation -generate_recovery_key() -> str # XXXX-XXXX-XXXX-... (32 chars) -hash_recovery_key(key) -> str # SHA-256 for storage -verify_recovery_key(key, hash) -> bool - -# QR code (obfuscated - scans as gibberish) -obfuscate_key(key) -> str # XOR with RECOVERY_OBFUSCATION_KEY -deobfuscate_key(data) -> str | None -generate_recovery_qr(key) -> bytes # PNG with obfuscated data -extract_key_from_qr(image) -> str | None - -# Stego backup (hide key in an image) -create_stego_backup(key, carrier_image) -> bytes -extract_stego_backup(stego_image, reference) -> str | None -``` - -### Database (`app_settings` table) - -- `recovery_key_hash` - SHA-256 of recovery key (or null if disabled) - -### Web Routes - -| Route | Method | Description | -|-------|--------|-------------| -| `/setup/recovery` | GET, POST | Step 2 of initial setup | -| `/recover` | GET, POST | Password reset page | -| `/recover/stego` | POST | Extract key from stego backup | -| `/account/recovery/regenerate` | GET, POST | Generate new key | -| `/account/recovery/disable` | POST | Remove recovery option | -| `/account/recovery/stego-backup` | POST | Create stego backup | - -### CLI Commands - -```bash -stegasoo admin recover --db path/to/stegasoo.db # Reset password -stegasoo admin generate-key [--qr] # Generate key (reference) -``` - -### Security Model - -1. Recovery key shown once during setup - only hash stored -2. QR codes XOR'd with `RECOVERY_OBFUSCATION_KEY` (fixed in constants.py) -3. Stego backups use fixed internal passphrase/PIN - security is obscurity -4. Instance-bound: recovery key hash must match in target database -5. Options: text file, QR image, stego image, or no recovery (most secure) diff --git a/PLAN-4.1.2.md b/PLAN-4.1.2.md deleted file mode 100644 index dbf7110..0000000 --- a/PLAN-4.1.2.md +++ /dev/null @@ -1,250 +0,0 @@ -# Stegasoo 4.1.2 Plan - -## Release Theme -Polish and UX improvements after the 4.1.1 stability release. - ---- - -## 1. Real Progress Bar for Encode/Decode - -**Status:** Done - -**Problem:** Users see elapsed time but no indication of how far along the operation is. Long DCT encodes on Pi can take 2-3 minutes with no feedback. - -**Solution:** Polling + progress file approach - -### Backend Changes - -1. **dct_steganography.py** - Write progress during block loop: - ```python - if progress_file and block_num % 50 == 0: - with open(progress_file, 'w') as f: - json.dump({"current": block_num, "total": total_blocks, "phase": "embedding"}, f) - ``` - -2. **app.py** - New endpoints: - - `POST /encode` returns `job_id`, starts subprocess - - `GET /encode/progress/` returns progress JSON - - `GET /encode/result/` returns final result when done - -3. **Subprocess wrapper** - Pass progress file path to encode/decode functions - -### Frontend Changes - -1. **stegasoo.js** - After form submit: - - Show progress bar (Bootstrap progress component) - - Poll `/encode/progress/{job_id}` every 500ms - - Update bar width and percentage text - - Show phase (hashing, embedding, encoding, etc.) - -2. **Templates** - Add progress bar markup to encode.html and decode.html - -### Files to Modify -- `src/stegasoo/dct_steganography.py` -- `frontends/web/app.py` -- `frontends/web/static/js/stegasoo.js` -- `frontends/web/templates/encode.html` -- `frontends/web/templates/decode.html` - ---- - -## 2. Granular Decode Error Messages - -**Status:** Done - -**Problem:** Decode failures show generic "Decryption failed" - users don't know if it's wrong photo, wrong passphrase, wrong PIN, corrupted image, or format mismatch. - -**Solution:** Bubble up specific error types from library to UI - -### Implementation -- Added new exceptions: InvalidMagicBytesError, ReedSolomonError, NoDataFoundError, ModeMismatchError -- DCT decode now raises InvalidMagicBytesError for wrong magic bytes -- DCT decode now raises ReedSolomonError (renamed from reedsolo's) for corruption -- app.py catches specific exceptions with user-friendly messages: - - Invalid magic → "Try a different mode (LSB/DCT)" - - RS error → "Image too corrupted, may have been re-saved" - - Invalid header → "Image may have been modified" - - Decryption error → "Wrong credentials" - -### Files Modified -- `src/stegasoo/exceptions.py` (new exceptions) -- `src/stegasoo/__init__.py` (exports) -- `src/stegasoo/dct_steganography.py` (raise specific exceptions) -- `frontends/web/app.py` (catch and display) - ---- - -## 3. Mobile-Responsive Polish - -**Status:** Done - -**Problem:** UI works on mobile but has rough edges - cramped buttons, hard-to-tap targets, awkward layouts on small screens. - -**Solution:** Targeted CSS/layout fixes for mobile breakpoints - -### Areas to Improve - -1. **Encode/Decode Forms:** - - Stack image drop zones vertically on mobile (currently side-by-side) - - Larger touch targets for file inputs - - Full-width buttons on small screens - - Passphrase input readable at smaller sizes - -2. **Navigation:** - - Hamburger menu for mobile navbar (if not already) - - Sticky header doesn't eat too much screen - - Easy thumb reach for main actions - -3. **Results/Output:** - - Download buttons full-width on mobile - - QR codes sized appropriately - - Click-to-copy message box works well with touch - -4. **Drop Zones:** - - Larger tap targets - - Visual feedback for touch (not just hover) - - Camera integration hint on mobile ("Tap to take photo or choose file") - -### Testing Targets -- iPhone SE (small) -- iPhone 14 (medium) -- iPad (tablet) -- Android Chrome - -### Files to Modify -- `frontends/web/static/css/style.css` (or new mobile.css) -- `frontends/web/templates/encode.html` -- `frontends/web/templates/decode.html` -- `frontends/web/templates/base.html` (navbar) - ---- - -## Testing Checklist - -- [ ] Progress bar works on localhost -- [ ] Progress bar works on Pi (slower, more visible) -- [ ] Cancellation handling (what if user navigates away?) -- [ ] Error states display correctly -- [ ] Smoke test passes - ---- - -## 4. Forced First-Login Setup - -**Status:** Done - -**Problem:** Users can navigate the app without creating an admin account first. Should force password setup before anything else. - -**Solution:** Middleware/decorator that redirects to setup page if no users exist. - -### Implementation -- Added `@app.before_request` hook that redirects to /setup if no users exist -- Skips redirect for static files and setup-related routes - -### Files Modified -- `frontends/web/app.py` (added require_setup before_request hook) - ---- - -## 5. Dropzone UX Fixes - -**Status:** Done - -**Problem:** Dropzone has some interaction bugs: -- Dropzone doesn't clear properly if first QR image fails -- Can't click on image preview to replace file (have to click surrounding border) - -**Solution:** Fix JS event handling and state management - -### Implementation -- Added click handler on preview images to trigger file input -- Made entire drop zone clickable (not just label) -- QR zone now resets after 2 seconds on error, allowing retry -- Clear file input on QR error so same file can be re-selected - -### Files Modified -- `frontends/web/static/js/stegasoo.js` - ---- - -## 6. Smoke Test Benchmarking - -**Status:** Done - -**Problem:** No way to measure encode/decode performance or track regressions. - -**Solution:** Add timing to smoke tests using `hyperfine` or `time`. - -### Implementation -- Added `--benchmark` flag to run encode/decode benchmarks after tests -- Added `--runs=N` flag to customize number of benchmark runs (default: 5) -- Uses hyperfine if available for precise timing with warmup -- Falls back to manual timing with bc if hyperfine not installed -- Outputs min/max/avg stats for both encode and decode operations - -### Files Modified -- `tests/smoke-test.sh` - ---- - -## 7. Docker Cleanup - -**Status:** Done (4.1.1) - -**Problem:** Docker build context is larger than needed (includes test images, rpi scripts, etc.) - -**Solution:** Added `.dockerignore` and fixed volume permissions in Dockerfile - -### Files Modified -- `.dockerignore` (created) -- `Dockerfile` (instance dir permissions) - ---- - -## 8. Release Validation Script - -**Status:** Done - -**Problem:** Manual release checklist is error-prone. Need automated validation. - -**Solution:** Script that runs through testable checklist items - -### Features -- Run pytest -- Build and test Docker image -- SSH to Pi and run smoke test (optional, if PI_IP provided) -- Report pass/fail summary - -### Files to Create -- `scripts/validate-release.sh` - ---- - -## 9. Smoke Test Docker Support - -**Status:** Done - -**Problem:** Smoke test expects systemd service, doesn't auto-create admin for Docker. - -**Solution:** Make smoke test Docker-aware - -### Features -- Skip systemd checks if not on Pi/Linux with systemd -- Auto-detect fresh Docker (no users) and create admin via /setup -- Add `--docker` flag to skip Pi-specific checks - -### Implementation -- Added `--docker` flag that sets localhost and skips SSH/systemd checks -- Docker health check verifies container responds with HTTP 200/302 -- Header shows "Docker Smoke Test" in Docker mode - -### Files Modified -- `rpi/smoke-test.sh` - ---- - -## Notes - -- Keep 4.1.2 focused - 9 features (9 done) -- Don't break DCT compatibility (4.1.1 RS format is stable) -- Test on Pi before release diff --git a/PLAN-4.1.3.md b/PLAN-4.1.3.md deleted file mode 100644 index 3cad59c..0000000 --- a/PLAN-4.1.3.md +++ /dev/null @@ -1,42 +0,0 @@ -# Stegasoo 4.1.3 Plan - -## Release Theme -Performance and admin features. - ---- - -## 1. DCT Performance Optimizations - -**Status:** Planned - -**Problem:** DCT encode/decode can be slow on Pi, especially for large images. - -**Ideas:** -- Vectorize block processing with NumPy -- Reduce Python loop overhead -- Parallel block processing (multiprocessing?) -- Profile and identify bottlenecks -- Consider Cython for hot paths - ---- - -## 2. User Management UI - -**Status:** Planned - -**Problem:** No way for admin to manage users via UI. Currently need direct DB access. - -**Features:** -- List all users -- Create new user (admin only) -- Delete user (admin only) -- Reset user password -- User activity/last login - ---- - -## Notes - -- These are heavier lifts than 4.1.2 -- Profile before optimizing -- Consider security implications of user management diff --git a/PLAN-4.1.4.md b/PLAN-4.1.4.md deleted file mode 100644 index 1bcf85d..0000000 --- a/PLAN-4.1.4.md +++ /dev/null @@ -1,165 +0,0 @@ -# Stegasoo 4.1.4 Plan - -## Build / Deploy -- [x] Pre-built Python 3.12 venv tarball for Pi (skip 20+ min compile) - see details below -- [x] Fixed partition sizing in flash script (16GB rootfs for faster imaging) -- [x] Rename `flash-pi.sh` → `flash-stock-img.sh` for clarity -- [x] pip-audit integration in release validation - -### Pi venv Tarball Approach -1. Flash fresh Pi image, let it fully build (20+ min compile) -2. Once running and working, SSH in and create optimized tarball: - ```bash - cd /opt/stegasoo - # Strip caches and tests (295MB → 208MB) - find venv/ -type d -name '__pycache__' -exec rm -rf {} + 2>/dev/null - find venv/ -type d -name 'tests' -exec rm -rf {} + 2>/dev/null - find venv/ -type d -name 'test' -exec rm -rf {} + 2>/dev/null - # Compress with zstd (208MB → 39MB) - tar -cf - venv/ | zstd -19 -T0 > /tmp/stegasoo-venv-pi-arm64.tar.zst - ``` -3. Pull tarball to host: `scp admin@pi:/tmp/stegasoo-venv-pi-arm64.tar.zst rpi/` -4. setup.sh auto-detects and extracts tarball if present in rpi/ -5. Re-flash and test fresh build with pre-built venv (should be <2 min vs 20+) - -## Features -- [x] QR channel key sharing (see detailed plan below) -- [ ] Role-based permissions: admin / mod / user -- [x] `stegasoo info` fastfetch-style command (version, service status, channel, CPU, temp, etc.) -- [ ] Better capacity estimates / pre-flight check before encode fails - ---- - -## QR Channel Key Sharing - Implementation Plan - -### Current State -- ✅ **CLI**: `stegasoo channel qr` generates ASCII/PNG QR for server channel key -- ✅ **Web UI (about.html)**: Client-side QR generator exists - input key, generate/show QR, download PNG -- ✅ **Account page**: Shows saved channel keys with fingerprint, rename, delete -- ❌ No role restrictions on QR sharing -- ❌ No QR button for saved keys on account page -- ❌ No QR scanning to import keys - -### Design Decisions - -**UI Placement** (avoiding encode/decode page crowding): -- Keep QR generator in **about.html** (already exists, logical place for tools) -- Add QR button to **account.html** saved keys (small icon, doesn't crowd) -- Both should be admin-only - -**Role Restriction** (per user request): -- QR sharing = admin only (hide generator + saved key QR buttons from non-admins) -- Prerequisite: Need role-based permissions feature first -- Interim option: Just hide from non-admin users using existing `is_admin` flag - -### Implementation Steps - -#### Phase 1: Admin-only restriction (quick win) -1. **about.html**: Wrap QR generator section in `{% if is_admin %}` block -2. **Account route**: Pass `is_admin` to template (if not already) -3. **account.html**: Add small QR icon button to saved keys row (admin only) - - Opens modal with QR canvas (reuse qrcode.js pattern from about.html) - - Download PNG button in modal - -#### Phase 2: QR Import (optional enhancement) -1. Add "Import via QR" button to account.html key-add section -2. Use device camera or file upload to scan QR -3. Decode and populate channel_key input field -4. Requires `pyzbar` on server OR client-side JS library like `jsQR` - -### Files to Modify - -``` -frontends/web/app.py - - about() route: Add missing vars: is_admin, channel_configured, - channel_fingerprint, channel_source (BUG: currently not passed!) - - account() route: ✅ Already passes is_admin - -frontends/web/templates/about.html - - Wrap channel key QR section in {% if is_admin %} - -frontends/web/templates/account.html - - Add QR button to saved keys (admin only) - - Add QR modal (copy pattern from about.html) - - Include qrcode.min.js CDN script -``` - -### Bug Found During Research -The about.html template uses `channel_configured`, `channel_fingerprint`, -`channel_source` but the route doesn't pass them - always shows "public mode". -Fix this while implementing QR admin restriction. - -### Exact Code Changes - -**app.py - Fix about() route (around line 1564):** -```python -@app.route("/about") -def about(): - from stegasoo.channel import get_channel_status - channel_status = get_channel_status() - - # Check if user is admin (for QR sharing) - current_user = get_current_user() - is_admin = current_user.is_admin if current_user else False - - return render_template( - "about.html", - has_argon2=has_argon2(), - has_qrcode_read=HAS_QRCODE_READ, - # Channel info (bugfix) - channel_configured=channel_status["configured"], - channel_fingerprint=channel_status.get("fingerprint"), - channel_source=channel_status.get("source"), - # Admin check for QR sharing - is_admin=is_admin, - ) -``` - -### Template Changes Preview - -**account.html - Add to saved key row:** -```html -{% if is_admin %} - -{% endif %} -``` - -**about.html - Wrap existing section:** -```html -{% if is_admin %} - -
- ...existing QR generator... -
-{% endif %} -``` - -### Testing Checklist (Phase 1 Implemented) -- [ ] Non-admin users cannot see QR generator in about.html -- [ ] Non-admin users cannot see QR buttons on account page -- [ ] Admin users can generate QR for any saved key -- [ ] QR downloads work correctly -- [ ] QR scans correctly with phone camera - -### Implementation Status -**Phase 1: COMPLETE** - Admin-only QR sharing implemented: -- `app.py`: Fixed about() route to pass channel status + is_admin -- `about.html`: QR generator wrapped in `{% if is_admin %}` with Admin badge -- `account.html`: QR button added to saved keys (admin only), modal + JS for generation/download - ---- - -## Security -- [ ] Optional encryption for temp file storage (paranoid mode, config toggle) - -## Docs -- [x] Update UNDER_THE_HOOD.md (v4.1 changes, channel keys) -- [ ] General docs refresh - -## Ideas (maybe later) -- [ ] Stego detection tool -- [ ] Browser extension -- [ ] Pi snapshot/backup feature diff --git a/PLAN-4.1.5.md b/PLAN-4.1.5.md deleted file mode 100644 index ddccfc2..0000000 --- a/PLAN-4.1.5.md +++ /dev/null @@ -1,147 +0,0 @@ -# Stegasoo 4.1.5 Plan - -## Decode Progress Bar (Real Progress) - -Mirror the encode async pattern for decode operations. - -### Backend Changes - -**1. Add async mode to `/decode` route (`app.py`)** -- Check for `async=true` form param -- Generate job_id, store job, submit to executor -- Return `{"job_id": ..., "status": "pending"}` immediately - -**2. Add decode status/progress endpoints (`app.py`)** -```python -@app.route("/decode/status/") -def decode_status(job_id): - # Return {"status": "pending|running|complete|error", "result": {...}} - -@app.route("/decode/progress/") -def decode_progress(job_id): - # Read from /tmp/stegasoo_progress_{job_id}.json - # Return {"percent": 0-100, "phase": "..."} -``` - -**3. Add `_run_decode_job()` background worker (`app.py`)** -- Similar to `_run_encode_job()` -- Pass `progress_file` param to decode function -- Store result/error in job dict - -**4. Update decode functions to write progress (`lsb_steganography.py`, `dct_steganography.py`)** - -Phases for decode: -- `"starting"` (0%) -- `"reading"` (10%) - reading stego image -- `"extracting"` (30%) - extracting hidden data -- `"decrypting"` (60%) - Argon2 + AES decryption -- `"verifying"` (80%) - HMAC verification -- `"finalizing"` (95%) - preparing output -- `"complete"` (100%) - -### Frontend Changes - -**5. Update decode form submission (`decode.html`)** -- Add async form handler like encode -- Call `Stegasoo.submitDecodeAsync(form, btn)` - -**6. Add decode async methods (`stegasoo.js`)** -```javascript -submitDecodeAsync(form, btn) // POST with async=true, show modal -pollDecodeProgress(jobId) // Poll /decode/status, /decode/progress -``` - -Reuse existing: -- `showProgressModal('Decoding')` -- `updateProgress(percent, phase)` - -**7. Handle decode result redirect** -- On complete: redirect to `/decode/result/{file_id}` or display inline - -### Files to Modify - -``` -frontends/web/app.py - - Add async handling to /decode route (~line 1300+) - - Add /decode/status/ endpoint - - Add /decode/progress/ endpoint - - Add _run_decode_job() function - -frontends/web/static/js/stegasoo.js - - Add submitDecodeAsync() - - Add pollDecodeProgress() - -frontends/web/templates/decode.html - - Update form submit to use async mode - -src/stegasoo/lsb_steganography.py - - Add progress_file param to decode() - - Write progress at each phase - -src/stegasoo/dct_steganography.py - - Add progress_file param to decode() - - Write progress at each phase -``` - -### Testing Checklist - -- [ ] Decode shows progress modal on submit -- [ ] Progress bar animates through phases -- [ ] Successful decode redirects to result -- [ ] Failed decode shows error in modal -- [ ] Works for both LSB and DCT modes -- [ ] Works for message and file payloads -- [ ] Progress file cleaned up after completion - ---- - ---- - -## Browser Webcam QR Scanning - -Add webcam-based QR code scanning for all key input fields. - -### Use Cases -- Import channel key via QR scan on account page -- Scan QR codes instead of typing long keys - -### Implementation - -**1. Add JS QR scanning library** -- Use `jsQR` or `html5-qrcode` (client-side, no server needed) -- Include via CDN in base template - -**2. Add camera button to channel key inputs** -- Account page: "Add Key" field -- Encode/decode pages: channel key selector (if manual input) - -**3. Camera modal component** -- Request camera permission -- Live video preview -- Auto-detect QR and populate input field -- Close modal on successful scan - -### Files to Modify -``` -frontends/web/templates/base.html - Add QR library CDN -frontends/web/templates/account.html - Camera button + modal -frontends/web/static/js/stegasoo.js - QR scan methods -``` - -### Testing Checklist -- [ ] Camera permission prompt works -- [ ] QR detected and input populated -- [ ] Works on mobile browsers -- [ ] Graceful fallback if no camera - ---- - -## Other 4.1.5 Ideas (if time) - -- [ ] Role-based permissions: admin / mod / user -- [ ] Better capacity estimates / pre-flight check -- [ ] Stego detection tool - -## Bugs / Nice to Have - -- [ ] **flash-stock-img.sh 16GB resize not working** - partition still full SD size after flash, makes dd pull slow. Investigate resize2fs/parted logic and test fix. diff --git a/RELEASE-4.1.1.md b/RELEASE-4.1.1.md deleted file mode 100644 index d917158..0000000 --- a/RELEASE-4.1.1.md +++ /dev/null @@ -1,93 +0,0 @@ -# Stegasoo 4.1.1 Release Notes - -**Release Date:** January 5, 2026 - -## Highlights - -- **Reed-Solomon Error Correction** - DCT steganography now includes RS error correction, making encoded images more resilient to minor corruption and compression artifacts -- **Completely Rewritten Pi Setup** - Fresh install tested and validated, works reliably from scratch -- **SSH Login Banner** - See your Stegasoo URL immediately on SSH login - -## New Features - -### Reed-Solomon Error Correction -DCT-encoded images now include Reed-Solomon error correction codes, allowing recovery from minor image corruption. This significantly improves reliability when images are shared through platforms that may slightly modify them. - -### SSH Login Banner (MOTD) -When you SSH into your Stegasoo Pi, you'll now see: -``` - ___ _____ ___ ___ _ ___ ___ ___ - / __||_ _|| __| / __| /_\ / __| / _ \ / _ \ - \__ \ | | | _| | (_ | / _ \ \__ \ | (_) || (_) | - |___/ |_| |___| \___//_/ \_\|___/ \___/ \___/ - - ● Stegasoo is running - https://192.168.0.4 -``` - -### Elapsed Time Counter -Encode/decode buttons now show elapsed time during operations. - -### Click-to-Copy Decoded Message -Click the decoded message box to copy to clipboard (no button needed). - -### Overclock Wizard Option -First-boot wizard now offers optional CPU overclocking for Pi 4/5 with active cooling. - -## Improvements - -### Setup Script (setup.sh) -- Fixed pyenv Python path resolution (handles 3.12 → 3.12.12 mapping) -- Changed default install location to `/opt/stegasoo` -- Fixed jpegio build order (clone stegasoo first, then build jpegio into venv) -- Added python3-dev to dependencies -- Added btop for system monitoring -- Shows `/setup` URL at completion for admin account creation - -### Sanitize Script -- Now clears port 443 iptables redirect (clean slate for wizard) -- Removes overclock settings before imaging - -### Documentation -- Updated all docs to reference `/opt/stegasoo` path -- Added pre-setup steps (chown /opt, install git) -- Added Pi 4 performance baseline (~60s for 10MB JPEG) - -### About Page -- Redesigned "Limits & Specs" section with key stats cards and accordion - -## Bug Fixes - -- Fixed DCT steganography for non-8-aligned images -- Fixed MOTD port detection (was using iptables which requires root) -- Fixed smoke test `--443` flag parsing - -## Performance - -On a Raspberry Pi 4 at 2GHz with USB 3.0 NVMe: -- ~50 seconds to encode a 10MB JPEG -- ~60 seconds to decode a 10MB JPEG -- Full encryption: passphrase + PIN + reference photo - -## Upgrade Notes - -If upgrading from 4.1.0: -```bash -cd /opt/stegasoo # or ~/stegasoo -git pull origin 4.1 -``` - -For fresh installs, see the [Pi README](rpi/README.md). - -## Pre-built Images - -- `stegasoo-rpi-4.1.1_20260105-2.img.zst` - Raspberry Pi 4/5 image - -Flash with: -```bash -zstdcat stegasoo-rpi-4.1.1_20260105-2.img.zst | sudo dd of=/dev/sdX bs=4M status=progress -``` - ---- - -Full changelog: [v4.1.0...v4.1.1](https://github.com/adlee-was-taken/stegasoo/compare/v4.1.0...v4.1.1) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 2bf6219..c33ce15 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,14 +1,41 @@ -## Stegasoo v4.1.3 +## Stegasoo v4.1.5 -### Fixes -- **SSL Certificate Generation**: First-boot wizard now properly generates self-signed certs when HTTPS is enabled -- **Download Bug Fixed**: No more "File expired or not found" errors - fixed multi-worker temp file sharing -- **Docker Build**: Reduced build context from 2.3GB to ~900KB +### Developer Experience +- **Educational Code Comments**: Core modules now include detailed explanations + - DCT: zig-zag coefficient diagrams, QIM embedding math, Reed-Solomon "Voyager" reference + - LSB: visual bit manipulation examples, ChaCha20 pixel selection + - Crypto: multi-factor KDF flow diagrams, Argon2id memory-hardness reasoning + - CLI/Web: architectural patterns for future contributors -### Improvements -- Docker memory limits increased to 2GB (prevents OOM on large DCT operations) -- Decode button now shows loading spinner during processing -- Headless Pi flash script with Trixie/NetworkManager support +### Raspberry Pi Improvements +- **Streamlined Image Creation**: `pull-image.sh` now handles everything + - Auto-resizes rootfs to exactly 16GB (consistent images from any SD card) + - Disables Pi OS auto-expand + - Compresses with zstd + - Optional .zst.zip wrapper for GitHub releases +- **16GB Minimum**: Pre-built images are now 16GB (was variable) +- **Host Requirements**: `rpi/host-requirements.txt` documents all dependencies +- **Test Automation**: `kickoff-pi-test.sh` for one-command flash+test cycles + +### MOTD Polish +- Dynamic temperature emoji (ice/cool/fire based on CPU temp) +- Rocket emoji for service status +- Cleaner formatting + +### Raspberry Pi Image +Download `stegasoo-rpi-4.1.5.img.zst.zip` from Releases. + +```bash +# Flash (auto-detects SD card) +sudo ./rpi/flash-image.sh stegasoo-rpi-4.1.5.img.zst.zip + +# Or manual +zstdcat stegasoo-rpi-4.1.5.img.zst | sudo dd of=/dev/sdX bs=4M status=progress +``` + +Default login: `admin` / `stegasoo` + +First boot runs the setup wizard for WiFi, HTTPS, and channel key configuration. ### Docker ```bash @@ -16,19 +43,5 @@ docker-compose up -d web # Web UI on :5000 docker-compose up -d api # REST API on :8000 ``` -### Raspberry Pi Image -Download `stegasoo-rpi-4.1.3.img.zst`, flash to SD card, and boot. The first-boot wizard will guide you through WiFi, HTTPS, and channel key setup. - -```bash -# Flash with included script -./rpi/flash-image.sh stegasoo-rpi-4.1.3.img.zst /dev/sdX - -# First time: save your WiFi credentials -./rpi/inject-wifi.sh --setup - -# Then inject WiFi after flashing -sudo ./rpi/inject-wifi.sh /dev/sdX -``` - ### Full Changelog -See [CHANGELOG.md](CHANGELOG.md) for complete details. +See [CHANGELOG.md](CHANGELOG.md) for complete version history.