Now with extra-sloppy frotend reference docs.
This commit is contained in:
946
frontends/API.md
Normal file
946
frontends/API.md
Normal file
@@ -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
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 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
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 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
|
||||||
|
|
||||||
|
<binary image data>
|
||||||
|
------FormBoundary
|
||||||
|
Content-Disposition: form-data; name="carrier"; filename="carrier.png"
|
||||||
|
Content-Type: image/png
|
||||||
|
|
||||||
|
<binary image data>
|
||||||
|
------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=<generated_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
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 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
|
||||||
|
- 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
|
||||||
634
frontends/CLI.md
Normal file
634
frontends/CLI.md
Normal file
@@ -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
|
||||||
739
frontends/WEB_UI.md
Normal file
739
frontends/WEB_UI.md
Normal file
@@ -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/<file_id>`
|
||||||
|
|
||||||
|
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
|
||||||
Reference in New Issue
Block a user