摘要
- OCSP 装订响应,是授权响应者针对一个 CertID、在明确时间点作出的签名陈述。签名能证明陈述来自谁,不能证明响应者已经看到后来发生的每一次撤销,更不能证明答案专为这次握手生成。
producedAt、thisUpdate与nextUpdate是三只不同的时钟;服务器获取、HTTP 缓存年龄、安装时间、客户端时钟和最大可接受年龄又增加了新的时钟。把它们统称为“有效期”会隐藏真实的重放与传播窗口。- TLS 只运送状态证据,后果由客户端策略决定。可辩护的接受结论必须同时保留 CertID、签名者授权、状态与时间、证书链覆盖、扩展协商、Must-Staple、软失败或硬失败以及运行中客户端的最终决定。
一份绿色答案越过了红色事件
响应者在 09:55 签出 good,服务器在 09:57 拉取并缓存。10:07,签发方系统记录撤销。四分钟后,客户端在新 TLS 握手中收到的仍是那份缓存对象。
签名验证成功,thisUpdate 没有越过客户端时钟,nextUpdate 也尚未到达。服务器没有改动任何字节。但这份答案当然不可能包含它签发之后才出现的事件。
把它叫作“假响应”,会把新鲜度问题误写成密码学问题;把连接叫作“已检查撤销”,则把一串有限权限的判断升级成了全局结论。应当追问的是:响应说了什么,由谁针对哪张证书、在哪个时间范围内说出,最终又由哪个客户端策略接受?
CertID 先界定问题对象
OCSP 并不回答“这个网站是否正常”。CertID 由签发者名称哈希、签发者密钥哈希、证书序列号和哈希算法组成。只有这些字段与待验证证书相符,响应才在对象上成立。
一份为另一个序列号签出的合法响应,不是较弱证据,而是回答了另一个问题。叶证书上的响应也不会自动覆盖中间证书。日志必须保留证书指纹、签发者、序列号、完整 CertID,以及响应挂在哪个证书链位置。
RFC 6960 对 good 的最低含义十分克制:当前处在有效期内、具有该序列号的证书,没有被记录为撤销。它甚至不必然证明该证书曾经签发,更不保证响应者已经吸收 thisUpdate 之后的事件。
因此,脱离对象的 ocsp=good 几乎没有取证权限。
签名授予陈述权,不授予全知
确定性的 OCSP 响应必须由证书签发者签名,或由签发者明确授权、带有 OCSP 签名用途的响应者签名。客户端既要验证密码学签名,也要验证这条授权关系。
这能回答“此密钥是否有权为该证书陈述状态”。它不能回答“握手发生时,此密钥是否已经得到签发系统的最新变化”。
未经授权的密钥即使签名数学上正确,仍然没有权限;经授权的响应者即使签名正确,也可能持有较早的状态视图。真实性与信息年龄是两条独立坐标。
生产证据应保存响应者证书、与签发者的关系、OCSP 签名授权、签名结果和原始响应哈希,不能只留下泛化的“证书链验证成功”。
三个协议时间,以及协议看不到的时间
producedAt 表示响应签名时间;thisUpdate 表示该状态最近一次被确认正确的时间;nextUpdate 表示不晚于何时会有更新信息。三者不是同一个“过期时间”。
RFC 6960 允许预先生成响应。RFC 9919 面向大规模部署的配置更明确地把缓存纳入设计,要求存在 nextUpdate,并要求客户端当前时间位于 thisUpdate 与 nextUpdate 之间。
运行系统还增加了签名对象里没有的时间:撤销登记、响应者摄取、HTTP Date 与 Age、服务器获取、缓存再验证、凭据安装、握手发生、客户端墙上时钟。监控还要保留单调时间,防止系统时钟回拨让旧答案看起来变年轻。
时钟偏差是受控容差,不是额外的新鲜度。超出偏差范围的未来 thisUpdate、已经过去的 nextUpdate,以及超过本地最大年龄的响应,都应成为独立失败原因。
nextUpdate 约束的是发布节奏,不保证撤销事件已经瞬间穿过签发者、响应者、HTTP 缓存、服务器内存和客户端策略。
缓存本来就在安全模型里
装订让服务器替客户端取得 OCSP 响应,减少每次连接的额外往返,保护客户端访问隐私,也避免让响应者可用性直接阻塞握手。复用不是偷懒,而是机制本身的设计属性。
RFC 9919 把 HTTP 缓存字段纳入运行约束:Date、Last-Modified、Expires、ETag 和 Cache-Control 可以控制复用与再验证,缓存寿命必须早于响应自身的更新时间边界。代理返回过期对象时,客户端可以用 no-cache 重试。
由此产生两个不同问题:响应是否满足签名时间字段?服务器手里的副本是否达到本地刷新承诺?前者属于客户端验证,后者属于服务端运行控制,不能互相代替。
服务器至少应记录来源、HTTP 头、原始哈希、获取时间、再验证结果、刷新期限和进入活动凭据的时间。若进程启动时载入有效响应,之后刷新任务停止,故障在客户端拒绝连接之前就已经发生。
共享装订无法变成逐握手 nonce
OCSP nonce 把请求和响应绑定起来,帮助请求者得到与新随机值对应的答案,而不是任意旧副本。RFC 8954 同时承认响应者可能省略 nonce,并以更短的有效区间缓解重放窗口。
一份要提供给大量客户端的装订响应,通常不可能携带每次握手各不相同的 nonce。它正是为了被缓存复用。这不表示装订不安全,而是说明其新鲜度权限来自签名时间、本地年龄上限与持续刷新,而不是“响应者刚为这个客户端生成”的证明。
因此,新握手只证明新的运送事件,不能被记成新的生成事件。
TLS 负责运送,客户端负责后果
TLS 1.2 及更早版本由客户端发送 status_request,服务器可通过 CertificateStatus 返回响应。TLS 1.3 把状态信息关联到证书条目。IANA 为 status_request 分配扩展值 5;status_request_v2 不用于 TLS 1.3。
这些机制证明协议可表达,不证明客户端接受。客户端仍需解析字节、匹配 CertID、验证签名者与授权、检查状态和时间,再决定失败是否终止握手。
“存在”不等于“成功”。BoringSSL 明确提醒,取到的是原始字节,不保证格式正确。OpenSSL 分别提供请求状态、服务端安装响应和客户端读取响应的接口。回调执行次数只能证明代码路径被触发,不能证明有效响应到达并通过检查。
“缺失”也不只有一种解释:客户端可能没有请求,连接可能是没有交换证书的恢复握手,服务器可能拒绝响应,证书可能有或没有 TLS Feature,客户端也可能软失败或硬失败。
所以证据必须保存 ClientHello 是否请求、完整或恢复握手、返回数量、链位置、逐项验证结果与应用最终看到的原因。stapled=true 只是清单字段。
Must-Staple 约束省略,不替响应作保
通常称为 Must-Staple 的 TLS Feature 用来抵抗静默降级。证书要求该特性时,服务器必须满足客户端的状态请求;若未满足,客户端可以拒绝连接。
这会改变“没有证据”的后果,避免攻击者或故障服务器把“必须有状态”降成“状态不可用但继续”。然而,有扩展不等于所有客户端都会执行同一硬失败策略。
Must-Staple 也不会让一份已出现的响应自动正确。CertID 不符、响应者无权、签名错误、时间不可接受、状态为 unknown 或明确 revoked,仍要各自失败。证书扩展只要求交付证据,OCSP 验证才决定证据能否采用。
负向测试必须同时覆盖“缺少必需响应”和“响应存在但无效”。只统计出现率,无法证明任何一种路径。
单个响应不能代表整条证书链
TLS 1.3 之前通常只装订叶证书响应;TLS 1.3 可以让多个证书条目带状态。OpenSSL 因此在旧 TLS 中暴露单个响应,在 TLS 1.3 中暴露与证书链对齐的响应栈,其中某些位置可以为空。
这不建立“所有中间证书都必须装订”的普遍规则,却要求观察者保留数量与位置。OCSP enabled 无法说明叶证书、中间证书或本地策略究竟覆盖了什么。
会话恢复还有一条边界。OpenSSL 说明,没有交换证书时不会调用状态回调。恢复连接可以按协议与实现复用先前认证状态,但不能被统计为一次新的证书与装订观察。
API 是管道,刷新才是运行控制
OpenSSL 分别提供查找 CertID、提取状态、按时钟偏差与最大年龄检查 thisUpdate/nextUpdate、验证签名与响应者权限的函数。没有一个函数单独拥有最终结论,应用必须组合它们并落实策略。
在不强制 nextUpdate 的场景中,本地最大年龄尤其重要。OpenSSL 警告,若缺少年龄上限,极老响应仍可能看起来可用。这个上限必须明确、可版本化并可观测。
GnuTLS 可以把 OCSP 纳入证书验证,并在 Must-Staple 下报告缺少状态。服务端仍要周期性更新。使用中的凭据对象只读,因此刷新可能需要创建新凭据并受控切换。
BoringSSL 建议在握手之外提前获取、配置并更新响应,而不要让回调临时访问网络。这能隔离响应者故障与握手延迟,却把安全权限转移给刷新调度、缓存和凭据切换。
真正应被审计的是运行事实:每个进程正在提供哪个响应哈希,何时安装,最后一次刷新是否成功,何时到达拒绝边界,哪些握手最终接受或拒绝。
用负向测试守住 good 的边界
提供一份签名正确但序列号错误的响应;使用没有签发者授权的响应者;把 thisUpdate 推到容差之外的未来;让代理返回过期响应并验证 no-cache 重试;移除 nextUpdate,确认本地最大年龄生效。
在稍后发生撤销后重放仍未过期的 good,测量真实接受窗口,而不是把它误称为伪造。省略 Must-Staple 要求的响应,提供损坏字节,只覆盖叶证书而缺少本地策略要求的中间证书。在 TLS 1.3 恢复会话中确认监控不会虚报新检查。
停止刷新任务,但先让握手继续成功。系统应在响应过期前告警。回拨墙上时钟时,单调年龄仍应增长。响应者离线时,握手不应在同步网络请求上阻塞;缓存证据不再可接受后,再按明确策略失败。
这组测试建立从对象身份、签名者权限、签名时间、缓存血缘、TLS 运送,到客户端验证和最终策略的证据阶梯。只有整条阶梯都存在,系统才有权限说“使用了当前可接受的状态证据”。
来源
- https://www.rfc-editor.org/rfc/rfc6960.html
- https://www.rfc-editor.org/rfc/rfc9919.html
- https://www.rfc-editor.org/rfc/rfc8954.html
- https://www.rfc-editor.org/rfc/rfc6066.html
- https://www.rfc-editor.org/rfc/rfc9846.html
- https://www.rfc-editor.org/rfc/rfc7633.html
- https://www.rfc-editor.org/rfc/rfc9325.html
- https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
- https://docs.openssl.org/3.6/man3/SSL_CTX_set_tlsext_status_cb/
- https://docs.openssl.org/3.6/man3/OCSP_resp_find_status/
- https://www.gnutls.org/manual/html_node/OCSP-stapling.html
- https://www.gnutls.org/manual/html_node/OCSP-API.html
- https://boringssl.googlesource.com/boringssl/+/refs/heads/main/include/openssl/ssl.h
- https://heng.lu/running-code-primary-the-patch-needed-to-preserve-the-internet-original-design/
会员简报
档案背景详情
使用相应会员等级登录,即可解锁完整简报与来源注释。
仅限 Strategic Circle
Strategic Circle
所有读者均可浏览。加入并登录后可解锁档案简报。
加入 Strategic Circle仅限 Leadership Alliance
Leadership Alliance
符合条件的 IP 资产所有者和管理层可登录查看 Leadership Alliance 简报。
加入 Leadership Alliance
