密码学应用基础 · kp-008

哈希函数与消息认证码(HMAC)

核心 约 15 分钟 状态:reviewed #密码学#哈希#HMAC#口令存储

一句话定义

密码学哈希函数把任意输入映射为固定长度摘要,需满足单向性与抗碰撞性,代表算法是 SHA-256;消息认证码(HMAC)在哈希基础上混入密钥,让接收方能验证"内容没被改过且确实出自持钥者"。

为什么重要

哈希是完整性的原子操作:文件校验、口令存储、签名预处理、内容寻址全部建立在其上;HMAC 则是"认证过的完整性",是 API 签名、JWT、TLS 记录层认证的通用构件。两者的使用边界(口令要用慢哈希、单纯哈希不能当认证)是最常被踩中的密码学误用点,直接衔接 kp-010。

前置知识

kp-006(对称加密):理解"密钥"与"保密性 vs 完整性"的分工。

核心概念

  • 哈希三性质:抗原像(由摘要反推输入不可行)、抗第二原像(找不到另一输入产生相同摘要)、抗碰撞(找不到任意两个输入同摘要)。碰撞难度 ≈ 摘要长度的平方根量级(生日界,约 2^(n/2))。
  • 算法现状:MD5 与 SHA-1 已被实际碰撞攻破,仅可用于非对抗性校验;新系统一律 SHA-256/SHA-3/BLAKE3。
  • 口令存储特殊要求:口令熵低,必须用"慢"哈希(bcrypt/Argon2id/PBKDF2)+ 每用户唯一盐,把离线爆破成本抬高数个量级。
  • HMAC 结构:HMAC(K, m) = H((K⊕opad) ∥ H((K⊕ipad) ∥ m)),双层结构天然免疫长度扩展攻击。
  • 长度扩展攻击:对 Merkle–Damgård 结构(MD5/SHA-1/SHA-256),已知 H(K∥m) 可在不知 K 的情况下计算 H(K∥m∥pad∥后缀)——因此"H(secret∥message)"不是安全认证。

公式、模型或图示

text
摘要长度 n 位:抗碰撞强度 ≈ 2^(n/2)   (SHA-256 → 2^128)
HMAC:  HMAC(K, m) = H( (K ⊕ opad) ∥ H( (K ⊕ ipad) ∥ m) )
        外层套密钥、内层套密钥 → 结构性免疫长度扩展
口令存储: hash = Argon2id(口令, salt=随机16B, cost=按硬件调)

原理与机制

哈希与 HMAC 的本质区别是"有没有秘密":无密钥的哈希任何人都能算,只能证明数据自校验一致(防意外损坏,不能防蓄意篡改——攻击者改完数据重算哈希即可);HMAC 中的密钥把验证能力限定在持钥方。认证加密中的 MAC 校验还必须"先比较后使用":用常数时间比较防时序侧信道。口令存储是哈希应用的特例——目标是让验证方算得快、攻击方算得慢,所以方向与通用哈希相反:故意慢(代价因子)、故意耗内存(Argon2id 的内存硬度),并用随机盐阻止彩虹表与跨用户批量破解。盐不需要保密(它防的是预计算,不是防读取),但必须每用户唯一。

实例或案例

  • 软件发布页附 SHA-256 校验值:验证下载完整性(防损坏;若需防篡改则须签名,见 kp-009)。
  • API 请求签名:客户端对"方法+路径+时间戳+体"计算 HMAC 附在头部,服务端持同一密钥验证,同时提供时效性与完整性。
  • Git 的对象寻址用 SHA-1(历史原因),行业正因 SHA-1 碰撞实证(2017 SHAttered)推进迁移——完整性场景对碰撞的态度可见一斑。

直观类比

哈希像食物的指纹榨汁机:不同食材几乎不可能榨出完全相同的汁,但从汁无法还原食材。HMAC 则是"配方掺了只有你家有的秘密香料"——别人能尝出味道对不对,却仿不出这个味道。

常见误区

  • 用 MD5 存口令:快是哈希的优点,却是口令存储的致命缺点——GPU 每秒可算上百亿次。
  • "H(K∥m)" 当认证:SHA-256 系结构存在长度扩展攻击,必须用标准 HMAC。
  • 盐要保密:盐的作用是唯一化,公开不影响安全性;需要保密的是慢哈希的输出与参数选择中的密钥(pepper)。

与其他知识点的关系

  • kp-009(数字签名与 PKI):签名是对"哈希值"做的非对称运算,哈希是签名的前置步骤。
  • kp-015(会话管理与认证安全):口令存储与认证策略的完整工程实践。

自测题

  1. 为什么下载站附 SHA-256 校验值不能防"被篡改的安装包"?要点:哈希无密钥,攻击者可替换文件并同时替换校验值;防蓄意篡改需数字签名。
  2. 口令存储为什么不用 SHA-256 而用 Argon2id?要点:口令熵低,需慢函数与内存硬度抬高离线爆破成本,盐保证唯一化。
  3. 长度扩展攻击针对什么写法?标准对策是什么?要点:H(secret∥message) 这类前缀拼接;对策是使用标准 HMAC 的双层结构。

延伸阅读

《NIST SP 800-63B: Digital Identity Guidelines》:口令存储与认证器的权威要求。