Skip to content

Latest commit

 

History

15 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Conceal - Image Steganography Service

A modular Flask web service for hiding secret messages (text or images) inside cover images using advanced steganography techniques with MLEA encryption.

Features

Core Functionality

  • Dual Payload Support: Hide both text messages and images
  • MLEA Encryption: Multi-Layer Encryption Algorithm with SHA-256 key derivation
  • LSB Steganography: Embeds data in blue channel least significant bits
  • Deterministic Shuffling: Block-based shuffling with key-derived seeds
  • Quality Metrics: RMSE and PSNR calculations for stego image quality

Web Interface

  • Modern UI: Responsive design with custom CSS design system
  • Interactive Gallery: Choose from predefined cover images or upload custom ones
  • Real-time Preview: Live image previews during upload
  • AJAX Integration: Seamless form submission without page reloads
  • Error Handling: User-friendly error messages and validation

API

  • REST API: Clean JSON endpoints for embedding and extraction
  • Type Safety: Python 3.10+ with type hints throughout
  • Comprehensive Tests: 45+ passing tests covering all functionality

Algorithm Overview

The steganography algorithm implements:

  1. Cover Image Transformation: Horizontal flip → Transpose → RGB conversion
  2. Blue Channel Processing: Split into 4 horizontal blocks, shuffle deterministically
  3. MLEA Encryption: 3-round encryption with XOR, byte rotation, and reversal
  4. 64-bit Header Format:
    • Magic number (0xC0DE, 16 bits)
    • Version (8 bits)
    • Payload type (8 bits: 0=text, 1=image)
    • Encrypted length (32 bits)
  5. LSB Embedding: Round-robin embedding across shuffled blocks
  6. Reconstruction: Unshuffle, merge channels, reverse transformations

Quick Start

Installation

# Clone the repository
git clone <your-repo-url>
cd conceal

# Install dependencies
pip install -r requirements.txt

# Copy environment template
cp .env.sample .env

# (Optional) Edit .env with your configuration
nano .env

Running the Application

# Development mode (recommended)
flask --app wsgi:app run --debug --port 5001

# Production mode
python wsgi.py

The application will start on http://127.0.0.1:5001 by default.

Access the Web Interface:

  • Homepage: http://127.0.0.1:5001/
  • Embed Secret: http://127.0.0.1:5001/embed
  • Extract Secret: http://127.0.0.1:5001/extract

API Endpoints:

  • Base URL: http://127.0.0.1:5001/api

Running Tests

# Run all tests
pytest -v

# Run specific test file
pytest tests/test_crypto.py -v

# Run with coverage
pytest --cov=app tests/

Web Interface Usage

The application includes a modern web interface for easy interaction with the steganography service.

Embedding a Secret

  1. Navigate to http://127.0.0.1:5001/embed
  2. Choose Cover Image:
    • Select "Use Predefined Image" and click on a gallery image, OR
    • Select "Upload Image" and choose a custom cover image
  3. Select Secret Type:
    • Choose "Text" and enter your secret message, OR
    • Choose "Image" and upload a secret image
  4. Enter Encryption Key: Provide a strong key for encryption
  5. Optional: Set a custom output filename and shuffle seed
  6. Click "Embed Secret" to generate the stego image
  7. Download the result or copy the link to the generated stego image

Extracting a Secret

  1. Navigate to http://127.0.0.1:5001/extract
  2. Upload Stego Image: Choose the image containing the hidden message
  3. Enter Key: Provide the same key used during embedding
  4. Click "Extract Secret" to reveal the hidden content
  5. View the extracted text or download the extracted image

Features

  • Gallery Selection: 5 predefined high-quality cover images available
  • Image Preview: See thumbnails before embedding/extracting
  • Real-time Validation: Form validation with helpful error messages
  • Download Results: Direct download links for generated images
  • Metrics Display: View RMSE and PSNR quality metrics after embedding

API Documentation

Base URL

http://127.0.0.1:5001/api

Endpoints

1. Health Check

GET /api/health

Response:

{
  "status": "ok"
}

