PyCryptodome中AES上下文对消息的链式加密机制是怎样的?
问题解答
核心原因
该现象是CBC加密模式的固有设计,并非PyCryptodome私有的特殊逻辑,也不是框架随机生成了新IV:CBC模式的AES上下文会自动保存上一次加密完成后的最后一个密文块,作为下一次加密操作的初始IV,以此实现多段加密的链式关联。
抽象算法逻辑
CBC模式的加密流程和上下文更新规则如下:
- 初始化阶段:调用
AES.new()创建上下文时,你传入的初始IV会被存入上下文的current_iv变量 - 单次加密流程(传入任意长度的对齐后明文):
- 将明文拆分为N个16字节的块
P1, P2, ..., PN - 按顺序计算每个密文块:
Ci = AES_Encrypt(密钥, Pi XOR 前一个输出块),其中第一个明文块的前一个输出块就是current_iv - 输出所有密文块拼接后的结果
- 上下文自动更新:把最后一个密文块
CN覆盖写入current_iv,供下一次加密使用
- 将明文拆分为N个16字节的块
对应你的代码示例:第一次加密完成后,上下文里存储的IV已经不是你最开始传入的b'16-byte init.vec',而是第一次加密输出的最后16字节密文,第二次加密相当于用这个新IV处理相同明文,结果自然不同。
手动复现第二次加密结果的方法
不需要依赖上下文的内置链式机制,你只需要手动把第一次加密输出的最后16字节作为IV,新建AES上下文加密相同明文,得到的结果和你示例中第二次输出完全一致:
from Crypto.Util.Padding import pad, unpad from Crypto.Cipher import AES key = b'Sixteen byte key' init_iv = b'16-byte init.vec' pt = pad(b'The quick brown fox jumped over the lazy dog', 16) # 原链式加密逻辑 cipher = AES.new(key, AES.MODE_CBC, init_iv) ct1 = cipher.encrypt(pt) print(ct1.hex()) # 第一次输出:95c44b... ct2 = cipher.encrypt(pt) print(ct2.hex()) # 第二次输出:dfa658... # 手动复现第二次输出 manual_iv = ct1[-16:] # 取第一次加密的最后一个密文块作为IV cipher_manual = AES.new(key, AES.MODE_CBC, manual_iv) ct2_manual = cipher_manual.encrypt(pt) print(ct2_manual.hex()) # 和上述第二次输出完全相同
内容的提问来源于stack exchange,提问作者Vlad Havriuk
相关产品推荐
相关产品推荐

