pateon / steganography
Invisible anti-counterfeiting for images using LSB Steganography (PHP 8.5+). Supports Imagick and GD.
Installs: 6
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/pateon/steganography
Requires
- php: >=8.5.0
- ext-zlib: *
Requires (Dev)
- phpunit/phpunit: ^11.0
Suggests
- ext-gd: Required if Imagick is not available
- ext-imagick: Recommended for better performance and quality
README
A PHP 8.5+ library for invisible anti-counterfeiting of images using LSB (Least Significant Bit) Steganography. This library hides a secret message inside an image file, invisible to the human eye.
Features
- ✅ Invisible: Modifies only the Least Significant Bits (LSB) of RGB pixel values
- ✅ Compression: Compresses messages using Zlib before embedding
- ✅ Unicode Support: Full support for UTF-8, including CJK characters and emoji
- ✅ Dual Driver Support: Prioritizes
Imagick, falls back toGDautomatically - ✅ Format Support: Reads JPG, PNG, GIF, WebP, BMP as source images
- ✅ Lossless Output: Always outputs as PNG to preserve hidden data
- ✅ PHP 8.5+: Uses modern PHP features (typed constants, readonly properties, match expressions)
- ✅ Composer Ready: PSR-4 autoloading, ready for integration
Requirements
- PHP >= 8.5
ext-zlib(for compression)ext-imagick(recommended) ORext-gd(at least one is required)
Installation
composer require pateon/steganography
Usage
Basic Usage
use Steganography\Processor; $processor = new Processor(); // Encode a message into an image $image = $processor->encode('source.jpg', 'This is my secret message! 秘密訊息'); $image->save('output.png'); // MUST save as PNG (lossless) // Decode the message from the image $message = $processor->decode('output.png'); echo $message; // "This is my secret message! 秘密訊息"
Force Specific Adapter
$processor = new Processor(); // Force GD $processor->setPreferredAdapter('gd'); // Force Imagick $processor->setPreferredAdapter('imagick');
Calculate Maximum Message Size
$processor = new Processor(); $maxBytes = $processor->calculateMaxMessageSize('source.jpg'); echo "Max message size: ~{$maxBytes} bytes";
Custom Compressor
use Steganography\Processor; use Steganography\Compressor\ZlibCompressor; $processor = new Processor( compressor: new ZlibCompressor(level: 9) // Maximum compression );
⚠️ Important Notes
-
Output Format: Always save encoded images as PNG. JPG compression is lossy and will destroy the hidden data.
-
Source Format: JPG, PNG, GIF, WebP, and BMP are supported as source images.
-
Image Size: Larger images can store more data. Use
calculateMaxMessageSize()to check capacity. -
Imagick vs GD: Imagick is preferred for better performance. GD is used as fallback.
Architecture
src/
├── Processor.php # Main entry point
├── Compressor/
│ ├── CompressorInterface.php
│ └── ZlibCompressor.php # Zlib compression
├── Encoder/
│ ├── EncoderInterface.php
│ └── DefaultEncoder.php # Base64 + Binary encoding
├── Exception/
│ ├── SteganographyException.php
│ ├── ImageTooSmallException.php
│ └── DecodeException.php
├── Image/
│ ├── Image.php # LSB steganography logic
│ ├── Color.php # RGBA color DTO
│ └── Adapter/
│ ├── ImageAdapterInterface.php
│ ├── GdAdapter.php # GD implementation
│ └── ImagickAdapter.php # Imagick implementation
└── Iterator/
├── BinaryIterator.php # Binary data iterator
└── RectIterator.php # Pixel coordinate iterator
How It Works
- Compression: The message is compressed using Zlib
- Encoding: Compressed data is Base64 encoded, then converted to binary (0s and 1s)
- Embedding: Each pixel's RGB values have their LSB modified to store 3 bits (1 per channel)
- Header: A 48-bit length header is prepended to know how much data to read when decoding
License
MIT License - see LICENSE file