Python Cryptography实现SSH AES-CTR模式首包正常后续包异常问题
SSH实现AES-CTR模式首包正常、后续包校验失败修复方案
不需要手动实现IV(计数器)递增逻辑,问题根源是CTR加解密实例被重复初始化,计数器状态被强制重置,和IV递增逻辑本身无关。
核心逻辑说明
- cryptography库内置的CTR模式会在每次调用
update()处理数据时,自动按AES块大小(16字节)推进计数器状态,无需开发者手动修改IV值 - SSH协议规范要求:同一连接的同一传输方向(发送/接收),在一次密钥交换生命周期内,CTR计数器必须从初始IV开始持续累加,直到下次密钥交换重新派生密钥和IV为止。计数器值和该方向处理过的总数据块数严格对应,不会按数据包边界重置
- 此前尝试按数据包个数手动递增IV的方案无效:计数器按加密块数递增,不是按包数递增。例如单包长度为80字节时,处理完该包计数器需要累加5(80/16=5个AES块),固定按包加1会直接导致计数器偏移错误。
问题定位
你当前封装的_SSH_Streamcipher类代码本身没有问题,bug出在类的调用逻辑上:
- 第一个包能正常通过服务端校验,是因为首次初始化加解密器时,计数器从初始IV开始计数,和对端状态完全匹配
- 后续所有包校验失败,是因为处理每个新数据包时,你重新实例化了
SSH_Cipher_AES_256_CTR类、或重复触发了加解密器的初始化逻辑,导致计数器被重置回初始IV,和对端已经推进过的计数器状态完全错位
修复方案
不需要修改现有封装类的代码,仅调整调用逻辑即可:
- 每次完成密钥交换派生新密钥和IV后,针对发送方向、接收方向分别初始化一个
SSH_Cipher_AES_256_CTR实例,全局保存复用,直到下一次密钥交换 - 后续所有待发送明文,统一调用发送方向实例的
encrypt()方法加密;所有收到的密文,统一调用接收方向实例的decrypt()方法解密 - 禁止按数据包维度重新初始化cipher实例、或重建encryptor/decryptor对象,库内部会自动维护计数器的连续递增状态
- 删除所有手动修改IV、手动累加计数器的冗余逻辑
可以在_SSH_Streamcipher的__init__方法中加打印日志验证,如果处理非首包时该日志被触发,即可确认是重复初始化导致的问题。
内容的提问来源于stack exchange,提问作者EviLDgL
相关产品推荐
相关产品推荐

