Skip to content

Commit 4c37f07

Browse files
committed
added steganography tutorial
1 parent f8817ad commit 4c37f07

File tree

6 files changed

+110
-0
lines changed

6 files changed

+110
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ This is a repository of all the tutorials of [The Python Code](https://www.thepy
1818
- [How to Create a Reverse Shell in Python](https://www.thepythoncode.com/article/create-reverse-shell-python). ([code](ethical-hacking/reverse_shell))
1919
- [How to Encrypt and Decrypt Files in Python](https://www.thepythoncode.com/article/encrypt-decrypt-files-symmetric-python). ([code](ethical-hacking/file-encryption))
2020
- [How to Make a Subdomain Scanner in Python](https://www.thepythoncode.com/article/make-subdomain-scanner-python). ([code](ethical-hacking/subdomain-scanner))
21+
- [How to use Steganography to Hide Secret Data in Images in Python](https://www.thepythoncode.com/article/hide-secret-data-in-images-using-steganography-python). ([code](ethical-hacking/steganography))
2122

2223
- ### [Machine Learning](https://www.thepythoncode.com/topic/machine-learning)
2324
- ### [Natural Language Processing](https://www.thepythoncode.com/topic/nlp)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# [How to use Steganography to Hide Secret Data in Images in Python](https://www.thepythoncode.com/article/hide-secret-data-in-images-using-steganography-python)
2+
To run this:
3+
- `pip3 install -r requimements.txt`
4+
- To encode some data to the imag `image.PNG` and decode it right away:
5+
```
6+
python steganography image.PNG "This is some secret data."
7+
```
8+
This will write another image with data encoded in it and **outputs:**
9+
```
10+
[*] Maximum bytes to encode: 125028
11+
[*] Encoding data...
12+
[+] Decoding...
13+
[+] Decoded data: This is some secret data.
14+
```
15+
- You can isolate encoding and decoding processes in two different Python files, which makes more sense.
Loading
813 KB
Loading
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
opencv-python
2+
numpy
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import cv2
2+
import numpy as np
3+
import sys
4+
5+
6+
def to_bin(data):
7+
"""Convert `data` to binary format as string"""
8+
if isinstance(data, str):
9+
return ''.join([ format(ord(i), "08b") for i in data ])
10+
elif isinstance(data, bytes) or isinstance(data, np.ndarray):
11+
return [ format(i, "08b") for i in data ]
12+
elif isinstance(data, int) or isinstance(data, np.uint8):
13+
return format(data, "08b")
14+
else:
15+
raise TypeError("Type not supported.")
16+
17+
18+
def encode(image_name, secret_data):
19+
# read the image
20+
image = cv2.imread(image_name)
21+
# maximum bytes to encode
22+
n_bytes = image.shape[0] * image.shape[1] * 3 // 8
23+
print("[*] Maximum bytes to encode:", n_bytes)
24+
if len(secret_data) > n_bytes:
25+
raise ValueError("[!] Insufficient bytes, need bigger image or less data.")
26+
print("[*] Encoding data...")
27+
# add stopping criteria
28+
secret_data += "====="
29+
data_index = 0
30+
# convert data to binary
31+
binary_secret_data = to_bin(secret_data)
32+
# size of data to hide
33+
data_len = len(binary_secret_data)
34+
35+
for row in image:
36+
for pixel in row:
37+
# convert RGB values to binary format
38+
r, g, b = to_bin(pixel)
39+
# modify the least significant bit only if there is still data to store
40+
if data_index < data_len:
41+
# least significant red pixel bit
42+
pixel[0] = int(r[:-1] + binary_secret_data[data_index], 2)
43+
data_index += 1
44+
if data_index < data_len:
45+
# least significant green pixel bit
46+
pixel[1] = int(g[:-1] + binary_secret_data[data_index], 2)
47+
data_index += 1
48+
if data_index < data_len:
49+
# least significant blue pixel bit
50+
pixel[2] = int(b[:-1] + binary_secret_data[data_index], 2)
51+
data_index += 1
52+
# if data is encoded, just break out of the loop
53+
if data_index >= data_len:
54+
break
55+
return image
56+
57+
58+
def decode(image_name):
59+
print("[+] Decoding...")
60+
# read the image
61+
image = cv2.imread(image_name)
62+
binary_data = ""
63+
for row in image:
64+
for pixel in row:
65+
r, g, b = to_bin(pixel)
66+
binary_data += r[-1]
67+
binary_data += g[-1]
68+
binary_data += b[-1]
69+
70+
# split by 8-bits
71+
all_bytes = [ binary_data[i: i+8] for i in range(0, len(binary_data), 8) ]
72+
# convert from bits to characters
73+
decoded_data = ""
74+
for byte in all_bytes:
75+
decoded_data += chr(int(byte, 2))
76+
if decoded_data[-5:] == "=====":
77+
break
78+
return decoded_data[:-5]
79+
80+
81+
if __name__ == "__main__":
82+
input_image = sys.argv[1]
83+
output_image = f"encoded_{input_image}"
84+
secret_data = sys.argv[2]
85+
86+
# encode the data into the image
87+
encoded_image = encode(image_name=input_image, secret_data=secret_data)
88+
# save the output image (encoded image)
89+
cv2.imwrite(output_image, encoded_image)
90+
# decode the secret data from the image
91+
decoded_data = decode(output_image)
92+
print("[+] Decoded data:", decoded_data)

0 commit comments

Comments
 (0)