土法炼钢兴趣小组的算法知识备份

OPAQUE(RFC 9807)详解:从协议原理到工程落地

目录

引言

在传统的用户名 + 密码登录系统中,服务器通常要么直接保存口令派生值(如 salt + hash(password)),要么依赖 TLS+密码的组合来实现认证。一旦服务器数据库被攻破,攻击者就可以对这些口令派生值做离线暴力破解,且整个系统的安全性高度依赖 TLS 与密码派生方案的组合是否正确实现。OPAQUE(The OPAQUE Augmented Password-Authenticated Key Exchange Protocol,标准化为 RFC 9807)试图系统性地解决这一问题:在不改变“用户只记一个密码”这一习惯的前提下,让服务器永远看不到明文密码,即使数据库泄露也只能付出与在线猜密码同一个量级的代价。

本文从 RFC 9807 的细节出发,系统介绍 OPAQUE 的设计目标、密码学原理、协议流程、实现要点、密码存储模型以及在实际工程中的落地方式,并配以 SVG 示意图帮助理解。

RFC 9807 概览

RFC 9807 将 OPAQUE 定义为一种增强型密码认证密钥交换协议(Augmented PAKE, aPAKE),由 IRTF CFRG 标准化,核心目标是:

  1. 密码永不暴露给服务器:包括注册阶段在内,服务器在任何时候都无法看到裸密码,也不能计算出简单的 hash(password)
  2. 数据库泄露风险最小化:即使攻击者拿到整个密码数据库,其能够发起的离线字典攻击成本也与在线尝试相当(需要与服务器交互或模拟完整协议流)。
  3. 提供密钥交换能力:不仅完成“谁是谁”的认证,还要产出高熵的共享会话密钥,可直接用于后续加密信道(例如集成到 TLS 中)。
  4. 独立于 PKI:不要求每个用户或服务器都依赖复杂的证书体系,协议本身在纯密码场景下也能安全运行(当然可以选择与 TLS/PKI 组合强化安全)。

从结构上看,RFC 9807 定义了:

简单理解:OPAQUE = OPRF + 密码封装的长程密钥 + AKE(例如 3DH) 的组合,并在 RFC 中给出了强约束的 API 与状态机定义。

高层原理:为什么 OPAQUE 安全

1. Augmented PAKE 的思路

与“对称 PAKE”(如 SRP、EKE 等)不同,增强型 PAKE 的核心思想是:

OPAQUE 在这一思想下进一步强化:

2. OPRF 在 OPAQUE 中的角色

OPRF(Oblivious Pseudorandom Function,不经意伪随机函数)是 OPAQUE 的基石。它允许客户端在不向服务器透露输入(密码)的情况下,获得服务器密钥对该输入的计算结果。

下图展示了 OPRF 的数学原理(基于 Diffie-Hellman 风格的乘法群):

OPRF 协议数学原理

在 OPAQUE 中:

  1. 盲化 (Blind):客户端将密码映射为群元素 \(H(pwd)\),并用随机数 \(r\) 进行盲化得到 \(H(pwd)^r\),发送给服务器。
  2. 评估 (Evaluate):服务器用私钥 \(k\) 计算 \((H(pwd)^r)^k\),返回给客户端。服务器无法消除 \(r\),因此无法得知 \(H(pwd)\)
  3. 去盲 (Finalize):客户端计算 \(((H(pwd)^r)^k)^{1/r} = H(pwd)^k\)

这一步实现了两个关键效果:

3. 长程密钥封装与 AKE

有了 \(F_k(pwd)\) 之后,OPAQUE 会:

在在线认证阶段:

这一结构保证:

协议整体流程示意

下面通过 SVG 图概览 OPAQUE 的注册和认证流程(略去底层数学细节)。

OPAQUE 协议整体流程示意图

从图可以看到:

  1. 注册阶段:密码经 OPRF “硬化”后,只留下被口令加密的 envelope 存在服务器;
  2. 认证阶段:客户端再次通过 OPRF + envelope 解包拿回自己的长程密钥,然后与服务器完成 AKE;
  3. 服务端全程从未看到明文密码,也从未保存可直接用于离线破解的简单哈希值。

注册协议细节(Registration Flow)

以 RFC 9807 的术语略化描述注册流程:

  1. 客户端输入密码并盲化
    • 客户端选择密码 pwd,生成随机盲因子 r,计算 blind = Blind(pwd, r)
    • blind 连同用户名 idU 发送给服务器。
  2. 服务器执行 OPRF 评估
    • 服务器持有 OPRF 密钥 k(可全局或按用户区分);
    • 计算 eval = OPRF_Evaluate(k, blind) 并返回给客户端,同时返回公共 OPAQUE 参数和自己的“身份材料”(如服务器公钥、配置版本号等)。
  3. 客户端去盲并派生密钥
    • 客户端用 reval 去盲得到 oprf_output = Finalize(pwd, r, eval)
    • 使用标准 KDF:prk = KDF_extract(salt, oprf_output)okm = KDF_expand(prk, info)
    • okm 派生:encryption_keymac_keyexport_key 等多个子密钥。
  4. 生成长程密钥对与 envelope
    • 客户端本地生成自己的长程密钥对 (skU, pkU),可为签名密钥或 KEM 密钥;
    • 构造 envelope 明文:包含 skU、用户元数据(如算法、版本)、可能还有服务器公钥绑定信息;
    • 使用 encryption_key 通过 AEAD 加密,得到 envelope = AuthEnc(encryption_key, nonce, plaintext, aad)
    • 这里的 aad (Additional Authenticated Data) 通常包含 pkU 和服务器身份信息,防止重放或替换攻击。
  5. 服务器存储注册记录
    • 服务器最终保存:record = { idU, envelope, pkU, oprf_public_data, masking_key }
    • 注意:RFC 9807 引入了 masking_key 机制来保护 envelope 免受枚举攻击,即使是合法的 envelope 也需要通过额外的密钥解掩码才能尝试解密。

