# SteganoN
**Steganon** is an extended implementation of the [LSB steganography algorithm](https://www.google.com/search?q=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 **R**ed, **G**reen and **B**lue 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](https://en.wikipedia.org/wiki/Bit_numbering) 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](https://en.wikipedia.org/wiki/Random_seed)** (short. `LSB_WS`). This is a (designed by [**me**](https://github.com/NotStatilko)) subclass of LSB that is use [**PRNG**](https://en.wikipedia.org/wiki/Pseudorandom_number_generator) with changeable [seed](https://en.wikipedia.org/wiki/Random_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](https://www.google.com/search?q=how+to+crack+lsb+stegano).
## Installation
**You can install SteganoN from PIP**
```bash
pip install steganon
```
**Or you can install with git clone**
```bash
python -m venv steganon-env
cd steganon-env && . bin/activate
git clone https://github.com/NonProjects/steganon
pip install ./steganon
```
## Example
### Hiding Secret Data
```python3
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)
```python
# 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
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
```python
# 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') # Opening 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)**](https://github.com/NonProjects/steganon/assets/43419673/4f0f7238-f51e-45c5-80b0-3e039b26c8de) and [**Image with written on pixels data (2)**](https://github.com/NonProjects/steganon/assets/43419673/ddc67292-d085-47dc-ae04-2dd131496899).
<img src="https://github.com/NonProjects/steganon/assets/43419673/45e529b6-c45a-454c-bbf3-8426ba9dd9f5" width="777" height="-1"></img>
[**Modified Image (2)**](https://github.com/NonProjects/steganon/assets/43419673/ddc67292-d085-47dc-ae04-2dd131496899) 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_WS
`steganon.LSB_WS` class has a `testmode` key. We can use it to check affected pixels under different seeds
<img src="https://github.com/NonProjects/steganon/assets/43419673/91d0c920-2749-4a5d-afa1-b43d76b29aa0" width="777" height="-1"></img>
## Additional Information
0. **Always use a different seed!** Pixel positions will be the same on different images and text!
1. All of this developed by me and currently **wasn't** verified by cryptography experts. Use with caution!
2. `hide()` process can be long on big Data and small image. Note: **one byte of data is 3 pixels**;
3. This library **will not** work with JPEG. PNG is OK and recommended. Other formats need testing;
4. Best template to hide data is a compressed JPEG turned to PNG. Library have `tools.pngify`, use it.
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**](https://github.com/NonProjects/steganon/assets/43419673/2b13ef7c-b37f-4d4f-a88f-7b035324a905) and extract secret data from it (may take some time :)\
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!
Raw data
{
"_id": null,
"home_page": "https://github.com/NonProjects/steganon",
"name": "steganon",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "Steganography,LSB,Cryptography",
"author": "NonProjects",
"author_email": "thenonproton@pm.me",
"download_url": "https://files.pythonhosted.org/packages/e9/59/aa0926f34a268a74fa9e23b78e3d931dc5dc1e40e09b20993f30dbb75f28/steganon-0.2.tar.gz",
"platform": null,
"description": "# SteganoN\n\n**Steganon** is an extended implementation of the [LSB steganography algorithm](https://www.google.com/search?q=LSB+steganography+algorithm).\n\nIn 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 **R**ed, **G**reen and **B**lue 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](https://en.wikipedia.org/wiki/Bit_numbering) 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).\n\n## Difference between classic LSB and LSB_WS\n\n\nThis repository implements a different type of LSB: **LSB With [Seed](https://en.wikipedia.org/wiki/Random_seed)** (short. `LSB_WS`). This is a (designed by [**me**](https://github.com/NotStatilko)) subclass of LSB that is use [**PRNG**](https://en.wikipedia.org/wiki/Pseudorandom_number_generator) with changeable [seed](https://en.wikipedia.org/wiki/Random_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](https://www.google.com/search?q=how+to+crack+lsb+stegano).\n\n## Installation\n\n**You can install SteganoN from PIP**\n```bash\npip install steganon\n```\n**Or you can install with git clone**\n```bash\npython -m venv steganon-env\ncd steganon-env && . bin/activate\n\ngit clone https://github.com/NonProjects/steganon\npip install ./steganon\n```\n\n## Example\n\n### Hiding Secret Data\n\n```python3\nfrom steganon import Image, LSB_WS\n\nimage = Image.open('example.png') # Open targeted Image\nlsb_ws = LSB_WS(image, b'seed_0') # Init with seed=b'seed_0'\n\nlsb_ws.hide(b'Secret!!!') # Write secret message to image pixels\nimage.save('example.png') # Save altered image with secret data\n```\n#### Under the hood (Pseudo-code)\n```python\n# Pseudo-code here! See source file for exact implementation\n\nimage = Image.open('example.png')\n\nsecret, seed = 'Secret!!!', b'seed_0'\nsecret_bin = binary(secret) = list('010100110110010101100011011100100110010101110100001000010010000100100001')\n\nprng = PRNG(seed) # In reality we use Python's random module, which is Mersenne Twister\n\nwhile secret_bin:\n # In the actual code we store position of pixels that we changed, so\n # if \"random_pixel\" will return us pixel that already been altered\n # we will request next position, up until we will not find empty one\n next_pixel = image.get_pixel(prng.random_pixel(image)) # (255, 0, 0)\n\n # Also, as there is three integers per pixel and only eight bits\n # per byte of secret data we add zero (0) to start of every bits of\n # byte of secret data so it's total size will be 9 and we can\n # easily hide whole byte of secret data in three pixels. In this\n # pseudo-code example this is ignored. 11111111 will be 011111111.\n\n new_pixel = []\n for color_integer in next_pixel:\n color_bits = binary(color_integer) # 255 = 11111111 (First Iteration)\n color_bits[-1] = secret_bin.pop(0) # color_bits ~= 11111110 (First Iteration)\n new_pixel.append(binary_to_int(color_bits)) # 11111110 = 254 (First Iteration)\n\n image.put_pixel(new_pixel) # [254, 1, 0] (After all Iterations)\n```\n### Extracting Secret Data\n```python\n# Secret Data extraction schema is pretty the same as hide process,\n# the only difference is that we only take last significant byte\n\nfrom steganon import Image, LSB_WS\n\nimage = Image.open('example.png') # Opening Image with hidden data\nlsb_ws = LSB_WS(image, b'seed_0') # Init with seed=b'seed_0'\n\nprint(lsb_ws.extract()) # b'Secret!!!'\n```\n\n## Image Comparison\n\nHere is comparison between [**Original image (1)**](https://github.com/NonProjects/steganon/assets/43419673/4f0f7238-f51e-45c5-80b0-3e039b26c8de) and [**Image with written on pixels data (2)**](https://github.com/NonProjects/steganon/assets/43419673/ddc67292-d085-47dc-ae04-2dd131496899).\n\n<img src=\"https://github.com/NonProjects/steganon/assets/43419673/45e529b6-c45a-454c-bbf3-8426ba9dd9f5\" width=\"777\" height=\"-1\"></img>\n\n[**Modified Image (2)**](https://github.com/NonProjects/steganon/assets/43419673/ddc67292-d085-47dc-ae04-2dd131496899) has whole [**Zen of Python**](https://peps.python.org/pep-0020/#the-zen-of-python) written on it.\\\nYou can extract Zen from **(2)** by using Seed `b'spam_eggs'`\n\n## TestMode on LSB_WS\n\n`steganon.LSB_WS` class has a `testmode` key. We can use it to check affected pixels under different seeds\n\n<img src=\"https://github.com/NonProjects/steganon/assets/43419673/91d0c920-2749-4a5d-afa1-b43d76b29aa0\" width=\"777\" height=\"-1\"></img>\n\n## Additional Information\n\n0. **Always use a different seed!** Pixel positions will be the same on different images and text!\n1. All of this developed by me and currently **wasn't** verified by cryptography experts. Use with caution!\n2. `hide()` process can be long on big Data and small image. Note: **one byte of data is 3 pixels**;\n3. This library **will not** work with JPEG. PNG is OK and recommended. Other formats need testing;\n4. Best template to hide data is a compressed JPEG turned to PNG. Library have `tools.pngify`, use it.\n\nContact me on thenonproton@pm.me (or just open Issue) if you have any feedback on this library.\n\n## All Aboard!\n\nTry to download [**this example image**](https://github.com/NonProjects/steganon/assets/43419673/2b13ef7c-b37f-4d4f-a88f-7b035324a905) and extract secret data from it (may take some time :)\\\nSeed is `b'OZZY'`, save data to the file with `.ogg` extension and play with your media player\n\n###### Crazy? But that's how it goes!\n",
"bugtrack_url": null,
"license": "LGPL-2.1",
"summary": "Steganography LSB (with PRNG by seed)",
"version": "0.2",
"project_urls": {
"Homepage": "https://github.com/NonProjects/steganon"
},
"split_keywords": [
"steganography",
"lsb",
"cryptography"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "2825a69e37cfcaad246bfc8817c3c700291d7d53c8f955f93154b93d1ded1818",
"md5": "3a07eab8fc75802cacb0888326c07bea",
"sha256": "7b67ed4b3ba9863f3ecec9a2ee3cb2249688700ca85640abcb059c29c62b3489"
},
"downloads": -1,
"filename": "steganon-0.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "3a07eab8fc75802cacb0888326c07bea",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 20212,
"upload_time": "2024-02-01T17:22:10",
"upload_time_iso_8601": "2024-02-01T17:22:10.038877Z",
"url": "https://files.pythonhosted.org/packages/28/25/a69e37cfcaad246bfc8817c3c700291d7d53c8f955f93154b93d1ded1818/steganon-0.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "e959aa0926f34a268a74fa9e23b78e3d931dc5dc1e40e09b20993f30dbb75f28",
"md5": "3ad07d3570448b74a196deb7d2ac14d5",
"sha256": "927f1b98f12a5334bba44ddb5072d08771695907840916faa01d83d9fd1ec1db"
},
"downloads": -1,
"filename": "steganon-0.2.tar.gz",
"has_sig": false,
"md5_digest": "3ad07d3570448b74a196deb7d2ac14d5",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 21395,
"upload_time": "2024-02-01T17:22:18",
"upload_time_iso_8601": "2024-02-01T17:22:18.823710Z",
"url": "https://files.pythonhosted.org/packages/e9/59/aa0926f34a268a74fa9e23b78e3d931dc5dc1e40e09b20993f30dbb75f28/steganon-0.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-02-01 17:22:18",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "NonProjects",
"github_project": "steganon",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "steganon"
}