1122 lines
27 KiB
Markdown
1122 lines
27 KiB
Markdown
# 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)
|
||
- [Embedding Modes](#embedding-modes)
|
||
- [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 (LSB or DCT mode)
|
||
- **Decode** messages from images (auto-detects mode)
|
||
- **Analyze** image capacity
|
||
|
||
The API supports both JSON (base64-encoded images) and multipart form data (direct file uploads).
|
||
|
||
### What's New in v3.0.2
|
||
|
||
- **DCT Steganography Mode** - JPEG-resilient embedding
|
||
- **Output Format Selection** - PNG or JPEG output
|
||
- **Color Mode Selection** - Color or grayscale processing
|
||
- **jpegio Integration** - Proper JPEG coefficient manipulation
|
||
|
||
---
|
||
|
||
## Installation
|
||
|
||
### From PyPI
|
||
|
||
```bash
|
||
pip install stegasoo[api]
|
||
```
|
||
|
||
This automatically installs DCT dependencies (scipy, jpegio) for full functionality.
|
||
|
||
### 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": "3.0.2",
|
||
"has_argon2": true,
|
||
"has_dct": true,
|
||
"has_jpegio": 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 |
|
||
| `has_dct` | boolean | Whether DCT mode is available (scipy) |
|
||
| `has_jpegio` | boolean | Whether native JPEG DCT 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 | Default | 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) |
|
||
| `embedding_mode` | string | | `"lsb"` | `"lsb"` or `"dct"` |
|
||
| `output_format` | string | | `"png"` | `"png"` or `"jpeg"` (DCT only) |
|
||
| `color_mode` | string | | `"color"` | `"color"` or `"grayscale"` (DCT only) |
|
||
|
||
\* 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",
|
||
"day_of_week": "Saturday",
|
||
"embedding_mode": "lsb",
|
||
"output_format": "png",
|
||
"color_mode": null
|
||
}
|
||
```
|
||
|
||
#### Response Fields
|
||
|
||
| Field | Type | Description |
|
||
|-------|------|-------------|
|
||
| `stego_image_base64` | string | Base64-encoded stego image |
|
||
| `filename` | string | Suggested filename |
|
||
| `capacity_used_percent` | float | Percentage of capacity used |
|
||
| `date_used` | string | Date embedded in image (YYYY-MM-DD) |
|
||
| `day_of_week` | string | Day name for passphrase rotation |
|
||
| `embedding_mode` | string | Mode used: `"lsb"` or `"dct"` |
|
||
| `output_format` | string | Output format: `"png"` or `"jpeg"` |
|
||
| `color_mode` | string\|null | Color mode (DCT only): `"color"` or `"grayscale"` |
|
||
|
||
#### cURL Example (LSB Mode - Default)
|
||
|
||
```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
|
||
```
|
||
|
||
#### cURL Example (DCT Mode with JPEG Output)
|
||
|
||
```bash
|
||
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\",
|
||
\"embedding_mode\": \"dct\",
|
||
\"output_format\": \"jpeg\",
|
||
\"color_mode\": \"color\"
|
||
}" | jq -r '.stego_image_base64' | base64 -d > stego.jpg
|
||
```
|
||
|
||
---
|
||
|
||
### 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="embedding_mode"
|
||
|
||
dct
|
||
------FormBoundary
|
||
Content-Disposition: form-data; name="output_format"
|
||
|
||
jpeg
|
||
------FormBoundary
|
||
Content-Disposition: form-data; name="color_mode"
|
||
|
||
color
|
||
------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 | Default | 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) |
|
||
| `embedding_mode` | string | | `"lsb"` | `"lsb"` or `"dct"` |
|
||
| `output_format` | string | | `"png"` | `"png"` or `"jpeg"` (DCT only) |
|
||
| `color_mode` | string | | `"color"` | `"color"` or `"grayscale"` (DCT only) |
|
||
|
||
\* At least one of `pin` or `rsa_key` required.
|
||
|
||
#### Response
|
||
|
||
Returns the image directly with headers:
|
||
|
||
```http
|
||
HTTP/1.1 200 OK
|
||
Content-Type: image/png
|
||
Content-Disposition: attachment; filename="a1b2c3d4_20251227.png"
|
||
X-Stegasoo-Date: 2025-12-27
|
||
X-Stegasoo-Day: Saturday
|
||
X-Stegasoo-Capacity-Used: 12.4
|
||
X-Stegasoo-Embedding-Mode: lsb
|
||
X-Stegasoo-Output-Format: png
|
||
|
||
<binary image data>
|
||
```
|
||
|
||
#### Response Headers
|
||
|
||
| Header | Description |
|
||
|--------|-------------|
|
||
| `Content-Type` | `image/png` or `image/jpeg` |
|
||
| `Content-Disposition` | Suggested filename |
|
||
| `X-Stegasoo-Date` | Encoding date |
|
||
| `X-Stegasoo-Day` | Day of week |
|
||
| `X-Stegasoo-Capacity-Used` | Capacity percentage |
|
||
| `X-Stegasoo-Embedding-Mode` | `lsb` or `dct` |
|
||
| `X-Stegasoo-Output-Format` | `png` or `jpeg` |
|
||
| `X-Stegasoo-Color-Mode` | `color` or `grayscale` (DCT only) |
|
||
|
||
#### cURL Example (DCT + JPEG)
|
||
|
||
```bash
|
||
curl -X POST http://localhost:8000/encode/multipart \
|
||
-F "message=Secret message for social media" \
|
||
-F "day_phrase=apple forest thunder" \
|
||
-F "pin=123456" \
|
||
-F "embedding_mode=dct" \
|
||
-F "output_format=jpeg" \
|
||
-F "color_mode=color" \
|
||
-F "reference_photo=@reference.jpg" \
|
||
-F "carrier=@carrier.png" \
|
||
--output stego.jpg
|
||
```
|
||
|
||
---
|
||
|
||
### POST /decode (JSON)
|
||
|
||
Decode a message using base64-encoded images. Auto-detects embedding mode.
|
||
|
||
#### 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 security factors used during encoding.
|
||
|
||
#### Response
|
||
|
||
```json
|
||
{
|
||
"message": "Secret message here",
|
||
"embedding_mode_detected": "dct"
|
||
}
|
||
```
|
||
|
||
#### Response Fields
|
||
|
||
| Field | Type | Description |
|
||
|-------|------|-------------|
|
||
| `message` | string | Decoded message |
|
||
| `embedding_mode_detected` | string | Detected mode: `"lsb"` or `"dct"` |
|
||
|
||
#### cURL Example
|
||
|
||
```bash
|
||
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 using direct file uploads. Auto-detects embedding mode.
|
||
|
||
#### 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 (.pem) |
|
||
| `rsa_password` | string | | Password for RSA key |
|
||
|
||
#### Response
|
||
|
||
```json
|
||
{
|
||
"message": "Secret message here",
|
||
"embedding_mode_detected": "lsb"
|
||
}
|
||
```
|
||
|
||
#### cURL Example
|
||
|
||
```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"
|
||
```
|
||
|
||
---
|
||
|
||
### POST /image/info
|
||
|
||
Get image information and capacity for both LSB and DCT modes.
|
||
|
||
#### Request (JSON)
|
||
|
||
```http
|
||
POST /image/info HTTP/1.1
|
||
Host: localhost:8000
|
||
Content-Type: application/json
|
||
|
||
```
|
||
|
||
#### Request (Multipart)
|
||
|
||
```bash
|
||
curl -X POST http://localhost:8000/image/info \
|
||
-F "image=@carrier.png"
|
||
```
|
||
|
||
#### Response
|
||
|
||
```json
|
||
{
|
||
"width": 1920,
|
||
"height": 1080,
|
||
"pixels": 2073600,
|
||
"format": "PNG",
|
||
"mode": "RGB",
|
||
"capacity": {
|
||
"lsb": {
|
||
"bytes": 776970,
|
||
"kb": 758
|
||
},
|
||
"dct": {
|
||
"bytes": 64800,
|
||
"kb": 63,
|
||
"note": "Approximate - actual capacity depends on image content"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
#### Response Fields
|
||
|
||
| Field | Type | Description |
|
||
|-------|------|-------------|
|
||
| `width` | integer | Image width in pixels |
|
||
| `height` | integer | Image height in pixels |
|
||
| `pixels` | integer | Total pixel count |
|
||
| `format` | string | Image format (PNG, JPEG, etc.) |
|
||
| `mode` | string | Color mode (RGB, L, etc.) |
|
||
| `capacity.lsb.bytes` | integer | LSB capacity in bytes |
|
||
| `capacity.lsb.kb` | integer | LSB capacity in KB |
|
||
| `capacity.dct.bytes` | integer | Estimated DCT capacity in bytes |
|
||
| `capacity.dct.kb` | integer | Estimated DCT capacity in KB |
|
||
| `capacity.dct.note` | string | Capacity estimation note |
|
||
|
||
---
|
||
|
||
## Embedding Modes
|
||
|
||
### LSB Mode (Default)
|
||
|
||
**Least Significant Bit** embedding modifies pixel values directly.
|
||
|
||
| Aspect | Details |
|
||
|--------|---------|
|
||
| **Parameter** | `"embedding_mode": "lsb"` |
|
||
| **Capacity** | ~3 bits/pixel (~770 KB for 1920×1080) |
|
||
| **Output** | PNG only (lossless required) |
|
||
| **Resilience** | ❌ Destroyed by JPEG compression |
|
||
| **Best For** | Maximum capacity, controlled channels |
|
||
|
||
### DCT Mode (Experimental)
|
||
|
||
**Discrete Cosine Transform** embedding hides data in frequency coefficients.
|
||
|
||
| Aspect | Details |
|
||
|--------|---------|
|
||
| **Parameter** | `"embedding_mode": "dct"` |
|
||
| **Capacity** | ~0.25 bits/pixel (~65 KB for 1920×1080) |
|
||
| **Output** | PNG or JPEG |
|
||
| **Resilience** | ✅ Survives JPEG compression |
|
||
| **Best For** | Social media, messaging apps |
|
||
|
||
> ⚠️ **Experimental**: DCT mode may have edge cases. Test with your workflow.
|
||
|
||
### DCT Options
|
||
|
||
| Option | Values | Default | Description |
|
||
|--------|--------|---------|-------------|
|
||
| `output_format` | `"png"`, `"jpeg"` | `"png"` | Output image format |
|
||
| `color_mode` | `"color"`, `"grayscale"` | `"color"` | Color processing mode |
|
||
|
||
### Capacity Comparison
|
||
|
||
| Mode | 1920×1080 Capacity |
|
||
|------|-------------------|
|
||
| LSB (PNG) | ~770 KB |
|
||
| DCT (PNG) | ~65 KB |
|
||
| DCT (JPEG) | ~30-50 KB |
|
||
|
||
---
|
||
|
||
## 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",
|
||
"embedding_mode": "lsb",
|
||
"output_format": "png",
|
||
"color_mode": "color"
|
||
}
|
||
```
|
||
|
||
### EncodeResponse
|
||
|
||
```json
|
||
{
|
||
"stego_image_base64": "string",
|
||
"filename": "string",
|
||
"capacity_used_percent": 12.4,
|
||
"date_used": "YYYY-MM-DD",
|
||
"day_of_week": "Saturday",
|
||
"embedding_mode": "lsb",
|
||
"output_format": "png",
|
||
"color_mode": null
|
||
}
|
||
```
|
||
|
||
### 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",
|
||
"embedding_mode_detected": "lsb"
|
||
}
|
||
```
|
||
|
||
### ImageInfoResponse
|
||
|
||
```json
|
||
{
|
||
"width": 1920,
|
||
"height": 1080,
|
||
"pixels": 2073600,
|
||
"format": "PNG",
|
||
"mode": "RGB",
|
||
"capacity": {
|
||
"lsb": {"bytes": 776970, "kb": 758},
|
||
"dct": {"bytes": 64800, "kb": 63, "note": "..."}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 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 |
|
||
| 400 | "Invalid embedding_mode" | Use `"lsb"` or `"dct"` |
|
||
| 400 | "output_format 'jpeg' requires embedding_mode 'dct'" | Use DCT mode for JPEG |
|
||
| 400 | "Message too long for DCT capacity" | Reduce message or use LSB |
|
||
| 401 | "Decryption failed. Check credentials." | Verify phrase, PIN, ref photo |
|
||
| 401 | "Invalid or missing Stegasoo header" | Wrong mode or corrupted image |
|
||
|
||
---
|
||
|
||
## 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 (LSB mode - default)
|
||
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)
|
||
|
||
# Encode using DCT mode for social media
|
||
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 for Instagram",
|
||
"day_phrase": "apple forest thunder",
|
||
"pin": "123456",
|
||
"embedding_mode": "dct",
|
||
"output_format": "jpeg",
|
||
"color_mode": "color"
|
||
})
|
||
|
||
with open("stego_social.jpg", "wb") as f:
|
||
f.write(response.content)
|
||
|
||
# Decode using multipart (auto-detects mode)
|
||
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"
|
||
})
|
||
|
||
result = response.json()
|
||
print(f"Decoded: {result['message']}")
|
||
print(f"Mode detected: {result['embedding_mode_detected']}")
|
||
```
|
||
|
||
### 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 encodeDCT() {
|
||
const form = new FormData();
|
||
form.append('message', 'Secret message for social media');
|
||
form.append('day_phrase', 'apple forest thunder');
|
||
form.append('pin', '123456');
|
||
form.append('embedding_mode', 'dct');
|
||
form.append('output_format', 'jpeg');
|
||
form.append('color_mode', 'color');
|
||
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.jpg', response.data);
|
||
console.log('Encoded with DCT mode');
|
||
console.log('Embedding mode:', response.headers['x-stegasoo-embedding-mode']);
|
||
}
|
||
|
||
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.jpg'));
|
||
|
||
const response = await axios.post(`${BASE_URL}/decode/multipart`, form, {
|
||
headers: form.getHeaders()
|
||
});
|
||
|
||
console.log('Decoded:', response.data.message);
|
||
console.log('Mode detected:', response.data.embedding_mode_detected);
|
||
}
|
||
|
||
encodeDCT().then(decode);
|
||
```
|
||
|
||
### Go
|
||
|
||
```go
|
||
package main
|
||
|
||
import (
|
||
"bytes"
|
||
"encoding/json"
|
||
"fmt"
|
||
"io"
|
||
"mime/multipart"
|
||
"net/http"
|
||
"os"
|
||
)
|
||
|
||
func main() {
|
||
// Encode with DCT mode
|
||
body := &bytes.Buffer{}
|
||
writer := multipart.NewWriter(body)
|
||
|
||
writer.WriteField("message", "Secret message")
|
||
writer.WriteField("day_phrase", "apple forest thunder")
|
||
writer.WriteField("pin", "123456")
|
||
writer.WriteField("embedding_mode", "dct")
|
||
writer.WriteField("output_format", "jpeg")
|
||
writer.WriteField("color_mode", "color")
|
||
|
||
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,
|
||
)
|
||
|
||
// Check embedding mode from header
|
||
fmt.Println("Embedding mode:", resp.Header.Get("X-Stegasoo-Embedding-Mode"))
|
||
|
||
stego, _ := os.Create("stego.jpg")
|
||
io.Copy(stego, resp.Body)
|
||
stego.Close()
|
||
resp.Body.Close()
|
||
|
||
fmt.Println("Encoded successfully with DCT mode")
|
||
}
|
||
```
|
||
|
||
### 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 with LSB (default)
|
||
echo "Encoding with LSB mode..."
|
||
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_lsb.png
|
||
|
||
echo "Encoded to stego_lsb.png"
|
||
|
||
# Encode with DCT for social media
|
||
echo "Encoding with DCT mode..."
|
||
curl -s -X POST "$BASE_URL/encode/multipart" \
|
||
-F "message=$MESSAGE" \
|
||
-F "day_phrase=$PHRASE" \
|
||
-F "pin=$PIN" \
|
||
-F "embedding_mode=dct" \
|
||
-F "output_format=jpeg" \
|
||
-F "color_mode=color" \
|
||
-F "reference_photo=@$REF_PHOTO" \
|
||
-F "carrier=@$CARRIER" \
|
||
--output stego_dct.jpg
|
||
|
||
echo "Encoded to stego_dct.jpg"
|
||
|
||
# Decode (auto-detects mode)
|
||
echo "Decoding..."
|
||
RESULT=$(curl -s -X POST "$BASE_URL/decode/multipart" \
|
||
-F "day_phrase=$PHRASE" \
|
||
-F "pin=$PIN" \
|
||
-F "reference_photo=@$REF_PHOTO" \
|
||
-F "stego_image=@stego_dct.jpg")
|
||
|
||
echo "Decoded message: $(echo $RESULT | jq -r '.message')"
|
||
echo "Mode detected: $(echo $RESULT | jq -r '.embedding_mode_detected')"
|
||
```
|
||
|
||
---
|
||
|
||
## 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
|
||
- DCT mode adds ~100MB for scipy operations
|
||
- Concurrent requests can exhaust memory
|
||
- Limit workers based on available RAM
|
||
|
||
**Worker calculation:**
|
||
```
|
||
workers = (available_RAM - 512MB) / 350MB
|
||
```
|
||
|
||
### 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
|
||
- Embedding mode values
|
||
- Output format compatibility
|
||
|
||
### Credential Handling
|
||
|
||
- Credentials are never logged
|
||
- No persistent storage of secrets
|
||
- Memory cleared after operations
|
||
|
||
### Embedding Mode Security
|
||
|
||
| Mode | Consideration |
|
||
|------|--------------|
|
||
| LSB | Maximum capacity but fragile |
|
||
| DCT | Lower capacity but survives recompression |
|
||
|
||
Both modes use identical encryption (AES-256-GCM with Argon2id).
|
||
|
||
---
|
||
|
||
## 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
|