Skip to content

NonProjects/steganon

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SteganoN

Steganon is an extended implementation of the LSB steganography algorithm.

In short, steganography LSB is a method of hiding data inside pixels of image. Every pixel of an image consist of three integers (0-255, or one byte). They describe an amount of Red, Green and Blue colors. We take User's data to hide and convert it to a bit string; then we take next target pixel and select first integer: R. We convert this integer into bit string and change it's least significant bit to the next bit of User's data. Repeat this process for G and B then write altered pixel back into image. Repeat 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 (three pixels per byte).

Difference between classic LSB and LSB_WS

This repository implements a different type of LSB: LSB With Seed (short. LSB_WS). This is a (designed by me) subclass of LSB that is use PRNG with changeable seed to determine targeted pixels. Here, Seed acts like password. You must know it to extract any hidden data, and fact that image contains any hidden data is more obscure. I believe that LSB_WS is more strong against any analyze.

Installation

You can install SteganoN from PIP

pip install steganon

Or you can install with git clone

python -m venv steganon-env
cd steganon-env && . bin/activate

git clone https://github.com/NonProjects/steganon
pip install ./steganon

SteganoN has basic CLI implementation

# Install SteganoN with CLI
pip install steganon[cli]

image

Example

Hiding Secret Data

from steganon import Image, LSB_WS

image = Image.open('example.png') # Open targeted Image
lsb_ws = LSB_WS(image, b'seed_0') # Init with seed=b'seed_0'

lsb_ws.hide(b'Secret!!!') # Write secret message to image pixels
image.save('example.png') # Save altered image with secret data

Under the hood (Pseudo-code)

# Pseudo-code here! See source file for exact implementation

image = Image.open('example.png')

secret, seed = 'Secret!!!', b'seed_0'
secret_bin = binary(secret) = list('010100110110010101100011011100100110010101110100001000010010000100100001')

prng = PRNG(seed) # In reality we use Python's random module, which is Mersenne Twister

# The first 9 pixels of "prng.random_pixel" will be "Information
# pixels". We will store the total bytesize of secret data in them,
# so it's easy to know how much pixels we need to extract. As
# 9 pixels is 3 bytes, the maximum allowed bytesize to hide per
# one image is 16MiB-1 bytes == 16777215 (as integer).
info_pixels = [prng.random_pixel(image) for _ in range(9)]

while secret_bin:
    # In the actual code we store position of pixels that we changed, so
    # if "random_pixel" will return us pixel that already been altered
    # we will request next position, up until we will not find empty one
    next_pixel = image.get_pixel(prng.random_pixel(image)) # (255, 0, 0)

    # Also, as there is three integers per pixel and only eight bits
    # per byte of secret data we add zero (0) to start of every bits of
    # byte of secret data so it's total size will be 9 and we can
    # easily hide whole byte of secret data in three pixels. In this
    # pseudo-code example this is ignored. 11111111 will be 011111111.

    new_pixel = []
    for color_integer in next_pixel:
        color_bits = binary(color_integer) # 255 = 11111111 (First Iteration)
        color_bits[-1] = secret_bin.pop(0) # color_bits ~= 11111110 (First Iteration)
        new_pixel.append(binary_to_int(color_bits)) # 11111110 = 254 (First Iteration)

    image.put_pixel(new_pixel) # [254, 1, 0] (After all Iterations)

Extracting Secret Data

# Secret Data extraction schema is pretty the same as hide process,
# the only difference is that we only take last significant byte

from steganon import Image, LSB_WS

image = Image.open('example.png') # Open Image with hidden data
lsb_ws = LSB_WS(image, b'seed_0') # Init with seed=b'seed_0'

print(lsb_ws.extract()) # b'Secret!!!'

Image Comparison

Here is comparison between Original image (1) and Image with written on pixels data (2).

Modified Image (2) has whole Zen of Python written on it.
You can extract Zen from (2) by using Seed b'spam_eggs'

TestMode on LSB_WS

steganon.LSB_WS class has a testmode key. We can use it to check affected pixels under different seeds

Additional Information

  1. Always use a different seed! Pixel positions will be the same on different images and text!
  2. All of this developed by me and currently wasn't verified by cryptography experts. Use with caution!
  3. hide() process can be long on big Data and small image. Note: one byte of data is 3 pixels;
  4. This library will not work with JPEG. PNG is OK and recommended. Other formats need testing;
  5. Best template to hide data is a compressed JPEG turned to PNG. Library have tools.pngify, use it;
  6. Recommended image size is 2000x2000+. The bigger your image the bigger amount of bytes you can hide.

Contact me on thenonproton@pm.me (or just open Issue) if you have any feedback on this library.

All Aboard!

Try to download this example image and extract secret information from it
Seed is b'OZZY', save data to the file with .ogg extension and play with your media player

Crazy? But that's how it goes!