“YOLO"不是有效的哈希构造方式
在Trail of Bits的审计工作中,“用哈希函数自建工具"是最常见的密码学失误之一。当客户面临"需要哈希多个不同值”、“需要MAC"或"需要密码密钥派生函数"等问题时,他们往往会选择最顺手的工具——哈希函数。
这些需求通常催生出所谓的"YOLO"构造:即临时拼凑的函数,以看似明显、直接(但通常是错误)的方式"解决"眼前问题。事实上,这些问题比表面看起来复杂得多。
YoloMultiHash
这是我们在审计中最常见的YOLO构造。当客户需要将复杂数据结构或值数组转换为Fiat-Shamir记录时经常使用。
构造方式
给定哈希函数H和消息集合M̂ = {M1,M2,…,Mn},选择分隔符S,计算:
|
|
问题根源
核心在于编码歧义性。如果消息包含分隔符S作为子字符串,攻击者可以将单个消息拆分为多个部分,导致不同语义的输入产生相同哈希值,实质上破坏了哈希函数的抗碰撞性。
解决方案
- 使用专为多值哈希设计的TupleHash(SP800-185标准)
- 采用BLAKE3规范描述的"有状态哈希对象”
- 使用Protocol Buffers/CBOR/BCS等序列化工具确保无歧义编码
YoloMAC
构造方式
给定密钥K和消息M,计算:
|
|
双重漏洞
- 长度扩展攻击:对于Merkle-Damgård结构哈希(如SHA256),攻击者可在未知密钥情况下构造有效MAC
- 编码歧义性:通过密钥/消息重组可制造不同密钥消息对产生相同MAC的情况,可能实现"可否认加密"攻击
解决方案
- SHA2家族:必须使用HMAC
- SHA3家族:使用KMAC(支持XOF模式、输出长度集成等特性)
- BLAKE2/3:直接使用内置的密钥哈希模式
YoloPBKDF
构造方式
给定密码P和盐值S,计算:
|
|
或迭代版本:
|
|
致命缺陷
- 无内存计算要求,攻击者可进行每秒数百亿次的暴力破解
- 防御成本呈线性增长(10倍迭代仅需攻击者增加10倍资源)
现代解决方案
- Argon2家族:强制内存计算(如64MB内存需求)
- scrypt:类似的内存困难函数
- FIPS兼容方案:组合PBKDF2与HKDF使用
核心建议
- 优先选用现代哈希设计:BLAKE3/SHA3等已内置多哈希和MAC支持
- 避免重复造轮子:HMAC、KMAC、TupleHash等方案已有成熟实现
- 强制内存计算:密码派生必须使用Argon2/scrypt等内存困难函数
- 规范序列化:结构化数据哈希前必须确保无损编码
密码学实现需要专业方案,临时构造的YOLO方法往往隐藏着致命安全漏洞。选择经过验证的标准方案,才是保障系统安全的正确之道。