长度扩展问题是什么
对采用迭代压缩结构的哈希,如果只把密钥拼在消息前面再发布整体摘要,攻击者已知消息长度时可以从该摘要推导出「更长消息」的合法摘要。修复方式是使用密钥化构造,或改用不受影响的哈希结构。这个问题只影响自研的拼接式认证,标准协议与成熟库的实现不受影响。
基本信息
| 受影响 | 采用迭代压缩结构的哈希算法 |
|---|---|
| 不受影响 | 海绵结构与树结构哈希 |
| 防护 | 使用密钥化构造 |
| 典型误用 | 把密钥直接拼在消息前面再取摘要 |
典型使用场景
- 接口签名审计:检查是否存在密钥直接拼接的写法
- 自研协议评审:确认认证值的构造方式
- 代码迁移:把拼接式校验改造为标准构造
- 排错:确认签名校验失败是否与构造方式有关
- 协议对接:双方需同时更换构造方式
安全写法
安全写法
import hmac, hashlib
# 不要使用:hashlib.sha256(secret + data).hexdigest()
tag = hmac.new(secret, data, hashlib.sha256).hexdigest() # 标准密钥化构造
hmac.compare_digest(tag, received) # 校验用常量时间比较构造方式对比
| 构造 | 是否受影响 | 说明 |
|---|---|---|
| 密钥拼在消息前 | 受影响 | 可从摘要扩展出更长消息 |
| 密钥拼在消息后 | 不直接受影响 | 仍有其他风险,不建议 |
| 密钥化构造 | 不受影响 | 按标准实现,推荐 |
| 海绵结构哈希 | 不受影响 | 结构本身不受该问题影响 |
该问题只影响「密钥与消息拼接」的自研构造;标准协议与成熟库的密钥化实现不受影响,审计时重点看拼接方式即可快速判断。
落地建议
- 统一使用库提供的密钥化构造
- 校验使用常量时间比较
- 把拼接式签名的搜寻纳入代码审计规则
- 协议对接时双方同步切换构造方式
改用不受影响的哈希结构可以规避该问题,但协议对接需要双方同时升级;单侧切换会造成校验全部失败。