• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Comprehensive Guide to AES Encryption and LSB Steganography for Beginners

blackhunt

(L2) cache
Пользователь
Регистрация
10.05.2023
Сообщения
333
Решения
8
Реакции
336
In the field of cyber security, the integration of AES encryption and LSB steganography is a powerful approach to protect sensitive data. This guide goes deep into advanced Python scripting that exemplifies these techniques and provides a comprehensive understanding for newbies. I hope this is a good comprehensive guide for all dear users.

Script 1: AES Encryption and LSB Steganography Fundamentals
Python:
from Cryptodome.Cipher import AES
from Cryptodome.Random import get_random_bytes
from PIL import Image
import numpy as np
import os


def generate_aes_key():
    return get_random_bytes(32)  # AES-256


def encrypt_data_aes(data, key):
    cipher = AES.new(key, AES.MODE_CBC)
    ciphertext = cipher.encrypt(pad(data))
    return cipher.iv + ciphertext 

# Padding function for AES
def pad(data):
    pad_len = AES.block_size - (len(data) % AES.block_size)
    padding = bytes([pad_len] * pad_len)
    return data + padding


def hide_data_in_image(input_image_path, output_image_path, data):
    img = Image.open(input_image_path)
    img_array = np.array(img)
    flat_img_array = img_array.flatten()

    data_bits = ''.join(format(byte, '08b') for byte in data)
    data_bits += '00000000' * 2 

    if len(data_bits) > len(flat_img_array):
        raise ValueError("Data is too large to hide in this image.")

    for i, bit in enumerate(data_bits):
        flat_img_array[i] = (flat_img_array[i] & ~1) | int(bit)

    img_array = flat_img_array.reshape(img_array.shape)
    result_img = Image.fromarray(img_array)
    result_img.save(output_image_path)


def get_input_paths():
    while True:
        try:
            input_image = input("Enter the input image path: ").strip()
            if not os.path.isfile(input_image):
                raise FileNotFoundError(f"The file '{input_image}' does not exist.")
            
            output_image = input("Enter the output image path: ").strip()
            secret_image = input("Enter the secret image path: ").strip()
            if not os.path.isfile(secret_image):
                raise FileNotFoundError(f"The file '{secret_image}' does not exist.")
            
            return input_image, output_image, secret_image
        except FileNotFoundError as e:
            print(f"Error: {e}")
        except Exception as e:
            print(f"Error: {e}")


def process_encryption():
    try:
        input_image, output_image, secret_image = get_input_paths()

        with open(secret_image, 'rb') as f:
            data_to_embed = f.read()

        aes_key = generate_aes_key()
        encrypted_data = encrypt_data_aes(data_to_embed, aes_key)

        print(f"Encryption key (keep this secret): {aes_key.hex()}")
        hide_data_in_image(input_image, output_image, encrypted_data)

        print("Encryption successful.")

    except Exception as e:
        print(f"Error during encryption: {e}")

process_encryption()

Overview​

This script lays the groundwork by showcasing the fundamental operations of AES encryption and LSB steganography. It emphasizes key generation, data encryption, and the embedding of encrypted data within image files.

Key Functions Explained​

AES Key Generation

Python:
from Cryptodome.Random import get_random_bytes

def generate_aes_key():
    return get_random_bytes(32)  # AES-256 key

Explanation: The generate_aes_key function generates a secure AES-256 key using get_random_bytes from the Cryptodome library. AES-256 provides robust encryption with a 256-bit key size.

AES Data Encryption
Python:
from Cryptodome.Cipher import AES
from Cryptodome.Util.Padding import pad

def encrypt_data_aes(data, key):
    cipher = AES.new(key, AES.MODE_CBC)
    ciphertext = cipher.encrypt(pad(data, AES.block_size))
    return cipher.iv + ciphertext

