ADD file via upload

main
p9x5lkiwf 4 months ago
parent f401064b74
commit 9814aa1725

@ -0,0 +1,182 @@
import tkinter as tk
from tkinter import ttk, messagebox, filedialog
import os
import base64
from .context import UIContext
def create_crypto_tab(notebook: ttk.Notebook, ctx: UIContext, crypto_mod) -> ttk.Frame:
frame = ttk.Frame(notebook)
notebook.add(frame, text="加密/解密")
top = ttk.Frame(frame)
top.pack(fill=tk.X, padx=10, pady=10)
ttk.Button(top, text="选择待处理文件", command=ctx.choose_file).pack(side=tk.LEFT, padx=5)
ttk.Label(top, text="算法:").pack(side=tk.LEFT)
alg_var = tk.StringVar(value="AES")
ttk.Combobox(top, textvariable=alg_var, values=["AES"], width=8, state="readonly").pack(side=tk.LEFT, padx=5)
ttk.Label(top, text="模式:").pack(side=tk.LEFT)
mode_var = tk.StringVar(value="GCM")
ttk.Combobox(top, textvariable=mode_var, values=["CBC", "GCM", "CTR"], width=8, state="readonly").pack(side=tk.LEFT, padx=5)
actions = ttk.Frame(frame)
actions.pack(fill=tk.X, padx=10, pady=6)
ttk.Button(actions, text="加密", command=lambda: _on_encrypt(ctx, crypto_mod, alg_var, mode_var)).pack(side=tk.LEFT, padx=5)
ttk.Button(actions, text="解密", command=lambda: _on_decrypt(ctx, crypto_mod, alg_var, mode_var)).pack(side=tk.LEFT, padx=5)
return frame
def _on_encrypt(ctx: UIContext, crypto_mod, alg_var: tk.StringVar, mode_var: tk.StringVar):
"""加密文件"""
if not ctx.ensure_impl(crypto_mod, "加密/解密"):
return
selected = ctx.get_selected_file()
if not selected:
messagebox.showinfo("提示", "请先选择文件")
return
algorithm = alg_var.get()
mode = mode_var.get()
try:
# 读取文件
with open(selected, 'rb') as f:
plaintext = f.read()
ctx.log(f"[加密] 文件: {selected}, 大小: {len(plaintext)} bytes")
ctx.log(f"[加密] 算法: AES-256-{mode}")
# 生成随机密钥和IV
key = crypto_mod.generate_aes_key(256)
iv = crypto_mod.generate_iv(16)
ctx.log(f"[加密] 生成密钥和IV...")
# 选择加密模式
if mode == 'CBC':
ciphertext = crypto_mod.aes_encrypt_cbc(plaintext, key, iv)
tag = None
elif mode == 'GCM':
ciphertext, tag = crypto_mod.aes_encrypt_gcm(plaintext, key, iv)
elif mode == 'CTR':
ciphertext = crypto_mod.aes_encrypt_ctr(plaintext, key, iv)
tag = None
else:
raise ValueError(f"未知的加密模式: {mode}")
ctx.log(f"[加密] 加密完成,密文大小: {len(ciphertext)} bytes")
# 保存加密结果
output_path = filedialog.asksaveasfilename(
defaultextension=".enc",
filetypes=[("加密文件", "*.enc"), ("所有文件", "*.*")],
initialfile=os.path.basename(selected) + ".enc"
)
if not output_path:
ctx.log("[加密] 用户取消保存")
return
# 构建加密文件格式mode(1字节) + key(32字节) + iv(16字节) + [tag(16字节)] + ciphertext
with open(output_path, 'wb') as f:
# 模式标识CBC=1, GCM=2, CTR=3
mode_byte = {'CBC': b'\x01', 'GCM': b'\x02', 'CTR': b'\x03'}[mode]
f.write(mode_byte)
f.write(key)
f.write(iv)
if tag is not None:
f.write(tag)
f.write(ciphertext)
ctx.log(f"[加密] 保存到: {output_path}")
messagebox.showinfo("加密成功", f"文件已加密并保存到:\n{output_path}")
except Exception as e:
import traceback
ctx.log(f"[加密] 失败: {e}")
ctx.log(traceback.format_exc())
messagebox.showerror("加密失败", str(e))
def _on_decrypt(ctx: UIContext, crypto_mod, alg_var: tk.StringVar, mode_var: tk.StringVar):
"""解密文件"""
if not ctx.ensure_impl(crypto_mod, "加密/解密"):
return
selected = ctx.get_selected_file()
if not selected:
messagebox.showinfo("提示", "请先选择加密文件")
return
try:
# 读取加密文件
with open(selected, 'rb') as f:
data = f.read()
if len(data) < 50:
raise ValueError("文件太小,不是有效的加密文件")
ctx.log(f"[解密] 文件: {selected}, 大小: {len(data)} bytes")
# 解析格式
mode_byte = data[0:1]
mode_map = {b'\x01': 'CBC', b'\x02': 'GCM', b'\x03': 'CTR'}
if mode_byte not in mode_map:
raise ValueError(f"未知的加密模式标识: {mode_byte.hex()}")
mode = mode_map[mode_byte]
ctx.log(f"[解密] 检测到模式: AES-256-{mode}")
key = data[1:33]
iv = data[33:49]
if mode == 'GCM':
tag = data[49:65]
ciphertext = data[65:]
else:
ciphertext = data[49:]
ctx.log(f"[解密] 密钥长度: {len(key)} bytes, IV长度: {len(iv)} bytes")
# 解密
if mode == 'CBC':
plaintext = crypto_mod.aes_decrypt_cbc(ciphertext, key, iv)
elif mode == 'GCM':
plaintext = crypto_mod.aes_decrypt_gcm(ciphertext, key, iv, tag)
elif mode == 'CTR':
plaintext = crypto_mod.aes_decrypt_ctr(ciphertext, key, iv)
else:
raise ValueError(f"未知的解密模式: {mode}")
ctx.log(f"[解密] 解密完成,明文大小: {len(plaintext)} bytes")
# 保存解密结果
output_path = filedialog.asksaveasfilename(
defaultextension="",
filetypes=[("所有文件", "*.*")],
initialfile=os.path.basename(selected).replace(".enc", "_decrypted")
)
if not output_path:
ctx.log("[解密] 用户取消保存")
return
with open(output_path, 'wb') as f:
f.write(plaintext)
ctx.log(f"[解密] 保存到: {output_path}")
messagebox.showinfo("解密成功", f"文件已解密并保存到:\n{output_path}")
except Exception as e:
import traceback
ctx.log(f"[解密] 失败: {e}")
ctx.log(traceback.format_exc())
messagebox.showerror("解密失败", str(e))
Loading…
Cancel
Save