Files
stegasoo/frontends/API.md
2026-01-01 14:04:55 -05:00

1229 lines
29 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Stegasoo REST API Documentation (v3.2.0)
Complete REST API reference for Stegasoo steganography operations.
## Table of Contents
- [Overview](#overview)
- [What's New in v3.2.0](#whats-new-in-v320)
- [Installation](#installation)
- [Authentication](#authentication)
- [Base URL](#base-url)
- [Endpoints](#endpoints)
- [GET /](#get--status)
- [GET /modes](#get-modes)
- [POST /generate](#post-generate)
- [POST /encode](#post-encode-json)
- [POST /encode/file](#post-encodefile)
- [POST /encode/multipart](#post-encodemultipart)
- [POST /decode](#post-decode-json)
- [POST /decode/multipart](#post-decodemultipart)
- [POST /compare](#post-compare)
- [POST /will-fit](#post-will-fit)
- [POST /image/info](#post-imageinfo)
- [POST /extract-key-from-qr](#post-extract-key-from-qr)
- [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 (passphrase, PINs, RSA keys)
- **Encode** messages or files into images (LSB or DCT mode)
- **Decode** messages or files from images (auto-detects mode)
- **Analyze** image capacity and compare modes
The API supports both JSON (base64-encoded images) and multipart form data (direct file uploads).
---
## What's New in v3.2.0
Version 3.2.0 introduces breaking changes to simplify the API:
| Change | Before (v3.1) | After (v3.2.0) |
|--------|---------------|----------------|
| Passphrase | Daily rotation (`phrases` dict) | Single `passphrase` string |
| Date parameter | `date_str` required/optional | Removed entirely |
| Field name | `day_phrase` | `passphrase` |
| Default words | 3 words | 4 words |
**Key benefits:**
- ✅ No need to track encoding dates
- ✅ Simpler request/response models
- ✅ True asynchronous communications
- ✅ Stronger default security (4 words = ~44 bits)
**Breaking Change:** v3.2.0 cannot decode images created with v3.1.x due to different key derivation.
---
## Installation
### From PyPI
```bash
pip install stegasoo[api]
```
This automatically installs DCT dependencies (scipy) 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.2.0",
"has_argon2": true,
"has_qrcode_read": true,
"has_dct": true,
"max_payload_kb": 500,
"available_modes": ["lsb", "dct"],
"dct_features": {
"output_formats": ["png", "jpeg"],
"color_modes": ["grayscale", "color"],
"default_output_format": "png",
"default_color_mode": "grayscale"
},
"breaking_changes": {
"date_removed": "No date_str parameter needed - encode/decode anytime",
"passphrase_renamed": "day_phrase → passphrase (single passphrase, no daily rotation)",
"format_version": 4,
"backward_compatible": false
}
}
```
#### Response Fields
| Field | Type | Description |
|-------|------|-------------|
| `version` | string | Stegasoo library version |
| `has_argon2` | boolean | Whether Argon2id is available |
| `has_qrcode_read` | boolean | Whether QR code reading is available |
| `has_dct` | boolean | Whether DCT mode is available (scipy) |
| `max_payload_kb` | integer | Maximum payload size in KB |
| `available_modes` | array | Available embedding modes |
| `dct_features` | object | DCT mode options (if available) |
| `breaking_changes` | object | v3.2.0 breaking changes info |
#### cURL Example
```bash
curl http://localhost:8000/
```
---
### GET /modes
Get available embedding modes and their status.
#### Request
```http
GET /modes HTTP/1.1
Host: localhost:8000
```
#### Response
```json
{
"lsb": {
"available": true,
"name": "Spatial LSB",
"description": "Embed in pixel LSBs, outputs PNG/BMP",
"output_format": "PNG (color)",
"capacity_ratio": "100%"
},
"dct": {
"available": true,
"name": "DCT Domain",
"description": "Embed in DCT coefficients, frequency domain steganography",
"output_formats": ["png", "jpeg"],
"color_modes": ["grayscale", "color"],
"capacity_ratio": "~20% of LSB",
"requires": "scipy"
}
}
```
---
### 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_passphrase` | integer | `4` | Words per passphrase (3-12) |
#### Response
```json
{
"passphrase": "abandon ability able about",
"pin": "847293",
"rsa_key_pem": null,
"entropy": {
"passphrase": 44,
"pin": 19,
"rsa": 0,
"total": 63
},
"phrases": null
}
```
#### Response Fields
| Field | Type | Description |
|-------|------|-------------|
| `passphrase` | string | Single passphrase (v3.2.0) |
| `pin` | string\|null | Generated PIN (if requested) |
| `rsa_key_pem` | string\|null | PEM-encoded RSA key (if requested) |
| `entropy.passphrase` | integer | Entropy from passphrase (bits) |
| `entropy.pin` | integer | Entropy from PIN (bits) |
| `entropy.rsa` | integer | Entropy from RSA key (bits) |
| `entropy.total` | integer | Combined entropy (bits) |
| `phrases` | null | Deprecated field (always null in v3.2.0) |
#### cURL Examples
**Default (PIN with 4-word passphrase):**
```bash
curl -X POST http://localhost:8000/generate \
-H "Content-Type: application/json" \
-d '{"use_pin": true}'
```
**RSA only with 6-word passphrase:**
```bash
curl -X POST http://localhost:8000/generate \
-H "Content-Type: application/json" \
-d '{"use_pin": false, "use_rsa": true, "rsa_bits": 4096, "words_per_passphrase": 6}'
```
**Both PIN and RSA:**
```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_passphrase": 6
}'
```
---
### POST /encode (JSON)
Encode a text 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 |
| `passphrase` | string | ✓ | | Passphrase (v3.2.0) |
| `pin` | string | * | | Static PIN (6-9 digits) |
| `rsa_key_base64` | string | * | | Base64-encoded RSA key PEM |
| `rsa_password` | string | | | Password for RSA key |
| `embed_mode` | string | | `"lsb"` | `"lsb"` or `"dct"` |
| `dct_output_format` | string | | `"png"` | `"png"` or `"jpeg"` (DCT only) |
| `dct_color_mode` | string | | `"grayscale"` | `"grayscale"` or `"color"` (DCT only) |
\* At least one of `pin` or `rsa_key_base64` required.
#### Response
```json
{
"stego_image_base64": "iVBORw0KGgo...",
"filename": "a1b2c3d4.png",
"capacity_used_percent": 12.4,
"embed_mode": "lsb",
"output_format": "png",
"color_mode": "color",
"date_used": null,
"day_of_week": 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 |
| `embed_mode` | string | Mode used: `"lsb"` or `"dct"` |
| `output_format` | string | Output format: `"png"` or `"jpeg"` |
| `color_mode` | string | Color mode: `"color"` or `"grayscale"` |
| `date_used` | null | Deprecated (always null in v3.2.0) |
| `day_of_week` | null | Deprecated (always null in v3.2.0) |
#### cURL Example (LSB Mode)
```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\",
\"passphrase\": \"apple forest thunder mountain\",
\"pin\": \"123456\"
}" | jq -r '.stego_image_base64' | base64 -d > stego.png
```
#### cURL Example (DCT Mode with JPEG)
```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\",
\"passphrase\": \"apple forest thunder mountain\",
\"pin\": \"123456\",
\"embed_mode\": \"dct\",
\"dct_output_format\": \"jpeg\",
\"dct_color_mode\": \"color\"
}" | jq -r '.stego_image_base64' | base64 -d > stego.jpg
```
---
### POST /encode/file
Encode a binary file using base64-encoded data.
#### Request
```http
POST /encode/file HTTP/1.1
Host: localhost:8000
Content-Type: application/json
```
#### Request Body
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `file_data_base64` | string | ✓ | Base64-encoded file data |
| `filename` | string | ✓ | Original filename |
| `mime_type` | string | | MIME type of file |
| `reference_photo_base64` | string | ✓ | Base64-encoded reference photo |
| `carrier_image_base64` | string | ✓ | Base64-encoded carrier image |
| `passphrase` | string | ✓ | Passphrase |
| `pin` | string | * | Static PIN |
| `rsa_key_base64` | string | * | Base64-encoded RSA key |
| `embed_mode` | string | | `"lsb"` or `"dct"` |
| `dct_output_format` | string | | `"png"` or `"jpeg"` |
| `dct_color_mode` | string | | `"grayscale"` or `"color"` |
#### Response
Same as `/encode` endpoint.
---
### POST /encode/multipart
Encode using direct file uploads. Returns the stego image directly.
#### Form Fields
| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `passphrase` | string | ✓ | | Passphrase (v3.2.0) |
| `reference_photo` | file | ✓ | | Reference photo file |
| `carrier` | file | ✓ | | Carrier image file |
| `message` | string | * | | Text message to encode |
| `payload_file` | file | * | | Binary file to embed |
| `pin` | string | ** | | Static PIN |
| `rsa_key` | file | ** | | RSA key file (.pem) |
| `rsa_key_qr` | file | ** | | RSA key from QR code image |
| `rsa_password` | string | | | Password for RSA key |
| `embed_mode` | string | | `"lsb"` | `"lsb"` or `"dct"` |
| `dct_output_format` | string | | `"png"` | `"png"` or `"jpeg"` |
| `dct_color_mode` | string | | `"grayscale"` | `"grayscale"` or `"color"` |
\* At least one of `message` or `payload_file` required.
\*\* At least one of `pin`, `rsa_key`, or `rsa_key_qr` required.
#### Response
Returns the image directly with headers:
```http
HTTP/1.1 200 OK
Content-Type: image/png
Content-Disposition: attachment; filename="a1b2c3d4.png"
X-Stegasoo-Capacity-Percent: 12.4
X-Stegasoo-Embed-Mode: lsb
X-Stegasoo-Output-Format: png
X-Stegasoo-Color-Mode: color
X-Stegasoo-Version: 3.2.0
<binary image data>
```
#### Response Headers
| Header | Description |
|--------|-------------|
| `Content-Type` | `image/png` or `image/jpeg` |
| `Content-Disposition` | Suggested filename |
| `X-Stegasoo-Capacity-Percent` | Capacity percentage used |
| `X-Stegasoo-Embed-Mode` | `lsb` or `dct` |
| `X-Stegasoo-Output-Format` | `png` or `jpeg` |
| `X-Stegasoo-Color-Mode` | `color` or `grayscale` |
| `X-Stegasoo-Version` | API version |
#### cURL Example (LSB)
```bash
curl -X POST http://localhost:8000/encode/multipart \
-F "passphrase=apple forest thunder mountain" \
-F "pin=123456" \
-F "message=Secret message" \
-F "reference_photo=@reference.jpg" \
-F "carrier=@carrier.png" \
--output stego.png
```
#### cURL Example (DCT + JPEG)
```bash
curl -X POST http://localhost:8000/encode/multipart \
-F "passphrase=apple forest thunder mountain" \
-F "pin=123456" \
-F "message=Secret message for social media" \
-F "embed_mode=dct" \
-F "dct_output_format=jpeg" \
-F "dct_color_mode=color" \
-F "reference_photo=@reference.jpg" \
-F "carrier=@carrier.png" \
--output stego.jpg
```
#### cURL Example (Embed File)
```bash
curl -X POST http://localhost:8000/encode/multipart \
-F "passphrase=apple forest thunder mountain" \
-F "pin=123456" \
-F "payload_file=@secret.pdf" \
-F "reference_photo=@reference.jpg" \
-F "carrier=@carrier.png" \
--output stego.png
```
---
### POST /decode (JSON)
Decode a message or file 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 | Default | Description |
|-------|------|----------|---------|-------------|
| `stego_image_base64` | string | ✓ | | Base64-encoded stego image |
| `reference_photo_base64` | string | ✓ | | Base64-encoded reference photo |
| `passphrase` | string | ✓ | | Passphrase |
| `pin` | string | * | | Static PIN |
| `rsa_key_base64` | string | * | | Base64-encoded RSA key |
| `rsa_password` | string | | | Password for RSA key |
| `embed_mode` | string | | `"auto"` | `"auto"`, `"lsb"`, or `"dct"` |
\* Must match security factors used during encoding.
#### Response (Text)
```json
{
"payload_type": "text",
"message": "Secret message here",
"file_data_base64": null,
"filename": null,
"mime_type": null
}
```
#### Response (File)
```json
{
"payload_type": "file",
"message": null,
"file_data_base64": "JVBERi0xLjQK...",
"filename": "secret.pdf",
"mime_type": "application/pdf"
}
```
#### Response Fields
| Field | Type | Description |
|-------|------|-------------|
| `payload_type` | string | `"text"` or `"file"` |
| `message` | string\|null | Decoded message (if text) |
| `file_data_base64` | string\|null | Base64-encoded file (if file) |
| `filename` | string\|null | Original filename (if file) |
| `mime_type` | string\|null | MIME type (if file) |
#### 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\",
\"passphrase\": \"apple forest thunder mountain\",
\"pin\": \"123456\"
}"
```
---
### POST /decode/multipart
Decode using direct file uploads. Auto-detects embedding mode.
#### Form Fields
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `passphrase` | string | ✓ | Passphrase |
| `reference_photo` | file | ✓ | Reference photo file |
| `stego_image` | file | ✓ | Stego image file |
| `pin` | string | * | Static PIN |
| `rsa_key` | file | * | RSA key file (.pem) |
| `rsa_key_qr` | file | * | RSA key from QR code image |
| `rsa_password` | string | | Password for RSA key |
| `embed_mode` | string | | `"auto"`, `"lsb"`, or `"dct"` |
#### Response
Same JSON format as `/decode` endpoint.
#### cURL Example
```bash
curl -X POST http://localhost:8000/decode/multipart \
-F "passphrase=apple forest thunder mountain" \
-F "pin=123456" \
-F "reference_photo=@reference.jpg" \
-F "stego_image=@stego.png"
```
---
### POST /compare
Compare LSB and DCT embedding modes for a carrier image.
#### Request
```http
POST /compare HTTP/1.1
Host: localhost:8000
Content-Type: application/json
```
#### Request Body
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `carrier_image_base64` | string | ✓ | Base64-encoded carrier image |
| `payload_size` | integer | | Optional payload size to check |
#### Response
```json
{
"width": 1920,
"height": 1080,
"lsb": {
"capacity_bytes": 776970,
"capacity_kb": 758.8,
"available": true,
"output_format": "PNG"
},
"dct": {
"capacity_bytes": 64800,
"capacity_kb": 63.3,
"available": true,
"output_formats": ["png", "jpeg"],
"color_modes": ["grayscale", "color"],
"ratio_vs_lsb_percent": 8.3
},
"payload_check": {
"size_bytes": 50000,
"fits_lsb": true,
"fits_dct": true
},
"recommendation": "dct (payload fits, better stealth)"
}
```
---
### POST /will-fit
Check if a payload of given size will fit in a carrier image.
#### Request
```http
POST /will-fit HTTP/1.1
Host: localhost:8000
Content-Type: application/json
```
#### Response
```json
{
"fits": true,
"payload_size": 50000,
"capacity": 776970,
"usage_percent": 6.4,
"headroom": 726970,
"mode": "lsb"
}
```
---
### POST /image/info
Get image information and capacity.
#### Request (Multipart)
```bash
curl -X POST http://localhost:8000/image/info \
-F "image=@carrier.png"
```
#### Response
```json
{
"width": 1920,
"height": 1080,
"pixels": 2073600,
"capacity_bytes": 776970,
"capacity_kb": 758,
"modes": {
"lsb": {
"capacity_bytes": 776970,
"capacity_kb": 758.8,
"available": true,
"output_format": "PNG"
},
"dct": {
"capacity_bytes": 64800,
"capacity_kb": 63.3,
"available": true,
"output_format": "PNG/JPEG (grayscale or color)"
}
}
}
```
---
### POST /extract-key-from-qr
Extract RSA key from a QR code image.
#### Request (Multipart)
```bash
curl -X POST http://localhost:8000/extract-key-from-qr \
-F "qr_image=@keyqr.png"
```
#### Response
```json
{
"success": true,
"key_pem": "-----BEGIN PRIVATE KEY-----\n...",
"error": null
}
```
---
## Embedding Modes
### LSB Mode (Default)
**Least Significant Bit** embedding modifies pixel values directly.
| Aspect | Details |
|--------|---------|
| **Parameter** | `"embed_mode": "lsb"` |
| **Capacity** | ~3 bits/pixel (~375 KB for 1920×1080) |
| **Output** | PNG only (lossless required) |
| **Resilience** | ❌ Destroyed by JPEG compression |
| **Best For** | Maximum capacity, controlled channels |
### DCT Mode
**Discrete Cosine Transform** embedding hides data in frequency coefficients.
| Aspect | Details |
|--------|---------|
| **Parameter** | `"embed_mode": "dct"` |
| **Capacity** | ~0.25 bits/pixel (~65 KB for 1920×1080) |
| **Output** | PNG or JPEG |
| **Resilience** | ✅ Better resistance to analysis |
| **Best For** | Stealth requirements |
### DCT Options
| Option | Values | Default | Description |
|--------|--------|---------|-------------|
| `dct_output_format` | `"png"`, `"jpeg"` | `"png"` | Output image format |
| `dct_color_mode` | `"grayscale"`, `"color"` | `"grayscale"` | Color processing mode |
### Capacity Comparison
| Mode | 1920×1080 Capacity |
|------|-------------------|
| LSB (PNG) | ~375 KB |
| DCT (PNG) | ~65 KB |
| DCT (JPEG) | ~50 KB |
---
## Data Models
### GenerateRequest
```json
{
"use_pin": true,
"use_rsa": false,
"pin_length": 6,
"rsa_bits": 2048,
"words_per_passphrase": 4
}
```
### GenerateResponse
```json
{
"passphrase": "word1 word2 word3 word4",
"pin": "123456",
"rsa_key_pem": null,
"entropy": {"passphrase": 44, "pin": 19, "rsa": 0, "total": 63},
"phrases": null
}
```
### EncodeRequest
```json
{
"message": "string",
"reference_photo_base64": "string",
"carrier_image_base64": "string",
"passphrase": "string",
"pin": "string",
"rsa_key_base64": "string",
"rsa_password": "string",
"embed_mode": "lsb",
"dct_output_format": "png",
"dct_color_mode": "grayscale"
}
```
### EncodeResponse
```json
{
"stego_image_base64": "string",
"filename": "string",
"capacity_used_percent": 12.4,
"embed_mode": "lsb",
"output_format": "png",
"color_mode": "color",
"date_used": null,
"day_of_week": null
}
```
### DecodeRequest
```json
{
"stego_image_base64": "string",
"reference_photo_base64": "string",
"passphrase": "string",
"pin": "string",
"rsa_key_base64": "string",
"rsa_password": "string",
"embed_mode": "auto"
}
```
### DecodeResponse
```json
{
"payload_type": "text",
"message": "string",
"file_data_base64": null,
"filename": null,
"mime_type": null
}
```
### ErrorResponse
```json
{
"detail": "Error message describing the problem"
}
```
---
## 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 |
| 501 | Not Implemented | Feature unavailable (e.g., QR without pyzbar) |
### 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 | "Carrier image too small" | Use larger carrier image |
| 400 | "DCT mode requires scipy" | Install scipy |
| 400 | "embed_mode must be 'lsb' or 'dct'" | Fix embed_mode value |
| 401 | "Decryption failed. Check credentials." | Verify passphrase, PIN, ref photo |
| 501 | "QR code reading not available" | Install pyzbar and libzbar |
---
## 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,
"words_per_passphrase": 4
})
creds = response.json()
print(f"Passphrase: {creds['passphrase']}")
print(f"PIN: {creds['pin']}")
# Encode using multipart (LSB mode)
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",
"passphrase": "apple forest thunder mountain",
"pin": "123456"
})
with open("stego.png", "wb") as f:
f.write(response.content)
# Encode with DCT 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",
"passphrase": "apple forest thunder mountain",
"pin": "123456",
"embed_mode": "dct",
"dct_output_format": "jpeg",
"dct_color_mode": "color"
})
with open("stego_social.jpg", "wb") as f:
f.write(response.content)
# Decode (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={
"passphrase": "apple forest thunder mountain",
"pin": "123456"
})
result = response.json()
if result['payload_type'] == 'text':
print(f"Decoded: {result['message']}")
else:
# Save decoded file
file_data = base64.b64decode(result['file_data_base64'])
with open(result['filename'], 'wb') as f:
f.write(file_data)
```
### 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 generate() {
const response = await axios.post(`${BASE_URL}/generate`, {
use_pin: true,
words_per_passphrase: 4
});
console.log('Passphrase:', response.data.passphrase);
console.log('PIN:', response.data.pin);
return response.data;
}
async function encode(passphrase, pin) {
const form = new FormData();
form.append('passphrase', passphrase);
form.append('pin', pin);
form.append('message', 'Secret message');
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 to stego.png');
}
async function decode(passphrase, pin) {
const form = new FormData();
form.append('passphrase', passphrase);
form.append('pin', pin);
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);
}
// Usage
generate()
.then(creds => encode(creds.passphrase, creds.pin))
.then(() => decode('apple forest thunder mountain', '123456'));
```
### Shell Script (Bash)
```bash
#!/bin/bash
BASE_URL="http://localhost:8000"
PASSPHRASE="apple forest thunder mountain"
PIN="123456"
# Generate credentials
echo "Generating credentials..."
CREDS=$(curl -s -X POST "$BASE_URL/generate" \
-H "Content-Type: application/json" \
-d '{"use_pin": true, "words_per_passphrase": 4}')
echo "Passphrase: $(echo $CREDS | jq -r '.passphrase')"
echo "PIN: $(echo $CREDS | jq -r '.pin')"
# Encode
echo "Encoding..."
curl -s -X POST "$BASE_URL/encode/multipart" \
-F "passphrase=$PASSPHRASE" \
-F "pin=$PIN" \
-F "message=Secret message" \
-F "reference_photo=@reference.jpg" \
-F "carrier=@carrier.png" \
--output stego.png
echo "Encoded to stego.png"
# Decode
echo "Decoding..."
RESULT=$(curl -s -X POST "$BASE_URL/decode/multipart" \
-F "passphrase=$PASSPHRASE" \
-F "pin=$PIN" \
-F "reference_photo=@reference.jpg" \
-F "stego_image=@stego.png")
echo "Decoded: $(echo $RESULT | jq -r '.message')"
```
---
## 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)
- Passphrase presence
- Image size limits
- RSA key validity
- Embedding mode values
- Output format compatibility
### 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
- [API Update Summary](api/API_UPDATE_SUMMARY_V3.2.0.md) - Migration guide
- [README](../README.md) - Project overview