Explanation: encrypt_data_aes encrypts data using AES in CBC (Cipher Block Chaining) mode. It pads the data to ensure it aligns with the AES block size and returns the initialization vector (cipher.iv) concatenated with the ciphertext.

Hiding Encrypted Data in an Image

Python:
from PIL import Image
import numpy as np

def hide_data_in_image(input_image_path, output_image_path, data):
    img = Image.open(input_image_path)
    img_array = np.array(img)
    flat_img_array = img_array.flatten()

    data_bits = ''.join(format(byte, '08b') for byte in data)
    data_bits += '00000000' * 2  # End marker: two zero bytes

    if len(data_bits) > len(flat_img_array):
        raise ValueError("Data exceeds image capacity.")

    for i, bit in enumerate(data_bits):
        flat_img_array[i] = (flat_img_array[i] & ~1) | int(bit)

    img_array = flat_img_array.reshape(img_array.shape)
    result_img = Image.fromarray(img_array)
    result_img.save(output_image_path)


Explanation: hide_data_in_image embeds encrypted data within an image using LSB (Least Significant Bit) steganography. It converts the data into binary form and modifies the least significant bit of each pixel in the image to store the data.

Detailed Workflow
Generate AES Key

aes_key = generate_aes_key()

Explanation: The script begins by generating an AES key (aes_key) using the generate_aes_key function.

Encrypt Data
encrypted_data = encrypt_data_aes(data_to_embed, aes_key)

Explanation: It then encrypts the data (data_to_embed) using AES encryption with the generated AES key.

Hide Encrypted Data in Image
hide_data_in_image(input_image, output_image, encrypted_data)

Explanation: The encrypted data is embedded within an input image (input_image) using the hide_data_in_image function and saved as output_image.

Script 2: Advanced AES Decryption and Data Extraction

Python:
from Cryptodome.Cipher import AES
from Cryptodome.Random import get_random_bytes
from PIL import Image
import numpy as np
import os
import imghdr
import string
import random

# Function to generate a random AES key
def generate_aes_key():
    return get_random_bytes(32)  # AES-256

# Function to encrypt data using AES in CBC mode
def encrypt_data_aes(data, key):
    cipher = AES.new(key, AES.MODE_CBC)
    ciphertext = cipher.encrypt(pad(data))
    return cipher.iv + ciphertext  # Prepend the IV for use in decryption

# Function to decrypt data using AES in CBC mode
def decrypt_data_aes(encrypted_data, key):
    iv = encrypted_data[:AES.block_size]
    cipher = AES.new(key, AES.MODE_CBC, iv=iv)
    decrypted_data = cipher.decrypt(encrypted_data[AES.block_size:])
    return decrypted_data  # Return decrypted data without unpadding

# Padding function for AES
def pad(data):
    pad_len = AES.block_size - (len(data) % AES.block_size)
    padding = bytes([pad_len] * pad_len)
    return data + padding

# Unpadding function for AES
def unpad(data):
    pad_len = data[-1]
    return data[:-pad_len]

# Function to hide data in an image (using LSB steganography)
def hide_data_in_image(input_image_path, output_image_path, data):
    img = Image.open(input_image_path)
    img_array = np.array(img)
    flat_img_array = img_array.flatten()

    data_bits = ''.join(format(byte, '08b') for byte in data)
    data_bits += '00000000' * 2  # Two zero bytes as end marker

    if len(data_bits) > len(flat_img_array):
        raise ValueError("Data is too large to hide in this image.")

    for i, bit in enumerate(data_bits):
        flat_img_array[i] = (flat_img_array[i] & ~1) | int(bit)

    img_array = flat_img_array.reshape(img_array.shape)
    result_img = Image.fromarray(img_array)
    result_img.save(output_image_path)

