else
This commit is contained in:
parent
81019bbaa7
commit
dd4bacf3ab
3 changed files with 60 additions and 18 deletions
3
Steganographic/examples/100pixels.png
Normal file
3
Steganographic/examples/100pixels.png
Normal file
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e890b050800c2ba0f0dc1aab56519c0c43b5d20fca4908976ddd41505a0393af
|
||||
size 136
|
3
Steganographic/examples/14pixels.png
Normal file
3
Steganographic/examples/14pixels.png
Normal file
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:19681c97997aaa6a0382b91bd62d71fd3ee85f5443597888acbcdf4f537187b7
|
||||
size 125
|
|
@ -3,14 +3,45 @@ For each color channel of each pixel in an Image, modify the least significant b
|
|||
This changes the RGB value of the pixel by a usually-imperceptible amount.
|
||||
The first 32 bits (10.66 pixels) will be used to store the length of the Secret content in big endian.
|
||||
Then, the Secret's extension is stored. A null byte indicates the end of the extension. This section is of variable length.
|
||||
A file with no extension will still require that null byte. A file with an extension will require 1 byte per character.
|
||||
A file with no extension requires only that null byte. A file with an extension requires 1 additional byte per character.
|
||||
|
||||
Each Image pixel holds 3 Secret bits, so the Image must have at least ((secretbytes * (8 / 3)) + 19) pixels
|
||||
An Image can hold ((3 * (pixels - 19)) / 8) Secret bytes.
|
||||
Smallest image possible = 16 pixels with 48 bit secret: 32 for header; 8 for null extension; 8 for data
|
||||
Each Image pixel holds 3 Secret bits, so the Image must have at least ((secretbytes * (8 / 3)) + 14) pixels
|
||||
An Image can hold ((3 * (pixels - 14)) / 8) Secret bytes.
|
||||
|
||||
Usage:
|
||||
> 3bitspixel.py encode imagefilename.png secretfilename.ext
|
||||
> 3bitspixel.py decode lacedimagename.png
|
||||
|
||||
|
||||
Reference table for files with NO EXTENSION.
|
||||
For each extension character, subtract 1 byte from secret size
|
||||
|
||||
pixels | example dimensions | Secret file size
|
||||
100 | 10 x 10 | 32 bytes
|
||||
400 | 20 x 20 | 144 bytes
|
||||
2,500 | 50 x 50 | 932 bytes
|
||||
10,000 | 100 x 100 | 3,744 bytes
|
||||
40,000 | 200 x 200 | 14,994 bytes
|
||||
25,000 | 500 x 500 | 93,744 bytes (91 kb)
|
||||
1,000,000 | 1,000 x 1,000 | 374,994 bytes (366 kb)
|
||||
4,000,000 | 2,000 x 2,000 | 1,499,994 bytes (1.43 mb)
|
||||
25,000,000 | 5,000 x 5,000 | 9,374,994 bytes (8.94 mb)
|
||||
100,000,000 | 10,000 x 10,000 | 37,499,994 bytes (35.7 mb)
|
||||
|
||||
pixels | example dimensions | Secret file size
|
||||
100 | 10 x 10 | 32 bytes
|
||||
697 | 25 x 28 (700) | 256 bytes
|
||||
2,745 | 50 x 55 (2,750) | 1,024 bytes (1 kb)
|
||||
21,860 | 142 x 154 (21,868) | 8,192 bytes (8 kb)
|
||||
87,396 | 230 x 380 (87,400) | 32,768 bytes (32 kb)
|
||||
349,540 | 463 x 755 (349,565) | 131,072 bytes (128 kb)
|
||||
1,398,116 | 1146 x 1120 (1,398,120) | 524,288 bytes (512 kb)
|
||||
2,796,217 | 1621 x 1725 (2,796,225) | 1,048,576 bytes (1 mb)
|
||||
11,184,825 | 3500 x 3200 (11,200,000) | 4,194,304 bytes (4 mb)
|
||||
44,739,257 | 6700 x 6700 (44,890,000) | 16,777,216 bytes (16 mb)
|
||||
89,478,500 | 9500 x 9500 (90,250,000) | 33,554,432 bytes (32 mb)
|
||||
|
||||
'''
|
||||
from PIL import Image
|
||||
import binascii
|
||||
|
@ -18,8 +49,8 @@ import math
|
|||
import os
|
||||
import sys
|
||||
|
||||
# 11 for the content length, and AT LEAST 8 for the extension (which always ends in 1 null byte)
|
||||
HEADER_SIZE = 19
|
||||
# 11 for the content length
|
||||
HEADER_SIZE = 11
|
||||
|
||||
class StegError(Exception):
|
||||
pass
|
||||
|
@ -44,6 +75,11 @@ def increment_pixel(save=True):
|
|||
pixel = list(image.getpixel( (pixel_index % image.size[0], pixel_index // image.size[0]) ))
|
||||
#print('opend', pixel)
|
||||
|
||||
def bytes_to_pixels(bytes):
|
||||
return ((bytes * (8 / 3)) + 14)
|
||||
|
||||
def pixels_to_bytes(pixels):
|
||||
return ((3 * (pixels - 14)) / 8)
|
||||
|
||||
############## #### #### ######## ###### ########## ##############
|
||||
#### ## #### #### #### #### #### #### #### #### #### ##
|
||||
|
@ -62,6 +98,18 @@ def encode(imagefilename, secretfilename):
|
|||
pixel_index = 0
|
||||
channel_index = 0
|
||||
|
||||
def modify_pixel(bit):
|
||||
global pixel
|
||||
global channel_index
|
||||
#print(channel_index, bit)
|
||||
#print(pixel_index, channel_index, bit)
|
||||
channel = pixel[channel_index]
|
||||
channel = binary(channel)[:7] + bit
|
||||
channel = int(channel, 2)
|
||||
pixel[channel_index] = channel
|
||||
#print(pixel)
|
||||
|
||||
|
||||
print('Hiding "%s" within "%s"' % (secretfilename, imagefilename))
|
||||
image = Image.open(imagefilename)
|
||||
|
||||
|
@ -78,25 +126,13 @@ def encode(imagefilename, secretfilename):
|
|||
|
||||
secret_extension = os.path.splitext(secretfilename)[1][1:]
|
||||
secret_content_length = (len(secret) * 8) + (len(secret_extension) * 8) + 8
|
||||
requiredpixels = math.ceil((secret_content_length / 3) + HEADER_SIZE)
|
||||
requiredpixels = math.ceil((secret_content_length + 32) / 3)
|
||||
if totalpixels < requiredpixels:
|
||||
raise StegError('Image does not have enough pixels to store the Secret'
|
||||
'Must have at least %d pixels' % requiredpixels)
|
||||
|
||||
print('%d available pixels, %d required' % (totalpixels, requiredpixels))
|
||||
|
||||
def modify_pixel(bit):
|
||||
global pixel
|
||||
global channel_index
|
||||
#print(channel_index, bit)
|
||||
#print(pixel_index, channel_index, bit)
|
||||
channel = pixel[channel_index]
|
||||
channel = binary(channel)[:7] + bit
|
||||
channel = int(channel, 2)
|
||||
pixel[channel_index] = channel
|
||||
#print(pixel)
|
||||
|
||||
|
||||
# --> YOU ARE HERE <--
|
||||
pixel = list(image.getpixel((0, 0)))
|
||||
|
||||
|
|
Loading…
Reference in a new issue