至此,用户注册完成。后续登录将复用相同的 envelope 和 OPRF 参数,无需再次生成长程密钥。

在线认证 + 密钥交换(Login / AKE Flow)

在线登录阶段,OPAQUE 将 “恢复长程密钥” 和 “执行 AKE” 两步紧密耦合在一起:

  1. 客户端发起登录
    • 用户输入 pwd
    • 客户端再次生成盲因子 r,计算 blind = Blind(pwd, r)
    • 发送 { idU, blind, client_ake_share } 给服务器(通常将 AKE 第一步合并发送)。
  2. 服务器返回 envelope 与 OPRF 评估结果
    • 服务器根据 idU 查表,取出 record
    • 计算 eval = OPRF_Evaluate(k, blind)
    • 生成服务器的 AKE 临时公钥 server_ake_share
    • 返回 { eval, envelope, server_ake_share, server_identity_proof }
  3. 客户端去盲并解 envelope
    • 客户端得到 eval 后去盲得到 oprf_output
    • 同注册时一样派生 encryption_key 等;
    • 使用 encryption_key 解密 envelope,成功恢复 (skU, pkU)
    • 关键点:如果解密失败(MAC 校验不过),说明密码错误,协议立即终止。
  4. 基于长程密钥执行 AKE
    • 客户端使用恢复的 skU 和服务器的公钥进行认证密钥交换(Authenticated Key Exchange)。
    • 常见的 AKE 模式是 3DH (Triple Diffie-Hellman)SIGMA-I
      • 结合双方的临时公钥(Ephemeral Keys)和长程公钥(Identity Keys)计算共享秘密。
      • 派生出 session_keysession_auth_key
    • 客户端发送 client_auth_mac 给服务器,证明自己成功解开了 envelope 并持有 skU
  5. 双方确认并进入会话
    • 服务器验证 client_auth_mac
    • 双方完成握手,后续通信使用 session_key 加密。
    • 此外,还可以导出一个 Export Key,用于加密应用层的静态数据(如磁盘加密密钥),这样只有在用户成功登录时才能解密数据。

若用户输入错误密码,则:

服务器如何安全地“保存密码”

与传统 hash(password) 模型不同,OPAQUE 中服务器保存的是:

这带来几方面安全优势:

  1. 数据库泄露时的攻击面更小
    • 攻击者拿到的是一堆 AEAD 加密的 envelope 和辅助数据;
    • 要验证某个候选密码是否正确,必须:
      1. 选择一个候选 pwd'
      2. 计算盲化值并用 k 评估 OPRF;
      3. 去盲得到 oprf_output' 并派生 encryption_key'
      4. 尝试解密 envelope 并验证 MAC;
    • 这一流程的代价远高于简单地对字典里每个单词做一次哈希。
  2. 可与传统哈希方案组合
    • 在实现时,完全可以在 OPAQUE 之外再做一层 Argon2id / scrypt 等密码哈希;
    • 比如使用 pwd_stretched = Argon2id(pwd, salt) 作为 OPRF 输入,进一步提高暴力破解难度;
    • 需要权衡的是:客户端本地拉长密码将增加登录延迟和设备负载。
  3. 密钥材料与密码相互独立
    • 客户端的长程公私钥对可以独立轮换、吊销或升级算法(例如从 P-256 迁移到 Ed25519 或后量子算法),而不需要用户更改密码;
    • 密码仅作为“解锁 envelope”的手段,不直接参与数据加解密或签名。

下图直观展示了传统“hash 存储”与 OPAQUE envelope 存储的差别:

OPAQUE 与传统密码存储对比

深度对比:OPAQUE vs Bcrypt/Argon2

虽然 OPAQUE 和传统的密码哈希算法(如 Bcrypt, Argon2, Scrypt)都旨在保护存储在服务器端的密码,但它们的安全模型和功能边界有着本质区别。

1. 核心特性对比表

