跳到主要内容
加密解密2026-07-136 分钟阅读

在线 HMAC 生成器:消息认证码原理与实践

什么是 HMAC

HMAC(Hash-based Message Authentication Code,基于哈希的消息认证码)是一种使用加密哈希函数和密钥来验证消息完整性和真实性的算法。

简单来说,HMAC 就是"带密钥的哈希"——只有拥有相同密钥的人才能生成或验证 HMAC 值。想自己生成一个?直接用我们的 HMAC 生成器,填入消息和密钥,签名立刻就出来。

HMAC vs 普通哈希

特性普通哈希(如 SHA-256)HMAC
输入仅消息消息 + 密钥
无密钥可验证✅❌
防伪造❌(攻击者可自行计算)✅(需要密钥)
典型用途文件完整性、密码存储API 签名、消息认证

HMAC 的工作原理

HMAC 的计算公式(RFC 2104):

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

其中:

  • K = 密钥(Key)
  • m = 消息(Message)
  • H = 哈希函数(如 SHA-256)
  • K' = 密钥处理:超过哈希块大小先哈希压缩(SHA-256 块 64 字节,SHA-384/512 块 128 字节),不足则零填充到块大小
  • opad = 外部填充(0x5c 重复一个块)
  • ipad = 内部填充(0x36 重复一个块)

两个关键设计直觉:

  1. 为什么是两次哈希而不是 H(key || message):内外两层填充把密钥混进哈希的两个不同阶段,外层哈希的输入不含原始消息——这正是它能抗住长度扩展攻击的结构原因(下文详述)。
  2. 密钥超长为什么要先哈希:块大小之外的密钥字节会被填充截断成「无效熵」——128 字节的密钥用在块 64 字节的 SHA-256 上,后 64 字节直接参与异或,反而会降低有效安全性。先哈希一次把任意长密钥规整到「不超过一个块」。

HMAC vs 数字签名 vs KDF:什么时候用什么

三个经常被混用的原语,分工完全不同:

HMAC数字签名(Ed25519/RSA)HKDF/PBKDF2
密钥模型对称(同一把钥签名+验证)非对称(私钥签、公钥验)从秘密派生新密钥
能否向第三方证明来源❌(验证方也能伪造)✅(不可否认性)不适用
速度极快(≈哈希速度)慢 1~3 个数量级HKDF 快 / PBKDF2 故意慢
典型场景API 签名、Webhook 验签、JWT HS256代码签名、证书、JWT RS256/EdDSA会话密钥派生、密码存储

判断口诀:通信双方互相信任且共享密钥 → HMAC;需要让不持有密钥的第三方验签 → 数字签名;手头已有高熵秘密要拆成多把密钥 → HKDF;手头只有口令 → PBKDF2/argon2。工具页顶部可切到 HKDF 模式 试 Extract/Expand;原理见 HKDF 详解。

如何使用在线 HMAC 生成器

本站 HMAC 生成器 是实时计算的——输入后无需点按钮,结果随敲随出。

HMAC 模式

  1. 模式选 HMAC
  2. 在 Message 框输入消息
  3. 在 Secret Key 框输入密钥
  4. 在 Output Format 选择输出格式(Hex 或 Base64)
  5. Display Mode 选 Show All 时五种算法(MD5 / SHA-1 / SHA-256 / SHA-384 / SHA-512)同时并列计算;选 Show Selected 只勾需要的算法
  6. 点结果旁的 Copy 复制对应的 HMAC 值

输出长度速查(Hex 格式):MD5 32 字符、SHA-1 40 字符、SHA-256 64 字符、SHA-384 96 字符、SHA-512 128 字符。Base64 格式约为 Hex 的 2/3 长。

HKDF 模式

  1. 模式选 HKDF(Extract + Expand)
  2. 填 IKM(高熵输入密钥材料;对照 RFC 向量时把输入编码切到 Hex)
  3. 可选填 Salt / Info(用途标签);长度填需要的 OKM 字节数
  4. 结果区同时显示 PRK(Extract) 与 OKM(Expand)

空 salt/info 合法(RFC 5869:空盐用 HashLen 个零字节)。不要用 HKDF 拉伸用户口令——那是慢 KDF 的活。

实现注记

工具全部在浏览器本地完成:HMAC 的 SHA-1/256/384/512 走 WebCrypto crypto.subtle.sign('HMAC', ...);MD5 因 WebCrypto 不支持,用 spark-md5 按 RFC 2104 手工实现。HKDF 模式:Extract 即 HMAC(salt, IKM),Expand 走 deriveBits({ name: 'HKDF', ... }),与 RFC 5869 附录向量对齐。消息/密钥/IKM 按所选编码处理;HMAC 下消息或密钥为空则不计算;空密钥会被 WebCrypto 拒绝。材料只留在浏览器 localStorage,不上传。

