基于AES算法实现视频帧加密

基本知识介绍

AES算法

AES加密流程

密钥扩展: 将初始密钥扩展为多个子密钥,进行后续加密处理。

初始轮:

  • 轮密钥加: 将数据块与第一个子密钥通过异或运算进行结合。

主要轮次 : 根据密钥长度,AES 有 10、12 或 14 个主要轮次。每个主要轮次包括四个步骤:

  • 字节代换: 使用一个固定的S-盒对每个字节进行替换。
  • 行移位 : 对状态矩阵的每一行进行循环左移操作。
  • 列混淆 : 对状态矩阵的每一列进行线性变换。
  • 轮密钥加: 将当前状态与本轮的子密钥进行异或运算。

最终轮: 与主要轮次类似,但省略了“列混淆”步骤。

字节代换-------> 行移位-------->轮密钥加

CFB模式

CFB(Cipher Feedback)是块密码的一种工作模式,它将块密码转换为流密码,用于加密和解密数据。

CFB工作模式的主要步骤

初始化向量 (IV): 选择一个随机的初始化向量,这个向量的长度等于块大小。

块加密:使用AES对IV进行加密,生成一个密钥流块。

生成密文:将密钥流块与明文块进行异或运算,生成密文块。

更新IV:将密文块的一部分作为新的IV,用于下一个明文块的加密。

设计步骤

AES加解密实现

定义AES加密和解密函数,使用Crypto.Cipher模块中的AES算法

# 加密函数
def aes_encrypt(data, key, iv):
    cipher = AES.new(key, AES.MODE_CFB, iv)
    return cipher.encrypt(data)

# 解密函数
def aes_decrypt(encrypted_data, key, iv):
    cipher = AES.new(key, AES.MODE_CFB, iv)
    return cipher.decrypt(encrypted_data)

aes_encrypt函数接收明文数据data、密钥key和初始化向量iv,使用AES的CFB模式进行加密,并返回加密后的数据。

aes_decrypt函数接收密文数据encrypted_data、密钥key和初始化向量iv,同样使用AES的CFB模式进行解密,并返回解密后的数据。

将完整视频转为帧

使用cv2.VideoCapture来读取视频文件,并将其转换为帧

cap = cv2.VideoCapture(video_file_path)
if not cap.isOpened():
    print(f"Error opening video file: {video_file_path}")
    return

frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
fps = int(cap.get(cv2.CAP_PROP_FPS))

cap.get(3)cap.get(4)分别获取视频的宽度和高度,cap.get(cv2.CAP_PROP_FPS)来获取视频的帧率。

对视频帧加密

定义encrypt_video_frame函数对单个视频帧进行加密

def encrypt_video_frame(frame, key, iv):
    frame_bytes = frame.tobytes()
    encrypted_frame_bytes = aes_encrypt(frame_bytes, key, iv)
    return np.frombuffer(encrypted_frame_bytes, dtype=np.uint8).reshape(frame.shape)

frame.tobytes()将视频帧转换为字节序列,然后用aes_encrypt函数对字节序列进行加密。

np.frombuffer将加密后的字节序列转换回NumPy数组,使用reshape调整为原始帧的形状。

对视频帧解密

定义decrypt_video_frame函数对单个视频帧进行解密

def decrypt_video_frame(encrypted_frame_bytes, key, iv, frame_shape):
    try:
        decrypted_frame_bytes = aes_decrypt(encrypted_frame_bytes, key, iv)
        decrypted_frame = np.frombuffer(decrypted_frame_bytes, dtype=np.uint8)
        return decrypted_frame.reshape(frame_shape)
    except Exception as e:
        print(f"解密失败:{e}")
        return None

aes_decrypt函数对加密的视频帧进行解密,np.frombuffer将解密后的字节序列转换回NumPy数组,然后使用reshape调整为原始帧的形状,如果解密失败则返回None。

核心主程序实现

打开视频文件并检查是否成功

cap = cv2.VideoCapture(video_file_path)
if not cap.isOpened():
    print(f"Error opening video file: {video_file_path}")
    return