2. Embed Secret

POST /api/embed
Content-Type: multipart/form-data

Parameters:

Field Type Required Description
cover_image file No* Cover image (png/jpg/jpeg)
predefined_cover_image string No* Predefined image filename (e.g., "babylon.png")
secret_text string No** Secret text message
secret_image file No** Secret image (png/jpg/jpeg)
key string Yes Encryption key
seed integer No Custom shuffle seed (default: derived from key)
output_name string No Output filename stem (default: UUID)

* Exactly one of cover_image or predefined_cover_image must be provided.
** Exactly one of secret_text or secret_image must be provided.

Predefined Cover Images:

  • babylon.png
  • Lena.png
  • pepper.png
  • stock_image1.jpg
  • stock_image2.jpg

Example - Embed Text:

curl -X POST http://127.0.0.1:5001/api/embed \
  -F "cover_image=@cover.png" \
  -F "secret_text=This is my secret message!" \
  -F "key=mySecretKey123"

Example - Embed Text with Predefined Cover:

curl -X POST http://127.0.0.1:5001/api/embed \
  -F "predefined_cover_image=babylon.png" \
  -F "secret_text=This is my secret message!" \
  -F "key=mySecretKey123"

Example - Embed Image:

curl -X POST http://127.0.0.1:5001/api/embed \
  -F "cover_image=@cover.png" \
  -F "secret_image=@secret.png" \
  -F "key=mySecretKey123" \
  -F "output_name=my_stego"

Success Response (200):

{
  "stego_filename": "my_stego.png",
  "width": 1024,
  "height": 768,
  "payload_type": "text",
  "payload_size_bytes": 27,
  "metrics": {
    "rmse": 0.4523,
    "psnr": 54.23
  }
}

Error Response (400):

{
  "error": "Payload too large: need 524288 bits, capacity 196608 bits"
}

3. Extract Secret

POST /api/extract
Content-Type: multipart/form-data

Parameters:

Field Type Required Description
stego_image file Yes Stego image containing hidden message
key string Yes Decryption key (must match embedding key)

Example:

curl -X POST http://127.0.0.1:5001/api/extract \
  -F "stego_image=@stego.png" \
  -F "key=mySecretKey123"

Success Response (200) - Text:

{
  "payload_type": "text",
  "secret_text": "This is my secret message!",
  "payload_size_bytes": 27
}

Success Response (200) - Image:

{
  "payload_type": "image",
  "secret_image_base64": "iVBORw0KGgoAAAANSUhEUgAA...",
  "payload_size_bytes": 15234
}

Error Response (400):

{
  "error": "Invalid magic number: 0xABCD (expected 0xC0DE)"
}

Project Structure

conceal/
├── app/
│   ├── __init__.py           # Flask app factory
│   ├── config.py             # Configuration
│   ├── routes/
│   │   ├── __init__.py
│   │   ├── frontend.py       # Frontend routes (/, /embed, /extract)
│   │   └── stego.py          # REST API endpoints
│   ├── services/
│   │   ├── __init__.py
│   │   ├── crypto.py         # MLEA encryption
│   │   └── steganography.py  # Embed/extract logic
│   ├── templates/            # Jinja2 HTML templates
│   │   ├── base.html         # Base template with navbar
│   │   ├── index.html        # Landing page
│   │   ├── embed.html        # Embed secret page
│   │   └── extract.html      # Extract secret page
│   └── utils/
│       ├── __init__.py
│       ├── image_codec.py    # Image ↔ base64 conversion
│       ├── metrics.py        # RMSE, PSNR
│       └── shuffle.py        # Block shuffling
├── static/
│   ├── css/
│   │   └── style.css         # Custom styles & design system
│   ├── js/
│   │   ├── main.js           # Shared utilities
│   │   ├── embed.js          # Embed page logic
│   │   └── extract.js        # Extract page logic
│   ├── predefined/           # Predefined cover images
│   │   ├── babylon.png
│   │   ├── Lena.png
│   │   ├── pepper.png
│   │   ├── stock_image1.jpg
│   │   └── stock_image2.jpg
│   └── uploads/              # Generated stego images
├── tests/
│   ├── __init__.py
│   ├── test_api.py
│   ├── test_crypto.py
│   ├── test_image_codec.py
│   └── test_steganography.py
├── .env.sample               # Environment template
├── .gitignore                # Git ignore rules
├── requirements.txt          # Python dependencies
├── wsgi.py                   # WSGI entry point
└── README.md                 # This file

