API 中的 HMAC:请求签名
实现基于 HMAC 的请求签名和重放攻击防护
API 中的 HMAC:请求签名 是 CoddyKit 上的免费 Cryptology Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Cryptology Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Cryptology Academy 课程共包含 4 节课。
欢迎
AWS、GitHub、Stripe 和 Twilio 都使用基于 HMAC 的请求签名来验证 API 调用。在本课中,我们将构建一个完整的请求签名系统。
为什么需要 API 请求签名
URL 中的 API 密钥可能会被记录在代理服务器、浏览器历史记录和服务器日志中。请求签名会将完整的请求正文纳入 MAC,从而确保载荷未被修改,也确保密钥不会单独暴露。
AWS Signature Version 4
AWS SigV4 的计算过程如下:
1. 规范化请求(方法 + URL + 标头 + 正文哈希)
2. 待签名字符串(日期 + 区域 + 服务 + 规范化请求哈希)
3. 签名密钥 = HMAC(HMAC(HMAC(HMAC('AWS4'+secret, date), region), service), 'aws4_request')
4. 签名 = HMAC(signing_key, string_to_sign)
GitHub Webhook 验证
GitHub 会为每个 Webhook 载荷签名:
X-Hub-Signature-256: sha256=HMACHEX
验证:
import hmac
expected = 'sha256=' + hmac.new(secret, payload, 'sha256').hexdigest()
hmac.compare_digest(expected, received_signature)
重放攻击威胁
如果攻击者捕获了一个有效的已签名请求,就可以多次重新发送它。一笔只签名一次的 100 美元转账可能会被重放 1000 次。HMAC 单独使用并不能防止重放。
基于时间戳的重放防护
在待签名消息中加入时间戳。拒绝早于 5 分钟的请求。Stripe 会发送包含时间戳的 X-Stripe-Signature。GitHub 使用 X-GitHub-Delivery(UUID),而不是基于时间戳的方案。
基于随机数的重放防护
为每个请求加入一个随机随机数。服务器会存储已经使用过的随机数(在带有 TTL 的 Redis 中)。拒绝包含已见过随机数的任何请求。对于分布式系统,这种方式比时间戳更可靠。
请求签名实现
import hmac, hashlib, time, os
def sign_request(secret, method, path, body, timestamp=None):
ts = timestamp or str(int(time.time()))
payload = f'{method}\n{path}\n{ts}\n' + hashlib.sha256(body).hexdigest()
sig = hmac.new(secret.encode(), payload.encode(), 'sha256').hexdigest()
return ts, sig
服务器端验证
def verify_request(secret, method, path, body, ts, received_sig):
# Check timestamp freshness
if abs(time.time() - int(ts)) > 300: # 5 minutes
return False
# Recompute and compare
_, expected = sign_request(secret, method, path, body, ts)
return hmac.compare_digest(expected, received_sig)
使用 HMAC 的 JWT(HS256)
HS256 JWT 使用共享密钥和 HMAC-SHA256。服务器既负责签名,也负责验证。其局限是:任何持有该密钥的一方都可以伪造令牌。对于非对称信任场景(例如第三方身份验证),请使用 RS256 或 ES256。
密钥轮换策略
应定期轮换 HMAC 密钥:生成新密钥,在过渡窗口(24 小时)内同时支持旧密钥和新密钥,然后停用旧密钥。AWS SigV4 会根据带日期的密钥派生密钥,从而支持每日轮换。
快速检查
为什么仅使用 HMAC 请求签名不足以防止重放攻击?
回顾
您已经实现了带重放防护的 HMAC 请求签名。接下来,我们将比较 CMAC 和 Poly1305 这两种基于分组密码的 MAC 替代方案。
常见问题解答
「API 中的 HMAC:请求签名」课时是免费的吗?
是的 — 「API 中的 HMAC:请求签名」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Cryptology Academy 课程的其余内容,请升级到 CoddyKit PRO。 Cryptology Academy 课程共包含 4 节课。
「API 中的 HMAC:请求签名」这节课中我会学到什么?
实现基于 HMAC 的请求签名和重放攻击防护 你通过在浏览器中直接运行的动手代码来练习 Cryptology Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Cryptology Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Cryptology Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「API 中的 HMAC:请求签名」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Cryptology Academy 课中编写并运行代码吗?
能。每节 Cryptology Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- MAC 概念与长度扩展攻击
- HMAC 构造与安全性证明
- API 中的 HMAC:请求签名
- CMAC 与 Poly1305:分组密码 MAC