首页/网络/协议速查/HMAC 与 HKDF 密钥派生

HMAC 与 HKDF 密钥派生

HMAC 用密钥把哈希变成「带认证的完整性校验」;HKDF 从共享秘密派生出多个用途明确的密钥,是 TLS 1.3 密钥调度的基础。

协议速查网络更新于 2026-10-13

两个函数各干什么

HMAC 用一个密钥把哈希函数变成带认证的完整性校验:只有持有密钥的一方能算出正确的校验值,因此它同时验证完整性与来源(RFC 2104)。HKDF 解决的是「从一份共享秘密派生出多把密钥」:先用提取阶段得到固定长度的伪随机密钥,再按不同上下文标识派生出任意多把用途明确的密钥(RFC 5869)。

为什么不能自己拼

直接把密钥拼在消息后面再哈希,不是 HMAC,会落入长度扩展一类问题;把哈希结果截断当密钥用,也缺少 HKDF 那样的结构性保证。TLS 1.3 的整个密钥调度都建立在 HKDF 之上,自己发明派生流程基本只是重复踩过的坑。

基本信息

HMAC 结构两轮哈希,密钥分别与内外填充异或,可抵御长度扩展
HKDF 阶段提取提炼熵,扩展按上下文派生多把密钥
比较要求必须用常量时间比较,普通字符串相等会泄露时序
规范RFC 2104、RFC 5869,TLS 1.3 见 RFC 8446 §7.1

典型使用场景

  • 开放接口签名:把参数与时间戳一起签名,防止篡改与重放
  • 消息队列或回调地址的完整性校验
  • 会话 Cookie 防篡改(签名而不是加密)
  • 协议与加密库内部的密钥派生

HMAC 示例

HMAC 示例
openssl dgst -sha256 -hmac 'secret-key' message.txt   # 命令行生成 HMAC
openssl rand -hex 32                                  # 生成对称密钥
# 代码里比较校验值必须用常量时间函数,例如 Python 的 hmac.compare_digest

易混概念对照

概念作用典型误用
HMAC带密钥的完整性校验把密钥直接拼在消息后做哈希
普通哈希只验完整性,不含密钥当作签名使用,任何人都能重算
HKDF从一份秘密派生多把密钥直接截断哈希结果充当密钥
AEAD同时完成加密与认证只用加密不校验,无法发现篡改
派生时的上下文标识要写清用途:同一份主秘密派生出的「加密密钥」与「登录令牌」必须使用不同标识,避免跨用途复用。
比较校验值不能用普通字符串相等:比较过程会因为首个不同字节的位置而耗时不同,理论上可被逐步猜出正确值。

易错点

  • 比较校验值使用普通字符串相等:泄露时序信息,存在被逐步试探的风险
  • 把密钥直接拼接在消息后做哈希:不是 HMAC,存在长度扩展类问题
  • 同一份主密钥派生多种用途密钥却不区分上下文:一处泄露牵连全部
  • 签名只覆盖参数、不覆盖时间戳与一次性随机数:签名可被重放
  • 自己发明密钥派生流程:应当直接使用 HKDF 这样经过审查的构造

数据来源与参考

  • RFC 2104(HMAC)
  • RFC 5869(HKDF)
  • RFC 8446 §7.1

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