Files
video/encryption/encryption.py
2025-09-15 18:08:54 +08:00

73 lines
2.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import base64
import os
from dotenv import load_dotenv
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes
# 加载环境变量(从 .env 文件读取密钥)
load_dotenv()
class AESCipher:
"""AES-CBC 对称加密工具类"""
# 从环境变量获取密钥AES-256 需 32 字节密钥AES-128 需 16 字节)
SECRET_KEY = "jr1vA6tfWMHOYi6UXw67UuO6fdak2rMa".encode("utf-8")
# AES 块大小固定为 16 字节
BLOCK_SIZE = 16
@classmethod
def _validate_key(cls):
"""校验密钥长度AES-256 需 32 字节AES-128 需 16 字节)"""
if len(cls.SECRET_KEY) not in (16, 32):
raise ValueError("AES 密钥长度必须为 16 字节AES-128或 32 字节AES-256")
@classmethod
def encrypt(cls, data: dict) -> dict:
"""
加密函数:将字典类型的 data 加密
返回:{encrypted_data: 加密后Base64字符串, iv: 16字节IV的Base64字符串}
"""
cls._validate_key()
# 1. 生成 16 字节随机 IV每次加密都生成新 IV无需保密但需和解密一致
iv = get_random_bytes(cls.BLOCK_SIZE)
# 2. 初始化 AES-CBC 加密器
cipher = AES.new(cls.SECRET_KEY, AES.MODE_CBC, iv)
# 3. 数据序列化字典转JSON字符串→ 编码为字节 → 填充PKCS7
data_str = str(data) # 若需更严谨,可使用 json.dumps(data, ensure_ascii=False)
data_bytes = data_str.encode("utf-8")
padded_data = pad(data_bytes, cls.BLOCK_SIZE, style="pkcs7")
# 4. 加密 → 转为 Base64 字符串(便于接口传输)
encrypted_bytes = cipher.encrypt(padded_data)
encrypted_data = base64.b64encode(encrypted_bytes).decode("utf-8")
iv_b64 = base64.b64encode(iv).decode("utf-8")
return {
"encrypted_data": encrypted_data,
"iv": iv_b64 # IV 需随密文一起返回,供前端解密
}
@classmethod
def decrypt(cls, encrypted_data: str, iv_b64: str) -> dict:
"""
解密函数:将加密后的 Base64 字符串解密为字典
参数encrypted_data加密数据、iv_b64加密时的IV
"""
cls._validate_key()
# 1. 解码 Base64IV 和 密文)
iv = base64.b64decode(iv_b64)
encrypted_bytes = base64.b64decode(encrypted_data)
# 2. 初始化 AES-CBC 解密器
cipher = AES.new(cls.SECRET_KEY, AES.MODE_CBC, iv)
# 3. 解密 → 去除填充 → 解码为字符串 → 转为字典(此处简化,实际可用 json.loads
decrypted_bytes = unpad(cipher.decrypt(encrypted_bytes), cls.BLOCK_SIZE, style="pkcs7")
decrypted_str = decrypted_bytes.decode("utf-8")
return eval(decrypted_str) # 生产环境建议用 json.loads避免 eval 安全风险