version:1.0.7
bugfixes: update:修改默认登录方式,增加播放加密视频
This commit is contained in:
191
ui/py/encryption_video.py
Normal file
191
ui/py/encryption_video.py
Normal file
@@ -0,0 +1,191 @@
|
||||
import tkinter as tk
|
||||
from tkinter import filedialog, messagebox, ttk
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Util.Padding import pad
|
||||
from Crypto.Random import get_random_bytes
|
||||
import os
|
||||
import base64
|
||||
|
||||
class VideoEncryptorGUI:
|
||||
def __init__(self, master):
|
||||
self.master = master
|
||||
master.title("视频加密工具")
|
||||
master.geometry("500x400")
|
||||
|
||||
self.input_file_path = None
|
||||
|
||||
# 创建GUI组件
|
||||
self.label_title = tk.Label(master, text="视频文件加密工具", font=("Arial", 14, "bold"))
|
||||
self.label_title.pack(pady=10)
|
||||
|
||||
self.btn_select = tk.Button(master, text="选择视频文件", command=self.select_file, width=20, height=2)
|
||||
self.btn_select.pack(pady=5)
|
||||
|
||||
self.label_file = tk.Label(master, text="未选择文件", wraplength=400)
|
||||
self.label_file.pack(pady=5)
|
||||
|
||||
# Key输入
|
||||
self.label_key = tk.Label(master, text="AES密钥 (Base64编码或16/24/32字节字符串):")
|
||||
self.label_key.pack(pady=(10,0))
|
||||
self.entry_key = tk.Entry(master, width=50)
|
||||
self.entry_key.pack(pady=5)
|
||||
|
||||
# IV输入
|
||||
self.label_iv = tk.Label(master, text="初始化向量IV (Base64编码或8字节字符串):")
|
||||
self.label_iv.pack(pady=(10,0))
|
||||
self.entry_iv = tk.Entry(master, width=50)
|
||||
self.entry_iv.pack(pady=5)
|
||||
|
||||
# 生成随机Key和IV按钮
|
||||
self.btn_generate = tk.Button(master, text="生成随机密钥和IV", command=self.generate_key_iv, width=20)
|
||||
self.btn_generate.pack(pady=5)
|
||||
|
||||
# 加密按钮
|
||||
self.btn_encrypt = tk.Button(master, text="加密文件", command=self.encrypt_video, width=20, height=2, bg="#4CAF50", fg="white")
|
||||
self.btn_encrypt.pack(pady=10)
|
||||
|
||||
self.status_label = tk.Label(master, text="", fg="blue")
|
||||
self.status_label.pack(pady=5)
|
||||
|
||||
# 说明文本
|
||||
help_text = "说明:输出文件将与输入文件同目录,扩展名为.hnv"
|
||||
self.label_help = tk.Label(master, text=help_text, fg="gray", font=("Arial", 9))
|
||||
self.label_help.pack(pady=10)
|
||||
|
||||
def select_file(self):
|
||||
"""选择要加密的文件"""
|
||||
file_path = filedialog.askopenfilename(
|
||||
title="选择视频文件",
|
||||
filetypes=[("视频文件", "*.mp4 *.avi *.mov *.mkv"), ("所有文件", "*.*")]
|
||||
)
|
||||
if file_path:
|
||||
self.input_file_path = file_path
|
||||
self.label_file.config(text=file_path)
|
||||
self.status_label.config(text="文件已选择,请设置密钥")
|
||||
|
||||
def generate_key_iv(self):
|
||||
"""生成随机的密钥和nonce"""
|
||||
# 生成随机密钥(32字节,AES-256)和nonce(8字节用于CTR模式)
|
||||
key = get_random_bytes(32)
|
||||
nonce = get_random_bytes(8) # AES CTR模式使用的nonce应该是8字节
|
||||
|
||||
# 转换为Base64编码字符串,显示在输入框中
|
||||
key_b64 = base64.b64encode(key).decode('utf-8')
|
||||
nonce_b64 = base64.b64encode(nonce).decode('utf-8')
|
||||
|
||||
self.entry_key.delete(0, tk.END)
|
||||
self.entry_key.insert(0, key_b64)
|
||||
self.entry_iv.delete(0, tk.END)
|
||||
self.entry_iv.insert(0, nonce_b64)
|
||||
|
||||
self.status_label.config(text="已生成随机密钥和nonce,请妥善保存!")
|
||||
|
||||
def encrypt_video(self):
|
||||
"""加密视频文件"""
|
||||
if not self.input_file_path:
|
||||
messagebox.showerror("错误", "请先选择要加密的文件")
|
||||
return
|
||||
|
||||
key_str = self.entry_key.get().strip()
|
||||
iv_str = self.entry_iv.get().strip()
|
||||
|
||||
if not key_str or not iv_str:
|
||||
messagebox.showerror("错误", "请输入密钥和IV")
|
||||
return
|
||||
|
||||
try:
|
||||
|
||||
# 处理密钥:尝试Base64解码,否则使用字符串编码
|
||||
|
||||
# try:
|
||||
# key = base64.b64decode(key_str)
|
||||
# except:
|
||||
key = key_str.encode('utf-8')
|
||||
|
||||
# 处理IV:尝试Base64解码,否则使用字符串编码
|
||||
|
||||
# try:
|
||||
# iv = base64.b64decode(iv_str)
|
||||
# except:
|
||||
iv = iv_str.encode('utf-8')
|
||||
|
||||
# 确保密钥长度为16、24或32字节
|
||||
# if len(key) not in [16, 24, 32]:
|
||||
# if len(key) < 16:
|
||||
# key = key.ljust(16, b'\0')
|
||||
# elif len(key) < 24:
|
||||
# key = key.ljust(24, b'\0')
|
||||
# elif len(key) < 32:
|
||||
# key = key.ljust(32, b'\0')
|
||||
# else:
|
||||
# key = key[:32]
|
||||
|
||||
# 确保IV长度为16字节
|
||||
# if len(iv) != 16:
|
||||
# if len(iv) < 16:
|
||||
# iv = iv.ljust(16, b'\0')
|
||||
# else:
|
||||
# iv = iv[:16]
|
||||
|
||||
# 生成输出文件路径
|
||||
file_dir = os.path.dirname(self.input_file_path)
|
||||
file_name = os.path.basename(self.input_file_path)
|
||||
file_base = os.path.splitext(file_name)[0]
|
||||
output_file = os.path.join(file_dir, f"{file_base}.hnv")
|
||||
|
||||
# 执行加密
|
||||
self.do_encryption(self.input_file_path, output_file, key, iv)
|
||||
|
||||
self.status_label.config(text=f"加密成功!输出文件: {output_file}")
|
||||
messagebox.showinfo("成功", f"文件加密完成!\n输出文件: {output_file}")
|
||||
|
||||
except Exception as e:
|
||||
messagebox.showerror("加密错误", f"加密过程中发生错误: {str(e)}")
|
||||
|
||||
def do_encryption(self, input_path, output_path, key, iv):
|
||||
print(f"iv len: {len(iv)}")
|
||||
|
||||
"""
|
||||
执行加密操作
|
||||
使用AES/CTR/NoPadding模式
|
||||
"""
|
||||
try:
|
||||
# 创建CTR模式加密器
|
||||
cipher = AES.new(key, AES.MODE_CTR, nonce=iv)
|
||||
with open(input_path, 'rb') as fin:
|
||||
with open(output_path, 'wb') as fout:
|
||||
# 将IV写入文件开头,解密时需要
|
||||
fout.write(iv)
|
||||
|
||||
# 逐块加密文件
|
||||
while True:
|
||||
chunk = fin.read(4096) # 每次读取4KB
|
||||
if len(chunk) == 0:
|
||||
break
|
||||
encrypted_chunk = cipher.encrypt(chunk)
|
||||
fout.write(encrypted_chunk)
|
||||
|
||||
except Exception as e:
|
||||
raise Exception(f"加密失败: {str(e)}")
|
||||
|
||||
def main():
|
||||
# 检查所需库是否已安装
|
||||
try:
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Util.Padding import pad
|
||||
from Crypto.Random import get_random_bytes
|
||||
except ImportError:
|
||||
print("正在安装所需库...")
|
||||
import subprocess
|
||||
import sys
|
||||
subprocess.check_call([sys.executable, "-m", "pip", "install", "pycryptodome"])
|
||||
print("库安装完成,请重新运行程序")
|
||||
return
|
||||
|
||||
# 创建主窗口
|
||||
root = tk.Tk()
|
||||
app = VideoEncryptorGUI(root)
|
||||
root.mainloop()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
38
ui/py/encryption_video.spec
Normal file
38
ui/py/encryption_video.spec
Normal file
@@ -0,0 +1,38 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
|
||||
|
||||
a = Analysis(
|
||||
['encryption_video.py'],
|
||||
pathex=[],
|
||||
binaries=[],
|
||||
datas=[],
|
||||
hiddenimports=[],
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
noarchive=False,
|
||||
optimize=0,
|
||||
)
|
||||
pyz = PYZ(a.pure)
|
||||
|
||||
exe = EXE(
|
||||
pyz,
|
||||
a.scripts,
|
||||
a.binaries,
|
||||
a.datas,
|
||||
[],
|
||||
name='encryption_video',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
runtime_tmpdir=None,
|
||||
console=False,
|
||||
disable_windowed_traceback=False,
|
||||
argv_emulation=False,
|
||||
target_arch=None,
|
||||
codesign_identity=None,
|
||||
entitlements_file=None,
|
||||
)
|
||||
Reference in New Issue
Block a user