哈希函数与消息完整性:SHA-256原理、HMAC、数字签名基础

哈希函数是密码学中最基础也最常用的原语之一。它能够将任意长度的输入数据压缩为固定长度的摘要(Digest),并且具备单向性和抗碰撞性。本章从 SHA-256 的内部结构出发,逐步讲解如何利用哈希函数构造消息认证码(HMAC)以及数字签名,从而保障数据的完整性与来源可信性。

2.1 哈希函数核心属性

一个安全的密码学哈希函数必须满足以下三个安全属性:

属性 定义 违反后果
抗原像性 给定摘要 y,无法找到任何 x 使得 H(x) = y 攻击者可伪造摘要对应的原始消息
抗第二原像性 给定 x₁,无法找到 x₂ ≠ x₁ 使得 H(x₁) = H(x₂) 攻击者可替换消息而不改变摘要
抗碰撞性 无法找到任意两个不同的 x₁、x₂ 使得 H(x₁) = H(x₂) 生日攻击可伪造数字签名
关键指标:SHA-256 输出 256 位摘要,抗碰撞安全强度为 128 位(生日攻击复杂度 2¹²⁸)。截至 2025 年,SHA-256 仍被 NIST 认定为适合大多数商用场景的安全哈希算法。

2.2 SHA-256 算法原理

SHA-256 属于 SHA-2 家族,采用 Merkle-Damgård 结构。处理流程分为三个阶段:

  1. 填充与长度编码:在消息末尾追加 1 位 '1',再填充若干 '0',最后附加 64 位原始消息长度(大端序),使总长度恰好为 512 位的整数倍。
  2. 消息分块:将填充后的消息划分为 512 位(64 字节)的块,每块进一步拆分为 16 个 32 位字。
  3. 压缩函数迭代:每个块经过 64 轮轮函数处理,使用 8 个初始工作变量(A-H)和 64 个常数 K₀…K₆₃,最终输出 256 位摘要。
实现提示:SHA-256 的 64 轮轮函数中,每轮使用不同的轮常数 Kᵢ(前 64 个质数的立方根小数部分的前 32 位)。这些常数是固定的,无需在运行时计算。
SHA-256 压缩函数单轮结构 SHA-256 单轮压缩函数数据流 输入 A-H (256 bit) A B C D E F G H 第 i 轮轮函数 (i = 0…63) Σ₀(A) + Maj(A,B,C) + Σ₁(E) + Ch(E,F,G) + Wᵢ + Kᵢ Σ₀ = ROTR²(A) ⊕ ROTR¹³(A) ⊕ ROTR²²(A) Σ₁ = ROTR⁶(E) ⊕ ROTR¹¹(E) ⊕ ROTR²⁵(E) Maj = (A∧B) ⊕ (A∧C) ⊕ (B∧C) , Ch = (E∧F) ⊕ (¬E∧G) A' B' C' D' E' F' G' H' (更新后) Wᵢ 消息调度

2.3 HMAC:基于哈希的消息认证码

单纯使用哈希函数只能检测消息是否被篡改,但无法验证消息的来源。HMAC(Hash-based Message Authentication Code)通过在哈希计算中混入共享密钥,同时提供完整性和真实性保护。

HMAC-SHA256 的计算公式如下:

HMAC(K, m) = SHA256( (K' ⊕ opad) || SHA256( (K' ⊕ ipad) || m ) )

其中:
  K'   = 如果 K 长度 > 64 字节,则 K' = SHA256(K);否则 K' = K(左补零至 64 字节)
  ipad = 0x3636…36(64 字节)
  opad = 0x5C5C…5C(64 字节)
  ||   = 字节串拼接
常见误区:不要直接使用 H(K || m) 或 H(m || K) 作为消息认证码。长度扩展攻击可针对 Merkle-Damgård 结构构造有效 MAC,而 HMAC 的双层嵌套结构可有效防御此类攻击。

2.4 数字签名基础

数字签名解决了 HMAC 的密钥分发问题——HMAC 要求通信双方预先共享密钥,而数字签名使用非对称密钥对:签名者用私钥签名,验证者用公钥验证。典型的数字签名方案包含三个算法:

  • KeyGen(1ⁿ) → (sk, pk):生成私钥 sk 和公钥 pk。
  • Sign(sk, m) → σ:使用私钥对消息 m 生成签名 σ。
  • Verify(pk, m, σ) → {0,1}:使用公钥验证签名是否有效。

实际应用中,数字签名通常先对消息做哈希,再对摘要签名,而非直接对长消息签名。这样做有两个好处:

  1. 提升效率:非对称签名运算只处理固定长度的摘要(如 256 位)。
  2. 兼容性:不同长度的消息都能统一签名流程。
数字签名流程:哈希+非对称签名 数字签名标准流程(先哈希后签名) 发送方 原始消息 m SHA-256 摘要 h 私钥签名 签名 σ 接收方 m' + σ' SHA-256 h' 公钥验证 有效/无效

2.5 三种完整性机制对比

机制 密钥类型 提供完整性 提供真实性 抗抵赖性 典型算法
哈希(Hash) 无密钥 ✅ ❌ ❌ SHA-256
消息认证码(MAC) 对称密钥 ✅ ✅ ❌ HMAC-SHA256
数字签名 非对称密钥对 ✅ ✅ ✅ ECDSA / RSA-PSS
选型建议:在端到端加密设计中,消息完整性通常由 HMAC 或 AEAD(认证加密)提供;数字签名主要用于证书签名、代码签名和区块链交易等需要公开验证的场景。如果通信双方已通过密钥交换协议(如 X3DH)获得共享密钥,优先使用 HMAC 而非数字签名,因为对称运算性能远优于非对称运算。