python-mini-projects 文件与文件夹加密实战:深入解析 AES-128 CFB 加密脚本 encrypt.py
2026/9/20 21:56:09 网站建设 项目流程

python-mini-projects 文件与文件夹加密实战:深入解析 AES-128 CFB 加密脚本 encrypt.py

【免费下载链接】python-mini-projectsA collection of simple python mini projects to enhance your python skills项目地址: https://gitcode.com/gh_mirrors/py/python-mini-projects

导读

本文围绕 python-mini-projects 仓库中的 Create_a_script_to_encrypt_files_and_folder 项目展开,系统讲解如何用一条命令行将单个文件或整个文件夹加密为.bin密文文件。文章不仅完整复刻原文档的使用方法,还深入 encrypt.py 的源码实现,剖析 AES-128 加密、CFB 分组模式、随机 IV 生成与落盘细节,并给出解密思路与已知限制,帮助读者真正掌握"脚本加密文件与文件夹"这一实战技能。

一、项目定位与整体设计

该迷你项目的核心诉求非常明确:在不引入复杂图形界面的前提下,用最少的代码实现对文件和文件夹的对称加密。从目录结构看,项目仅包含三个文件:

  • README.md:说明脚本的调用方式与输出产物;
  • encrypt.py:全部加密逻辑所在,共 39 行;
  • requirements.txt:声明唯一依赖pycryptodome==3.9.8

加密方案上,脚本选用PyCryptodome库实现的AES 对称加密,配合CFB(Cipher Feedback,密码反馈)模式。AES 是当前使用最广泛的对称分组密码标准,CFB 模式则将分组密码转换为流密码的工作方式,对数据逐段异或加密,天然支持任意长度明文,无需像 ECB/CBC 那样进行 PKCS#7 填充,非常适合文件这种长度不固定的场景。

脚本对外暴露一个统一接口python encrypt.py <path>,内部根据路径类型自动分流:目录走目录遍历加密,普通文件走单文件加密,其余特殊文件(socket、FIFO、设备文件)则给出提示。

二、环境准备:安装加密依赖

脚本对第三方库的依赖极简,仅需 PyCryptodome。官方 requirements.txt 中锁定版本为:

pycryptodome==3.9.8

安装命令:

pip install -r projects/Create_a_script_to_encrypt_files_and_folder/requirements.txt # 或直接 pip install pycryptodome==3.9.8

安装完成后,脚本通过from Cryptodome.Cipher import AESfrom Cryptodome import Random导入加密能力(PyCryptodome 同时提供CryptoCryptodome两种导入名,仓库中的 aes_encode.py 则使用Crypto前缀,二者指向同一套库)。该库支持 Python 2.6 到 3.x 的主流版本,仓库运行环境以 Python 3 为准(脚本中使用了sys.argvos.walk等标准库)。

三、快速上手:命令行使用方式

原文档给出了完整的使用范式,核心命令格式为:

python encrypt.py path(file or folder)

即第一个位置参数path既可以指向一个普通文件,也可以指向一个文件夹,脚本会自动识别。

3.1 加密单个文件

python encrypt.py test.txt

运行后,加密产物test.txt.bin会生成在与原文件相同的位置("encrypted files will be generated in original location")。

3.2 加密整个文件夹

python encrypt.py ./testdir

脚本会递归遍历testdir下的所有文件并逐一加密,每个文件都产出对应的.bin文件。控制台会打印每个正在处理的文件路径,例如:

testdir/a.txt is encrypting. testdir/sub/b.txt is encrypting.

小提示:原 README 中的示例python eccrypt.py ./testdir(folder)存在拼写笔误(eccrypt),实际可执行脚本名为encrypt.py,请以正确拼写运行。

四、源码级剖析:脚本的三条处理路径

encrypt.py 的整体结构非常清晰,入口逻辑位于文件末尾(第 33~39 行):

path = sys.argv[1] if os.path.isdir(path) and os.path.exists(path): encrypt_dir(path) elif os.path.isfile(path) and os.path.exists(path): encrypt_file(path) else: print("it's a special file(socket,FIFO,device file)")