Usage Examples

Python Client Example

import requests

# Embed text
with open('cover.png', 'rb') as f:
    response = requests.post(
        'http://127.0.0.1:5001/api/embed',
        files={'cover_image': f},
        data={
            'secret_text': 'My secret message',
            'key': 'my-encryption-key'
        }
    )
    
result = response.json()
print(f"Stego image: {result['stego_filename']}")
print(f"PSNR: {result['metrics']['psnr']} dB")

# Extract
with open(f"static/uploads/{result['stego_filename']}", 'rb') as f:
    response = requests.post(
        'http://127.0.0.1:5001/api/extract',
        files={'stego_image': f},
        data={'key': 'my-encryption-key'}
    )
    
secret = response.json()
print(f"Extracted: {secret['secret_text']}")

Image Extraction Example

import requests
import base64
import cv2
import numpy as np

# Extract image
with open('stego.png', 'rb') as f:
    response = requests.post(
        'http://127.0.0.1:5001/api/extract',
        files={'stego_image': f},
        data={'key': 'my-key'}
    )

result = response.json()

if result['payload_type'] == 'image':
    # Decode base64 to image
    img_bytes = base64.b64decode(result['secret_image_base64'])
    img_array = np.frombuffer(img_bytes, dtype=np.uint8)
    secret_img = cv2.imdecode(img_array, cv2.IMREAD_COLOR)
    
    # Save or display
    cv2.imwrite('extracted_secret.png', secret_img)

Configuration

Environment variables (in .env file):

# Flask environment (development|production)
FLASK_ENV=development

# Secret key for Flask sessions
SECRET_KEY=your-secret-key-here-change-in-production

# Maximum upload size in bytes (50MB for large cover/stego images)
MAX_CONTENT_LENGTH=52428800

Capacity Calculation

The capacity depends on the cover image size:

Capacity (bits) = width × height (of blue channel after transformation)

For example:

  • 512×512 image: ~262,144 bits (~32 KB)
  • 1024×1024 image: ~1,048,576 bits (~128 KB)
  • 2048×2048 image: ~4,194,304 bits (~512 KB)

Remember: Payload is encrypted before embedding, so encrypted size may be larger than original.

Security Considerations

  • Key Management: Use strong, unique keys for each use case
  • HTTPS: Use HTTPS in production to protect keys in transit
  • Deterministic Seed: Seed is derived from key by default, ensuring reproducibility
  • Header Validation: Magic number validation prevents accidental extraction
  • Encryption: MLEA provides confidentiality even if stego image is detected

Testing

The test suite includes:

  • Unit tests: Crypto, image codec, metrics, shuffle utilities
  • Integration tests: Embed/extract roundtrips for text and images
  • API tests: All endpoints with success and error cases

Run specific test categories:

# Test cryptography
pytest tests/test_crypto.py -v

# Test steganography
pytest tests/test_steganography.py -v

# Test API
pytest tests/test_api.py -v

Metrics

RMSE (Root Mean Square Error)

Measures pixel-level differences between cover and stego images. Lower is better (0 = identical).

PSNR (Peak Signal-to-Noise Ratio)

Measures image quality in dB. Higher is better (infinity = identical). Typically:

  • > 40 dB: Excellent quality
  • 30-40 dB: Good quality
  • < 30 dB: Noticeable degradation

License

See LICENSE file for details.

Acknowledgments

Based on the image steganography algorithm described in the research on LSB embedding with block shuffling and multi-layer encryption.

Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Support

For issues, questions, or contributions, please open an issue on the GitHub repository.

About

Conceal - Image Steganography Service

Topics

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages