如何编写文件加密解密脚本

wen 实用脚本 1

从零到一:如何编写跨平台文件加密解密脚本(Python + AES + 实战指南)


目录导读

  1. 为什么你需要自己写加密脚本? —— 商业软件 vs 自研脚本的博弈
  2. 加密算法选型: AES-256 vs ChaCha20,谁更适合文件?
  3. 环境准备: Python 虚拟环境与依赖库安装(cryptography / pycryptodome)
  4. 核心代码拆解: 分块读写、盐值(Salt)、密钥派生(PBKDF2)与 GCM 模式
  5. 实战演练: 加密脚本与解密脚本的完整流程
  6. 安全陷阱与规避: 填充攻击、IV 复用、内存泄露
  7. 扩展与自动化: 命令行参数、批量文件处理、定时任务
  8. 常见问题 FAQ: 密码忘记怎么办?能破 AES 吗?

在数据泄露频发的今天,无论是保护个人隐私还是企业核心资产,文件加密都是最后一道防线,市面上的加密软件虽然便捷,但存在“闭源黑盒”风险——你无法确认它是否留有后门。编写自己的加密解密脚本,意味着你掌握了对数据的绝对控制权,本文将手把手教你用 Python 编写一个生产级(Production-Ready)的文件加密工具。

如何编写文件加密解密脚本

为什么你需要自己写加密脚本?

商用加密软件(如某些网盘加密功能)通常将密钥托管在云端,一旦账户被盗,数据随之泄露,自研脚本的核心优势在于 零信任模型:密钥只存在于你的内存中,本地计算,离线处理,脚本的可定制性极高——你可以为特定文件类型(如数据库备份)定制加密策略,而无需购买昂贵的企业套件。

加密算法选型:AES-256-GCM 是首选

  • AES-256:硬件加速支持广泛(AES-NI指令集),在主流CPU上加密速度极快。
  • GCM(Galois/Counter Mode):一种认证加密模式(AEAD),它同时提供机密性完整性校验,如果文件被篡改,解密时会直接报错,防止“密文替换攻击”。
  • 为什么不选 Chacha20? 它在无硬件加速的ARM架构上更优秀,但如果你主要跑在x86的PC或服务器上,AES-GCM 更具性能优势,本教程采用 AES-256-GCM

环境准备:安装依赖

python -m venv encrypt_env
source encrypt_env/bin/activate  # Windows: encrypt_env\Scripts\activate
pip install cryptography

cryptography 库提供了高级加密接口,比 pycryptodome 更安全,且算法实现经过严格审计。

核心代码拆解:从密钥到密文

一个健壮的加密脚本必须包含三个关键要素:

  • 盐值(Salt):随机生成的16字节数据,与用户密码一起输入密钥派生函数(KDF),盐值防彩虹表攻击,这意味着同一密码加密不同文件会产生不同密文。
  • 密钥派生(PBKDF2HMAC):将输入的弱密码拉伸为强密钥(32字节),迭代次数建议 10万次以上100_000),以大幅提升暴力破解成本。
  • IV(初始向量):GCM模式需要12字节随机IV。绝对禁止复用同一个IV加密两个不同文件。

加密逻辑架构图(脑内构建):

密码 + 随机盐 → PBKDF2 → 32字节密钥
文件数据分割为64KB块 → AES-256-GCM加密每块 → 写入密文 + 头部元数据(盐+IV)

实战演练:完整脚本示例

文件:crypto_tool.py

import os
import sys
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
# 加密函数
def encrypt_file(password: bytes, input_file: str, output_file: str = None):
    # 1. 生成盐和IV
    salt = os.urandom(16)
    iv = os.urandom(12)
    # 2. 派生密钥
    kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, 
                     salt=salt, iterations=100_000)
    key = kdf.derive(password)
    # 3. 初始化 AESGCM
    aesgcm = AESGCM(key)
    # 4. 分块读文件并加密
    encrypted_size = 0
    with open(input_file, 'rb') as f_in, open(output_file, 'wb') as f_out:
        # 写入头部:盐和IV,用于解密
        f_out.write(salt + iv)
        while True:
            chunk = f_in.read(64 * 1024)  # 64KB 块
            if not chunk:
                break
            ciphertext = aesgcm.encrypt(iv, chunk, None)  # 关联数据为空
            f_out.write(ciphertext)
            encrypted_size += len(ciphertext)
    print(f"[成功] 加密完成,密文长度:{encrypted_size} 字节")
