HMAC(Hash-based Message Authentication Code)是一种现代密码学结构,用于保证消息的完整性与认证性。它结合了哈希函数与密钥,通过特殊的双层结构抵御多种密码学攻击。HMAC 属于对称密码学范畴,是目前互联网中最广泛部署的认证算法之一。
HMAC在中文中通常称为“基于哈希的消息认证码”。它是一种利用哈希函数和密钥共同生成的认证数据,用于验证消息是否被篡改以及消息是否来自可信的一方。HMAC 目前广泛应用于 HTTPS、API 认证、JWT、云服务签名、区块链系统等场景,是现代互联网安全体系中非常重要的组成部分。
本深度分析文章从数学结构、安全性分析、攻击模型、防御机制、实现细节等角度系统展开,适合对密码学原理有一定基础的读者。
在 HMAC 之前,人们通常使用以下方式对消息进行认证:
但这些结构都存在严重问题,例如:
HMAC用于防止消息内容在传输过程中被篡改, 确认消息确实来自持有同一密钥的一方(身份认证),它提供了数据完整性和身份认证功能,其主要特点如下:
HMAC 的最终结构由 Bellare、Canetti 和 Krawczyk 于 1996 年提出,是当今最成功的通用 MAC 构造之一。
HMAC 依赖两个基本元素:
它通过“密钥 + 消息”的组合计算出一个哈希值,这个值被称为 MAC(Message Authentication Code)。
如果消息或密钥被修改,生成的 MAC 就会完全不同。
HMAC 使用一种特定的结构来防止简单拼接导致的安全漏洞。
其核心步骤如下:
将密钥处理为固定长度(不同哈希函数有不同的 block size,如 SHA-256 的 block size 为 64 字节)。
生成两个派生密钥:
计算以下值:
HMAC = Hash( (key XOR opad) + Hash((key XOR ipad) + message) )
其中:
这种双重哈希结构可以有效避免长度扩展攻击,使得 HMAC 比简单的 "Hash(key + message)" 安全得多。
HMAC 的输入包括:
输出是一个固定长度的哈希值。例如:
输出长度完全取决于哈希函数。
HMAC(K, M) = H( (K ⊕ opad) ∥ H((K ⊕ ipad) ∥ M ) )
其中:
密钥必须先经过处理,使其长度等于哈希函数的块大小(block size)。例如 SHA-256 block size 为 512 位(64 字节)。
Inner = H((K XOR ipad) + message)
Outer = H((K XOR opad) + Inner)
这形成一种“哈希中的哈希”,双重结构极大提升了安全性。
HMAC 的安全性来源于以下要素:
普通哈希函数如 SHA-1、SHA-256 存在长度扩展攻击:
攻击者可以构造: Hash(original + padding + extra)
但 HMAC 使用两个不同的密钥派生值:
攻击者即使能扩展内部哈希,也无法伪造外层哈希。
这使得 HMAC 彻底避免了 Merkle-Damgård 系列哈希的结构性弱点。
攻击者要伪造 HMAC,需要解决以下问题之一:
由于外层哈希独立作用于内部结果,这种“双壳结构”使得:
HMAC 的安全性理论上可以归约为底层哈希函数的伪随机性与抗碰撞性。
即使底层哈希函数被证明存在碰撞(如 MD5、SHA-1),HMAC 仍然在许多场景下具有有限的安全性。
原因是:
因此:
HMAC 的安全性被证明可归约为两个假设:
这是一个强性质,使其成为密码协议中非常可靠的构件。
下面分析常见攻击类型及 HMAC 的防御能力。
HMAC 完全免疫。
若密钥泄露,则攻击者可伪造 MAC。 但在密钥不泄露的情况下无法伪造。
HMAC 本身不防重放,必须结合:
攻击者若要恢复密钥,需要破坏以下之一:
目前没有任何成功的攻击能做到这一点(对安全哈希而言)。
即使攻击者能找到:
H(A) = H(B)
仍然无法构造:
HMAC(K, A) = HMAC(K, B)
因为密钥参与了输入,且哈希前后两层输入都完全不同。
密钥必须满足:
例如:
短密钥可能导致暴力猜测攻击的可行性上升。
现代推荐使用:
不再推荐:
HMAC 的输出长度完全由底层哈希函数决定。
HMAC常见算法对比:
| 算法名称 | 输出长度 | 推荐程度 | 适合场景 |
|---|---|---|---|
| HMAC-SHA256 | 32 字节 | ★★★★★ | API 鉴权、JWT、云服务 |
| HMAC-SHA1 | 20 字节 | ★★☆☆☆ | 旧系统兼容 |
| HMAC-SHA512 | 64 字节 | ★★★★★ | 高安全级别场景 |
| HMAC-MD5 | 16 字节 | ★☆☆☆☆ | 不推荐(仅兼容旧系统) |
HMAC 只需要两次哈希调用:
现代 CPU,尤其是支持 SHA-NI 指令集的 CPU,可以极快执行 HMAC。
HMAC 内部存在依赖顺序:
因此难以全面并行化,但其速度仍然能满足绝大多数场景。
HMAC 在互联网系统中非常常见,以下是典型案例。
许多云服务(如 AWS、阿里云、腾讯云)要求客户端使用 HMAC-SHA256 对请求进行签名,从而防止请求被伪造或篡改。
JWT 中常见的 HS256、HS384、HS512 都是典型的 HMAC 算法。
TLS1.2 使用 HMAC 来验证数据完整性。
HMAC 常用于构建更复杂的密码系统,例如 PBKDF2、HKDF。
| 场景 | 用的 HMAC 类型 | 例子 |
|---|---|---|
| 微信/支付宝/云服务 API 签名 | HMAC-SHA256 | AccessKey + SecretKey |
| JWT(Json Web Token) | HMAC-SHA256(HS256) | 登录态 token |
| AWS S3、阿里云、腾讯云签名 | HMAC-SHA256/SHA1 | 请求防篡改 |
| GitHub Webhook | HMAC-SHA256 | secret 验证来源 |
| 银行、支付 MAC 计算 | HMAC-SHA256 | 8583 报文完整性保护 |
| Cookie 防篡改 | HMAC-SHA256 | session_id + 用户信息 + HMAC |
| 微信小程序登录凭证校验 | HMAC-SHA256 | session_key 校验 code2Session |
在线HMAC计算工具: HMAC加密
HMAC 的成功来自以下优势:
因此,HMAC 是密码学中极为经典和重要的组件,被视为安全协议设计的“黄金标准”。
尽管 HMAC 安全可靠,但错误使用仍可能导致漏洞。
常见误用包括:
避免这些风险是安全工程的重要任务。
HMAC 是一种简单、快速、非常可靠的消息认证机制。它通过“密钥 + 哈希”的形式,确保消息不能被篡改,并验证发送者身份。
它具有以下特点:
Q:HMAC 能不能当加密用?
A:不能!HMAC 只防篡改,不防偷看。想加密请用 AES-GCM。
Q:密钥多久换一次?
A:建议每 90 天或泄露后立即更换。泄露后立即失效。
Q:密钥太短怎么办?
A:HMAC 会自动把短密钥用 0 填充到块大小,不影响安全,但建议至少 32字节随机密钥。
Q:HMAC 和数字签名(RSA/ECC)有什么区别?
A:HMAC:双方共享同一个密钥(对称),速度极快;数字签名:私钥签名、公钥验证(非对称),可防抵赖,但慢几百倍
对于普通的哈希函数,只能证明数据没有损坏(完整性)。HMAC不仅能证明数据没损坏,还能证明是谁发的(认证性)。普通的哈希 (MD5/SHA)函数就像给信件按了一个指纹。如果有人改了信件,指纹就不对上了。但是,坏人可以伪造信件并按上一个新的指纹。HMAC 就像给信件按指纹时,同时盖了一个只有你和收信人有钥匙的私密印章。坏人可以改信件,但他没有那个印章(密钥),所以造不出正确的认证码。