
什么是 HMAC?
HMAC(基于哈希的消息认证码)是一种特定类型的消息认证码,它结合了密码学哈希函数和密钥。它融合了哈希函数(数据完整性)和共享密钥(真实性)的能力,在单个紧凑输出中同时提供两者。
HMAC 在 RFC 2104 中标准化,广泛应用于从 AWS 请求签名到 GitHub 和 Stripe 的 webhook 验证等场景。

为什么不直接对消息进行哈希?
如果仅对消息进行哈希并将两者一起发送,攻击者可以:
- 拦截消息和哈希值。
- 修改消息。
- 计算修改后消息的新哈希值。
- 替换两者——接收方无法检测到篡改。
HMAC 可以防止这种情况,因为计算有效的 MAC 需要密钥。没有密钥,攻击者无法为修改后的消息伪造有效的 MAC。
HMAC 的工作原理
HMAC(K, m) = H((K' ⊕ opad) || H((K' ⊕ ipad) || m))
其中:
- H = 哈希函数(SHA-256、SHA-512 等)
- K = 密钥(填充到块大小作为 K')
- m = 消息
- opad = 外部填充(0x5c 重复)
- ipad = 内部填充(0x36 重复)
密钥被处理两次:一次混合到内部哈希中,另一次混合到外部哈希中。这种双重密钥结构可以防止影响普通哈希的长度扩展攻击。
HMAC 与普通哈希对比
| 属性 | 普通哈希 | HMAC |
|---|---|---|
| 需要密钥 | ❌ | ✅ |
| 完整性验证 | ✅ | ✅ |
| 真实性验证 | ❌ | ✅ |
| 无需密钥即可伪造 | ✅ | ❌ |
| 抗长度扩展 | ❌ (SHA-2) | ✅ |

为 HMAC 选择哈希算法
| HMAC 变体 | 安全性 | 常见用途 |
|---|---|---|
| HMAC-MD5 | 弱 | 仅限遗留系统 |
| HMAC-SHA1 | 可接受 | Git、旧协议 |
| HMAC-SHA256 | ✅ 强 | AWS Signature V4、大多数 API |
| HMAC-SHA512 | ✅ 非常强 | 高安全要求 |
HMAC-SHA256 是大多数应用的现代标准。
实际应用中的 HMAC
Webhook 签名验证
当 GitHub、Stripe 或 Shopify 向你的服务器发送 webhook 时,它们会在请求头中包含 HMAC 签名。你通过使用密钥计算请求体的 HMAC 并进行比较来验证它。
// 验证 GitHub webhook
const crypto = require('crypto');
function verifySignature(secret, payload, signature) {
const computed = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(computed),
Buffer.from(signature)
);
}
注意使用 timingSafeEqual——逐字符比较 MAC 值会泄露攻击者可利用的时序信息。始终使用常量时间比较。

AWS Signature Version 4
每个 AWS API 请求都使用 HMAC-SHA256 签名,密钥由你的秘密访问密钥派生而来:
SigningKey = HMAC(HMAC(HMAC(HMAC("AWS4" + SecretKey, Date), Region), Service), "aws4_request")
Signature = HMAC(SigningKey, StringToSign)
这种多级派生意味着即使某个请求的签名密钥意外暴露,也无法用于签署其他日期、区域或服务的请求。
JWT HS256 签名
当 JWT 使用 HS256 算法时,它使用 HMAC-SHA256 签名:
const signature = HMAC_SHA256(secret, base64url(header) + '.' + base64url(payload));
Cookie 和会话完整性
Express.js 等框架使用 HMAC 签名 cookie 以防止篡改:
// Express cookie-session 内部使用 HMAC
app.use(session({
secret: 'your-secret-key', // 用于 HMAC 签名
resave: false,
saveUninitialized: true
}));
安全注意事项
- 密钥长度——对于 HMAC-SHA256 密钥,至少使用 32 字节(256 位)。
- 密钥轮换——定期轮换 HMAC 密钥。轮换时,支持一个短暂的过渡窗口,新旧密钥同时有效。
- 常量时间比较——始终在常量时间内比较 MAC,以防止时序攻击。
- 密钥存储——切勿在源代码中硬编码 HMAC 密钥。使用环境变量或密钥管理器。
使用此工具
输入你的消息和密钥,选择哈希算法(MD5、SHA-1、SHA-256、SHA-384、SHA-512),工具将在浏览器中计算 HMAC。你可以将结果输出为十六进制(默认)、Base64 或 Base64URL 格式。
→ 尝试 HMAC 生成器