# 解密函数
def decrypt_file(password: bytes, input_file: str, output_file: str = None):
    with open(input_file, 'rb') as f_in:
        salt = f_in.read(16)
        iv = f_in.read(12)
        kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, 
                         salt=salt, iterations=100_000)
        key = kdf.derive(password)
        aesgcm = AESGCM(key)
        with open(output_file, 'wb') as f_out:
            while True:
                chunk = f_in.read(64 * 1024 + 16)  # +16字节的GCM标签
                if not chunk:
                    break
                # 解密失败会抛异常,阻止写入垃圾数据
                plaintext = aesgcm.decrypt(iv, chunk, None)
                f_out.write(plaintext)
    print("[成功] 文件解密完成,已验证完整性。")
if __name__ == "__main__":
    # 命令行入口:python script.py encrypt <file> <password>
    action = sys.argv[1]
    file_path = sys.argv[2]
    pwd = sys.argv[3].encode('utf-8')
    if action == "encrypt":
        encrypt_file(pwd, file_path, file_path + ".enc")
    elif action == "decrypt":
        # 自动去掉 .enc 后缀
        out = file_path.replace(".enc", "")
        decrypt_file(pwd, file_path, out)

重点笔记:解密时,AESGCM.decrypt 会校验认证标签,如果文件被篡改或密码错误,会直接抛出 InvalidTag 异常,此时程序应立即终止并删除不完整的输出文件,防止数据损坏。

安全陷阱与规避

  • 陷阱1:密码硬编码,切勿将密码写在脚本里,应通过环境变量或交互式 getpass 模块输入。
  • 陷阱2:零填充(Zero Padding),GCM模式不需要填充,但如果你改用CBC模式,务必使用PKCS7填充,否则解密会出现乱码。
  • 陷阱3:密钥重用,每次加密必须重新生成随机的盐和IV,即使密码相同,密文也完全不同。

扩展与自动化

  • 批量加密:用 os.walk() 遍历目录,对每个文件调用 encrypt_file
  • 密码强度控制:在代码中加入 len(password) >= 8 的检查,并同时校验字母数字混合。
  • 压缩后加密:调用 gzip 模块先压缩再加密,可以显著提升高熵数据(如日志)的加密效率。

常见问题 FAQ

Q1:如果我忘记密码,有办法恢复文件吗? A:完全没有,这是加密设计的根本原则,即使是作者本人也没有后门,这就是“零知识加密”的代价,建议将密码存放在密码管理器中(如 Bitwarden)。

Q2:暴力破解 AES-256 现实吗? A:以目前全球算力总和,即使使用百亿亿次超级计算机,暴力破解 AES-256 也需要远超宇宙年龄的时间,攻击的重点永远是弱密码和密钥泄露,而不是算法本身,务必使用高熵密码(如:#Vb3!xQ9@LmZ)。

Q3:脚本加密后的文件能缩小体积吗? A:不能,加密旨在混淆数据,密文体积通常比原文略大(增加约28字节的头部和认证标签),想要减小体积,应先压缩再加密。

Q4:为什么我的脚本解密100MB大文件时内存爆了? A:请检查是否用了 f.read() 一次性读取全部内容,本教程采用64KB分块读取,内存占用恒定在几十KB级别,完全不受文件大小影响。


编写加密脚本并非天方夜谭,而是每个开发者都应掌握的安全基本功,通过本文的代码,你已具备构建私有加密工具链的能力。密码是铁门,脚本是锁芯,而你的安全意识才是那根结实的门链,请妥善保管密钥,切勿随意公开你的加密算法实现中的自定义逻辑(如有),以防针对性攻击,立即动手写一个,尝试加密你的第一个测试文件吧。

抱歉,评论功能暂时关闭!