# Function to extract data from an image (using LSB steganography)
def extract_data_from_image(input_image_path):
    img = Image.open(input_image_path)
    img_array = np.array(img)
    flat_img_array = img_array.flatten()

    data_bits = []
    for i in range(len(flat_img_array)):
        data_bits.append(flat_img_array[i] & 1)

    data_bits = ''.join(str(bit) for bit in data_bits)
    end_marker_index = data_bits.find('00000000' * 2)  # Finding the end marker
    data_bits = data_bits[:end_marker_index]

    # Pad data to match AES block size
    padded_data = pad(bytes(int(data_bits[i:i+8], 2) for i in range(0, len(data_bits), 8)))

    return padded_data

# Function to get input path from user with error handling
def get_input_path(prompt):
    while True:
        try:
            file_path = input(prompt).strip()
            if not os.path.isfile(file_path):
                raise FileNotFoundError(f"The file '{file_path}' does not exist.")
            return file_path
        except FileNotFoundError as e:
            print(f"Error: {e}")
        except Exception as e:
            print(f"Error: {e}")

# Function to perform decryption based on user input
def process_decryption():
    try:
        encrypted_image_path = get_input_path("Enter the path of the encrypted image: ")

        aes_key_hex = input("Enter the encryption key in hexadecimal format: ")
        aes_key = bytes.fromhex(aes_key_hex)

        encrypted_data = extract_data_from_image(encrypted_image_path)
        decrypted_data = decrypt_data_aes(encrypted_data, aes_key)

        output_filename = generate_random_filename(encrypted_image_path)
        with open(output_filename, 'wb') as f:
            f.write(decrypted_data)

        print(f"Decryption successful. Data saved to '{output_filename}'.")

    except Exception as e:
        print(f"Error during decryption: {e}")

# Function to generate a random filename with the same extension as the input image
def generate_random_filename(input_image_path):
    file_extension = imghdr.what(input_image_path)
    random_string = ''.join(random.choices(string.ascii_letters + string.digits, k=10))
    return f"decrypted_{random_string}.{file_extension}"

# Calling the function to perform decryption based on user input
process_decryption()

Overview​

This script enhances the previous functionality by introducing decryption capabilities and more sophisticated data extraction techniques from images containing hidden data.

Advanced Functions Explained​


AES Data Decryption
Python:
from Cryptodome.Util.Padding import unpad

def decrypt_data_aes(encrypted_data, key):
    iv = encrypted_data[:AES.block_size]
    cipher = AES.new(key, AES.MODE_CBC, iv=iv)
    decrypted_data = unpad(cipher.decrypt(encrypted_data[AES.block_size:]), AES.block_size)
    return decrypted_data

Explanation: decrypt_data_aes decrypts AES-encrypted data by extracting the initialization vector (iv) and using it to decrypt the ciphertext. It then removes any padding applied during encryption using unpad.

Extracting Data from an Image
Python:
def extract_data_from_image(input_image_path):
    img = Image.open(input_image_path)
    img_array = np.array(img)
    flat_img_array = img_array.flatten()

    data_bits = []
    for i in range(len(flat_img_array)):
        data_bits.append(flat_img_array[i] & 1)

    data_bits = ''.join(str(bit) for bit in data_bits)
    end_marker_index = data_bits.find('00000000' * 2)  # Finding the end marker
    data_bits = data_bits[:end_marker_index]

    extracted_data = bytes(int(data_bits[i:i+8], 2) for i in range(0, len(data_bits), 8))

    return extracted_data

Explanation: extract_data_from_image retrieves hidden data from an image encoded using LSB steganography. It reconstructs the binary data from the least significant bits of the image pixels and returns the extracted data.


Detailed Workflow

1.Encrypt Data and Hide in Image (as previously described)
2.Extract and Decrypt Data
extracted_data = extract_data_from_image(input_image)
decrypted_data = decrypt_data_aes(extracted_data, aes_key)

Explanation: The script retrieves hidden data from the output image (input_image) using extract_data_from_image. It then decrypts the extracted data (extracted_data) using AES decryption with the previously generated AES key (aes_key).