特性 传统哈希 (Bcrypt / Argon2) OPAQUE (RFC 9807)
服务器可见性 可见 (登录时服务器需接收明文密码或其哈希) 不可见 (服务器只处理盲化数据,永远不知道密码)
数据库泄露后果 离线暴力破解 (攻击者可在本地利用 GPU/ASIC 跑字典) 无法离线破解 (必须通过 OPRF 密钥在线交互,或先破解 OPRF 密钥)
抗预计算攻击 依赖 Salt (盐) 天然免疫 (依赖 OPRF 密钥和随机数)
认证产出 仅布尔值 (登录成功/失败) 高熵会话密钥 (Session Key) + 认证状态
前向安全 (PFS) 无 (除非依赖外部 TLS) 天然支持 (基于 AKE 的临时密钥协商)
性能开销 内存/CPU 密集 (故意变慢以抗破解) 计算密集 (ECC 点乘) + 网络 (多轮往返)

2. 为什么 Argon2 还不够?

目前的最佳实践通常推荐使用 Argon2id,它通过内存困难 (Memory-Hard) 属性来抵御 GPU/FPGA 加速破解。然而,Argon2 仍然存在局限性:

  1. 明文传输风险:在 TLS 终止点(如负载均衡器)到应用服务器之间,或者在应用服务器内存中,密码是明文存在的。如果服务器被植入内存马,密码就会泄露。OPAQUE 彻底消除了这一风险,因为线路上传输的和服务器内存里处理的都是盲化数据。
  2. 离线攻击的必然性:只要攻击者拿到了 salthash,他们就可以在自己的设备上无限次尝试猜测密码,唯一的限制是算力。而 OPAQUE 引入了 OPRF 密钥(通常由 HSM 或独立服务管理),攻击者如果没有这个密钥,连“尝试猜测”这一步都做不到(无法计算 F_k(guess))。

3. OPAQUE vs “加盐 + Pepper”

一种改进传统哈希的方法是使用 Pepper(一个存储在应用代码或 HSM 中的全局密钥)对密码进行 HMAC,然后再哈希:Hash(HMAC(pepper, pwd), salt)

实现要点与工程细节

1. 选择密码学库与参数

在工程实践中,一般不建议自己手写底层 OPRF 和 AKE,实现时可以考虑:

2. 客户端实现中的坑

3. 服务器实现中的注意事项

4. 与现有账户系统集成

把 OPAQUE 接入现有“账号中心 / IAM 平台”时,典型做法是:

  1. 为每个用户增加一个 opaque_record 字段,保存 envelope 及相关参数;
  2. 新用户注册时,用 OPAQUE 注册协议填充该字段;
  3. 老用户迁移时,在首次登录时同时执行:
    • 用旧的 hash(password) 成功认证;
    • 使用明文密码在后台跑一遍 OPAQUE 注册流程,生成 opaque_record
    • 成功后标记用户为“OPAQUE 已启用”,下次登录走新路径。

在业务层,你可以把“登录成功”这一事件抽象为:

5. Export Key 的妙用

OPAQUE 的一个强大特性是除了会话密钥外,还能导出一个 Export Key。这个密钥具有以下特性: - 确定性:只要密码不变,每次登录导出的 Export Key 都是相同的。 - 独立性:与具体的会话无关,服务器无法获知。

应用场景: - 端到端加密存储:可以用 Export Key 加密用户的私有数据(如笔记、钱包私钥)。服务器只负责存储加密后的数据 blob。用户登录时,客户端自动计算出 Export Key 并解密数据。 - 无感数据迁移:即使用户更换了设备,只要密码正确,就能恢复出解密密钥,无需云端备份明文密钥。

实际项目中的应用场景

  1. 高价值后台系统(运维平台、管理后台)
    • 这类系统一旦账号泄露影响极大,传统密码+短信验证码防护能力有限;
    • 引入 OPAQUE 可以显著提高密码数据库泄露后的安全边界,尤其适合没有条件为每个运维人员配备硬件令牌的场景。
  2. ToC 互联网业务的密码登录
    • 在大多数用户仍习惯使用“记得住的密码”的现实下,OPAQUE 是一种在“不改变用户习惯”的前提下提升安全性的方式;
    • 可以与 WebAuthn / Passkey 等无密码方案并存,对不方便使用 Passkey 的用户提供更安全的 fallback。
  3. 云 API / 内部微服务认证
    • 某些内部系统可能用“服务账号 + 密码”形式互相调用,传统的 Basic Auth 风险较大;
    • 可将 OPAQUE 封装为一个独立的“密码认证服务”,其他服务通过短会话密钥或 token 与之对接。
  4. 与密码管理器结合
    • 现代密码管理器可以在本地对用户主密码做额外强化(如 Argon2id),再将结果作为 OPAQUE 的输入;
    • 这样即使用户主密码偏弱,整体系统仍然具备较高的抗暴力破解能力。

小结

OPAQUE(RFC 9807)通过 OPRF + envelope + AKE 的组合,把“记一个密码”这种低熵秘密,升级成了在数学上严谨建模的安全认证与密钥交换协议。它与传统 salt + hash(password) 相比,不仅大幅降低了数据库泄露后的离线攻击能力,而且天然提供高熵会话密钥,可平滑接入 TLS、JWT、API 认证等常见工程组件。对于正在建设或改造账号系统的团队来说,OPAQUE 提供了一个在不牺牲用户体验的前提下,大幅提升密码认证安全性的现代化选项。


By .