加密解密脚本怎么写?从零到一的手把手实战指南
📖 目录导读
- 加密解密的核心概念
- 脚本编写前的准备(语言与库)
- 对称加密脚本实战(Python + AES)
- 非对称加密脚本实战(Python + RSA)
- 常见错误与调试技巧
- 问答区:高频疑惑解答
加密解密的核心概念
在开始写脚本之前,你需要搞清楚三个关键术语:

- 明文:你真正想保护的数据(比如密码、文件内容)。
- 密钥:一把“锁”,能控制谁能解密。
- 密文:经过加密后看起来像乱码的文本。
加密类型分为两类:
- 对称加密(如AES、DES):加密和解密用同一把密钥,适合文件、数据库加密。
- 非对称加密(如RSA、ECC):用“公钥”加密,必须用“私钥”才能解密,常用于HTTPS、数字签名。
问答:为什么需要这两类?
对称加密速度快,但密钥分发难(万一密钥被偷,加密就废了),非对称加密速度慢,但安全性更高(公钥可以公开),实际中,常混合使用:用非对称加密传输对称密钥,再用对称加密处理大量数据。
脚本编写前的准备
选择编程语言
- Python(推荐):标准库自带
hashlib、base64,第三方库cryptography功能全面。 - JavaScript:Node.js的
crypto模块适合前端加密。 - Go、Java:企业级应用常用,但脚本灵活性稍弱。
安装必要的库(Python示例)
pip install pycryptodome cryptography
注意:
pycryptodome是经典库,但部分系统需额外编译,新手建议直接装cryptography(纯Python兼容更好)。
文件结构建议
encryption_scripts/
├── aes_demo.py # 对称加密示例
├── rsa_demo.py # 非对称加密示例
└── keys/ # 存放生成的密钥(别上传到Git!)
对称加密脚本实战(Python + AES)
场景:快速加密一个文本文件
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
import base64
# 生成密钥和初始化向量(IV)
key = get_random_bytes(16) # AES-128需要16字节密钥
iv = get_random_bytes(16)
def encrypt_file(data: bytes, key: bytes, iv: bytes) -> bytes:
cipher = AES.new(key, AES.MODE_CBC, iv)
# 填充数据到16字节倍数(PKCS7)
padded_data = data + (16 - len(data) % 16) * bytes([16 - len(data) % 16])
return base64.b64encode(iv + cipher.encrypt(padded_data))
def decrypt_file(encrypted_data: bytes, key: bytes) -> bytes:
raw = base64.b64decode(encrypted_data)
iv = raw[:16]
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted = cipher.decrypt(raw[16:])
# 去除填充
pad_len = decrypted[-1]
return decrypted[:-pad_len]
# 用法
plaintext = b"My secret password: bank123456"
encrypted = encrypt_file(plaintext, key, iv)
print(f"加密后:{encrypted}")
decrypted = decrypt_file(encrypted, key)
print(f"解密后:{decrypted.decode()}")
关键点:
- IV(初始化向量)像“盐”,每次加密必须随机生成,否则同一明文加密结果相同(容易破解)。
- 填充模式:AES要求数据块是16字节倍数,不满足时需填充(PKCS7是最常用方案)。
问答:为什么解密时IV要拼接在密文前面?
因为解密时也需要用IV,把它直接附在密文前面,解密时先取出前16字节作为IV,不增加额外存储接口。
非对称加密脚本实战(Python + RSA)
场景:安全传输密钥或短消息
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import serialization, hashes
# 生成密钥对
private_key = rsa.generate_private_key(
public_exponent=65537, # 固定值,不可改
key_size=2048 # 至少2048位,1024已不安全
)
public_key = private_key.public_key()
# 加密:用公钥加密(消息长度有限,最多256字节)
message = b"Confidential data"
ciphertext = public_key.encrypt(
message,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# 解密:用私钥解密
plaintext = private_key.decrypt(
ciphertext,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
print(plaintext.decode())
注意事项:
- RSA加密慢,且一次只能加密少量数据(密钥长度决定上限),想加密大文件?先用AES加密文件,再用RSA加密AES密钥。
- 填充方式:OAEP是安全标准,不要使用旧版的PKCS1v1.5(易被攻击)。
问答:公钥可以公开,那为什么还要防破解?
公钥公开是设计目标(比如别人用你的公钥加密数据,只有你的私钥能解密),但攻击者若从公钥推导出私钥,则需破解数学难题(目前2048位RSA需数百年)。
常见错误与调试技巧
错误1:填充不匹配
现象:Padding is incorrect
原因:加密和解密用的填充方法不一致(比如一个用PKCS7,一个用None)。
解决:统一使用aes.MODE_CBC + pad函数。
错误2:密钥或IV长度不对
现象:Key must be 16, 24, or 32 bytes long
原因:AES-128需16字节,AES-192需24,AES-256需32。
解决:len(key)检查,或使用固定长度生成函数(如get_random_bytes(32))。
错误3:非对称加密的明文超长
现象:Plaintext too long for RSA
解决:按密钥长度限制:RSA 2048位最多加密256字节(含填充后约240字节可用),建议用“混合加密”(AES加密数据 → RSA加密AES密钥)。
问答区:高频疑惑解答
Q1:我想加密一个10MB的视频文件,用哪种方法?
- 方案:对称加密AES(CBC或GCM模式),非对称加密太慢。
- 实现:读取文件分块加密(每块1MB),最后连接密文。
Q2:密钥怎么安全存储?不应该硬编码在脚本里?
- 绝对不要硬编码!可以用环境变量(
.env文件)、操作系统密钥管理工具(Windows的DPAPI、macOS的Keychain)、或加密硬件模块(HSM)。 - 本地测试时,可生成临时密钥文件,但生产环境必须分离。
Q3:我应该用CBC还是GCM模式?
- CBC:传统模式,速度快,但无法检测数据篡改(需要额外MAC校验)。
- GCM:支持认证加密(同时保证机密性和完整性),推荐用于网络传输或文件防篡改。
Q4:加密脚本写好了,但别人拿到密文和密钥能解密吗?
- 如果密钥泄露,任何拿到密钥的人都能解密,所以密钥管理是加密系统的核心,建议:
- 密钥定期更换。
- 不同数据使用不同密钥(分层密钥体系)。
- 用硬件安全模块(TPM或专用芯片)保护密钥。
Q5:有没有不需要自己写脚本的现成工具?
- 命令行工具:
OpenSSL(强大但复杂)、GnuPG(适合邮件加密)。 - 在线服务:不推荐传输敏感数据给第三方。
总结与行动建议
加密解密脚本的编写,本质是算法选择 (AES/RSA) + 安全规范 (密钥管理) + 代码封装 的结合。
- 入门:先从AES对称加密做起,理解填充、IV、BASE64编码。
- 进阶:掌握RSA + AES混合加密模式(HTTPS的核心原理)。
- 警惕:不要自己发明加密算法,永远用公开、经审计的标准库。
你可以:
- 用本文的AES脚本加密你的个人密码文件。
- 尝试用GCM模式写一个“加密 → 传输 → 解密”的小工具。
- 把你的脚本加上命令行参数支持(如
python encrypt.py -i file.txt -k mykey.bin)。
最后一句:加密不是“写了就安全”,而是“写对了才安全”,多测试边界情况,关注库的更新(比如Python 3.9以上推荐用cryptography替代老旧的pycrypto)。