Script 3: Dynamic AES Key Generation and Steganography with OpenCV


Python:
from Cryptodome.Cipher import AES
from Cryptodome.Random import get_random_bytes
from Cryptodome.Util.Padding import pad, unpad
import cv2
import numpy as np

# Function to generate AES encryption key
def generate_aes_key(length=32):
    return get_random_bytes(length) 


def generate_aes_key_for_data(data):
    data_size = len(data)
  
    if data_size <= 16:
        return get_random_bytes(16)
    elif data_size <= 24:
        return get_random_bytes(24)
    else:
        return get_random_bytes(32)


def encrypt_data_aes(data, key):
    cipher = AES.new(key, AES.MODE_CBC)
    ciphertext = cipher.encrypt(pad(data, AES.block_size))
    return cipher.iv + ciphertext


def decrypt_data_aes(encrypted_data, key):
    iv = encrypted_data[:AES.block_size]
    cipher = AES.new(key, AES.MODE_CBC, iv)
    decrypted_data = unpad(cipher.decrypt(encrypted_data[AES.block_size:]), AES.block_size)
    return decrypted_data


def test_aes_key(data, key):
    try:
        encrypted_data = encrypt_data_aes(data, key)
        decrypted_data = decrypt_data_aes(encrypted_data, key)
        return decrypted_data == data
    except Exception as e:
        print(f"Error during key test: {e}")
        return False


def hide_data_in_image(input_image, output_image, data):
    img = cv2.imread(input_image)
    data_size = len(data)
    data = np.frombuffer(data, dtype=np.uint8)

    size_data = np.array([data_size >> 24, (data_size >> 16) & 0xFF, (data_size >> 8) & 0xFF, data_size & 0xFF], dtype=np.uint8)
    data = np.concatenate((size_data, data))

    binary_data = ''.join(format(byte, '08b') for byte in data)
    data_index = 0

    for row in img:
        for pixel in row:
            for channel in range(3):
                if data_index < len(binary_data):
                    pixel[channel] = int(bin(pixel[channel])[2:-1] + binary_data[data_index], 2)
                    data_index += 1

    cv2.imwrite(output_image, img)
    print(f"Data hidden successfully in {output_image}")


def extract_data_from_image(input_image, key):
    img = cv2.imread(input_image)
    extracted_data = []
    binary_data = ''

    for row in img:
        for pixel in row:
            for channel in range(3):
                binary_data += bin(pixel[channel])[-1]

    for i in range(0, len(binary_data), 8):
        byte = binary_data[i:i+8]
        extracted_data.append(int(byte, 2))

    extracted_data = bytes(extracted_data)

    # Extract the original data size
    original_size = int.from_bytes(extracted_data[:4], byteorder='big')
    actual_data = extracted_data[4:4+original_size]

    decrypted_data = decrypt_data_aes(actual_data, key)

    return decrypted_data


def main():
    mode = input("Enter 'encrypt' to encrypt data into an image or 'extract' to extract data from an image: ").strip().lower()

    if mode == 'encrypt':
        input_image = input("Enter the path of the input image file (e.g., input_image.png): ").strip()
        output_image = input("Enter the path for the output image file (e.g., output_image.png): ").strip()
        text_file_path = input("Enter the path of the text file to be embedded: ").strip()

        with open(text_file_path, 'rb') as f:
            data_to_embed = f.read()

        aes_key = generate_aes_key_for_data(data_to_embed)
        encrypted_data = encrypt_data_aes(data_to_embed, aes_key)

        
        if not test_aes_key(data_to_embed, aes_key):
            print("Generated key is invalid.")
            return

        print(f"Encryption key (keep this secret): {aes_key.hex()}")
        print(f"Encrypted data (in hexadecimal format): {encrypted_data.hex()}")

        hide_data_in_image(input_image, output_image, encrypted_data)

    elif mode == 'extract':
        input_image = input("Enter the path of the input image file (e.g., output_image.png): ").strip()
        encryption_key = input("Enter the encryption key (in hexadecimal format): ").strip()

        try:
            aes_key = bytes.fromhex(encryption_key)
            if len(aes_key) not in [16, 24, 32]:
                raise ValueError("Invalid key length. Key must be 16, 24, or 32 bytes long.")

            extracted_data = extract_data_from_image(input_image, aes_key)
            print("Extracted data:")
            print(extracted_data.decode('utf-8'))  # Assuming the data is text
        except ValueError as e:
            print(str(e))
        except Exception as e:
            print(f"Error during extraction: {e}")

    else:
        print("Invalid mode. Please enter either 'encrypt' or 'extract'.")


