首页/安全/加密与证书速查/Poly1305 一次性认证码
加密算法基础95 条

Poly1305 一次性认证码

RFC 8439 定义的认证算法:使用 32 字节一次性密钥对消息生成 16 字节标签,通常与 ChaCha20 组合为 AEAD 使用。

加密与证书速查安全更新于 2026-10-13

Poly1305 是什么

Poly1305 是 RFC 8439 定义的一次性认证码(one-time MAC):使用 32 字节密钥对消息计算 16 字节标签,验证方用同一密钥重算并比对。它的核心运算是在素数 2^130-5 上做多项式求值,实现简洁、速度快,且不依赖查表,天然适合恒定时间实现。最常见的形态是与 ChaCha20 组合成 ChaCha20-Poly1305 这类 AEAD 算法,用于 TLS 1.3、WireGuard、SSH 等协议。

基本信息

标准RFC 8439 §2.5
密钥32 字节,每条消息一次性使用
标签16 字节(128 位)
常见组合ChaCha20-Poly1305(AEAD)
能力边界只提供完整性与认证,不单独提供机密性
性能特点无查表运算,软件实现快且不易受缓存计时攻击影响

典型使用场景

  • TLS 1.3 的 ChaCha20-Poly1305 套件:缺少 AES 硬件加速的移动与嵌入式设备首选
  • WireGuard 等 VPN 协议的报文加密与认证
  • 需要恒定时间软件实现的场景:避免 AES 查表带来的缓存计时侧信道
  • 受限终端上的 AEAD:无 AES 指令集时纯软件效率明显好于 AES-GCM
  • 作为 AEAD 构造的一部分使用,nonce 与密钥派生交给上层协议管理

示例与要点

示例与要点
# Python(cryptography):一次性密钥生成与标签校验
from cryptography.hazmat.primitives.poly1305 import Poly1305
import os

key = os.urandom(32)                           # 每条消息一个新密钥
tag = Poly1305.generate_tag(key, b'message')   # 生成 16 字节标签
Poly1305.verify_tag(key, b'message', tag)      # 校验失败抛 InvalidSignature
# 实际使用:不要手工生成密钥,按 RFC 8439 从会话密钥派生
# ChaCha20-Poly1305 的 32 字节 one-time key 由 ChaCha20 对 nonce 加密得到

与通用 MAC 的差别

对比项Poly1305HMAC-SHA256
密钥复用严禁,每条消息一次性允许长期复用
速度极快,无查表依赖哈希实现,通常较慢
密钥长度32 字节任意长度
典型定位AEAD 内部认证件通用消息认证
密钥复用是致命错误:同一密钥认证两条不同消息会泄漏密钥材料,攻击者可以直接伪造后续标签。组合使用时密钥必须按 RFC 8439 的规则派生,不能直接用约定字符串或固定值。
选择建议:桌面与服务器通常具备 AES 硬件加速,AES-GCM 更快;手机、家用路由与缺少 AES 指令集的老设备上,ChaCha20-Poly1305 的纯软件性能明显更好。两者都属于当前推荐集合,按客户端能力择优即可。

易错点

  • 把 Poly1305 当通用 MAC 长期复用密钥 → 认证强度被直接破坏,等于给攻击者伪造能力
  • ChaCha20-Poly1305 中 96 位 nonce 在同一密钥下重复 → 机密性与完整性同时失效
  • 自行拼装 ChaCha20 与 Poly1305 却不按 RFC 8439 派生一次性密钥 → 双方标签不一致或强度下降
  • 先使用明文再校验标签 → 未认证数据参与业务逻辑,还可能形成行为差异被外部探测

数据来源与参考

  • RFC 8439 §2.5(Poly1305)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