HMAC-SM3 消息认证码(MAC)原理:消息完整性与来源验证

算法原理 · 2026-08-17

概述

HMAC(Hash-based Message Authentication Code,基于哈希的消息认证码)是一种使用密码杂凑函数和共享密钥计算消息认证码的结构化算法,最早由 Krawczyk、Belling 和 Ramachandran 于 1996 年在 RFC 2104 中定义。HMAC 的核心目标是同时提供消息完整性保护和消息来源认证:接收方可以确认消息未被篡改,且确实来自声称的发送方。

在国密体系中,将 HMAC 结构与 SM3 杂凑函数结合形成的 HMAC-SM3 是 TLS 1.3 国密套件(如 TLS_SM4_GCM_SM3)中用于消息认证的核心组件,也是 GM/T 0024-2023《SSL VPN 技术规范》和 GM/T 0129-2023《SSH 密码协议规范》中消息完整性验证的底层原语。

注意:本文聚焦 HMAC-SM3 的密码学原理和结构分析,属于概念/算法类 wiki 文章。如需工程实现指南(含 Python 代码),请参考 blog/sm3-hmac-message-authentication。

背景:为什么需要 HMAC

安全威胁场景

假设 Alice 向 Bob 发送一条金融转账指令:

CODE
转账 | 收款人:张三 | 金额:10000 元

如果仅通过公钥密码(如 SM2)加密,虽然保障了机密性,但存在以下风险:

  • 重放攻击:攻击者截获加密消息后重新发送,Bob 无法区分这是新指令还是旧指令的复制
  • 替换攻击:攻击者修改密文(在某些模式下),解密后得到不同的明文
  • 伪造消息:攻击者构造一条假消息,Bob 无法验证其来源
单纯使用哈希(如 SM3)不够,因为任何人都可以计算 SM3 摘要;单纯使用加密也不够,因为加密只提供机密性。

HMAC 解决了这个问题:只有持有共享密钥的通信双方才能生成和验证 MAC,第三方无法伪造。

与数字签名的区别

特性HMAC(对称)SM2 数字签名(非对称)
密钥类型共享对称密钥签发方私钥 / 验证方公钥
身份模型共享密钥意味着信任通道证书 + PKI 信任链
性能极快(约 SM2 的 1/100)较慢
适用场景高速内部通信(TLS 数据面)身份认证、文档签署
不可否认性无(双方都可生成)有(仅私钥持有者可签名)
HMAC 不替代 SM2 签名,而是与之互补:HMAC 用于高速消息完整性,SM2 用于身份认证和不可否认。

HMAC 密码学原理

结构设计思想

HMAC 采用双重哈希结构,其核心思想是:

  • 将密钥与一个内填充值(ipad=0x36 重复)做异或,与消息拼接后做哈希——这一步将密钥"嵌入"消息的初始状态
  • 将密钥与一个外填充值(opad=0x5C 重复)做异或,与第一步的哈希结果拼接后再做一次哈希——这一步将前一步的结果"封存"
这种结构设计带来两个关键安全属性:
  • 密钥不可逆:即使攻击者知道 HMAC 输出和消息,也无法反推密钥
  • 防长度扩展攻击:双重哈希结构阻止了 MD/SHA 系列常见的长度扩展攻击

HMAC 通用公式(RFC 2104)

$$\text{HMAC}(K, m) = H\left((K' \oplus opad) \parallel H((K' \oplus ipad) \parallel m)\right)$$

其中:

  • $K$:原始密钥(长度任意)
  • $K'$:固定长度的密钥(若 $K$ 过长则 $K' = H(K)$,若过短则右补零至块长度)
  • $ipad$:内填充,字符 0x36 重复 block_size 次
  • $opad$:外填充,字符 0x5C 重复 block_size 次
  • $H$:底层密码杂凑函数(此处为 SM3)
  • $\parallel$:串联操作
  • $\oplus$:按字节异或

SM3 参数适配

将通用 HMAC 公式中的 $H$ 替换为 SM3:

参数SM3 值
杂凑输出长度 $h$256 bit(32 字节)
分组长度 $\ell$512 bit(64 字节)
ipad0x36 重复 64 次(64 字节)
opad0x5C 重复 64 次(64 字节)
最大消息长度$2^{61}$ 字节(SM3 限制)
SM3 的分组长度为 512 bit(64 字节),与 SHA-256 相同,因此 HMAC-SM3 的计算流程在结构上与 HMAC-SHA256 完全一致,仅替换了底层哈希函数。

HMAC-SM3 计算步骤详解

第一步:密钥处理

设原始共享密钥为 $K$(长度可任意),目标块长度为 $B = 64$ 字节(SM3 分组长度):

情况 A:$K$ 长度 $\leq B$