首先打开传入的视频文件路径video_file_path,并检查是否成功打开。如果打开失败则打印错误信息并退出函数。

获取视频信息

frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
fps = int(cap.get(cv2.CAP_PROP_FPS))

分别获取视频的宽度、高度和帧率

创建视频写入对象

fourcc = cv2.VideoWriter_fourcc(*'mp4v')
output_file_path = 'encrypted_video.mp4' if encrypt else 'decrypted_video.mp4'
out = cv2.VideoWriter(output_file_path, fourcc, fps, (frame_width, frame_height))

根据是否加密,设置输出文件的路径(名)

创建cv2.VideoWriter对象将处理后的帧写入新的视频文件中

初始化变量

frame_count = 0
encrypted_frame_indices = []
encrypted_frames_data = []

进行初始化变量帧计数器frame_count,加密帧索引列表encrypted_frame_indices和加密帧数据列表encrypted_frames_data

加密流程

if encrypt:
    while True:
        ret, frame = cap.read()
        if not ret:
            break

        frame_count += 1

        if (frame_count - 1) % 400 < 150:
            encrypted_frame = encrypt_video_frame(frame, key, iv)
            encrypted_frames_data.append(encrypted_frame)
            encrypted_frame_indices.append((frame_count - 1, len(encrypted_frames_data) - 1))
            out.write(encrypted_frame)
        else:
            out.write(frame)

    with open('encrypted_frame_indices.txt', 'w') as f:
        for original_index, encrypted_index in encrypted_frame_indices:
            f.write(f"{original_index} --> {encrypted_index}\n")

    np.save('encrypted_frames_data.npy', encrypted_frames_data)

详细加密流程,逐帧读取视频并根据条件(frame_count - 1) % 400 < 150(每400帧加密一次,每次加密150帧)来决定是否加密。加密的帧会被添加到encrypted_frames_data中,并记录索引映射到encrypted_frame_indices。最后,将加密帧索引映射保存到文件encrypted_frame_indices.txt中,将加密帧数据保存到文件encrypted_frames_data.npy中。

解密流程

else:
    with open('encrypted_frame_indices.txt', 'r') as f:
        encrypted_frame_indices = [(int(line.split(' --> ')[0]), int(line.split(' --> ')[1])) for line in f]

    encrypted_frames_data = np.load('encrypted_frames_data.npy', allow_pickle=True)

    encrypted_frame_indices_dict = {orig_index: enc_index for orig_index, enc_index in encrypted_frame_indices}

    while True:
        ret, frame = cap.read()
        if not ret:
            break

        frame_count += 1

        if frame_count - 1 in encrypted_frame_indices_dict:
            enc_index = encrypted_frame_indices_dict[frame_count - 1]
            encrypted_frame = encrypted_frames_data[enc_index]
            decrypted_frame = decrypt_video_frame(encrypted_frame.tobytes(), key, iv, frame.shape)
            if decrypted_frame is not None:
                out.write(decrypted_frame)
            else:
                print("某帧解密失败,使用原始帧替代")
                out.write(frame)
        else:
            out.write(frame)

详细解密流程,首先从文件encrypted_frame_indices.txt中读取加密帧的索引映射,并从文件encrypted_frames_data.npy中加载加密后的帧数据。接着逐帧读取视频,对于加密的帧,根据索引映射找到对应的加密帧数据,并进行解密。如果解密成功,就将解密后的帧写入视频文件;如果解密失败,打印错误信息并使用原始帧替代。

释放资源打印完成信息

cap.release()
out.release()
cv2.destroyAllWindows()
print(f"\n{output_file_path} 已生成。")

释放视频捕获和视频写入对象,关闭所有OpenCV窗口;打印完成信息,输出文件的路径。

实现结果

4k.mp4 原视频
encrypted_video.mp4 加密视频
encrypted_frames_data.npy 加密的帧数据
encrypted_frame_indices.txt  原视频帧与加密帧对应关系
decrypted_video.mp4 解密视频

加密后的视频内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值