摘要

  • RFC 9458 把一次请求拆给中继和网关:前者看见客户端的网络来源但不能解密,后者解密请求但只看见中继。要实现文档所述隐私目标,两者不能是同一实体。
  • 密码学只切断了传输路径上的一种连接。Cookie、账户字段、设备标识、单客户端密钥配置、复用的 HPKE 上下文、共享日志、低流量和时序或大小相关性,都可能把“谁”和“说了什么”重新接起来。
  • Christopher A. Wood 与 Martin Thomson 的贡献,应被理解为一套可检验的知识分离机制,而非匿名万能证明。真实部署还必须证明运营独立、状态最小化、配置共用、密钥删除、重放安全和匿名集健康。

分析:把一项权力拆成两项不完整的能力

传统 HTTPS 解决的是链路上第三方能否读写内容,却常把两种信息同时交给服务端:连接来自哪个网络地址,以及连接里说了什么。对运维而言,这种完整视角很方便;对隐私而言,它也是一种集中权力。

OHTTP 换了一种安排。客户端先把请求编码成二进制 HTTP 消息,再根据网关的公开配置,用 HPKE 封装。封装后的对象通过 HTTPS 交给中继。中继接到了客户端连接,知道它要发往哪个网关,却没有打开消息的私钥。中继另建一条 HTTPS 连接,把密文交给网关。网关解封装后取得请求明文,再访问目标资源;在网关眼里,上游是中继,而不是原始客户端。响应沿相反方向封装返回。

所以,这套机制不是“数据不存在”,而是“完整观察者不应存在”。中继掌握网络意义上的“谁”,网关掌握应用意义上的“什么”,任何一方都不该独自回答“谁说了什么”。

RFC 9458 对此写得很明确:若要达到所述隐私目标,中继和网关不能属于同一实体。困难在于,生产系统中的“实体”并不等于两个域名、两个容器或两张架构图方框。两套服务可能由同一管理员控制,写入同一日志平台,接受同一事故处置账号,或者属于两家在合同上可以自由交换原始数据的供应商。

RFC 明示的是角色不得合一;进一步要求法律主体、管理权限和数据路径保持足够独立,是本文基于运行机制作出的运营判断。这个判断不能冒充规范原文,却是审计必须回答的问题。如果来源日志和明文日志最终能在同一查询里按时间拼接,那么协议在传输途中拿掉的连接,已经被运维系统重新制造出来。

把作者放回共同创作与明确假设之中

RFC 9458 于 2024 年 1 月作为 IETF 标准轨文档发布,署名作者是 Martin Thomson 与 Christopher A. Wood。本文在 2026 年 9 月 1 日留存的 IETF Datatracker 页面,将 Wood 介绍为在 Apple 从事密码工程的工程师,并列出其名下 24 份 RFC,其中包括 RFC 9458。这些是采集时点的公开信息,未来可能变化;它们既不表示 Wood 独自发明 OHTTP,也不表示他控制或担保任何具体部署。

在最终 RFC 发布前,Wood 与 Jonathan Hoyland 还共同撰写过一份 Cloudflare 形式化分析说明。他们用 Tamarin 建模协议消息、密钥和攻击者能力。模型允许攻击者观察网络,并在中继与网关之间自适应攻陷一个角色;同时假定两者不串通,也禁止中继把可识别客户端的信息直接传给网关。

公开仓库保存了对请求和响应保密性、绑定、一致性、随机数使用等性质的验证。其不可链接结论有清楚边界:在模型内,如果攻击者同时知道查询内容和发到中继的加密连接,就意味着中继和网关两个角色都已被攻陷。作者同时提醒,这并不是一般意义上的不可区分性证明。直接推断和统计分析仍然可能利用现实流量。

这一区分非常重要。形式化证明可以审查代数模型中的消息是否按预期保护,却看不到一家公司的权限组、日志留存、共同承包商、司法披露路径,也看不到某个小地区只有一位活跃用户。它证明的是“在这些假设下,模型具有这些性质”,不是“凡是写着 OHTTP 的生产系统都已通过隐私审计”。

