Skip to content

Commit 813a9be

Browse files
authored
Merge pull request #212 from Nibba2018/image_stegano
Image Steganography along with Encryption
2 parents ca31643 + 57f81cd commit 813a9be

File tree

10 files changed

+239
-0
lines changed

10 files changed

+239
-0
lines changed

Python/Image-Steganography/README.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Image Steganography
2+
Steganography is the art and science of embedding secret messages in a cover message or file in such a way that no one, apart from the sender and the intended recipient, suspects the existence of the message. In case of Image Steganography, secret messages are embedded in images.
3+
4+
![flowchart](https://d1jnx9ba8s6j9r.cloudfront.net/blog/wp-content/uploads/2019/01/SteganogarphyModel-528x259.png)
5+
6+
One of the algorithms to do so is known as **Least Significant Bit Insertion**. In this script the following operations are done:
7+
8+
**While Hiding:**
9+
1. Image and message is read from a text file.
10+
2. The message is encrypted with a key.
11+
3. The encrypted message is then embedded with the image.
12+
13+
**While Retrieving:**
14+
1. Encrypted message is extracted from the image.
15+
2. Exncrypted message is then decrypted using the previous key.
16+
17+
## Executing the script:
18+
* First install dependencies using: `pip install -r requirements.txt`
19+
* To hide run: `python hide.py <image_path> <message_file_path>`
20+
* for e.g: `python hide.py sample.png info.txt`
21+
* To retrieve run: `python retrieve.py <image_path> <key_path>`
22+
* for e.g: `python retrieve.py sample_secret.png key`
23+
24+
> Note: Avoid using JPEG or JPG files as they ruin the integrity of the message due to compression.
25+
26+
27+
## Output:
28+
29+
**sample.png:**
30+
31+
![sample source](images/sample.png)
32+
33+
**info.txt:**
34+
35+
```txt
36+
Hello, this file's content will be hidden.
37+
```
38+
39+
**Hiding:**
40+
41+
![hiding](images/hiding.png)
42+
43+
44+
**sample_secret.png**
45+
46+
![sample secret](images/sample_secret.png)
47+
48+
The image with the hidden message.
49+
50+
51+
**key:**
52+
53+
`hrnyzqoF3aOwaOO4n9vnunH9KUD-nh-Ee5fjQcuLU9k=`
54+
55+
**Retrieving:**
56+
57+
![retrieving](images/retrieving.png)
58+
59+
Thank You!

Python/Image-Steganography/hide.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import cv2
2+
import numpy as np
3+
import sys
4+
from cryptography.fernet import Fernet
5+
6+
# Check if the user has entered commandline arguments correctly or not.
7+
if len(sys.argv) < 3:
8+
print("Provide appropriate commandline arguments.")
9+
sys.exit()
10+
11+
12+
# Method to convert various data to binary.
13+
def message_to_binary(message):
14+
if type(message) == str:
15+
return ''.join([ format(ord(i), "08b") for i in message ])
16+
elif type(message) == bytes or type(message) == np.ndarray:
17+
return [ format(i, "08b") for i in message ]
18+
elif type(message) == int or type(message) == np.uint8:
19+
return format(message, "08b")
20+
else:
21+
raise TypeError("Input type not supported")
22+
23+
24+
# Method to generate key and encrypt secrect message.
25+
def encrypt_message(message):
26+
key = Fernet.generate_key()
27+
encrypted_message = Fernet(key).encrypt(message.encode())
28+
29+
return encrypted_message, key
30+
31+
32+
# Method to embed encrypted message within the image.
33+
def hide_info(image, message):
34+
35+
# Encrypt the message.
36+
enc_message, key = encrypt_message(message)
37+
enc_message = enc_message.decode()
38+
39+
# Get the maximum amount of byte data that can be embeded within the image.
40+
max_bytes = image.shape[0] * image.shape[1] * 3//8
41+
42+
# Check if the data is within limits.
43+
if len(enc_message) > max_bytes:
44+
raise ValueError("Insufficient bytes, provide bigger image or shorter message.")
45+
46+
# Add salt delimiter.
47+
enc_message += "#####"
48+
49+
data_index = 0
50+
bin_enc_message = message_to_binary(enc_message)
51+
52+
data_len = len(bin_enc_message)
53+
54+
# Initiate embedding process.
55+
for values in image:
56+
for pixel in values:
57+
# Convert pixel data to binary.
58+
r, g, b = message_to_binary(pixel)
59+
60+
# modify the least significant bit remaining data is available.
61+
if data_index < data_len:
62+
# Hide data into LSB of red pixel
63+
pixel[0] = int(r[:-1] + bin_enc_message[data_index], 2)
64+
data_index += 1
65+
66+
if data_index < data_len:
67+
# Hide data into LSB of green pixel
68+
pixel[1] = int(g[:-1] + bin_enc_message[data_index], 2)
69+
data_index += 1
70+
71+
if data_index < data_len:
72+
# Hide data into LSB of blue pixel
73+
pixel[2] = int(b[:-1] + bin_enc_message[data_index], 2)
74+
data_index += 1
75+
76+
# Break out of the loop if there isn't any data left to embed.
77+
if data_index >= data_len:
78+
break
79+
80+
# Save the encryption key in a file.
81+
with open("key", "wb") as f:
82+
f.write(key)
83+
84+
return image
85+
86+
87+
# Extract image and message path.
88+
image_path = sys.argv[1]
89+
message_path = sys.argv[2]
90+
91+
92+
# Load image and message to memory.
93+
source_image = cv2.imread(image_path)
94+
with open(message_path, "r") as f:
95+
message = f.read()
96+
97+
98+
# Perform the embeded operation and save the resultant image.
99+
secret_image = hide_info(source_image, message)
100+
secret_image_path = image_path.split(".")
101+
secret_image_path = secret_image_path[-2]+"_secret."+secret_image_path[-1]
102+
cv2.imwrite(secret_image_path, secret_image)
103+
print("Message successfully hidden.")
8.74 KB
Loading
10.5 KB
Loading
61.8 KB
Loading
Loading

Python/Image-Steganography/info.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hello, this file's content will be hidden.

Python/Image-Steganography/key

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
hrnyzqoF3aOwaOO4n9vnunH9KUD-nh-Ee5fjQcuLU9k=
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
opencv-python
2+
cryptography
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
from cryptography.fernet import Fernet
2+
import cv2
3+
import numpy as np
4+
import sys
5+
6+
7+
# Check if user has provided commandline arguments or not.
8+
if len(sys.argv) < 3:
9+
print("Provide appropriate commandline arguments.")
10+
sys.exit()
11+
12+
13+
# Convert various data to binary.
14+
def message_to_binary(message):
15+
if type(message) == str:
16+
return ''.join([ format(ord(i), "08b") for i in message ])
17+
elif type(message) == bytes or type(message) == np.ndarray:
18+
return [ format(i, "08b") for i in message ]
19+
elif type(message) == int or type(message) == np.uint8:
20+
return format(message, "08b")
21+
else:
22+
raise TypeError("Input type not supported")
23+
24+
25+
# Decrypt an encrypted message.
26+
def decrypt_message(enc_message, key):
27+
dec_message = Fernet(key).decrypt(enc_message)
28+
return dec_message
29+
30+
31+
# Retrive the message from an image.
32+
def retrieve_info(image, key):
33+
34+
binary_data = ""
35+
36+
for values in image:
37+
for pixel in values:
38+
# Convert pixel to binary.
39+
r, g, b = message_to_binary(pixel)
40+
41+
# Extracting data from the LSB of all the channels.
42+
binary_data += r[-1]
43+
binary_data += g[-1]
44+
binary_data += b[-1]
45+
46+
# split by 8 bits.
47+
all_bytes = [binary_data[i: i+8] for i in range(0, len(binary_data), 8)]
48+
49+
# Convert to ASCII values.
50+
decoded_data = ""
51+
for byte in all_bytes:
52+
decoded_data += chr(int(byte, 2))
53+
if decoded_data[-5:] == "#####":
54+
break
55+
56+
# Decrypt the encryption.
57+
message = decrypt_message(decoded_data[:-5].encode(), key).decode()
58+
59+
return message
60+
61+
62+
# Extract the image and key path.
63+
image_path = sys.argv[1]
64+
key_path = sys.argv[2]
65+
66+
67+
# Read the image and key.
68+
steg_image = cv2.imread(image_path)
69+
with open(key_path, "rb") as f:
70+
key = f.read()
71+
72+
# Display the secrect message.
73+
print(f"Secret Message:{retrieve_info(steg_image, key)}")

0 commit comments

Comments
 (0)