直接右补零至 64 字节:

CODE
K' = K || 0x00...0x00  (共 B 字节)

情况 B:$K$ 长度 $> B$

先对 $K$ 做 SM3 杂凑,得到 $K' = \text{SM3}(K)$,再右补零:

CODE
K' = SM3(K) || 0x00...0x00  (共 B 字节)
国密工程实践:在国密 TLS 协议中,密钥通常来自 KDF(密钥派生函数),长度已固定为 32 字节(SM3 输出长度),直接属于情况 A。

第二步:内填充与第一次杂凑

将 $K'$ 与内填充 $ipad$(64 字节 0x36)做按字节异或,再与消息 $m$ 拼接,进行 SM3 杂凑:

$$\text{inner} = \text{SM3}((K' \oplus ipad) \parallel m)$$

$K' \oplus ipad$ 的结果是一个 64 字节的"密钥掩码",它混合了密钥熵到哈希的初始状态中。

第三步:外填充与第二次杂凑

将 $K'$ 与外填充 $opad$(64 字节 0x5C)做按字节异或,再与 inner 拼接,进行 SM3 杂凑:

$$\text{HMAC-SM3}(K, m) = \text{SM3}((K' \oplus opad) \parallel \text{inner})$$

两次异或的值不同(0x36 vs 0x5C),确保内层和外层哈希的密钥掩码完全不同,增强了抗分析能力。

完整流程图

与国密协议的关联

GM/T 0024-2023 SSL VPN 技术规范

GM/T 0024-2023 定义了 SSL VPN 网关的密码技术要求,其中消息完整性保护使用 HMAC-SM3(与 SM4-GCM 的 AEAD 模式相比,HMAC-SM3 适用于非 AEAD 的 SM4-CBC 模式)。

关键条款映射:

GM/T 0024 要求HMAC-SM3 实现
数据传输完整性保护使用 HMAC-SM3 生成消息认证码
密钥派生KDF 输出作为 HMAC 共享密钥
随机数要求符合 GM/T 0005-2012 随机性检测

GM/T 0129-2023 SSH 密码协议规范

GM/T 0129-2023《SSH 密码协议规范》规定了国密 SSH 协议的完整交互流程,其中认证阶段和数据传输阶段的完整性校验均使用 HMAC-SM3。

SSH MAC 协商示例:

CODE
SSH 客户端 → 服务器:MAC algorithms [hmac-sm3]
SSH 服务器 → 客户端:MAC algorithms [hmac-sm3,hmac-sha2-256]
协商结果:hmac-sm3

国密 TLS 1.3 套件

在 TLS 1.3 的国密密码套件中(如 TLS_SM4_GCM_SM3),HMAC-SM3 虽然不再用于记录层(AEAD 模式自带认证),但在以下场景仍有应用:

  • 密钥派生:HKDF 中的 hash 函数使用 SM3
  • Finished 消息:TLS 1.3 握手后期的 finished 验证使用 PRF,其底层为 HKDF-SM3
  • 早期数据(0-RTT):部分国密扩展草案中涉及 HMAC-SM3 用于早期数据验证

安全性分析

抗碰撞安全性

HMAC 的安全性依赖于底层哈希函数的抗碰撞性。对于 HMAC-SM3:

  • SM3 输出长度 256 bit,抗碰撞安全性约 128 bit(生日攻击)
  • 若攻击者能打破 SM3 的抗碰撞性,则 HMAC-SM3 的安全性随之下降
  • 目前 SM3 未发现有效的碰撞攻击

密钥长度与安全性

  • HMAC-SM3 的推荐密钥长度为 32 字节(256 bit),与 SM3 输出长度一致
  • 密钥长度不足时,安全强度受限于最短的密钥长度
  • 国密标准要求 HMAC 密钥使用 GM/T 0005-2012 符合性检测的随机数生成器产生

已知攻击与防御

攻击类型对 HMAC-SM3 的影响防御措施
长度扩展攻击不适用(双重哈希结构)结构设计已免疫
密钥重用安全性降低不同用途使用不同密钥(密钥派生分离)
侧信道攻击执行时间/功耗可能泄露使用恒定时间实现

与其他 MAC 方案的对比

方案底层哈希密钥长度输出长度国密适配
HMAC-SM3SM3(256bit)任意(推荐 32B)256 bit✅ 原生支持
HMAC-SHA256SHA-256任意(推荐 32B)256 bit❌ 国际算法
CMAC-SM4SM4(分组密码)128/192/256 bit128 bit✅ 需额外定义
Poly1305ChaCha20 派生256 bit128 bit❌ 国际算法
选择建议:国密合规场景优先选用 HMAC-SM3;非国密场景(如与 AWS KMS 等第三方集成)可考虑 HMAC-SHA256。

相关实践