https://github.com/nonprojects/steganon
Steganography LSB (with PRNG by seed)
https://github.com/nonprojects/steganon
lsb-steganography steganography steganography-algorithms steganography-library
Last synced: about 2 months ago
JSON representation
Steganography LSB (with PRNG by seed)
- Host: GitHub
- URL: https://github.com/nonprojects/steganon
- Owner: NonProjects
- License: lgpl-2.1
- Created: 2024-01-25T12:08:28.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2024-07-24T13:54:57.000Z (11 months ago)
- Last Synced: 2024-10-31T17:47:05.656Z (8 months ago)
- Topics: lsb-steganography, steganography, steganography-algorithms, steganography-library
- Language: Python
- Homepage:
- Size: 58.6 KB
- Stars: 3
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# SteganoN
**Steganon** is an extended implementation of the [LSB Matching steganography algorithm](https://www.google.com/search?q=LSB+Matching+steganography+algorithm).
In short, steganography **LSB** is a method of hiding data inside pixels of image. Every pixel of a regular image typically consist of three integers (**0-255**, or **one byte**). They describe an amount of **R**ed, **G**reen and **B**lue colors. We take User's data to hide and convert it to a **bits**; then we take the next target pixel and select first (color channel) integer: **R**. If the last bit of color channel is the **same as our next bit** from the data bit string, **we do nothing**; **if they differ**, we **randomly add or subtract 1 from color channel**. For example, if channel is `222`, we **randomly** `+1` or `-1`, so result would be either `221` or `223`. However, **if channel is** `0` **we always** `+1`, and **if** `255` **we always** `-1`. This essentially will change the [least significant bit](https://en.wikipedia.org/wiki/Bit_numbering) of color channel (e.g **R**) to the bit we want. Repeat this process for **G** and **B** then write altered pixel back into image. Repeat on the next pixels until User's data is not empty. Such change to **RGB** is invisible to human eye and gives us chance to hide **three bits** of data **per pixel** (or, in this library, — three pixels per byte).
## Difference between classic LSB and LSB\_MWS
This repository implements a special type of LSB Matching: **LSB Matching With [Seed](https://en.wikipedia.org/wiki/Random_seed)** (short. `LSB_MWS`). This algorithm utilizes [**PRNG**](https://en.wikipedia.org/wiki/Pseudorandom_number_generator) with changeable [seed](https://en.wikipedia.org/wiki/Random_seed) to select targeted pixels. Moreover, in `LSB_MWS`, one cover Image may contain different, multiple secret Datas on different, multiple Seeds. Thus, this project supports the **Deniable Hide** feature — you can reveal as much Data as you want.
**Deniable Hide** works as a chain of Seeds. Instead of specifying only one Seed, you can pass as many as you wish and attach unique secret Data to each one of them independently. `LSB_MWS` *Hide function* will ensure that each bit of different Datas are stored in unique Pixel without overlapping. On *Extract*, to get a first hidden Data you will need to provide a Seed`(1)`, to get a second Data — Seed`(1)` & Seed`(2)`, to get a third Data — Seed`(1)`, Seed`(2)` & Seed`(3)`, and so on. There is a **zero correlations between Seeds**. In case of extortion, **you can reveal only Seed**`(1)` and criminal—or *whoever*, will **never** know that there is more hidden data deeper.
**We don't feed Seeds directly into the PRNG**, we **hash** them firstly in a special\
manner with `SHA512` **truncated to the *last* 32 bytes**.***(Iterations on MultiSeed with three Seeds)***
1. We create *Initializator* hash by hashing a constant-*Basis* with `ImageSize` (*Width*/*Height*);
2. We hash *Initializator* with **Seed**`(1)` — that is our ***first*** **prngS**`(1)` (PRNG Seed);
3. We hash **prngS**`(1)` with **Seed**`(2)`, — that is our ***second*** PRNG Seed;
4. We hash **prngS**`(2)` with **Seed**`(3)`, — that is our ***third*** PRNG Seed.It means that **Seeds are dependent on each other** and *Initializator* **depends on the Image Width & Height**, thus, each unique-sized Image will utilize **different Seed values for PRNG**. This will add some protection against the brute-force or seed re-usage.
###### This can be disabled with `use_raw_seed=True` on `LSB_MWS`, though *not* recommended.
## Installation
**You can install SteganoN with PIP**
```bash
pip install steganon
```
**Or you can install it after `git clone`**
```bash
python -m venv steganon-env
cd steganon-env && . bin/activategit clone https://github.com/NonProjects/steganon
pip install ./steganon
```
**SteganoN has basic CLI implementation**
```bash
# Install SteganoN with CLI
pip install steganon[cli]
```
## Example
### (One Seed) Hiding Secret Data
```python3
from steganon import Image, LSB_MWSimage = Image.open('example.png') # Open targeted Image
lsb_mws = LSB_MWS(image, b'seed_0') # Init with seed=b'seed_0'lsb_mws.hide(b'Secret!!!') # Write secret message to image pixels
image.save('example.png') # Save altered image with secret data
```### (One Seed) Extracting Secret Data
```python
from steganon import Image, LSB_MWSimage = Image.open('example.png') # Open Image with hidden data
lsb_mws = LSB_MWS(image, b'seed_0') # Init with seed=b'seed_0'print(lsb_mws.extract()) # b'Secret!!!'
```### (MultiSeed) Hiding Secret Data
```python3
from steganon import Image, LSB_MWSimage = Image.open('example.png') # Open targeted Image
seeds = (b'seed_0', b'seed_1', b'seed_2') # You can use as many as you want
lsb_mws = LSB_MWS(image, seeds) # Init LSB_MWS with multiple seedslsb_mws.hide(b'Secret data on Seed(0)!!!') # Write secret message to image pixels
lsb_mws.next() # Switch to the next Seed (b'seed_1')lsb_mws.hide(b'Secret data on Seed(1)!!!') # Write secret message to image pixels
lsb_mws.next() # Switch to the next Seed (b'seed_2')lsb_mws.hide(b'Secret data on Seed(2)!!!') # Write secret message to image pixels
image.save('example.png') # Save altered image with secret data
```### (MultiSeed) Extracting Secret Data
```python
from steganon import Image, LSB_MWSimage = Image.open('example.png') # Open targeted Image
seeds = (b'seed_0', b'seed_1', b'seed_2') # You can use as many as you want
lsb_mws = LSB_MWS(image, seeds) # Init LSB_MWS with multiple seedsprint(lsb_mws.extract()) # b'Secret data on Seed(0)!!!'
lsb_mws.next() # Switch to the next Seed (b'seed_1')
print(lsb_mws.extract()) # b'Secret data on Seed(1)!!!'
lsb_mws.next() # Switch to the next Seed (b'seed_2')
print(lsb_mws.extract()) # b'Secret data on Seed(2)!!!'
```## Image Comparison
Here is comparison between [**Original image (1)**](https://github.com/user-attachments/assets/2d639687-718e-4868-afbb-fc431b35e747) and [**Image with written on pixels data (2)**](https://github.com/user-attachments/assets/4b3de992-2fcb-4c54-84e2-94546cd0c168).
[**Modified Image (2)**](https://github.com/user-attachments/assets/4b3de992-2fcb-4c54-84e2-94546cd0c168) has whole [**Zen of Python**](https://peps.python.org/pep-0020/#the-zen-of-python) written on it.\
You can extract Zen from **(2)** by using Seed `b'spam_eggs'`## TestMode on LSB\_MWS
`steganon.LSB_MWS` class has a `testmode` key. We can use it to check affected pixels under different seeds
## Additional Information
**Tested formats:**
* ✅ **PNG**
* ✅ **BMP**
* ✅ **TIFF**
* ✅ **WEBP**
* ✅ **JPEG2000**
* ❌ **JPG**
* ❌ **HEIF**0. This library & implementation **wasn't** verified by steganography experts. **Use with caution!**
1. **Always use a different seed!** Pixel positions `*`may be the same on different Images and Data!
2. This library **will not** work with JPEG due to its lossy design. **Use lossless formats** (e.g PNG, WEBP, etc);
3. Best `**`template to hide data is a **compressed JPEG turned to PNG**. Library has `tools.pngify`, use it;
4. The **bigger your Image**, the **bigger amount of Data you can hide** (though the less data—the `***`better).`* ` If Image Width/Height and Seed are the same. **Always use a unique Seed**\
`** ` Your cover Image **should** have a decent amount of "Noise" / Compression\
`***` Quite obviously, **the lower coverage**, the **less chance for analyze tools**Contact me on **[email protected]** (or just [**open Issue**](https://github.com/NonProjects/steganon/issues)) if you have any feedback on this library.
## All Aboard!
Try to download [**this example image**](https://github.com/user-attachments/assets/cd1e1785-fead-4a80-83c7-f3400334c756) and extract secret information from it with seed `b'OZZY'`\
Save data to the file with `.ogg` extension and play it with your favourite media player.###### *Flying high again!*