version:1.0.7

bugfixes:
update:修改默认登录方式,增加播放加密视频
This commit is contained in:
2026-02-25 10:39:28 +08:00
parent c5980c419a
commit 85ccdcce72
23 changed files with 1079 additions and 76 deletions

191
ui/py/encryption_video.py Normal file
View 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和nonce8字节用于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()

View 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,
)