尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

HMAC 签名算法详解

HMAC 签名算法详解 一、什么是 HMACHMACHash-based Message Authentication Code基于哈希的消息认证码是一种结合密码学哈希函数与对称密钥来生成消息认证码的算法。它同时继承了哈希函数的高效计算特性与对称密钥的认证能力核心作用是验证消息的完整性与真实性—— 确保消息在传输过程中未被篡改且确实来自持有密钥的合法发送方。HMAC 由 Mihir Bellare、Ran Canetti 和 Hugo Krawczyk 于 1996 年提出1997 年被纳入 RFC 2104 国际标准是目前工业界应用最广泛的消息认证码方案。它不绑定特定哈希函数可灵活搭配 MD5、SHA-1、SHA-256、SHA-512 等任意哈希算法对应记作 HMAC-MD5、HMAC-SHA256、HMAC-SHA512 等。二、核心设计思想很多人会将 HMAC 简单理解为 “密钥 消息拼接后做哈希”即Hash(key message)。这种朴素实现存在严重的安全缺陷最典型的就是长度扩展攻击攻击者在不知道原始密钥的情况下可以在消息末尾追加任意数据直接推导出合法的哈希值从而伪造签名。HMAC 的设计目标就是从结构上规避这类攻击它采用双层哈希 两次密钥异或的嵌套结构不直接拼接密钥与消息而是将密钥分别与两个固定常量ipad、opad做异或运算生成两组相互独立的派生密钥先将内层派生密钥与原始消息拼接执行第一次哈希运算再将外层派生密钥与第一次哈希的结果拼接执行第二次哈希运算最终输出 HMAC 值。这种 “内哈希 外哈希” 的嵌套结构从根本上阻断了长度扩展攻击的路径同时几乎没有损失哈希函数的计算效率。三、标准计算流程3.1 前置定义设H为所选底层哈希函数如 SHA-256K为原始签名密钥B为哈希函数的分组长度单位字节例如 SHA-256 分组长度为 64 字节SHA-512 为 128 字节L为哈希函数的输出长度单位字节例如 SHA-256 输出 32 字节ipad 0x36 重复 B 次内层填充常量opad 0x5C 重复 B 次外层填充常量text为待签名的原始消息3.2 密钥预处理密钥长度必须对齐哈希函数的分组长度因此需要先做标准化处理若密钥长度大于分组长度 B先对密钥执行一次哈希将哈希结果作为新密钥长度变为 L若密钥长度小于分组长度 B在密钥末尾补 0将其填充至 B 字节长度。最终得到长度恰好为 B 字节的标准化密钥K0。3.3 完整计算步骤计算内层派生密钥K_inner K0 XOR ipad将内层派生密钥与原始消息拼接得到内层输入K_inner || text对内层输入执行哈希运算得到内层摘要inner_hash H(K_inner || text)计算外层派生密钥K_outer K0 XOR opad将外层派生密钥与内层摘要拼接得到外层输入K_outer || inner_hash对外层输入执行哈希运算最终结果即为 HMAC 值\(\text{HMAC}(K, \text{text}) H\left( (K_0 \oplus \text{opad}) \parallel H\left( (K_0 \oplus \text{ipad}) \parallel \text{text} \right) \right)\)3.4 常量 0x36 与 0x5C 的设计依据这两个数值并非随机选取0x36 的二进制为001101100x5C 为01011100二者汉明距离大每一位差异尽可能多异或后能让密钥的比特位充分扩散降低内外层派生密钥的相关性提升整体安全性。四、安全特性分析4.1 核心安全优势天然抵抗长度扩展攻击这是 HMAC 最核心的安全价值。由于外层哈希完整包裹了内层哈希的输出攻击者无法通过追加消息的方式推导合法签名这也是它优于Hash(keymessage)朴素实现的根本原因。哈希碰撞影响有限即使底层哈希函数出现碰撞漏洞如 MD5、SHA-1HMAC 的安全性下降幅度也远小于裸哈希。例如 HMAC-MD5 至今仍未被完全攻破其安全强度显著高于单独使用 MD5。密钥不直接暴露密钥始终以异或后的派生形态参与运算不会直接出现在哈希输入的首尾降低了密钥侧信道泄露的风险。对称认证性只有持有相同密钥的双方才能生成和验证签名可确认消息来源的真实性。4.2 安全边界与注意事项HMAC 属于对称算法不具备不可否认性收发双方都可以生成签名无法替代数字签名密钥长度建议至少等于哈希输出长度过短的密钥会大幅降低暴力破解的成本不建议继续使用 HMAC-MD5、HMAC-SHA1生产环境优先选择 HMAC-SHA256 及以上强度的组合。五、典型应用场景5.1 API 接口鉴权开放平台与服务端通信中客户端将请求参数按规则排序拼接后用密钥生成 HMAC 签名服务端收到请求后按相同规则重新计算签名并比对。该方案可有效防止参数被篡改配合时间戳与随机数还能防御重放攻击是 AWS、阿里云、微信支付等绝大多数开放平台的标准鉴权方案。5.2 JWT 令牌签名JSON Web Token 中的 HS256、HS384、HS512 算法本质就是 HMAC-SHA256、HMAC-SHA384、HMAC-SHA512。服务端用密钥对 Payload 签名客户端无法篡改令牌内容服务端校验通过即可信任身份信息。5.3 文件完整性校验在分发安装包、固件等文件时发布方同时公布文件的 HMAC 值与共享密钥下载方计算本地文件的 HMAC 并比对可确认文件未被植入恶意代码。相比普通哈希校验HMAC 还能防止攻击者同时篡改文件和哈希校验值。5.4 密码存储不推荐HMAC 有时被用来哈希存储用户密码但它并非为慢哈希设计计算速度过快容易被彩虹表和暴力破解攻击。存储用户密码应优先使用 bcrypt、Argon2、PBKDF2 等专用慢哈希算法。六、代码实现示例6.1 PythonPython 标准库hmac提供了原生实现import hmac import hashlib key byour_secret_key message bHello, HMAC! # 生成 HMAC-SHA256 签名 signature hmac.new(key, message, digestmodhashlib.sha256).hexdigest() print(signature)6.2 GoGo 语言crypto/hmac标准库package main import ( crypto/hmac crypto/sha256 encoding/hex fmt ) func main() { key : []byte(your_secret_key) message : []byte(Hello, HMAC!) h : hmac.New(sha256.New, key) h.Write(message) signature : hex.EncodeToString(h.Sum(nil)) fmt.Println(signature) }6.3 Node.jsconst crypto require(crypto); const key your_secret_key; const message Hello, HMAC!; const signature crypto.createHmac(sha256, key) .update(message) .digest(hex); console.log(signature);七、总结HMAC 是密码学工程中极其经典且实用的基础组件它以极低的实现成本解决了网络通信中最常见的 “消息篡改” 与 “身份伪造” 问题。其双层哈希的设计思想简洁而精妙历经数十年工业界实战检验依然稳固。在工程实践中只要涉及对称密钥下的消息认证、接口签名、令牌校验HMAC-SHA256 都是默认的安全选型。理解其原理不仅能帮助开发者正确使用它也能避免因自行封装错误如实现hash(keymsg)朴素方案而引入安全漏洞。
返回列表