用Python编写Windows右键菜单小工具:实现文件快速加密与解密
详细讲解如何用Python编写一个Windows右键菜单小工具,实现对文件的快速加密与解密操作,包含完整代码、注册表配置和常见问题解决方案。
在Windows资源管理器中右键点击一个文件,直接选择"加密"或"解密"就能完成操作——这个功能可以用一个不到100行的Python脚本加上几条注册表配置实现。本文会带你完成从脚本编写、打包到注册右键菜单的全部过程,最终得到一个可以日常使用的文件加密解密小工具。
整体思路与实现路径
这个小工具的核心由两部分组成:一个负责加密和解密的Python脚本,以及一组让Windows在右键菜单中显示操作入口的注册表项。右键菜单只是一个"入口",它把选中文件的路径作为参数传递给Python脚本,脚本完成实际的加密或解密工作。
加密算法选择AES-256-CBC模式。AES是目前广泛使用的对称加密标准,256位密钥长度提供了足够的安全性。CBC模式需要一个初始化向量(IV),每次加密随机生成,保证相同文件多次加密后的密文不同。密钥通过用户输入的密码,经PBKDF2算法派生,避免直接使用短密码带来的安全风险。
准备开发环境
开始之前需要确认两件事:系统上安装了Python 3.7或更高版本,以及pip可以正常使用。打开命令提示符,输入以下命令检查:
python --version
pip --version
确认Python可用后,安装加密库pycryptodome。这个库提供了AES加密所需的全部功能:
pip install pycryptodome
如果后续要打包成EXE让没有Python环境的电脑也能使用,还需要安装pyinstaller:
pip install pyinstaller
编写加密解密脚本
脚本需要处理两种操作模式:加密和解密。通过命令行参数区分——运行时传入encrypt或decrypt以及文件路径。密码通过tkinter弹出的简单对话框获取,这样即使从右键菜单启动也能交互输入。
创建一个名为file_crypto.py的文件,完整代码如下:
import sys
import os
import tkinter as tk
from tkinter import simpledialog, messagebox
from Crypto.Cipher import AES
from Crypto.Protocol.KDF import PBKDF2
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad
SALT_SIZE = 16
IV_SIZE = 16
KEY_SIZE = 32
ITERATIONS = 100000
def get_password(title):
root = tk.Tk()
root.withdraw()
password = simpledialog.askstring(title, "请输入密码:", show="*")
root.destroy()
if not password:
sys.exit(0)
return password.encode("utf-8")
def encrypt_file(filepath):
password = get_password("文件加密")
salt = get_random_bytes(SALT_SIZE)
key = PBKDF2(password, salt, dkLen=KEY_SIZE, count=ITERATIONS)
iv = get_random_bytes(IV_SIZE)
cipher = AES.new(key, AES.MODE_CBC, iv)
with open(filepath, "rb") as f:
plaintext = f.read()
ciphertext = cipher.encrypt(pad(plaintext, AES.block_size))
output_path = filepath + ".enc"
with open(output_path, "wb") as f:
f.write(salt + iv + ciphertext)
root = tk.Tk()
root.withdraw()
messagebox.showinfo("完成", f"文件已加密:\n{output_path}")
root.destroy()
def decrypt_file(filepath):
password = get_password("文件解密")
with open(filepath, "rb") as f:
data = f.read()
salt = data[:SALT_SIZE]
iv = data[SALT_SIZE:SALT_SIZE + IV_SIZE]
ciphertext = data[SALT_SIZE + IV_SIZE:]
key = PBKDF2(password, salt, dkLen=KEY_SIZE, count=ITERATIONS)
cipher = AES.new(key, AES.MODE_CBC, iv)
try:
plaintext = unpad(cipher.decrypt(ciphertext), AES.block_size)
except ValueError:
root = tk.Tk()
root.withdraw()
messagebox.showerror("错误", "密码不正确或文件已损坏。")
root.destroy()
sys.exit(1)
if filepath.endswith(".enc"):
output_path = filepath[:-4]
else:
output_path = filepath + ".dec"
with open(output_path, "wb") as f:
f.write(plaintext)
root = tk.Tk()
root.withdraw()
messagebox.showinfo("完成", f"文件已解密:\n{output_path}")
root.destroy()
if __name__ == "__main__":
if len(sys.argv) != 3:
print("用法: file_crypto.py [encrypt|decrypt] 文件路径")
sys.exit(1)
action = sys.argv[1].lower()
target = sys.argv[2]
if not os.path.isfile(target):
print(f"文件不存在:{target}")
sys.exit(1)
if action == "encrypt":
encrypt_file(target)
elif action == "decrypt":
decrypt_file(target)
else:
print(f"未知操作:{action}")
sys.exit(1)
代码要点说明
密钥派生:PBKDF2函数接收用户密码和随机salt,迭代100000次生成32字节(256位)密钥。高迭代次数让暴力破解密码的成本大幅增加。每次加密都使用新的随机salt,因此同一密码对同一文件多次加密会产生不同的密文。
文件格式:加密后的文件依次存储salt(16字节)、IV(16字节)和密文。解密时按固定偏移量分别读取这三部分。这种结构简单可靠,salt和IV本身不需要保密,它们的作用是保证每次加密的唯一性。
错误处理:解密时如果密码错误,unpad函数会因为填充格式不符抛出ValueError异常。脚本捕获这个异常并弹出错误提示,而不是让程序直接崩溃。
在命令行中可以先验证脚本功能:
REM 加密一个测试文件
python file_crypto.py encrypt C:\test\example.txt
REM 解密刚刚生成的加密文件
python file_crypto.py decrypt C:\test\example.txt.enc
运行加密命令后会弹出密码输入框,输入密码并确认后,在同目录下生成example.txt.enc。解密时输入相同密码,会还原出example.txt。
打包为可执行文件
如果只是自己使用并且电脑上有Python环境,可以跳过打包步骤,直接用python file_crypto.py运行。但要分享给别人或者避免依赖Python环境,需要用PyInstaller打包成EXE。
在脚本所在目录打开命令提示符,执行:
pyinstaller --onefile --noconsole --name file_crypto file_crypto.py
参数说明:--onefile把所有依赖打包进单个EXE文件;--noconsole运行时不弹出命令行窗口(因为交互通过tkinter对话框完成);--name指定输出文件名。打包完成后在dist目录下找到file_crypto.exe。
把这个EXE复制到一个固定位置,比如C:\Tools\file_crypto.exe。后续注册表里会用到这个路径,所以放好之后就不要移动了。
配置Windows右键菜单
Windows的右键菜单项由注册表控制。需要在HKEY_CLASSES_ROOT\*\shell下创建两个子项,分别对应"加密文件"和"解密文件"操作。*表示对所有文件类型生效。
手动编辑注册表
按Win+R输入regedit打开注册表编辑器,导航到HKEY_CLASSES_ROOT\*\shell。
添加"加密文件"菜单项:在shell下新建项,命名为EncryptFile。选中EncryptFile,将右侧"默认"值改为使用密码加密(这是右键菜单中显示的文字)。在EncryptFile下再新建一个名为command的子项,将其默认值设为:
"C:\Tools\file_crypto.exe" encrypt "%1"
%1是Windows传递给命令的文件路径占位符。
添加"解密文件"菜单项:同样在shell下新建DecryptFile项,默认值设为解密文件。在DecryptFile下新建command子项,默认值设为:
"C:\Tools\file_crypto.exe" decrypt "%1"
使用注册表脚本快速配置
手动编辑注册表容易出错,更方便的方式是创建一个.reg文件双击导入。新建一个文本文件,保存为add_crypto_menu.reg(注意编码选择UTF-16 LE BOM),内容如下:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\*\shell\EncryptFile]
@="使用密码加密"
"Icon"="C:\\Tools\\file_crypto.exe,0"
[HKEY_CLASSES_ROOT\*\shell\EncryptFile\command]
@="\"C:\\Tools\\file_crypto.exe\" encrypt \"%1\""
[HKEY_CLASSES_ROOT\*\shell\DecryptFile]
@="解密文件"
"Icon"="C:\\Tools\\file_crypto.exe,0"
[HKEY_CLASSES_ROOT\*\shell\DecryptFile\command]
@="\"C:\\Tools\\file_crypto.exe\" decrypt \"%1\""
双击这个.reg文件,确认导入后右键菜单立即生效。如果需要卸载,创建另一个.reg文件:
Windows Registry Editor Version 5.00
[-HKEY_CLASSES_ROOT\*\shell\EncryptFile]
[-HKEY_CLASSES_ROOT\*\shell\DecryptFile]
项名前的减号-表示删除该注册表项及其所有子项。
HKEY_CLASSES_ROOT需要管理员权限。运行.reg文件时如果提示权限不足,右键选择"以管理员身份运行"。如果不想影响所有用户,可以把路径改为HKEY_CURRENT_USER\Software\Classes\*\shell,效果相同但只对当前用户生效。
使用方法与验证
配置完成后,在资源管理器中右键点击任意文件,上下文菜单中会出现"使用密码加密"和"解密文件"两个选项。
加密文件:右键选择"使用密码加密",在弹出的对话框中输入密码。确认后,同目录下生成一个.enc后缀的加密文件。原文件不会被删除或修改。
解密文件:右键点击.enc文件,选择"解密文件",输入加密时使用的密码。解密成功后在同目录生成去掉.enc后缀的文件。如果密码错误,会弹出错误提示。
验证加密效果的简单方法:用文本编辑器打开加密前后的文件。原文件内容正常显示,.enc文件打开后是无法辨认的乱码。解密后的文件应该和原文件完全一致,可以用certutil计算哈希值确认:
certutil -hashfile C:\test\example.txt SHA256
certutil -hashfile C:\test\example.txt.enc.dec SHA256
两个命令输出的SHA256哈希值应该完全相同。
安全性考量与改进方向
这个小工具适合保护日常文件不被随意查看,比如加密个人文档后存到U盘或云盘。但在正式的安全场景中,有几个方面值得注意:
密码强度:AES-256的安全性取决于密码质量。PBKDF2的10万次迭代可以拖慢单次密码试探的速度,但面对过于简单的密码(比如123456)仍然不够。建议使用至少12位、包含大小写字母和数字的密码。
原文件处理:当前脚本在加密后保留了原文件。在对安全性要求较高的场景中,可能需要加密后安全删除原文件。普通的文件删除可以被数据恢复工具还原,彻底删除需要覆写文件内容。可以在加密成功后添加覆写逻辑:
import struct
def secure_delete(filepath, passes=3):
length = os.path.getsize(filepath)
with open(filepath, "r+b") as f:
for _ in range(passes):
f.seek(0)
f.write(get_random_bytes(length))
f.flush()
os.fsync(f.fileno())
os.remove(filepath)
大文件处理:当前实现会将整个文件读入内存。处理几百MB甚至更大的文件时可能导致内存不足。改进方法是分块读取和加密,每次处理固定大小(如64KB)的数据块。这需要修改加密逻辑,对最后一个块进行填充,中间块保持原始大小。
密码确认:加密时只要求输入一次密码。实际使用中可以增加二次确认,避免因输入错误导致文件被用错误密码加密而无法恢复。只需在get_password函数中加入确认步骤。
常见问题
右键菜单没有出现:先确认.reg文件是否成功导入——打开注册表编辑器,检查HKEY_CLASSES_ROOT\*\shell下是否存在EncryptFile和DecryptFile项。如果项存在但菜单不显示,尝试重启资源管理器(任务管理器中右键"Windows资源管理器"选择"重新启动"),或注销后重新登录。
点击菜单后没有反应:检查command子项中的EXE路径是否正确、文件是否存在。路径中包含空格时必须用双引号包裹。可以在命令提示符中手动运行完整命令测试:
"C:\Tools\file_crypto.exe" encrypt "C:\test\example.txt"
如果手动运行也报错,可能是打包时缺少依赖,重新运行PyInstaller并检查输出日志。
解密提示密码错误但密码没输错:确认加密文件没有被修改或传输过程中损坏。如果文件通过邮件等方式传输,附件可能被截断。比较原始.enc文件和收到的文件大小是否一致。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









