This repository has been archived by the owner on Jun 12, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlsb_steganography.py
123 lines (100 loc) · 4.15 KB
/
lsb_steganography.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# bin: int --> binary
# ord: char --> int
from PIL import Image
default_sample_img_path = './images/sample_image.png'
default_stega_img_path = './images/stega_image.png'
# Indices
RED = 0
GREEN = 1
BLUE = 2
class LsbStega():
def __init__(self):
super().__init__()
def to_binary(self, char):
decimal = ord(char)
binary = bin(decimal)
return binary
def text_to_bits(self, text, encoding='utf-8', errors='surrogatepass'):
bits = bin(int.from_bytes(text.encode(encoding, errors), 'big'))[2:]
return self.fill_bits(bits, 8)
def text_from_bits(self, bits, encoding='utf-8', errors='surrogatepass'):
n = int(bits, 2)
return n.to_bytes((n.bit_length() + 7) // 8, 'big').decode(encoding, errors) or '\0'
def fill_bits(self, value, bitcount):
return value.zfill(bitcount * ((len(value) + (bitcount-1)) // bitcount))
def encode_text(self, text, img_path=default_sample_img_path):
print("Hiding text in picture")
text_length_binary = bin(len(text))[2:]
text_length_bits = self.fill_bits(text_length_binary, 16)
text_as_bits = self.text_to_bits(text)
data_to_hide = text_length_bits + text_as_bits
img = Image.open(img_path)
src_img_pixels = img.load()
img_x_size = img.size[0]
img_y_size = img.size[1]
result_img = Image.new("RGB", (img_x_size, img_y_size))
result_img_pixels = result_img.load()
current_position = 0
for y in range(img_y_size):
for x in range(img_x_size):
if current_position >= len(data_to_hide) or (bin(src_img_pixels[x, y][BLUE])[-1]) == data_to_hide[current_position]:
result_img_pixels[x, y] = src_img_pixels[x, y]
else:
pixel = src_img_pixels[x, y]
blue_binary = self.fill_bits(bin(pixel[BLUE])[2:], 8)
blue_binary = blue_binary[:-1] + \
data_to_hide[current_position]
result_img_pixels[x, y] = (
src_img_pixels[x, y][RED], src_img_pixels[x, y][GREEN], int(blue_binary, 2))
# print(
# "src pixel:", src_img_pixels[x, y], "--> result pixel:", result_img_pixels[x, y])
current_position += 1
result_img.save(default_stega_img_path)
print("Your text was hidden in the picture saved at",
default_stega_img_path)
def decode_text(self, img_path=default_stega_img_path):
print("Extracting text from picture")
img = Image.open(img_path)
img_x_size = img.size[0]
img_y_size = img.size[1]
blue_values = img.split()[BLUE]
length_binary = ''
for x in range(16):
length_binary += bin(blue_values.getpixel((x, 0)))[-1]
length_decimal = int(length_binary, 2)
bits_to_read = length_decimal * 8
current_position = -15
extracted_data = ''
for y in range(img_y_size):
for x in range(img_x_size):
if current_position <= bits_to_read:
extracted_data += bin(blue_values.getpixel((x, 0)))[-1]
current_position += 1
else:
break
extracted_data = extracted_data[16:]
text = self.text_from_bits(extracted_data)
print("Extracted text from picture")
return text
def main():
action = input(
"(e) Encode image (hide message) or (d) Decode image (extract message): ")
stega = LsbStega()
if action == 'e':
img_path = input(
"Enter the path to the image (leave empty for default): ")
text = input("Enter your hidden message: ")
if img_path:
stega.encode_text(text, img_path)
else:
stega.encode_text(text)
elif action == 'd':
img_path = input(
"Enter the path to the image (leave empty for default): ")
if img_path:
text = stega.decode_text(img_path=img_path)
else:
text = stega.decode_text()
print("Extracted text:", text)
if __name__ == "__main__":
main()