Fourier domain steganography for .mp4 video in python3

157 Views Asked by At

Well, one could say I got inspired by a project I saw on github made in rust that takes a .zip file and embeds it in a video that you could upload to youtube to have "file storage".

I wanted to do the same but in python and with Fourier domain steganography (not sure if that even works). I managed to use chatgpt (never doing that again, god it is awful now) to make a function that should (idk if it does) embed bytes from a .tar.gz file (or any file) into the video frames.

My main issues are that I don't know if it works. The code runs without error and it seems to work...but I don't know if it actually did embed the file bytes in the video. On top of that I don't know how to retrieve those file bytes that were supposedly embedded into the video frames. I am also unsure if the video being made via "generate_video()" has anything to do with any issues I may come across.

Here is some code that I have for context and that I am working on.

import cv2
import numpy as np
from scipy.fft import fft2, ifft2
import secrets
import string
import os
import tqdm

def clear():
    os.system('clear||cls')



# Generate a random file name using secrets and string libraries
def generate_filename():
    alphabet = string.ascii_letters + string.digits
    filename = ''.join(secrets.choice(alphabet) for i in range(12)) + ".mp4"
    return filename


# Function to generate random visual noise/static
def generate_video():
    # Set video parameters
    width = 640
    height = 480
    fps = 30
    duration = 30


    # Create video writer object
    filename = generate_filename()
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    out = cv2.VideoWriter(filename, fourcc, fps, (width, height))

    # Write frames to the video
    for i in range(duration * fps):
        noise = np.random.randint(0, 256, (height, width, 3), dtype=np.uint8)
        out.write(noise)

    # Release the video writer and display filename
    out.release()
    return filename





def encode_video(file_name):
    with open(file_name, 'rb') as rb:
        file_bytes = rb.read()

    video_path = generate_video()

    # Load video
    cap = cv2.VideoCapture(video_path)

    # Get video dimensions
    width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    fps = int(cap.get(cv2.CAP_PROP_FPS))
    num_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))

    # Calculate number of bytes to hide per frame
    bytes_per_frame = len(file_bytes) // num_frames

    # Create tqdm progress bar
    progress_bar = tqdm.tqdm(total=num_frames, desc="Embedding Data...")

    # Loop through video frames and hide bytes in each frame
    for i in range(num_frames):
        ret, frame = cap.read()

        if ret:
            # Convert frame to grayscale
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

            # Take the 2D fast Fourier transform of the grayscale frame
            fft = np.fft.fft2(gray)

            # Flatten the 2D Fourier transform into a 1D array
            fft_flat = fft.flatten()

            # Hide bytes in the Fourier coefficients
            start_index = i * bytes_per_frame
            end_index = start_index + bytes_per_frame
            bytes_to_hide = np.frombuffer(file_bytes[start_index:end_index], dtype=np.uint8)
            fft_flat[start_index:end_index] += bytes_to_hide

            # Reshape the modified Fourier coefficients back into a 2D array
            fft_modified = fft_flat.reshape(height, width)

            # Take the inverse Fourier transform to get the modified grayscale frame
            gray_modified = np.fft.ifft2(fft_modified).real

            # Convert the modified grayscale frame back to BGR color format
            frame_modified = cv2.cvtColor(gray_modified.astype(np.uint8), cv2.COLOR_GRAY2BGR)

            # Write the modified frame to the output video file
            if i == 0:
                # Create the VideoWriter object on the first iteration
                output_path = 'special_vid.mp4'
                fourcc = cv2.VideoWriter_fourcc(*'mp4v')
                out = cv2.VideoWriter(output_path, fourcc, fps, (width, height), True)
            out.write(frame_modified)

            # Update progress bar
            progress_bar.update(1)

    progress_bar.close()

    # Release resources
    cap.release()
    out.release()
    cv2.destroyAllWindows()


    os.remove(video_path)
    os.rename(output_path, video_path)

    clear()
    print("Data successfully embedded.")

I don't have a function to extract the file bytes/data that was embedded in the first place. (yet..kinda hoping to get help with that too)

As for what I have tried, I couldn't find a place to start, searching things up didn't seem to help and all I got was definitions for steganography. I've also tried to use chatgpt like how I was able to get some sort of template to work off of like the "encode_video()" function...but that went about as well as one could expect...(didn't work). Everything it gave me just didn't seem to give me the correct bytes or data to write to a file.

For this question and why I have come to stack are the following

  • To know if the "encode_video" function works and will even do what it's supposed to do.(hide/embed a file in the video)

  • To get some help with a function to retrieve the embedded file from the video.

And if "Fourier domain steganography" will actually work, and if it doesn't, then some help on figuring out a different method for hiding a file in a video and retrieving the file.

Any advice, resources, or help would be VERY appreciated and loved.




TLDR; I am using "Fourier domain steganography" to try and hide a file in a video and idk if the function even works properly. I could use help with making a function to retrieve the file embedded into the video. And if this isn't possible, what other methods are there and can I get help with that as well.

(This is also the last time I even try to use chatgpt, but then again, I couldn't find any easily available resources covering what I wanted to do.)

0

There are 0 best solutions below