这里先用sys.argv[1]取出命令行传入的路径,再按优先级判断:

  1. 目录os.path.isdir(path)为真且路径存在 → 调用encrypt_dir(path)
  2. 普通文件os.path.isfile(path)为真且路径存在 → 调用encrypt_file(path)
  3. 其他情况:路径不存在或属于 socket、FIFO、设备文件等特殊类型 → 打印提示it's a special file(socket,FIFO,device file)后退出。

注意os.path.isdir对不存在的路径返回False,因此脚本对"路径不存在"与"特殊文件"两种异常统一走了 else 分支,只在控制台给出一条提示,不会抛异常中断。

4.1 单文件加密:encrypt_file 的完整流程

encrypt_file 是核心加密函数,其流程可分四步:

def encrypt_file(path): # get the plaintext with open(path) as f: plain_text = f.read() # The key length must be 16 (AES-128), 24 (AES-192), or 32 (AES-256) Bytes. key = b'this is a 16 key' iv = Random.new().read(AES.block_size) mycipher = AES.new(key, AES.MODE_CFB, iv) ciphertext = iv + mycipher.encrypt(plain_text.encode()) # output with open(path + ".bin", "wb") as file_out: file_out.write(ciphertext[16:])

第 1 步:读取明文。open(path)以文本模式读出文件全部内容。这里的隐含约束是:脚本面向文本文件设计(默认按系统编码解码文本,随后plain_text.encode()再编码为 UTF-8 字节流参与加密);对于二进制文件,直接以文本模式读取可能导致解码异常或数据损坏,这一点会在"已知限制"一节展开。

第 2 步:确定密钥。源码将密钥硬编码为 16 字节的b'this is a 16 key',对应AES-128。代码注释同时说明了 AES 对密钥长度的硬性要求:16 字节(AES-128)、24 字节(AES-192)或 32 字节(AES-256),超出或不足都会在AES.new()处抛出ValueError

第 3 步:生成 IV 并加密。Random.new().read(AES.block_size)从系统安全随机源生成 16 字节(AES.block_size == 16)的初始向量 IV;随后以AES.MODE_CFB模式构造密码对象,将明文编码后的字节流加密,得到mycipher.encrypt(...)ciphertext = iv + mycipher.encrypt(...)将 IV 拼接到密文头部,这是 CFB 模式的标准做法——解密时必须使用与加密时完全相同的 IV,因此 IV 需要随密文一起保存或传输。

第 4 步:写出密文。以二进制写模式打开path + ".bin",将ciphertext[16:]写入磁盘,即只写入去除 IV 头部后的纯密文流(第 30 行)。这一点值得注意,详见下文"IV 的保存"分析。

4.2 目录加密:encrypt_dir 的遍历逻辑

encrypt_dir 负责文件夹场景:

def encrypt_dir(path): for root, _, files in os.walk("."): for file in files: file_path = os.path.join(root, file) print(file_path + " is encrypting.") encrypt_file(file_path)

它利用os.walk递归遍历目录树,对每个子目录下的每个普通文件拼接完整路径后调用encrypt_file逐一加密,并在控制台输出xxx is encrypting.的进度信息。

从源码结构看,这里有一个值得注意的实现细节:函数虽然接收了path参数,但os.walk(".")遍历的是进程的当前工作目录,而非传入的path。也就是说,python encrypt.py ./testdir实际加密的是"在 ./testdir 下运行时该目录内的所有文件",加密结果取决于执行命令时所在的目录。理解这一点有助于规避"加密了非预期文件"的误用场景。

五、加密原理详解:AES-128 + CFB 模式

5.1 为什么选 CFB 模式

AES 本身是分组密码,一次处理 16 字节。若直接对文件分块加密(ECB 模式),相同明文块会生成相同密文块,存在明显的模式泄露风险。CFB 模式通过"反馈链"将 AES 变为流式加密:用密钥加密上一个密文块(首块为 IV)得到密钥流,再与当前明文块异或产生密文块。其特性包括:

  • 无需填充:明文长度可以是任意值,适合文本、配置等长度不定的文件;
  • 解密可并行性较差但实现简单:解密同样按反馈链顺序进行;
  • IV 的随机性直接影响安全性:IV 必须每次加密时重新生成(脚本通过Random.new()每次随机生成,做法正确),否则相同密钥下相同明文会产生相同密文。

