CSF_ACW_1/Txt_Steg/txt_steg.py

151 lines
5.3 KiB
Python

import numpy as np
class txt_steg:
def __init__(self, text_file: str = "text.txt", bit_to_hide: int = 2):
"""
Initialize the class
:param text_file: PathName of the text file to encode or decode
:type text_file: str
:param bit_to_hide: Bit to hide the data in (1 - LSB to 8 - MSB)
:type bit_to_hide: int
"""
self.text_file = text_file
self.bit_to_hide = 8 - bit_to_hide
self.delimiter = "abc12345"
def to_bin(self, data: str) -> str | list[str]:
"""
Convert text file data to binary format as string
:param data: String
:type data: str
:return: Binary Data: String | List[String]
"""
if isinstance(data, str):
return ''.join([format(ord(i), "08b") for i in data])
elif isinstance(data, bytes) or isinstance(data, np.ndarray):
return [format(i, "08b") for i in data]
elif isinstance(data, int) or isinstance(data, np.unit8):
return format(data, "08b")
else:
raise TypeError("Type not supported")
def from_bin(self, data: str) -> str:
"""
Convert binary `data` back to the original format
:param data: String
:type data: str
:return: Original Data: String
"""
binary_data = ''.join([c for c in data if c in ('0', '1')]) # Remove non-binary characters
# Split the binary data into chunks of 8 bits
binary_parts = [binary_data[i:i + 8] for i in range(0, len(binary_data), 8)]
# Convert each chunk to its corresponding ASCII character
decoded_data = ''.join([chr(int(part, 2)) for part in binary_parts])
return decoded_data
def encode(self, secret_data: str = "Hello World"):
"""
Encode the secret data into the text file
:param secret_data: String
:type secret_data: str
"""
print("[+] Encoding...")
# Read text file and covert to binary
if self.text_file != "":
with open(self.text_file, "r") as f:
data = f.read()
f.close()
data = self.to_bin(data)
else:
raise FileNotFoundError("File not found")
bits_to_hide = self.bit_to_hide
secret_data += self.delimiter # Add delimiter
binary_secret_data = self.to_bin(secret_data)
data_len = len(data)
# Check if secret data can be encoded into text file
if len(binary_secret_data) > data_len:
raise ValueError(f"[-] Error: Binary Secret data length {len(binary_secret_data)} "
f"is greater than data length {data_len}")
encoded_data = ""
# For every 8 bits in the data, hide 1 bit of secret data in the bit_to_hide position
data_index = 0
for i in range(0, data_len, 8):
data_byte = data[i:i + 8]
if data_index < len(binary_secret_data):
secret_bit = binary_secret_data[data_index]
modified_byte = data_byte[:bits_to_hide] + secret_bit + data_byte[bits_to_hide + 1:]
encoded_data += modified_byte
data_index += 1
else:
encoded_data += data_byte
encoded_data = self.from_bin(encoded_data)
return encoded_data
def decode(self) -> str:
"""
Decode the encoded data from the text file
:return: Decoded Data: String
"""
print("[+] Decoding...")
# Read text file and covert to binary
if self.text_file != "":
with open(self.text_file, "r") as f:
data = f.read()
f.close()
data = self.to_bin(data)
else:
raise FileNotFoundError("File not found")
# Split the data into bytes
bytes_data = [data[i:i + 8] for i in range(0, len(data), 8)]
# Extract the bits at the bit_to_hide position
secret_data = [byte[self.bit_to_hide] for byte in bytes_data]
# Concatenate the bits into a binary string
binary_data = ''.join(secret_data)
# Split the binary data using the delimiter
delimeter_as_bin = self.to_bin(self.delimiter)
binary_data = binary_data.split(delimeter_as_bin)[0]
# Convert the binary data back to the original text
decoded_data = self.from_bin(binary_data)
return decoded_data
def main():
print("Welcome to Text Steganography")
print("1. Encode\n2. Decode\n3. Exit")
choice = int(input("Enter your choice: "))
if choice == 1:
text_file_name = input("Enter name of text file to encode: ")
secret_data = input("Enter data to encode: ")
bit_to_hide = int(input("Enter bit to hide (1 - LSB to 8 - MSB): "))
encoded_data = txt_steg(text_file_name, bit_to_hide).encode(secret_data)
extension = text_file_name.split(".")[-1]
with open(f"encoded_text.{extension}", "w") as f:
f.write(encoded_data)
print("Encoded Data:", encoded_data)
elif choice == 2:
text_file_name = input("Enter name of text file to decode: ")
bit_to_hide = int(input("Enter bit to hide (1 - LSB to 8 - MSB): "))
decoded_data = txt_steg(text_file_name, bit_to_hide).decode()
print("Decoded Data:", decoded_data)
if __name__ == "__main__":
main()