You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyCryptodome中AES上下文对消息的链式加密机制是怎样的?

问题解答

核心原因

该现象是CBC加密模式的固有设计,并非PyCryptodome私有的特殊逻辑,也不是框架随机生成了新IV:CBC模式的AES上下文会自动保存上一次加密完成后的最后一个密文块,作为下一次加密操作的初始IV,以此实现多段加密的链式关联。

抽象算法逻辑

CBC模式的加密流程和上下文更新规则如下:

  1. 初始化阶段:调用AES.new()创建上下文时,你传入的初始IV会被存入上下文的current_iv变量
  2. 单次加密流程(传入任意长度的对齐后明文):
    • 将明文拆分为N个16字节的块P1, P2, ..., PN
    • 按顺序计算每个密文块:Ci = AES_Encrypt(密钥, Pi XOR 前一个输出块),其中第一个明文块的前一个输出块就是current_iv
    • 输出所有密文块拼接后的结果
    • 上下文自动更新:把最后一个密文块CN覆盖写入current_iv,供下一次加密使用

对应你的代码示例:第一次加密完成后,上下文里存储的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.15 13:15:02