如何利用PyCryptodome模块在Python中对敏感数据进行AES加密?
- 内容介绍
- 文章标签
- 相关推荐
本文共计795个文字,预计阅读时间需要4分钟。
由于AES是分组加密算法,原始明文长度必须是16字节(AES-128)的整数倍,且不能直接处理任意字符字符串。常见错误是输入UTF-8字符串后报错ValueError: Data must be a multiple of block length。正确做法是:
PyCryptodome 不提供自动填充,得自己补。推荐用 PKCS#7 填充(注意不是 PKCS#5,虽然对 AES 来说二者等价):
from Crypto.Util.Padding import pad, unpad from Crypto.Cipher import AES <p>key = b'0123456789abcdef' # 16字节密钥 data = b'secret message' padded = pad(data, AES.block_size) # 补到16/24/32字节对齐 cipher = AES.new(key, AES.MODE_CBC) ciphertext = cipher.encrypt(padded)
AES.MODE_CBC 必须配随机 iv,别硬编码
CBC 模式下,相同的明文+密钥总会生成相同密文,这会暴露数据模式(比如大量重复的“STATUS:OK”)。攻击者可能通过观察密文长度和重复性推测内容。所以每次加密都必须用新 iv,且要和密文一起保存或传输。
别写 iv = b'1234567890123456' —— 这等于没加 IV。正确做法:
立即学习“Python免费学习笔记(深入)”;
-
iv = get_random_bytes(16)(需from Crypto.Random import get_random_bytes) - 加密时:用该
iv初始化AES.new(key, AES.MODE_CBC, iv) - 解密时:必须用**同一个**
iv,通常把iv放在密文前 16 字节(如iv + ciphertext),解密时切出来
密钥长度不匹配会导致 ValueError: Invalid key size
AES 只接受 128/192/256 位密钥,也就是 16/24/32 字节的 bytes。常见错误包括:
- 用字符串当密钥:
key = "mykey123"→ 错,必须是b"mykey123"或"mykey123".encode() - 密钥太短:如 8 字节 → 报错,不能自动补零
- 从口令派生密钥?别手写哈希,用
scrypt或PBKDF2:from Crypto.Protocol.KDF import scrypt,否则弱口令=弱密钥
敏感数据加密后别存成裸 bytes,优先转 base64
二进制密文含不可见、不可打印字符(比如 \x00、\xff),直接写入 JSON / CSV / 日志会出错或截断。常见现象是解密时报 ValueError: Padding is incorrect,实际是传输过程损坏了字节流。
解决方案很简单:
import base64 encoded = base64.b64encode(iv + ciphertext).decode('ascii') # 得到字符串 # 存库、传 API、写文件都用这个字符串 <h1>解密时反向:</h1><p>raw = base64.b64decode(encoded) iv, ct = raw[:16], raw[16:] cipher = AES.new(key, AES.MODE_CBC, iv) plain = unpad(cipher.decrypt(ct), AES.block_size)
IV 和密文必须一起 base64 编码,否则无法分离。
记住:AES 本身不解决密钥管理、完整性校验(别漏 HMAC)、密钥轮换这些事。如果数据要长期存储或跨服务共享,光靠 AES.MODE_CBC + 手动 padding 是不够稳健的。
本文共计795个文字,预计阅读时间需要4分钟。
由于AES是分组加密算法,原始明文长度必须是16字节(AES-128)的整数倍,且不能直接处理任意字符字符串。常见错误是输入UTF-8字符串后报错ValueError: Data must be a multiple of block length。正确做法是:
PyCryptodome 不提供自动填充,得自己补。推荐用 PKCS#7 填充(注意不是 PKCS#5,虽然对 AES 来说二者等价):
from Crypto.Util.Padding import pad, unpad from Crypto.Cipher import AES <p>key = b'0123456789abcdef' # 16字节密钥 data = b'secret message' padded = pad(data, AES.block_size) # 补到16/24/32字节对齐 cipher = AES.new(key, AES.MODE_CBC) ciphertext = cipher.encrypt(padded)
AES.MODE_CBC 必须配随机 iv,别硬编码
CBC 模式下,相同的明文+密钥总会生成相同密文,这会暴露数据模式(比如大量重复的“STATUS:OK”)。攻击者可能通过观察密文长度和重复性推测内容。所以每次加密都必须用新 iv,且要和密文一起保存或传输。
别写 iv = b'1234567890123456' —— 这等于没加 IV。正确做法:
立即学习“Python免费学习笔记(深入)”;
-
iv = get_random_bytes(16)(需from Crypto.Random import get_random_bytes) - 加密时:用该
iv初始化AES.new(key, AES.MODE_CBC, iv) - 解密时:必须用**同一个**
iv,通常把iv放在密文前 16 字节(如iv + ciphertext),解密时切出来
密钥长度不匹配会导致 ValueError: Invalid key size
AES 只接受 128/192/256 位密钥,也就是 16/24/32 字节的 bytes。常见错误包括:
- 用字符串当密钥:
key = "mykey123"→ 错,必须是b"mykey123"或"mykey123".encode() - 密钥太短:如 8 字节 → 报错,不能自动补零
- 从口令派生密钥?别手写哈希,用
scrypt或PBKDF2:from Crypto.Protocol.KDF import scrypt,否则弱口令=弱密钥
敏感数据加密后别存成裸 bytes,优先转 base64
二进制密文含不可见、不可打印字符(比如 \x00、\xff),直接写入 JSON / CSV / 日志会出错或截断。常见现象是解密时报 ValueError: Padding is incorrect,实际是传输过程损坏了字节流。
解决方案很简单:
import base64 encoded = base64.b64encode(iv + ciphertext).decode('ascii') # 得到字符串 # 存库、传 API、写文件都用这个字符串 <h1>解密时反向:</h1><p>raw = base64.b64decode(encoded) iv, ct = raw[:16], raw[16:] cipher = AES.new(key, AES.MODE_CBC, iv) plain = unpad(cipher.decrypt(ct), AES.block_size)
IV 和密文必须一起 base64 编码,否则无法分离。
记住:AES 本身不解决密钥管理、完整性校验(别漏 HMAC)、密钥轮换这些事。如果数据要长期存储或跨服务共享,光靠 AES.MODE_CBC + 手动 padding 是不够稳健的。

