user21612887
user21612887

Reputation:

How to correctly encrypt the I-frames in video files?

I'm trying to encrypt only the I-frames of a video file so that the energy overhead is lessened compared to if I tried to encrypt the whole file. However, after encrypting what I thought were the I-frames, the video seems to play normally (except for the encrypted frames). I thought that the point of encrypting the I-frames was so that the other frames would be distorted, but that doesn't seem to be the case. I was wondering what seems to be wrong ? The file format is avi with codec MPEG-4 video (FMP4).

I used ffmpeg to identity the I frames of a certain video (named "video1") : "ffprobe -select_streams v -show_frames -of csv video1.avi > video_frame_info.csv". I got this table which seems to indicate that every 12th frame is an I-frame. I then used this python program to encrypt every 12th frame with chacha20 from the pycryptodome library :

from Crypto.Cipher import ChaCha20
from Crypto.Random import get_random_bytes
import cv2
import numpy as np

def read_frames(video_path):
    # Load the video file
    video = cv2.VideoCapture(video_path)

    # Initialize a list to hold frames
    frames = []

    # Loop until there are frames left in the video file
    while video.isOpened():
        ret, frame = video.read()
        if not ret:
            break

        frames.append(frame)

    video.release()

    return frames

def encrypt_iframes(frames, key):
    # Initialize the cipher
    cipher = ChaCha20.new(key=key)

    # Encrypt every 12th frame (considering the first frame as an I-frame)
    for i in range(0, len(frames), 12):
        frame = frames[i]
        # Flatten and bytes-encode the frame
        flat_frame = frame.flatten()
        bytes_frame = flat_frame.tobytes()

        # Encrypt the frame
        encrypted_frame = cipher.encrypt(bytes_frame)

        # Replace the original frame with the encrypted one
        frames[i] = np.frombuffer(encrypted_frame, dtype=flat_frame.dtype).reshape(frame.shape)

    return frames

def write_frames(frames, output_path):
    # Assume all frames have the same shape
    height, width, _ = frames[0].shape

    # Create a VideoWriter object
    out = cv2.VideoWriter(output_path, cv2.VideoWriter_fourcc(*'mpv4'), 30, (width, height))

    for frame in frames:
        out.write(frame)

    out.release()

def main():
    # Generate a random key
    key = get_random_bytes(32)

    # Read frames from video
    frames = read_frames('video1.avi')

    # Encrypt I-frames
    encrypted_frames = encrypt_iframes(frames, key)

    # Write encrypted frames to a new video file
    write_frames(encrypted_frames, 'reprise.avi')

if __name__ == "__main__":
    main()

When I play the video, every 12th frame there is just noise on the screen, which makes sense since it was encrypted. However, all the other frames seem to be completely normal, even thought they are P-frames and should depend on the I-frames. What am I doing wrong, and how can I make it so that it works as intended ? Thanks in advance

Upvotes: 0

Views: 228

Answers (0)

Related Questions