5.2 IV 的生成与保存问题

脚本生成 IV 的方式是标准的:Random.new().read(AES.block_size)从加密安全随机源(PyCryptodome 的Random模块基于操作系统熵源)读取 16 字节。问题出现在写盘环节——file_out.write(ciphertext[16:])将拼接好的iv + ciphertext中的 IV 部分(前 16 字节)丢弃了,落盘的.bin只包含纯密文流。

从源码结构可以推断:由于解密时需要用到加密时的 IV,而该 IV 未随.bin文件持久化,当前脚本产出的密文文件本身并不携带解密所需的完整参数。若要实现可逆的解密,需要额外保存 IV(例如将写入语句改为file_out.write(ciphertext),把 IV 一并落盘)。

5.3 密钥管理

脚本将密钥硬编码在源码中(b'this is a 16 key'),这是教学演示项目常见的简化做法,便于读者直接复现。但在真实生产场景中,硬编码密钥意味着任何拿到源码的人都能解密数据,密钥应通过环境变量、密钥文件或密钥管理系统注入,并按文件单独轮换。

六、解密思路:仓库内配套示例佐证

该目录本身未提供解密脚本,但 python-mini-projects 仓库中同主题的 Encrypt_and_decrypt_text 项目提供了可对照的解密实现 aes_encode.py,其核心解密逻辑为:

key = b'this is a 16 key' iv = ciphertext[:16] # 从密文头部取回 IV mydecrypt = AES.new(key, AES.MODE_CFB, iv) decrypttext = mydecrypt.decrypt(ciphertext[16:])

对照这段代码可以清晰理解 CFB 解密所需的三个要素:

  1. 相同的密钥:与加密端一致的 16 字节密钥;
  2. 相同的 IV:从密文流头部截取前 16 字节(这正是"加密时将 IV 拼到密文前面"这一设计的原因);
  3. 相同的模式AES.MODE_CFB

这从侧面印证了第五节的分析——aes_encode.py在解密前通过ciphertext[:16]取回 IV,而本项目的encrypt.py写盘时恰好截掉了这 16 字节,因此如需落地解密功能,建议参考该配套示例并修正 IV 的落盘策略。

七、已知限制与改进方向(基于源码推断)

综合源码实现,可以归纳出以下需要注意或可改进的点:

关注点现状(源码依据)影响与建议
二进制文件支持open(path)以文本模式读取(encrypt.py)对图片、压缩包等二进制文件可能解码失败;建议改用open(path, "rb")直接操作字节流
IV 持久化写盘仅写ciphertext[16:](encrypt.py)密文文件不含 IV,无法独立解密;建议写入完整ciphertext
密钥硬编码密钥固定为b'this is a 16 key'(encrypt.py)仅适合教学演示;生产环境需外部注入并支持 AES-192/256
目录遍历基准os.walk(".")遍历当前工作目录(encrypt.py)实际加密范围与执行目录相关,建议改为os.walk(path)并补充"遍历到目录自身"的判断
文件编码文本模式读取依赖系统默认编码跨平台可能存在编码差异,建议显式指定encoding="utf-8"
加密文件二次加密.bin会被再次识别为普通文件重复运行会对已加密文件再加密,建议按扩展名过滤或跳过.bin

八、总结

本项目的价值在于用极简的 39 行代码,完整演示了"文件 + 文件夹"两种粒度的 AES 对称加密实战:

  • 一条命令即可上手:python encrypt.py <file-or-folder>
  • 加密产物为原路径下的.bin文件,不破坏原始文件;
  • 技术上覆盖了 AES 密钥长度约束、CFB 无填充流式加密、随机 IV 生成与密文组装等核心知识点;
  • 仓库配套的 aes_encode.py 提供了同密钥 CFB 解密的直接参考。

对于学习者而言,它是理解"脚本化批量加密"的最佳入门样例;若要投入真实使用,则需在二进制读取、IV 落盘与密钥管理三处做针对性增强,这也正是从"能跑的脚本"迈向"可用的工具"的关键一步。

【免费下载链接】python-mini-projectsA collection of simple python mini projects to enhance your python skills项目地址: https://gitcode.com/gh_mirrors/py/python-mini-projects

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询