因此,Wood 的人物价值不在于借个人声望给产品贴上安全标签,而在于把隐私承诺缩成了可以定位的边界:两种知识必须被不同角色持有,且任何人都不能悄悄把它们重新合并。

网关不是目标资源,密钥分发也不是后勤工作

OHTTP 的端到端保护止于网关,而非客户端真正想访问的目标资源。网关解开消息后,决定如何把请求送给目标,也能够决定返回给客户端的内容。客户端与网关之间有消息级认证和机密性,客户端与目标之间却没有通过这层机制建立同样的直接关系。

这意味着客户端必须知道:哪一个网关被授权代表哪一个目标;它拿到的网关密钥配置来自谁;配置有没有被替换。把密钥分发视为外围后勤,会漏掉真正的信任入口。谁能替换配置,谁就能改变明文出现的位置。

常见的目标证书固定策略也不能原样穿过这套中介结构。应用必须另行界定网关可访问的目标范围、目标如何验证网关来源、网关与目标若属于不同来源时如何使用 HTTPS,以及错误响应由谁负责。OHTTP 能让目标不直接收到客户端网络地址,却不应被说成客户端已经直接认证了目标。

配置还可能成为隐形身份证。如果每台设备拿到不同的网关密钥或参数组合,密码学完全正确也没有用:唯一配置本身就能追踪设备。每个活跃配置都会切分匿名集。轮换时若新旧配置重叠太短,按版本、地区或账户分出来的小群体也会暴露身份。

因此,配置审计不能只看签名是否有效,还要看每套配置由多少活跃客户端共享、持续多久、通过什么渠道下发、是否按账户定制,以及旧私钥是否真正删除。

明文里的一枚 Cookie 可以绕过整座架构

设想中继与网关在组织上完全独立,也从不交换日志。客户端却在封装内容里放进账户 Cookie、授权头、设备编号或稳定的分析标识。网关无需知道 IP 地址,也能直接认出用户。传输层的不可链接性没有被破解,而是被应用层绕过。

RFC 9458 明确指出,只有当应用内容不携带可关联状态时,这种传输不可链接性才有意义。检查对象必须是进入 HPKE 之前的真实二进制消息,而不是产品文档里写着“匿名”的接口。SDK 可能自动加头,重试逻辑可能带回诊断令牌,语言、地区和设备能力的稀有组合也可能构成稳定指纹。

成功路径并不代表失败路径安全。第一次请求可能没有 Cookie,超时后却附带一个永久错误编号。正常响应不设置状态,反滥用模块却返回仅属于这台设备的挑战值。隐私测试需要覆盖首次请求、错误、超时、重试、升级和版本回退。

中继也有对应义务:不能用 Via 或 Forwarded 把客户端标识带到网关。若客户端确实把可识别信息交给中继,则必须有理由相信中继会去除它。最稳妥的做法,是让不必要的信息根本不进入这条路径。

所谓“无状态”,应当是一份字段清单和抓包验证结果,而不是架构图上的形容词。它要回答每个字段能否跨请求稳定、能否被其他数据集连接、谁批准它存在,以及删除后会损失什么功能。

新的加密上下文与新的业务动作不是一回事

RFC 9180 规定的 HPKE 通过密钥封装、密钥派生和认证加密建立保护上下文。RFC 9458 要求每个请求使用新上下文。复用上下文可能让请求彼此关联,在相关故障条件下还可能让中继接触本应保密的内容。这不是可以用性能收益抵消的小瑕疵。

重试也必须建立新上下文,但“重新加密”不等于“可以重新执行”。客户端超时,只能说明它没有收到响应,不能说明网关没有处理第一份请求。若请求修改账户、提交表单或触发付款,第二次发送可能产生第二次效果。