HMAC 的常见应用场景

1. API 请求签名

许多 API(如 AWS、Stripe、微信支付)要求请求携带 HMAC 签名:

// 请求头示例
Authorization: HMAC-SHA256 signature=abc123...

服务端用相同密钥对请求参数计算 HMAC,与客户端提交的签名对比,验证请求未被篡改。

2. Webhook 验证

GitHub、Stripe 等平台的 Webhook 使用 HMAC-SHA256 签名验证:

const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

3. JWT 签名

JWT(JSON Web Token)的 HS256 算法本质上就是 HMAC-SHA256:

header.payload.signature
其中 signature = HMAC-SHA256(base64(header) + "." + base64(payload), secret)

想亲手验证:把 JWT 的 header.payload 部分原样粘进 HMAC 生成器 的消息框,密钥填签名密钥,算法选 SHA-256,输出转 Base64URL 后应与 signature 段一致。签名原理与 alg=none 攻击等坑详见 JWT 详解。

4. 消息完整性校验

在不可信网络中传输消息时,附带 HMAC 可以验证消息未被篡改。

HMAC 密钥安全建议

  1. 密钥长度:至少 256 位(32 字节),推荐使用密码学安全随机数生成
  2. 密钥存储:不要硬编码在源代码中,使用环境变量或密钥管理服务
  3. 密钥轮换:定期更换密钥,使用新密钥验证前一个周期的请求
  4. 时间戳防重放:在签名消息中包含时间戳,拒绝过期请求

长度扩展攻击:HMAC 为什么存在

朴素构造在 Merkle-Damgård 哈希(SHA-256 在内)上会断:知道 hash(key+message) 的攻击者无需密钥就能算出 hash(key+message+suffix)——长度扩展攻击。这不是理论:它真的攻破过生产 API(Flickr 2009 年签名伪造)。HMAC 的双哈希结构(内外双层密钥填充)可证明地抵抗它。实现者的教训:永不发明 MAC 构造——每个标准库的 HMAC-SHA256(key, data) 就是正确答案,任何拿 sha256(secret+payload) 当「签名」的代码是漏洞不是简化。

常数时间比较:时序侧信道

用 == 比较收到的 MAC 和算出的 MAC 会泄露:字符串比较在第一个不同的字节返回 false,能量化响应时间的攻击者逐字节恢复正确的 MAC(几秒的请求不是几年)。每个严肃的库都带常数时间比较——Node 的 crypto.timingSafeEqual、Python 的 hmac.compare_digest、浏览器的 crypto/subtle.timingSafeEqual。你的 webhook 处理器如果用 === 验签——今天就修;这是最常见的现实 HMAC bug。配套控制:验证端点限速(攻击需要大量计时请求)。

重放防护:MAC 说真实不说新鲜

合法 HMAC 证明消息来自持钥者——什么都不证明时间。重放攻击(截获签名请求重发)单靠 HMAC 无解;标准模式是把时间戳和 nonce 签进 payload:HMAC(key, 时间戳+nonce+body),拒绝时间窗外的时间戳、窗口内跟踪 nonce。Stripe 的 webhook 签名就是这个形状。没有 nonce,窗口内的攻击者仍可重放;没有时间戳,重放永远有效。

FAQ

HMAC 和数字签名有什么区别?

HMAC 使用对称密钥(同一密钥生成和验证),数字签名使用非对称密钥(私钥签名,公钥验证)。HMAC 更快,但无法向第三方证明签名来源。选择取决于是否需要不可否认性。

应该选哪个哈希算法?

推荐 HMAC-SHA256,它是目前最广泛使用的标准。SHA-1 和 MD5 已被认为不安全,不应在新项目中使用。

HMAC 可以防止重放攻击吗?

单独不行。HMAC 只验证消息完整性,不防止重放。需要结合时间戳(timestamp 参数)或随机数(nonce)来防重放。

工具里 MD5/SHA-1 还能用吗?

HMAC 的安全性和裸哈希不同:MD5/SHA-1 的碰撞攻击对 HMAC 不直接生效(攻击者不掌握密钥),HMAC-MD5 目前没有被实际攻破的记录。但两者都已废弃,新项目没有理由使用——它们留在工具里是为了验证遗留系统和教学对比,不是用来给新系统签名的。

相关阅读


来自 ToolVault 工具匣 的开发手记。更多免费本地工具见 首页。