if __name__ == "__main__":
    main()

Script 3: Dynamic AES Key Generation and Steganography with OpenCV

IMAGE-TO-TEXT

Overview​

This script extends functionality by dynamically generating AES keys based on data size and integrating OpenCV for more advanced image processing operations in steganography

Advanced Functions Explained

Dynamic AES Key Generation

Python:
def generate_aes_key_for_data(data):
    data_size = len(data)
    if data_size <= 16:
        return get_random_bytes(16)
    elif data_size <= 24:
        return get_random_bytes(24)
    else:
        return get_random_bytes(32)
Explanation: generate_aes_key_for_data generates an AES key of appropriate length (16, 24, or 32 bytes) based on the size of the input data.

Enhanced Data Hiding in Image
Python:
import cv2

def hide_data_in_image(input_image, output_image, data):
    img = cv2.imread(input_image)
    data_size = len(data)
    data = np.frombuffer(data, dtype=np.uint8)

    size_data = np.array([data_size >> 24, (data_size >> 16) & 0xFF, (data_size >> 8) & 0xFF, data_size & 0xFF], dtype=np.uint8)
    data = np.concatenate((size_data, data))

    binary_data = ''.join(format(byte, '08b') for byte in data)
    data_index = 0

    for row in img:
        for pixel in row:
            for channel in range(3):
                if data_index < len(binary_data):
                    pixel[channel] = int(bin(pixel[channel])[2:-1] + binary_data[data_index], 2)
                    data_index += 1

    cv2.imwrite(output_image, img)
    print(f"Data hidden successfully in {output_image}")

Explanation: hide_data_in_image employs OpenCV to manipulate image pixels efficiently. It encodes data in the least significant bits of the image channels, ensuring minimal visual impact on the image while concealing the data effectively.

Advanced Data Extraction from Image
Python:
def extract_data_from_image(input_image, key):
    img = cv2.imread(input_image)
    extracted_data = []
    binary_data = ''

    for row in img:
        for pixel in row:
            for channel in range(3):
                binary_data += bin(pixel[channel])[-1]

    for i in range(0, len(binary_data), 8):
        byte = binary_data[i:i+8]
        extracted_data.append(int(byte, 2))

    extracted_data = bytes(extracted_data)

    original_size = int.from_bytes(extracted_data[:4], byteorder='big')
    actual_data = extracted_data[4:4+original_size]

    decrypted_data = decrypt_data_aes(actual_data, key)

    return decrypted_data

Explanation: extract_data_from_image leverages OpenCV to extract hidden data from an image using LSB steganography. It reconstructs the binary data from the least significant bits of the image pixels and performs AES decryption to retrieve the original data.

Result :
These advanced techniques in AES encryption and LSB steganography provide a robust framework for securing and concealing sensitive data. By understanding and implementing these scripts, even newcomers can gain a deep insight into the intricate interplay between cryptography and steganography, thereby enhancing data security and privacy in practical applications.


Author : blackhunt
Specially for xss.pro

~./Enjoy !
 

Вложения

  • 3.png
    3.png
    76.7 КБ · Просмотры: 15
  • stego.zip
    4.2 КБ · Просмотры: 5


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх