hmac
HMAC 将哈希函数与共享密钥结合,只有持有密钥的一方才能生成正确签名。它能发现内容被修改,但不提供加密和防重放能力。
生成与验证
import hashlib
import hmac
key = b"server-secret"
message = b"user=42&expires=1893456000"
signature = hmac.new(key, message, hashlib.sha256).digest()
received = signature # 实际来自请求
if hmac.compare_digest(signature, received):
print("签名有效")
也可以使用 hmac.digest(key, msg, "sha256") 快速计算。签名通常传输为十六进制或 Base64;验证时先解码,并拒绝格式错误的输入。
签名协议设计
签名必须覆盖所有关键字段,并规定稳定的序列化方式。例如把方法、路径、时间戳和正文按固定顺序拼接,避免不同语言产生不同字节:
canonical = "\\n".join([method.upper(), path, timestamp, body]).encode()
tag = hmac.new(key, canonical, hashlib.sha256).hexdigest()
验证时检查时间窗口、随机数或唯一请求 ID,防止攻击者重放旧请求;共享密钥应放在密钥管理系统或环境变量中,不写入源码和日志。密钥轮换时可支持当前密钥与上一把密钥短暂并存。
与哈希、加密的区别
普通哈希没有密钥,任何人都能计算;HMAC 需要共享密钥,提供认证;加密则用于保密。不要把 HMAC 输出当作密码,也不要自行拼接 sha256(key + message) 替代 HMAC。