服务端或应用需要拒绝重放,或者保证重复执行不会增加效果。自动重试应建立在一个明确的未处理信号上,而不是猜测。封装密钥值可以作为重放检测的随机标记;时间字段可以缩短窗口,却带来时钟同步、容忍范围和状态留存问题。RFC 8470 提供了 HTTP 早期数据重放的相关词汇,但不会替 OHTTP 应用决定业务幂等性。

网关长期密钥还有另一条时间边界。在一套密钥配置存续期间,OHTTP 本身不提供跨整个周期的前向保密。如果私钥后来泄露,攻击者又掌握了相关流量或取得中继配合,就可能打开这一配置下的历史请求与响应。

轮换只能缩短暴露窗口,删除才决定窗口是否真正关闭。活动节点换了新密钥,并不代表旧密钥已从备份、调试包、崩溃转储和事故系统里消失。一个可信的轮换记录应同时包含签发、分发、激活、过渡、过期、各副本删除和删除验证。

HTTPS 保护字节,却不会让所有流量长得一样

客户端到中继、中继到网关都必须使用 HTTPS。这能阻止许多旁观者读取或修改转发对象,却不会隐藏时间、大小、顺序、消息边界和总量。

在每秒有大量相似请求的系统里,一个事件可以混入人群。若某地区五分钟只有一位用户发送了一条很大的请求,中继端出现一次特征大小,网关端紧接着出现相似对象,观察者不需要解密就能推测它们相连。响应长度和周期性还会增加把握。

填充可以降低大小差异;延迟、抖动与批处理可以模糊时间。每项措施都要付出带宽、响应速度和实现复杂度。高峰期临时关闭填充并非纯性能优化,而是隐私级别变化,应该进入变更记录与用户承诺。

中继还可能主动缩小匿名集。选择性阻断、限速、优先转发和反滥用标签,都能把某类客户端单独分出来。即使没有解密,恶意或被攻陷的中继也可以通过差异化处理协助关联。

所以,匿名集不是注册用户总数,而是同一时间窗口、同一配置、同一路径上真正发出难以区分请求的人数。仪表盘若只显示“HPKE 成功率 100%”,仍可能掩盖某一条请求在流量形状上独一无二。

给“互不知情”建立可核验的收据链

一次成熟审计应先画出四列:客户端、中继、网关、目标。每列分别记录法律控制者、基础设施账户、管理员、分包商、所在地区、产生的日志、保留期限和事故权限。接着把所有跨列连接画出来:共同日志仓库、统一身份系统、支持工单、反欺诈模型、备份、监控供应商与司法响应流程。

客户端侧需要保存配置来源与验证、配置共享规模、明文字段清单、新 HPKE 上下文测试和重试语义。中继侧需要证明没有加入客户端标识头,来源日志已最小化,差异化转发不会变成标记通道。网关侧需要证明目标授权、明文留存限制、密钥轮换和旧密钥删除。目标侧则负责允许的网关、请求效果和重放控制。

事故演练不能笼统地写“服务被攻陷”。只攻陷中继,攻击者获得来源、时序和转发控制;只攻陷网关,获得明文、密钥和配置分区;攻陷共同日志平台,则可能直接获得完整连接。三者的隔离和处置不同。

Heng Lu 的“运行代码优先”提供了恰当尺度:把信用给实际执行的功能。OHTTP 的运行代码能分离可见性,却不能自动证明两家机构没有共用管理员。其“最小初始规范”观点说明,小而清楚的公共机制有利于自愿采用;反过来,地方实现也不能以便利为由抹去使公共机制成立的最小假设。

从这个角度看,隐私不是系统知道多少,而是它刻意保留多少不知道。中继不应知道内容,网关不应知道来源,分析平台不应替两者恢复全景,应用也不应塞进一个替代身份。

Christopher A. Wood 的这段人物故事,最终不是“密码学家让 HTTP 匿名化”的英雄叙事。它更值得被记住的部分,是把隐私从信任口号改写为职责分离:一项任何单一运营方都不该拥有的完整知识。最有说服力的部署证明也不该只写“我们使用 OHTTP”,而应展示为何没有任何一方能够同时回答——是谁发来的,以及里面说了什么。

来源