From 5c6f86a12c27de8adee591db7092d37a26e45440 Mon Sep 17 00:00:00 2001 From: "Aaron D. Lee" Date: Sat, 27 Dec 2025 23:57:29 -0500 Subject: [PATCH] Now with extra-sloppy frotend reference docs. --- frontends/API.md | 946 ++++++++++++++++++++++++++++++++++++++++++++ frontends/CLI.md | 634 +++++++++++++++++++++++++++++ frontends/WEB_UI.md | 739 ++++++++++++++++++++++++++++++++++ 3 files changed, 2319 insertions(+) create mode 100644 frontends/API.md create mode 100644 frontends/CLI.md create mode 100644 frontends/WEB_UI.md diff --git a/frontends/API.md b/frontends/API.md new file mode 100644 index 0000000..f65beca --- /dev/null +++ b/frontends/API.md @@ -0,0 +1,946 @@ +# Stegasoo REST API Documentation + +Complete REST API reference for Stegasoo steganography operations. + +## Table of Contents + +- [Overview](#overview) +- [Installation](#installation) +- [Authentication](#authentication) +- [Base URL](#base-url) +- [Endpoints](#endpoints) + - [GET /](#get--status) + - [POST /generate](#post-generate) + - [POST /encode](#post-encode-json) + - [POST /encode/multipart](#post-encodemultipart) + - [POST /decode](#post-decode-json) + - [POST /decode/multipart](#post-decodemultipart) + - [POST /image/info](#post-imageinfo) +- [Data Models](#data-models) +- [Error Handling](#error-handling) +- [Code Examples](#code-examples) +- [Rate Limiting](#rate-limiting) +- [Security Considerations](#security-considerations) + +--- + +## Overview + +The Stegasoo REST API provides programmatic access to all steganography operations: + +- **Generate** credentials (phrases, PINs, RSA keys) +- **Encode** messages into images +- **Decode** messages from images +- **Analyze** image capacity + +The API supports both JSON (base64-encoded images) and multipart form data (direct file uploads). + +--- + +## Installation + +### From PyPI + +```bash +pip install stegasoo[api] +``` + +### From Source + +```bash +git clone https://github.com/example/stegasoo.git +cd stegasoo +pip install -e ".[api]" +``` + +### Running the Server + +**Development:** +```bash +cd frontends/api +python main.py +``` + +**Production:** +```bash +cd frontends/api +uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4 +``` + +**Docker:** +```bash +docker-compose up api +``` + +--- + +## Authentication + +The API currently operates without authentication. For production deployments, implement authentication at the reverse proxy level (nginx, Caddy) or add API key middleware. + +--- + +## Base URL + +| Environment | URL | +|-------------|-----| +| Local Development | `http://localhost:8000` | +| Docker | `http://localhost:8000` | +| Production | Configure as needed | + +--- + +## Endpoints + +### GET / (Status) + +Check API status and configuration. + +#### Request + +```http +GET / HTTP/1.1 +Host: localhost:8000 +``` + +#### Response + +```json +{ + "version": "2.0.0", + "has_argon2": true, + "day_names": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] +} +``` + +#### Response Fields + +| Field | Type | Description | +|-------|------|-------------| +| `version` | string | Stegasoo library version | +| `has_argon2` | boolean | Whether Argon2id is available | +| `day_names` | array | Day names for phrase mapping | + +#### cURL Example + +```bash +curl http://localhost:8000/ +``` + +--- + +### POST /generate + +Generate credentials for encoding/decoding. + +#### Request + +```http +POST /generate HTTP/1.1 +Host: localhost:8000 +Content-Type: application/json + +{ + "use_pin": true, + "use_rsa": false, + "pin_length": 6, + "rsa_bits": 2048, + "words_per_phrase": 3 +} +``` + +#### Request Body + +| Field | Type | Default | Description | +|-------|------|---------|-------------| +| `use_pin` | boolean | `true` | Generate a PIN | +| `use_rsa` | boolean | `false` | Generate an RSA key | +| `pin_length` | integer | `6` | PIN length (6-9) | +| `rsa_bits` | integer | `2048` | RSA key size (2048, 3072, 4096) | +| `words_per_phrase` | integer | `3` | Words per phrase (3-12) | + +#### Response + +```json +{ + "phrases": { + "Monday": "abandon ability able", + "Tuesday": "actor actress actual", + "Wednesday": "advice aerobic affair", + "Thursday": "afraid again age", + "Friday": "agree ahead aim", + "Saturday": "airport aisle alarm", + "Sunday": "album alcohol alert" + }, + "pin": "847293", + "rsa_key_pem": null, + "entropy": { + "phrase": 33, + "pin": 19, + "rsa": 0, + "total": 52 + } +} +``` + +#### Response Fields + +| Field | Type | Description | +|-------|------|-------------| +| `phrases` | object | Day-to-phrase mapping | +| `pin` | string\|null | Generated PIN (if requested) | +| `rsa_key_pem` | string\|null | PEM-encoded RSA key (if requested) | +| `entropy.phrase` | integer | Entropy from phrases (bits) | +| `entropy.pin` | integer | Entropy from PIN (bits) | +| `entropy.rsa` | integer | Entropy from RSA key (bits) | +| `entropy.total` | integer | Combined entropy (bits) | + +#### cURL Examples + +**PIN only:** +```bash +curl -X POST http://localhost:8000/generate \ + -H "Content-Type: application/json" \ + -d '{"use_pin": true, "use_rsa": false}' +``` + +**RSA only:** +```bash +curl -X POST http://localhost:8000/generate \ + -H "Content-Type: application/json" \ + -d '{"use_pin": false, "use_rsa": true, "rsa_bits": 4096}' +``` + +**Both with custom settings:** +```bash +curl -X POST http://localhost:8000/generate \ + -H "Content-Type: application/json" \ + -d '{ + "use_pin": true, + "use_rsa": true, + "pin_length": 9, + "rsa_bits": 4096, + "words_per_phrase": 6 + }' +``` + +--- + +### POST /encode (JSON) + +Encode a message using base64-encoded images. + +#### Request + +```http +POST /encode HTTP/1.1 +Host: localhost:8000 +Content-Type: application/json + +{ + "message": "Secret message here", + "reference_photo_base64": "iVBORw0KGgo...", + "carrier_image_base64": "iVBORw0KGgo...", + "day_phrase": "apple forest thunder", + "pin": "123456", + "rsa_key_base64": null, + "rsa_password": null, + "date_str": null +} +``` + +#### Request Body + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `message` | string | ✓ | Message to encode | +| `reference_photo_base64` | string | ✓ | Base64-encoded reference photo | +| `carrier_image_base64` | string | ✓ | Base64-encoded carrier image | +| `day_phrase` | string | ✓ | Today's passphrase | +| `pin` | string | * | Static PIN (6-9 digits) | +| `rsa_key_base64` | string | * | Base64-encoded RSA key PEM | +| `rsa_password` | string | | Password for RSA key | +| `date_str` | string | | Date override (YYYY-MM-DD) | + +\* At least one of `pin` or `rsa_key_base64` required. + +#### Response + +```json +{ + "stego_image_base64": "iVBORw0KGgo...", + "filename": "a1b2c3d4_20251227.png", + "capacity_used_percent": 12.4, + "date_used": "2025-12-27" +} +``` + +#### Response Fields + +| Field | Type | Description | +|-------|------|-------------| +| `stego_image_base64` | string | Base64-encoded stego PNG | +| `filename` | string | Suggested filename | +| `capacity_used_percent` | float | Percentage of capacity used | +| `date_used` | string | Date embedded in image | + +#### cURL Example + +```bash +# Prepare base64-encoded images +REF_B64=$(base64 -w0 reference.jpg) +CARRIER_B64=$(base64 -w0 carrier.png) + +curl -X POST http://localhost:8000/encode \ + -H "Content-Type: application/json" \ + -d "{ + \"message\": \"Secret message\", + \"reference_photo_base64\": \"$REF_B64\", + \"carrier_image_base64\": \"$CARRIER_B64\", + \"day_phrase\": \"apple forest thunder\", + \"pin\": \"123456\" + }" | jq -r '.stego_image_base64' | base64 -d > stego.png +``` + +--- + +### POST /encode/multipart + +Encode a message using direct file uploads. Returns the stego image directly. + +#### Request + +```http +POST /encode/multipart HTTP/1.1 +Host: localhost:8000 +Content-Type: multipart/form-data; boundary=----FormBoundary + +------FormBoundary +Content-Disposition: form-data; name="message" + +Secret message here +------FormBoundary +Content-Disposition: form-data; name="day_phrase" + +apple forest thunder +------FormBoundary +Content-Disposition: form-data; name="pin" + +123456 +------FormBoundary +Content-Disposition: form-data; name="reference_photo"; filename="ref.jpg" +Content-Type: image/jpeg + + +------FormBoundary +Content-Disposition: form-data; name="carrier"; filename="carrier.png" +Content-Type: image/png + + +------FormBoundary-- +``` + +#### Form Fields + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `message` | string | ✓ | Message to encode | +| `reference_photo` | file | ✓ | Reference photo file | +| `carrier` | file | ✓ | Carrier image file | +| `day_phrase` | string | ✓ | Today's passphrase | +| `pin` | string | * | Static PIN | +| `rsa_key` | file | * | RSA key file (.pem) | +| `rsa_password` | string | | Password for RSA key | +| `date_str` | string | | Date override (YYYY-MM-DD) | + +\* At least one of `pin` or `rsa_key` required. + +#### Response + +Returns the PNG image directly with headers: +- `Content-Type: image/png` +- `Content-Disposition: attachment; filename=.png` + +#### cURL Examples + +**With PIN:** +```bash +curl -X POST http://localhost:8000/encode/multipart \ + -F "message=Secret message" \ + -F "day_phrase=apple forest thunder" \ + -F "pin=123456" \ + -F "reference_photo=@reference.jpg" \ + -F "carrier=@carrier.png" \ + --output stego.png +``` + +**With RSA key:** +```bash +curl -X POST http://localhost:8000/encode/multipart \ + -F "message=Secret message" \ + -F "day_phrase=apple forest thunder" \ + -F "rsa_key=@mykey.pem" \ + -F "rsa_password=keypassword" \ + -F "reference_photo=@reference.jpg" \ + -F "carrier=@carrier.png" \ + --output stego.png +``` + +**With both PIN and RSA:** +```bash +curl -X POST http://localhost:8000/encode/multipart \ + -F "message=Maximum security message" \ + -F "day_phrase=apple forest thunder" \ + -F "pin=123456" \ + -F "rsa_key=@mykey.pem" \ + -F "rsa_password=keypassword" \ + -F "reference_photo=@reference.jpg" \ + -F "carrier=@carrier.png" \ + --output stego.png +``` + +**With custom date:** +```bash +curl -X POST http://localhost:8000/encode/multipart \ + -F "message=Backdated message" \ + -F "day_phrase=monday phrase here" \ + -F "pin=123456" \ + -F "date_str=2025-12-29" \ + -F "reference_photo=@reference.jpg" \ + -F "carrier=@carrier.png" \ + --output stego.png +``` + +--- + +### POST /decode (JSON) + +Decode a message using base64-encoded images. + +#### Request + +```http +POST /decode HTTP/1.1 +Host: localhost:8000 +Content-Type: application/json + +{ + "stego_image_base64": "iVBORw0KGgo...", + "reference_photo_base64": "iVBORw0KGgo...", + "day_phrase": "apple forest thunder", + "pin": "123456", + "rsa_key_base64": null, + "rsa_password": null +} +``` + +#### Request Body + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `stego_image_base64` | string | ✓ | Base64-encoded stego image | +| `reference_photo_base64` | string | ✓ | Base64-encoded reference photo | +| `day_phrase` | string | ✓ | Passphrase for encoding day | +| `pin` | string | * | Static PIN | +| `rsa_key_base64` | string | * | Base64-encoded RSA key | +| `rsa_password` | string | | Password for RSA key | + +\* Must match the security factors used during encoding. + +#### Response + +```json +{ + "message": "Secret message here" +} +``` + +#### cURL Example + +```bash +# Prepare base64-encoded images +STEGO_B64=$(base64 -w0 stego.png) +REF_B64=$(base64 -w0 reference.jpg) + +curl -X POST http://localhost:8000/decode \ + -H "Content-Type: application/json" \ + -d "{ + \"stego_image_base64\": \"$STEGO_B64\", + \"reference_photo_base64\": \"$REF_B64\", + \"day_phrase\": \"apple forest thunder\", + \"pin\": \"123456\" + }" +``` + +--- + +### POST /decode/multipart + +Decode a message using direct file uploads. + +#### Request + +```http +POST /decode/multipart HTTP/1.1 +Host: localhost:8000 +Content-Type: multipart/form-data +``` + +#### Form Fields + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `stego_image` | file | ✓ | Stego image file | +| `reference_photo` | file | ✓ | Reference photo file | +| `day_phrase` | string | ✓ | Passphrase for encoding day | +| `pin` | string | * | Static PIN | +| `rsa_key` | file | * | RSA key file | +| `rsa_password` | string | | Password for RSA key | + +#### Response + +```json +{ + "message": "Secret message here" +} +``` + +#### cURL Examples + +**With PIN:** +```bash +curl -X POST http://localhost:8000/decode/multipart \ + -F "day_phrase=apple forest thunder" \ + -F "pin=123456" \ + -F "reference_photo=@reference.jpg" \ + -F "stego_image=@stego.png" +``` + +**With RSA key:** +```bash +curl -X POST http://localhost:8000/decode/multipart \ + -F "day_phrase=apple forest thunder" \ + -F "rsa_key=@mykey.pem" \ + -F "rsa_password=keypassword" \ + -F "reference_photo=@reference.jpg" \ + -F "stego_image=@stego.png" +``` + +--- + +### POST /image/info + +Get information about an image's capacity. + +#### Request + +```http +POST /image/info HTTP/1.1 +Host: localhost:8000 +Content-Type: multipart/form-data +``` + +#### Form Fields + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `image` | file | ✓ | Image file to analyze | + +#### Response + +```json +{ + "width": 1920, + "height": 1080, + "pixels": 2073600, + "capacity_bytes": 776970, + "capacity_kb": 758 +} +``` + +#### Response Fields + +| Field | Type | Description | +|-------|------|-------------| +| `width` | integer | Image width in pixels | +| `height` | integer | Image height in pixels | +| `pixels` | integer | Total pixel count | +| `capacity_bytes` | integer | Maximum message capacity (bytes) | +| `capacity_kb` | integer | Maximum message capacity (KB) | + +#### cURL Example + +```bash +curl -X POST http://localhost:8000/image/info \ + -F "image=@myimage.png" +``` + +--- + +## Data Models + +### GenerateRequest + +```json +{ + "use_pin": true, + "use_rsa": false, + "pin_length": 6, + "rsa_bits": 2048, + "words_per_phrase": 3 +} +``` + +### GenerateResponse + +```json +{ + "phrases": {"Monday": "...", "Tuesday": "...", ...}, + "pin": "123456", + "rsa_key_pem": "-----BEGIN PRIVATE KEY-----...", + "entropy": {"phrase": 33, "pin": 19, "rsa": 0, "total": 52} +} +``` + +### EncodeRequest + +```json +{ + "message": "string", + "reference_photo_base64": "string", + "carrier_image_base64": "string", + "day_phrase": "string", + "pin": "string", + "rsa_key_base64": "string", + "rsa_password": "string", + "date_str": "YYYY-MM-DD" +} +``` + +### EncodeResponse + +```json +{ + "stego_image_base64": "string", + "filename": "string", + "capacity_used_percent": 12.4, + "date_used": "YYYY-MM-DD" +} +``` + +### DecodeRequest + +```json +{ + "stego_image_base64": "string", + "reference_photo_base64": "string", + "day_phrase": "string", + "pin": "string", + "rsa_key_base64": "string", + "rsa_password": "string" +} +``` + +### DecodeResponse + +```json +{ + "message": "string" +} +``` + +### ImageInfoResponse + +```json +{ + "width": 1920, + "height": 1080, + "pixels": 2073600, + "capacity_bytes": 776970, + "capacity_kb": 758 +} +``` + +### ErrorResponse + +```json +{ + "error": "ErrorType", + "detail": "Error description" +} +``` + +--- + +## Error Handling + +### HTTP Status Codes + +| Code | Meaning | Use Case | +|------|---------|----------| +| 200 | OK | Successful operation | +| 400 | Bad Request | Invalid input, capacity error | +| 401 | Unauthorized | Decryption failed (wrong credentials) | +| 500 | Internal Error | Unexpected server error | + +### Error Response Format + +```json +{ + "detail": "Error message describing the problem" +} +``` + +### Common Errors + +| Status | Error | Solution | +|--------|-------|----------| +| 400 | "Must enable at least one of use_pin or use_rsa" | Set `use_pin` or `use_rsa` to true | +| 400 | "rsa_bits must be one of [2048, 3072, 4096]" | Use valid RSA key size | +| 400 | "Carrier image too small" | Use larger carrier image | +| 400 | "PIN must be 6-9 digits" | Fix PIN format | +| 401 | "Decryption failed. Check credentials." | Verify phrase, PIN, ref photo | +| 400 | "Message too long" | Reduce message size or use larger carrier | + +--- + +## Code Examples + +### Python with requests + +```python +import base64 +import requests + +BASE_URL = "http://localhost:8000" + +# Generate credentials +response = requests.post(f"{BASE_URL}/generate", json={ + "use_pin": True, + "use_rsa": False, + "words_per_phrase": 3 +}) +creds = response.json() +print(f"PIN: {creds['pin']}") +print(f"Monday phrase: {creds['phrases']['Monday']}") + +# Encode using multipart +with open("reference.jpg", "rb") as ref, open("carrier.png", "rb") as carrier: + response = requests.post(f"{BASE_URL}/encode/multipart", files={ + "reference_photo": ref, + "carrier": carrier, + }, data={ + "message": "Secret message", + "day_phrase": "apple forest thunder", + "pin": "123456" + }) + + with open("stego.png", "wb") as f: + f.write(response.content) + +# Decode using multipart +with open("reference.jpg", "rb") as ref, open("stego.png", "rb") as stego: + response = requests.post(f"{BASE_URL}/decode/multipart", files={ + "reference_photo": ref, + "stego_image": stego, + }, data={ + "day_phrase": "apple forest thunder", + "pin": "123456" + }) + + print(f"Decoded: {response.json()['message']}") +``` + +### JavaScript/Node.js + +```javascript +const FormData = require('form-data'); +const fs = require('fs'); +const axios = require('axios'); + +const BASE_URL = 'http://localhost:8000'; + +async function encode() { + const form = new FormData(); + form.append('message', 'Secret message'); + form.append('day_phrase', 'apple forest thunder'); + form.append('pin', '123456'); + form.append('reference_photo', fs.createReadStream('reference.jpg')); + form.append('carrier', fs.createReadStream('carrier.png')); + + const response = await axios.post(`${BASE_URL}/encode/multipart`, form, { + headers: form.getHeaders(), + responseType: 'arraybuffer' + }); + + fs.writeFileSync('stego.png', response.data); + console.log('Encoded successfully'); +} + +async function decode() { + const form = new FormData(); + form.append('day_phrase', 'apple forest thunder'); + form.append('pin', '123456'); + form.append('reference_photo', fs.createReadStream('reference.jpg')); + form.append('stego_image', fs.createReadStream('stego.png')); + + const response = await axios.post(`${BASE_URL}/decode/multipart`, form, { + headers: form.getHeaders() + }); + + console.log('Decoded:', response.data.message); +} + +encode().then(decode); +``` + +### Go + +```go +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "mime/multipart" + "net/http" + "os" +) + +func main() { + // Encode + body := &bytes.Buffer{} + writer := multipart.NewWriter(body) + + writer.WriteField("message", "Secret message") + writer.WriteField("day_phrase", "apple forest thunder") + writer.WriteField("pin", "123456") + + ref, _ := os.Open("reference.jpg") + refPart, _ := writer.CreateFormFile("reference_photo", "reference.jpg") + io.Copy(refPart, ref) + ref.Close() + + carrier, _ := os.Open("carrier.png") + carrierPart, _ := writer.CreateFormFile("carrier", "carrier.png") + io.Copy(carrierPart, carrier) + carrier.Close() + + writer.Close() + + resp, _ := http.Post( + "http://localhost:8000/encode/multipart", + writer.FormDataContentType(), + body, + ) + + stego, _ := os.Create("stego.png") + io.Copy(stego, resp.Body) + stego.Close() + resp.Body.Close() + + fmt.Println("Encoded successfully") +} +``` + +### Shell Script (Bash) + +```bash +#!/bin/bash + +BASE_URL="http://localhost:8000" +REF_PHOTO="reference.jpg" +CARRIER="carrier.png" +PHRASE="apple forest thunder" +PIN="123456" +MESSAGE="Secret message" + +# Encode +echo "Encoding..." +curl -s -X POST "$BASE_URL/encode/multipart" \ + -F "message=$MESSAGE" \ + -F "day_phrase=$PHRASE" \ + -F "pin=$PIN" \ + -F "reference_photo=@$REF_PHOTO" \ + -F "carrier=@$CARRIER" \ + --output stego.png + +echo "Encoded to stego.png" + +# Decode +echo "Decoding..." +DECODED=$(curl -s -X POST "$BASE_URL/decode/multipart" \ + -F "day_phrase=$PHRASE" \ + -F "pin=$PIN" \ + -F "reference_photo=@$REF_PHOTO" \ + -F "stego_image=@stego.png" | jq -r '.message') + +echo "Decoded message: $DECODED" +``` + +--- + +## Rate Limiting + +The API does not implement rate limiting by default. For production: + +1. **Reverse Proxy**: Use nginx or Caddy rate limiting +2. **Application Level**: Add FastAPI middleware + +Example nginx rate limiting: +```nginx +limit_req_zone $binary_remote_addr zone=stegasoo:10m rate=10r/s; + +location /api/ { + limit_req zone=stegasoo burst=20 nodelay; + proxy_pass http://localhost:8000/; +} +``` + +--- + +## Security Considerations + +### In Transit + +- Use HTTPS in production +- Configure TLS at reverse proxy level + +### Memory Usage + +- Argon2id requires 256MB RAM per operation +- Concurrent requests can exhaust memory +- Limit workers based on available RAM + +### Input Validation + +The API validates: +- PIN format (6-9 digits, no leading zero) +- Message size (max 50KB) +- Image size (max 5MB file, ~4MP dimensions) +- RSA key validity + +### Credential Handling + +- Credentials are never logged +- No persistent storage of secrets +- Memory cleared after operations + +--- + +## Interactive Documentation + +When the API is running, visit: + +- **Swagger UI**: http://localhost:8000/docs +- **ReDoc**: http://localhost:8000/redoc + +--- + +## See Also + +- [CLI Documentation](CLI.md) - Command-line interface +- [Web UI Documentation](WEB_UI.md) - Browser interface +- [README](README.md) - Project overview diff --git a/frontends/CLI.md b/frontends/CLI.md new file mode 100644 index 0000000..9b5a89c --- /dev/null +++ b/frontends/CLI.md @@ -0,0 +1,634 @@ +# Stegasoo CLI Documentation + +Complete command-line interface reference for Stegasoo steganography operations. + +## Table of Contents + +- [Installation](#installation) +- [Quick Start](#quick-start) +- [Commands](#commands) + - [generate](#generate-command) + - [encode](#encode-command) + - [decode](#decode-command) + - [info](#info-command) +- [Security Factors](#security-factors) +- [Workflow Examples](#workflow-examples) +- [Piping & Scripting](#piping--scripting) +- [Error Handling](#error-handling) +- [Exit Codes](#exit-codes) + +--- + +## Installation + +### From PyPI + +```bash +# CLI only +pip install stegasoo[cli] + +# With all extras +pip install stegasoo[all] +``` + +### From Source + +```bash +git clone https://github.com/example/stegasoo.git +cd stegasoo +pip install -e ".[cli]" +``` + +### Verify Installation + +```bash +stegasoo --version +stegasoo --help +``` + +--- + +## Quick Start + +```bash +# 1. Generate credentials (do this once, memorize results) +stegasoo generate --pin --words 3 + +# 2. Encode a message +stegasoo encode \ + --ref secret_photo.jpg \ + --carrier meme.png \ + --phrase "apple forest thunder" \ + --pin 123456 \ + --message "Meet at midnight" + +# 3. Decode a message +stegasoo decode \ + --ref secret_photo.jpg \ + --stego stego_abc123_20251227.png \ + --phrase "apple forest thunder" \ + --pin 123456 +``` + +--- + +## Commands + +### Generate Command + +Generate credentials for encoding/decoding operations. Creates daily passphrases and optionally a PIN and/or RSA key. + +#### Synopsis + +```bash +stegasoo generate [OPTIONS] +``` + +#### Options + +| Option | Short | Type | Default | Description | +|--------|-------|------|---------|-------------| +| `--pin/--no-pin` | | flag | `--pin` | Generate a PIN | +| `--rsa/--no-rsa` | | flag | `--no-rsa` | Generate an RSA key | +| `--pin-length` | | 6-9 | 6 | PIN length in digits | +| `--rsa-bits` | | choice | 2048 | RSA key size (2048, 3072, 4096) | +| `--words` | | 3-12 | 3 | Words per daily phrase | +| `--output` | `-o` | path | | Save RSA key to file | +| `--password` | `-p` | string | | Password for RSA key file | +| `--json` | | flag | | Output as JSON | + +#### Examples + +**Basic generation with PIN (default):** +```bash +stegasoo generate +``` + +Output: +``` +════════════════════════════════════════════════════════════ + STEGASOO CREDENTIALS +════════════════════════════════════════════════════════════ + +⚠️ MEMORIZE THESE AND CLOSE THIS WINDOW + Do not screenshot or save to file! + +─── STATIC PIN ─── + 847293 + +─── DAILY PHRASES ─── + Monday │ abandon ability able + Tuesday │ actor actress actual + Wednesday │ advice aerobic affair + Thursday │ afraid again age + Friday │ agree ahead aim + Saturday │ airport aisle alarm + Sunday │ album alcohol alert + +─── SECURITY ─── + Phrase entropy: 33 bits + PIN entropy: 19 bits + Combined: 52 bits + + photo entropy: 80-256 bits +``` + +**Generate with RSA key:** +```bash +stegasoo generate --rsa --rsa-bits 4096 +``` + +**Save RSA key to encrypted file:** +```bash +stegasoo generate --rsa -o mykey.pem -p "mysecretpassword" +``` + +**Maximum security (longer phrases + both factors):** +```bash +stegasoo generate --pin --rsa --words 6 --pin-length 9 +``` + +**JSON output for scripting:** +```bash +stegasoo generate --json | jq '.phrases.Monday' +``` + +**RSA only (no PIN):** +```bash +stegasoo generate --no-pin --rsa -o key.pem -p "password123" +``` + +--- + +### Encode Command + +Encode a secret message into an image using steganography. + +#### Synopsis + +```bash +stegasoo encode [OPTIONS] +``` + +#### Options + +| Option | Short | Type | Required | Description | +|--------|-------|------|----------|-------------| +| `--ref` | `-r` | path | ✓ | Reference photo (shared secret) | +| `--carrier` | `-c` | path | ✓ | Carrier image to hide message in | +| `--phrase` | `-p` | string | ✓ | Today's passphrase | +| `--message` | `-m` | string | | Message to encode | +| `--message-file` | `-f` | path | | Read message from file | +| `--pin` | | string | * | Static PIN (6-9 digits) | +| `--key` | `-k` | path | * | RSA key file | +| `--key-password` | | string | | Password for RSA key | +| `--output` | `-o` | path | | Output filename | +| `--date` | | YYYY-MM-DD | | Date override | +| `--quiet` | `-q` | flag | | Suppress output | + +\* At least one of `--pin` or `--key` is required. + +#### Message Input Methods + +1. **Command line argument:** + ```bash + stegasoo encode -r ref.jpg -c carrier.png -p "phrase" --pin 123456 -m "Secret message" + ``` + +2. **From file:** + ```bash + stegasoo encode -r ref.jpg -c carrier.png -p "phrase" --pin 123456 -f message.txt + ``` + +3. **From stdin (pipe):** + ```bash + echo "Secret message" | stegasoo encode -r ref.jpg -c carrier.png -p "phrase" --pin 123456 + ``` + +#### Examples + +**Basic encoding with PIN:** +```bash +stegasoo encode \ + --ref photos/vacation.jpg \ + --carrier memes/funny_cat.png \ + --phrase "correct horse battery" \ + --pin 847293 \ + --message "The package arrives Tuesday" +``` + +Output: +``` +✓ Encoded successfully! + Output: a1b2c3d4_20251227.png + Size: 245,832 bytes + Capacity used: 12.4% + Date: 2025-12-27 +``` + +**With RSA key:** +```bash +stegasoo encode \ + -r reference.jpg \ + -c carrier.png \ + -p "apple forest thunder" \ + -k mykey.pem \ + --key-password "secretpassword" \ + -m "Encrypted with RSA" +``` + +**Both PIN and RSA (maximum security):** +```bash +stegasoo encode \ + -r ref.jpg \ + -c carrier.png \ + -p "word1 word2 word3" \ + --pin 123456 \ + -k mykey.pem \ + --key-password "pass" \ + -m "Double-locked message" +``` + +**Custom output filename:** +```bash +stegasoo encode \ + -r ref.jpg \ + -c carrier.png \ + -p "phrase words here" \ + --pin 123456 \ + -m "Message" \ + -o holiday_photo.png +``` + +**Encoding with specific date (for testing):** +```bash +stegasoo encode \ + -r ref.jpg \ + -c carrier.png \ + -p "monday phrase here" \ + --pin 123456 \ + -m "Message" \ + --date 2025-12-29 +``` + +**Long message from file:** +```bash +stegasoo encode \ + -r ref.jpg \ + -c large_image.png \ + -p "phrase" \ + --pin 123456 \ + -f secret_document.txt \ + -o output.png +``` + +**Quiet mode for scripting:** +```bash +stegasoo encode -r ref.jpg -c carrier.png -p "phrase" --pin 123456 -m "msg" -q -o out.png +# No output, just creates the file +``` + +--- + +### Decode Command + +Decode a secret message from a stego image. + +#### Synopsis + +```bash +stegasoo decode [OPTIONS] +``` + +#### Options + +| Option | Short | Type | Required | Description | +|--------|-------|------|----------|-------------| +| `--ref` | `-r` | path | ✓ | Reference photo (same as encoding) | +| `--stego` | `-s` | path | ✓ | Stego image to decode | +| `--phrase` | `-p` | string | ✓ | Passphrase for the encoding day | +| `--pin` | | string | * | Static PIN | +| `--key` | `-k` | path | * | RSA key file | +| `--key-password` | | string | | Password for RSA key | +| `--output` | `-o` | path | | Save message to file | +| `--quiet` | `-q` | flag | | Output only the message | + +\* Must provide the same security factors used during encoding. + +#### Examples + +**Basic decoding with PIN:** +```bash +stegasoo decode \ + --ref photos/vacation.jpg \ + --stego received_image.png \ + --phrase "correct horse battery" \ + --pin 847293 +``` + +Output: +``` +✓ Decoded successfully! + +The package arrives Tuesday +``` + +**With RSA key:** +```bash +stegasoo decode \ + -r reference.jpg \ + -s stego_image.png \ + -p "apple forest thunder" \ + -k mykey.pem \ + --key-password "secretpassword" +``` + +**Save decoded message to file:** +```bash +stegasoo decode \ + -r ref.jpg \ + -s stego.png \ + -p "phrase" \ + --pin 123456 \ + -o decoded_message.txt +``` + +Output: +``` +✓ Decoded successfully! + Saved to: decoded_message.txt +``` + +**Quiet mode (message only):** +```bash +stegasoo decode -r ref.jpg -s stego.png -p "phrase" --pin 123456 -q +``` + +Output: +``` +The package arrives Tuesday +``` + +**Pipe to another command:** +```bash +stegasoo decode -r ref.jpg -s stego.png -p "phrase" --pin 123456 -q | gpg --decrypt +``` + +--- + +### Info Command + +Display information about an image's capacity and embedded date. + +#### Synopsis + +```bash +stegasoo info IMAGE +``` + +#### Arguments + +| Argument | Type | Description | +|----------|------|-------------| +| `IMAGE` | path | Path to image file | + +#### Examples + +**Check carrier image capacity:** +```bash +stegasoo info vacation_photo.png +``` + +Output: +``` +Image: vacation_photo.png + Dimensions: 1920 × 1080 + Pixels: 2,073,600 + Mode: RGB + Format: PNG + Capacity: ~776,970 bytes (758 KB) +``` + +**Check stego image (shows encoding date):** +```bash +stegasoo info stego_a1b2c3d4_20251227.png +``` + +Output: +``` +Image: stego_a1b2c3d4_20251227.png + Dimensions: 1920 × 1080 + Pixels: 2,073,600 + Mode: RGB + Format: PNG + Capacity: ~776,970 bytes (758 KB) + Embed date: 2025-12-27 (Saturday) +``` + +--- + +## Security Factors + +Stegasoo uses multiple authentication factors: + +| Factor | Description | Entropy | +|--------|-------------|---------| +| Reference Photo | A photo both parties have | ~80-256 bits | +| Day Phrase | Changes daily (e.g., 3 BIP-39 words) | ~33 bits (3 words) | +| Static PIN | Same every day (6-9 digits) | ~20 bits (6 digits) | +| RSA Key | Shared key file | ~128 bits effective | + +### Minimum Requirements + +- At least one of PIN or RSA key must be provided +- Reference photo is always required +- Day phrase is always required + +### Security Configurations + +| Configuration | Entropy (excl. photo) | Use Case | +|--------------|----------------------|----------| +| 3-word phrase + 6-digit PIN | ~53 bits | Casual use | +| 6-word phrase + 9-digit PIN | ~96 bits | Standard security | +| 3-word phrase + RSA 2048 | ~161 bits | File-based auth | +| 6-word phrase + PIN + RSA | ~224 bits | Maximum security | + +--- + +## Workflow Examples + +### Daily Secure Communication + +**Setup (once):** +```bash +# Both parties generate same credentials +stegasoo generate --pin --words 3 + +# Or share RSA key securely +stegasoo generate --rsa -o shared_key.pem -p "agreedpassword" +# Securely transfer shared_key.pem to recipient +``` + +**Sender (daily):** +```bash +# Get today's phrase from your memorized list +TODAY_PHRASE="monday phrase words" + +# Encode message +stegasoo encode \ + -r our_shared_photo.jpg \ + -c random_meme.png \ + -p "$TODAY_PHRASE" \ + --pin 847293 \ + -m "Meeting moved to 3pm" + +# Share output image via normal channels (email, chat, etc.) +``` + +**Recipient (daily):** +```bash +# Use the phrase for the day the message was SENT +stegasoo decode \ + -r our_shared_photo.jpg \ + -s received_image.png \ + -p "monday phrase words" \ + --pin 847293 +``` + +### Batch Processing + +**Encode multiple messages:** +```bash +#!/bin/bash +PHRASE="apple forest thunder" +PIN="123456" +REF="reference.jpg" + +for file in messages/*.txt; do + name=$(basename "$file" .txt) + stegasoo encode \ + -r "$REF" \ + -c "carriers/${name}.png" \ + -p "$PHRASE" \ + --pin "$PIN" \ + -f "$file" \ + -o "output/${name}_stego.png" \ + -q + echo "Encoded: $name" +done +``` + +### Archive with Date Preservation + +```bash +# Encode with specific date for archival +stegasoo encode \ + -r ref.jpg \ + -c carrier.png \ + -p "archive phrase words" \ + --pin 123456 \ + -m "Historical record" \ + --date 2025-01-15 \ + -o archive_2025-01-15.png +``` + +--- + +## Piping & Scripting + +### Stdin/Stdout Support + +**Encode from pipe:** +```bash +cat secret.txt | stegasoo encode -r ref.jpg -c carrier.png -p "phrase" --pin 123456 -o out.png +``` + +**Decode to pipe:** +```bash +stegasoo decode -r ref.jpg -s stego.png -p "phrase" --pin 123456 -q | less +``` + +**Chain with encryption:** +```bash +# Encode GPG-encrypted content +gpg -e -r recipient@email.com secret.txt +cat secret.txt.gpg | base64 | stegasoo encode -r ref.jpg -c carrier.png -p "phrase" --pin 123456 + +# Decode and decrypt +stegasoo decode -r ref.jpg -s stego.png -p "phrase" --pin 123456 -q | base64 -d | gpg -d +``` + +### JSON Output for Scripts + +```bash +# Get credentials as JSON +creds=$(stegasoo generate --json) + +# Extract specific fields +pin=$(echo "$creds" | jq -r '.pin') +monday=$(echo "$creds" | jq -r '.phrases.Monday') +entropy=$(echo "$creds" | jq -r '.entropy.total') + +echo "PIN: $pin" +echo "Monday phrase: $monday" +echo "Total entropy: $entropy bits" +``` + +### Error Handling in Scripts + +```bash +#!/bin/bash +set -e + +if ! stegasoo decode -r ref.jpg -s stego.png -p "phrase" --pin 123456 -q 2>/dev/null; then + echo "Decryption failed - check credentials" + exit 1 +fi +``` + +--- + +## Error Handling + +### Common Errors + +| Error | Cause | Solution | +|-------|-------|----------| +| "Must provide --pin or --key" | No security factor given | Add `--pin` or `--key` option | +| "PIN must be 6-9 digits" | Invalid PIN format | Use numeric PIN, 6-9 chars | +| "PIN cannot start with zero" | Leading zero in PIN | Use PIN starting with 1-9 | +| "Carrier image too small" | Message exceeds capacity | Use larger carrier image | +| "Decryption failed" | Wrong credentials | Verify phrase, PIN, ref photo | +| "RSA key is password-protected" | Missing key password | Add `--key-password` option | + +### Troubleshooting Decryption Failures + +1. **Check the encoding date:** The filename often contains the date (e.g., `_20251227`) +2. **Use correct phrase:** The phrase must match the day the message was encoded, not today +3. **Verify reference photo:** Must be the exact same file, not a resized copy +4. **Check stego image:** Ensure it wasn't resized, recompressed, or converted + +--- + +## Exit Codes + +| Code | Meaning | +|------|---------| +| 0 | Success | +| 1 | General error | +| 2 | Invalid arguments/options | + +--- + +## Environment Variables + +| Variable | Description | +|----------|-------------| +| `PYTHONPATH` | Include `src/` for development | + +--- + +## See Also + +- [API Documentation](API.md) - REST API reference +- [Web UI Documentation](WEB_UI.md) - Browser interface guide +- [README](README.md) - Project overview and security model diff --git a/frontends/WEB_UI.md b/frontends/WEB_UI.md new file mode 100644 index 0000000..0b5232a --- /dev/null +++ b/frontends/WEB_UI.md @@ -0,0 +1,739 @@ +# Stegasoo Web UI Documentation + +Complete guide for the Stegasoo web-based steganography interface. + +## Table of Contents + +- [Overview](#overview) +- [Installation & Setup](#installation--setup) +- [Pages & Features](#pages--features) + - [Home Page](#home-page) + - [Generate Credentials](#generate-credentials) + - [Encode Message](#encode-message) + - [Decode Message](#decode-message) + - [About Page](#about-page) +- [User Interface Guide](#user-interface-guide) +- [Workflow Examples](#workflow-examples) +- [Security Features](#security-features) +- [Configuration](#configuration) +- [Troubleshooting](#troubleshooting) +- [Mobile Support](#mobile-support) + +--- + +## Overview + +The Stegasoo Web UI provides a user-friendly browser-based interface for: + +- **Generating** secure credentials (phrases, PINs, RSA keys) +- **Encoding** secret messages into images +- **Decoding** hidden messages from images +- **Learning** about the security model + +Built with Flask, Bootstrap 5, and a modern dark theme. + +### Features + +- ✅ Drag-and-drop file uploads +- ✅ Image previews +- ✅ Client-side date detection +- ✅ Native sharing (Web Share API) +- ✅ Responsive design (mobile-friendly) +- ✅ Password-protected RSA key downloads +- ✅ Real-time entropy calculations +- ✅ Automatic file cleanup + +--- + +## Installation & Setup + +### From PyPI + +```bash +pip install stegasoo[web] +``` + +### From Source + +```bash +git clone https://github.com/example/stegasoo.git +cd stegasoo +pip install -e ".[web]" +``` + +### Running the Server + +**Development:** +```bash +cd frontends/web +python app.py +``` +Server starts at http://localhost:5000 + +**Production with Gunicorn:** +```bash +cd frontends/web +gunicorn --bind 0.0.0.0:5000 --workers 2 --threads 4 --timeout 60 app:app +``` + +**Docker:** +```bash +docker-compose up web +``` + +### First-Time Setup + +1. Navigate to http://localhost:5000 +2. Click "Generate" to create your credentials +3. **Memorize** your phrases and PIN +4. Share credentials securely with your communication partner + +--- + +## Pages & Features + +### Home Page + +**URL:** `/` + +The landing page introduces Stegasoo and provides quick access to all features. + +#### Main Actions + +| Card | Description | Link | +|------|-------------|------| +| **Encode Message** | Hide a secret in an image | `/encode` | +| **Decode Message** | Extract a hidden message | `/decode` | +| **Generate Keys** | Create new credentials | `/generate` | + +#### "How It Works" Section + +Explains the three key components: +1. **Reference Photo** - Shared secret image +2. **Day Phrase** - Changes daily +3. **Static PIN** - Same every day + +--- + +### Generate Credentials + +**URL:** `/generate` + +Create a new set of credentials for steganography operations. + +#### Configuration Options + +| Option | Range | Default | Description | +|--------|-------|---------|-------------| +| Words per phrase | 3-12 | 3 | BIP-39 words per daily phrase | +| Use PIN | on/off | on | Generate a numeric PIN | +| PIN length | 6-9 | 6 | Digits in the PIN | +| Use RSA Key | on/off | off | Generate an RSA key pair | +| RSA key size | 2048/3072/4096 | 2048 | Key size in bits | + +#### Entropy Calculator + +The UI displays real-time entropy calculations: + +``` +Estimated entropy: ~53 bits +[==========> ] Good for most use cases +• Reference photo adds ~80-256 bits more +``` + +#### Generated Output + +After clicking "Generate Credentials": + +**Static PIN** (if enabled): +``` +┌─────────────────────┐ +│ 8 4 7 2 9 3 │ +└─────────────────────┘ +Use this 6-digit PIN every day +``` + +**Daily Phrases:** +``` +Day │ Phrase +───────────────────────────────────────── +Monday │ abandon ability able +Tuesday │ actor actress actual +Wednesday │ advice aerobic affair +Thursday │ afraid again age +Friday │ agree ahead aim +Saturday │ airport aisle alarm +Sunday │ album alcohol alert +``` + +**RSA Key** (if enabled): +- Copy to clipboard button +- Download as password-protected .pem file + +**Security Summary:** +``` +Phrase entropy: 33 bits/phrase +PIN entropy: 19 bits/PIN +RSA entropy: 128 bits/RSA +───────────────────────────── +Total: 180 bits ++ reference photo (~80-256 bits) = 260+ bits combined +``` + +#### RSA Key Download + +1. Click "Download as .pem" +2. Enter a password (minimum 8 characters) +3. Click "Download Protected Key" +4. Save the file securely +5. Share with your communication partner through a secure channel + +--- + +### Encode Message + +**URL:** `/encode` + +Hide a secret message inside an image. + +#### Input Fields + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| Reference Photo | Image file | ✓ | Your shared secret photo | +| Carrier Image | Image file | ✓ | Image to hide message in | +| Secret Message | Text | ✓ | Message to hide (max 50KB) | +| Day Phrase | Text | ✓ | Today's passphrase | +| PIN | Number | * | Your static PIN | +| RSA Key | .pem file | * | Your shared RSA key | +| RSA Key Password | Password | | Password for encrypted key | + +\* At least one security factor (PIN or RSA Key) required. + +#### Drag-and-Drop Upload + +Both image upload zones support: +- Click to browse +- Drag and drop files +- Instant image preview +- File name display + +#### Character Counter + +``` +Message: [ ] + 1,234 / 50,000 characters 2% +``` + +Shows warning at 80% capacity. + +#### Day Detection + +The page automatically detects your local day of week and updates the label: +``` +Saturday's Phrase: [ ] +``` + +#### Encoding Process + +1. Fill in all required fields +2. Click "Encode Message" +3. Wait for processing (shows spinner) +4. Redirected to result page + +#### Result Page + +**URL:** `/encode/result/` + +After successful encoding: + +``` +┌────────────────────────────────────────┐ +│ ✓ Message Encoded Successfully! │ +│ │ +│ 📄 a1b2c3d4_20251227.png │ +│ Your secret message is hidden │ +│ in this image │ +│ │ +│ [ Download Image ] │ +│ [ Share Image ] │ +│ │ +│ ⚠️ File expires in 5 minutes. │ +│ Download or share now. │ +│ │ +│ [ Encode Another Message ] │ +└────────────────────────────────────────┘ +``` + +**Share Options:** + +1. **Native Share** (mobile/supported browsers): + - Uses Web Share API + - Opens system share sheet + - Can share directly to apps + +2. **Fallback Share** (desktop): + - Email link + - Telegram link + - WhatsApp link + - Copy link to clipboard + +--- + +### Decode Message + +**URL:** `/decode` + +Extract a hidden message from a stego image. + +#### Input Fields + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| Reference Photo | Image file | ✓ | Same photo used for encoding | +| Stego Image | Image file | ✓ | Image containing hidden message | +| Day Phrase | Text | ✓ | Phrase for the **encoding** day | +| PIN | Number | * | Same PIN used for encoding | +| RSA Key | .pem file | * | Same RSA key used for encoding | +| RSA Key Password | Password | | Password for encrypted key | + +\* Must match security factors used during encoding. + +#### Date Detection from Filename + +When you upload a stego image with a date in the filename (e.g., `stego_20251227.png`), the UI: +1. Extracts the date +2. Determines the day of week +3. Updates the phrase label: "Saturday's Phrase" + +This helps you use the correct daily phrase. + +#### Decoding Process + +1. Fill in all required fields +2. Click "Decode Message" +3. Wait for processing +4. View decoded message on same page + +#### Successful Decode + +``` +┌────────────────────────────────────────┐ +│ ✓ Message Decrypted Successfully! │ +│ │ +│ Decoded Message: │ +│ ┌──────────────────────────────────┐ │ +│ │ Meet at midnight. The package │ │ +│ │ will be under the bridge. │ │ +│ └──────────────────────────────────┘ │ +│ │ +│ [ Decode Another Message ] │ +└────────────────────────────────────────┘ +``` + +#### Troubleshooting Tips + +The page includes built-in troubleshooting guidance: + +- ✓ Use the **exact same reference photo** file +- ✓ Use the phrase for the **encoding day**, not today +- ✓ Provide the **same security factors** used during encoding +- ✓ Ensure the stego image hasn't been **resized or recompressed** +- ✓ If using RSA key, verify the **password is correct** + +--- + +### About Page + +**URL:** `/about` + +Learn about Stegasoo's security model and best practices. + +#### Sections + +**System Status:** +- Argon2id availability (vs PBKDF2 fallback) +- AES-256-GCM encryption status + +**Security Model Table:** + +| Component | Entropy | Purpose | +|-----------|---------|---------| +| Reference Photo | ~80-256 bits | Something you have | +| 3-Word Phrase | ~33 bits | Something you know (daily) | +| 6-Digit PIN | ~20 bits | Something you know (static) | +| Date | N/A | Automatic key rotation | +| **Combined** | **133+ bits** | **Beyond brute force** | + +**Attack Resistance:** + +What attackers can't do: +- Brute force (2^133 combinations) +- Use rainbow tables (random salt) +- Detect hidden data (random pixels) +- Use GPU farms (256MB RAM per attempt) + +Real threats: +- Social engineering +- Physical device access +- Malware/keyloggers +- Shoulder surfing + +**Best Practices:** + +Do: +- Memorize phrases and PIN +- Use reference photo both parties have +- Use different carrier images each time +- Share stego images through normal channels + +Don't: +- Transmit the reference photo +- Reuse carrier images +- Store credentials digitally +- Resize/recompress stego images + +--- + +## User Interface Guide + +### Navigation + +The navbar provides quick access to all pages: + +``` +[Logo] Stegasoo Home | Encode | Decode | Generate | About +``` + +### Color Scheme + +| Element | Color | Purpose | +|---------|-------|---------| +| Background | Dark gradient | Reduce eye strain | +| Cards | Semi-transparent | Visual hierarchy | +| Headers | Purple gradient | Brand identity | +| Success | Green | Positive actions | +| Warning | Yellow | Caution messages | +| Error | Red | Error states | + +### Form Validation + +- Real-time validation feedback +- Clear error messages in alerts +- Required field indicators +- Input constraints (max length, format) + +### Loading States + +During long operations: +- Button shows spinner +- Button text changes (e.g., "Encoding...") +- Button is disabled to prevent double-submit + +### Flash Messages + +``` +┌──────────────────────────────────────────────┐ +│ ✓ Credentials Generated! [×] │ +└──────────────────────────────────────────────┘ +``` + +Types: +- Success (green) - Operation completed +- Error (red) - Operation failed +- Warning (yellow) - Caution needed + +--- + +## Workflow Examples + +### First-Time Setup (Both Parties) + +**Party A:** +1. Go to `/generate` +2. Configure: PIN ✓, 3 words, 6 digits +3. Click "Generate Credentials" +4. **Write down** phrases and PIN on paper +5. **Memorize** over the next few days +6. Destroy the paper + +**Share with Party B (in person or secure channel):** +- The 7 daily phrases +- The PIN +- The reference photo file (if not already shared) + +### Sending a Secret Message + +1. Go to `/encode` +2. Upload your shared reference photo +3. Upload any carrier image (meme, vacation photo, etc.) +4. Type your secret message +5. Enter today's phrase (check your memory!) +6. Enter your PIN +7. Click "Encode Message" +8. Download or share the resulting image +9. Send via any channel (email, social media, chat) + +### Receiving a Secret Message + +1. Receive the stego image through any channel +2. Go to `/decode` +3. Upload the same reference photo +4. Upload the received stego image +5. Note the date in the filename (e.g., `_20251227`) +6. Enter the phrase for **that day** (not today!) +7. Enter the PIN +8. Click "Decode Message" +9. Read the secret message + +### Changing Credentials + +To rotate to new credentials: +1. Both parties generate new credentials together +2. Agree on a cutover date +3. Messages encoded before cutover use old credentials +4. Messages encoded after cutover use new credentials + +--- + +## Security Features + +### Client-Side Security + +| Feature | Implementation | +|---------|----------------| +| Local date detection | JavaScript `Date()` object | +| No credential storage | Nothing saved in browser | +| Automatic cleanup | Files deleted after 5 minutes | +| HTTPS support | Configure at server level | + +### Server-Side Security + +| Feature | Implementation | +|---------|----------------| +| Memory-hard KDF | Argon2id (256MB RAM) | +| Authenticated encryption | AES-256-GCM | +| Random salt | Per-message salt | +| Temporary storage | In-memory, auto-expiring | +| Input validation | All inputs validated | +| File size limits | 5MB max upload | + +### File Security + +| Aspect | Protection | +|--------|------------| +| Upload location | `/tmp/stego_uploads` (Docker) | +| Storage duration | 5 minutes maximum | +| Access control | Random 16-byte file ID | +| Cleanup | Automatic + manual | + +--- + +## Configuration + +### Environment Variables + +| Variable | Default | Description | +|----------|---------|-------------| +| `FLASK_ENV` | production | Flask environment | +| `PYTHONPATH` | - | Include `src/` for development | + +### Application Limits + +| Limit | Value | Config Location | +|-------|-------|-----------------| +| Max file upload | 5 MB | `app.config['MAX_CONTENT_LENGTH']` | +| File expiry | 5 minutes | `TEMP_FILE_EXPIRY` | +| Max image pixels | 4 MP | `stegasoo.constants` | +| Max message size | 50 KB | `stegasoo.constants` | +| PIN length | 6-9 digits | `stegasoo.constants` | + +### Production Deployment + +**With Gunicorn:** +```bash +gunicorn \ + --bind 0.0.0.0:5000 \ + --workers 2 \ + --threads 4 \ + --timeout 60 \ + app:app +``` + +**Worker Calculation:** +- Each encode/decode uses ~256MB RAM (Argon2) +- Formula: `workers = (available_RAM - 512MB) / 256MB` + +**With Nginx (reverse proxy):** +```nginx +server { + listen 80; + server_name stegasoo.example.com; + + client_max_body_size 10M; + + location / { + proxy_pass http://127.0.0.1:5000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_read_timeout 120s; + } +} +``` + +**With Docker Compose:** +```yaml +services: + web: + build: + context: . + target: web + ports: + - "5000:5000" + deploy: + resources: + limits: + memory: 512M + reservations: + memory: 256M +``` + +--- + +## Troubleshooting + +### Common Issues + +#### "Decryption failed" + +**Causes:** +- Wrong day phrase +- Wrong PIN +- Different reference photo +- Stego image was modified + +**Solutions:** +1. Check the date in the stego filename +2. Use the phrase for that specific day +3. Verify you're using the original reference photo +4. Ensure the stego image wasn't resized/recompressed + +#### "Carrier image too small" + +**Cause:** Message too large for carrier capacity + +**Solutions:** +1. Use a larger carrier image (more pixels) +2. Shorten the message +3. Check capacity with `/info` command (CLI) + +#### "You must provide at least a PIN or RSA Key" + +**Cause:** No security factor selected + +**Solution:** Enter a PIN and/or upload an RSA key + +#### Upload fails silently + +**Causes:** +- File too large (>5MB) +- Invalid file type +- Browser issue + +**Solutions:** +1. Reduce file size +2. Use PNG, JPG, or BMP formats +3. Try a different browser + +#### RSA key password error + +**Causes:** +- Wrong password +- Unencrypted key with password provided +- Corrupted key file + +**Solutions:** +1. Verify the correct password +2. If key is unencrypted, leave password blank +3. Re-download or regenerate the key + +### Browser Compatibility + +| Browser | Status | Notes | +|---------|--------|-------| +| Chrome 80+ | ✓ Full | Web Share API supported | +| Firefox 80+ | ✓ Full | Limited Web Share | +| Safari 14+ | ✓ Full | Web Share on iOS | +| Edge 80+ | ✓ Full | Web Share API supported | +| IE 11 | ✗ None | Not supported | + +### Performance Issues + +**Slow encoding/decoding:** +- Normal: Argon2 is intentionally slow (security feature) +- Expected time: 2-5 seconds per operation + +**High memory usage:** +- Normal: Argon2 requires 256MB RAM +- Configure worker count based on available RAM + +--- + +## Mobile Support + +### Responsive Design + +The UI adapts to mobile screens: +- Single-column layout on small screens +- Touch-friendly buttons (48px minimum) +- Readable text without zooming +- Scrollable tables + +### Mobile-Specific Features + +**Native Sharing:** +On supported mobile browsers, the "Share Image" button opens the native share sheet, allowing you to share directly to: +- Messaging apps (iMessage, WhatsApp, Telegram) +- Social media (Instagram, Twitter) +- Email +- Other installed apps + +**Camera Upload:** +File input accepts camera capture: +- Take a new photo as reference +- Capture carrier image directly + +### PWA Support (Future) + +The web app can be added to home screen on mobile devices for quick access. + +--- + +## Keyboard Shortcuts + +| Shortcut | Action | +|----------|--------| +| `Tab` | Navigate between fields | +| `Enter` | Submit form (when focused) | +| `Esc` | Close modal/alert | + +--- + +## Accessibility + +| Feature | Implementation | +|---------|----------------| +| Screen readers | ARIA labels on interactive elements | +| Keyboard navigation | Full tab support | +| Color contrast | WCAG AA compliant | +| Focus indicators | Visible focus rings | +| Form labels | All inputs labeled | + +--- + +## See Also + +- [CLI Documentation](CLI.md) - Command-line interface +- [API Documentation](API.md) - REST API reference +- [README](README.md) - Project overview