密码学中的“YOLO”哈希构造:安全隐患与正确实践

本文深入分析三种常见的“YOLO”式哈希构造(YoloMultiHash、YoloMAC、YoloPBKDF)的安全缺陷,包括编码歧义、长度扩展攻击和密码破解漏洞,并提供基于标准算法的替代方案。

“YOLO”不是有效的哈希构造——Trail of Bits 博客

作者:Opal Wright
日期:2024年8月21日
分类:密码学

在 Trail of Bits 常见的密码学错误中,“用哈希函数自建工具”是最典型的案例之一。客户常提出类似需求:“需要将多个值哈希到一起”“需要消息认证码(MAC)”或“需要密码密钥派生函数”,而他们手边最现成的工具就是哈希函数。

这些需求往往通过所谓的“YOLO”构造来实现:即临时设计一个看似直观、直接但通常错误的函数来“解决”眼前问题。

事实上,这些问题比表面更复杂。我们看到客户产品中反复出现自研解决方案时感到沮丧,因为这些问题早已有成熟解决方案。下面将分析几种常见的 YOLO 构造、其缺陷以及正确替代方案。

YoloMultiHash

这是 Trail of Bits 最常见的 YOLO 构造。客户通常在处理复杂数据结构或值数组,并需要将其转换为 Fiat-Shamir 转录时使用此方法。

YOLO 构造

给定哈希函数 H 和消息集合 M̂ = {M₁, M₂, …, Mₙ},选择分隔符字符串 S,计算:
YoloMultiHash(M̂) = H(M₁‖S‖M₂‖S‖…‖S‖Mₙ)

问题

核心问题在于编码歧义。如果消息包含分隔符 S 作为子字符串,例如消息 Mᵢ 包含 S,则可将其拆分为 M′ᵢ‖S‖M′′ᵢ 并定义新集合 M̃ = {M₁, …, M′ᵢ, M′′ᵢ, …, Mₙ},此时 YoloMultiHash(M̂) = YoloMultiHash(M̃)。两个语义不同的输入产生了相同哈希值,这等同于破坏哈希函数的抗碰撞性,是严重的安全问题。

此问题并非理论假设,实际已被用于破解广泛使用的库。

改进方案

应使用专为哈希多个独立值设计的函数,例如 SP800-185 定义的 TupleHash。其他哈希函数(如 BLAKE3)也支持类似功能,其规范描述了创建“有状态哈希对象”的方法。

另一种方案是改进数据序列化。推荐使用 Protocol Buffers、CBOR、BCS 等工具,它们能生成无歧义的数据编码,确保不同值结构不会产生相同哈希输入。注意:虽然多数序列化方法产生无歧义编码,但并非所有都产生唯一编码(例如 JSON 对空格和元素顺序不敏感)。

YoloMAC

YOLO 构造

给定密钥 K 和消息 M,计算 YoloMAC(K,M) = H(K‖M)。有时会加入盐值或定制字符串 S 实现域分离,例如 YoloMAC(K,M,S) = H(K‖S‖M),但这不改变攻击本质。

问题一:长度扩展攻击

若 H 是 Merkle-Damgård 哈希算法(如 SHA256),攻击者可在不知道 K 或 M 的情况下,根据 H(K‖M) 计算 H(K‖M‖X)(X 为任意选择值)。在加密-then-MAC 场景中,攻击者可向明文追加垃圾数据并更新 MAC,可能导致解析器崩溃或时序信息泄露。

问题二:编码歧义

即使使用抗长度扩展攻击的哈希函数(如 SHA3、Skein、BLAKE3),此问题仍存在。例如:
假设 256 位密钥 K = K₁‖K₂(各 128 位),计算 C₁ = YoloMAC(K,M) = H(K₁‖K₂‖M)
定义 M′ = K₂‖M,以 K₁ 为密钥计算 C₂ = YoloMAC(K₁,M′) = H(K₁‖K₂‖M) = C₁
此时两个不同消息/密钥对产生了相同 MAC,可能造成可否认性攻击(例如同一哈希值既可对应犯罪PDF也可对应无害JPG)。

此问题在 Keccak 中尤需注意,因其官网建议“直接将密钥置于消息前”实现 MAC,但未强调密钥长度和格式的假设。

改进方案

  • SHA2 系列(SHA256/384/512等):必须使用 HMAC,其设计专门规避长度扩展攻击,且所有主流密码库均支持。
  • SHA3:使用 KMAC(2016年标准化),支持 XOF 模式、输出长度集成计算和域分离定制字符串。虽可用 HMAC-SHA3,但 KMAC 更高效灵活。
  • BLAKE2/BLAKE3:直接使用内置的密钥哈希模式,性能优于 HMAC 方案。

YoloPBKDF

YOLO 构造

给定密码 P 和盐值 S,计算 K = YoloPBKDF(S,P) = H(S‖P)H(P‖S),甚至迭代计算 Kᵢ = H(S‖Kᵢ₋₁)(K₀ = P)。

问题

密码密钥派生是极其复杂的难题,需要“多年国际标准化努力”。YoloPBKDF 的安全性缺陷已被密码学界批判数十年,但仍在安全评审中出现。

攻击者可通过租赁 AWS GPU 实例每秒测试数千亿个密码候选,内存开销可忽略(仅需存储盐值、哈希状态和当前测试密码)。攻击速度与处理器性能呈线性关系:若 Alice 将迭代次数增加 10 倍,攻击者仅需付出 10 倍成本即可维持相同攻击速率。

改进方案

使用现代密码 KDF,如 Argon2scrypt。它们不仅要求计算资源,还要求内存资源,大幅提高攻击并行化难度。例如 Argon2d 要求 64MB 内存:

  • Alice 在 8GB 内存笔记本上仅占用 0.8% 资源。
  • 攻击者若想每秒测试 100 万个密码,需每秒处理 64TB 数据。

在 FIPS 环境中,可组合使用内存硬化函数(如 Argon2)和 NIST 批准的 PBKDF2,再通过 HKDF 生成最终密钥。

总结

若未锁定特定哈希函数,应全面考虑使用场景并选择现代方案。新哈希设计(如 BLAKE2/BLAKE3)原生支持密钥哈希和 MAC,KMAC 广泛集成于 SHA3 库,TupleHash 常与 KMAC 共同实现。切记:哈希函数应用已有大量研究,应优先选择经过验证的方案而非自创。


原文链接The Trail of Bits Blog
版权声明:© 2025 Trail of Bits,基于 Hugo 和 Mainroad 主题生成。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计