摘要

  • RFC 9588 用 SPAKE、会话记录哈希与派生密钥,让冒充 KDC 的主动攻击者通常无法把一次交换变成离线口令验证器;这属于完整路径,不属于 PA-SPAKE 标签本身。
  • SPAKE 失败后若回退到加密时间戳,被动旁观者可能离线测试用户刚输入的口令。即使预认证成功,也不能据此证明应用授权或资源已经交付。

一个客户端先尝试更安全的方法。服务器返回失败,它便悄悄改走旧路,再让用户输入一次。可用性看板会把这记成“登录流程继续”;抓包者却可能把同一个动作记成“终于得到可离线验证的材料”。

RFC 9588 正文的关键不只在 SPAKE 算法,而在第 10.5 节对回退的警告。SPAKE 原本要阻止冒充 KDC 的主动攻击者离线核验口令猜测;攻击者仍可诱导客户端改用加密时间戳。若错误口令先触发 SPAKE 失败,随后又被旧机制加密发送,被动观察者便可能离线攻击这个错误值。人的错误往往与正确口令结构相近,因此“没猜对”不等于“没有泄露价值”。

协议并未自相矛盾。改变的是实际运行路径,也就是安全结论的适用范围。

能力声明还不是安全回执

IANA 将 PA-SPAKE 登记为预认证类型 151。KDC 可以表示支持,客户端可以提交偏好的群组,KDC 可以选择其中一个。这里每一步都可观测,却没有一步单独证明双方已经验证出同一组派生密钥。

早期消息也不是天然可信。支持与挑战消息含有未经认证的明文;未使用 FAST 时,因子列表在响应验证前既可见,也没有完整性保护。认证集合中的 PA-SPAKE-HINT 只帮助客户端判断某条路是否可能成功,它不进入 transcript,也不能代替正式交换。

真正的机制完成点在后面:双方把群组、共享结果、会话记录和 KDC 请求体纳入密钥派生;KDC 成功解密因子响应并验证所需因子;回复密钥只在最后一次被强化为 K'[0]。KDC 不会再发一条最终 PA-SPAKE 确认,客户端仍需依赖加密的 KDC 回复完成原有的 KDC 认证。

回退不是纯粹的可用性动作

若 SPAKE 失败后仍重试 SPAKE,威胁模型没有自动改变。若失败后转向加密时间戳,抓到的数据可能允许离线试探。RFC 因此建议客户端提供按 realm 禁用加密时间戳的配置。

这比“支持 SPAKE”更严格。一套系统可以在能力清单中全绿,同时因为兼容策略而保留旧暴露面。要审计的不是静态支持率,而是每次实际选择了哪条认证链、为何失败、失败后又走向哪里。

SPAKE 也不会消灭在线猜测。KDC 仍需要观察失败并实施限速。只统计成功 SPAKE 交换、却不统计回退、在线失败与限速决定,相当于只测量首选通道,而忽略攻击者想进入的通道。

预认证成功不等于业务授权

成功交换证明客户端知道初始回复密钥,并提交了实际要求且验证通过的因子。登记表中的 SF-NONE 明确表示“不使用第二因子”;把所有 SPAKE 登录称为多因素认证,会创造规范没有给出的事实。

回复密钥强化之后,还需要新的回执:客户端验证 KDC 回复、取得并使用服务票据、到达应用,再通过应用自己的授权规则。Transcript 绑定 KDC 请求体,不会因此给数据库角色授权,也不会释放付款或证明受保护资源已交付。

这正是现实分层:编号登记不证明部署;协商不证明验证;验证不证明票据使用;票据使用不证明授权。把这些阶段压缩成“安全登录”,会抹掉回退真正改变风险的位置。

实现细节本身就是安全输入

RFC 要求检查公钥点属于正确群组,随机标量必须均匀且不得跨不同回复密钥复用,掩码点不得拥有已知离散对数,实现还必须防止计时等侧信道。任一条件失守,都可能重开离线攻击或泄露长期密钥。

无状态 KDC 可把标量与 transcript 状态放入 PA-FX-COOKIE。这块 cookie 需要保密、完整性、短重放窗口,以及与 principal 和机制的绑定。在有效期内重放最后一条预认证消息,可能让 realm 中另一台 KDC 误以为客户端已完成认证。Cookie 密钥托管不是内部细节,而是整条证据链的一部分。

规范还明确说该机制并非为前向保密而设计。某些实现选择可能保护过去的票据会话密钥,但若长期口令密钥与 cookie 加密密钥同时失守,结论就会变化。

来源