OCSP 响应与请求解码器
从 DER 文件、base64、PEM 或抓包得到的十六进制文本中读取 RFC 6960 消息,并按客户端看到的样子展开。对响应而言,先看 OCSPResponseStatus:只有 successful 才携带数据,因此六个字节的 tryLater 本身就是一份完整而合法的响应,它对任何证书都没有表态,把它当成被截断的文件是常见的误判。接着是响应方 ID 及其形式(按名称,还是按响应方密钥的 SHA-1 哈希)、producedAt,以及每条单证书响应中的 CertID、good/revoked/unknown 状态、thisUpdate、nextUpdate,若已吊销还有吊销时间与 CRLReason。值得一读的扩展会被解析成具体值而不是罗列 OID:请求与响应两级的 nonce、归档截止、CRL 引用,以及 extended-revoke —— 设置了它的响应方会对从未签发过的证书也返回 revoked,于是 unknown 的含义随之改变。本页还回答人们真正打开解码器时想问的问题。这份响应还新鲜吗:thisUpdate 与 nextUpdate 会与页面上显示的基准时刻比较,没有 nextUpdate 的响应会被明确标为"直到被取代前一直有效",而不是含糊地当作有效。响应方回送我的 nonce 了吗:把发出的请求粘进来即可比对,调试 stapling 时最常见的意外就是 nonce 不见了。是 CA 自己签的还是受委派的响应方签的:对随附的每张证书计算公钥哈希,与 CertID 中的 issuerKeyHash 比对;若是受委派的响应方却缺少 id-kp-OCSPSigning,则会给出警告,因为客户端必须拒绝这种响应。有两处局限值得直说。CertID 用签发者名称哈希、签发者公钥哈希加序列号来指代证书,无法反推出主体名称;本页也不验证签名,那需要签发者公钥,而页面并不持有。所以这里呈现的是字节所述,而不是信任判断。
使用方法
- 拖入 .der 文件,或把响应以 base64、PEM 或抓包的十六进制形式粘贴进来。所有解析都在页面内完成。
- 先看响应状态。凡不是 successful 的,都是一份完整而未签名的响应,不含任何证书状态。
- 查看证书状态表:good、revoked 或 unknown,旁边是 thisUpdate 与 nextUpdate,已吊销的还会给出吊销时间与原因。
- 注意时效那一行以及旁边的基准时刻。超过 nextUpdate 的响应,合规客户端会拒绝。
- 在最后一个输入框粘贴发出的请求,确认 nonce 是否回送;再看证书部分,确认受委派的响应方是否具备 id-kp-OCSPSigning。
常见问题
- 我的响应只有六个字节,是被截断了吗?
- 几乎可以肯定不是。OCSPResponse 是一个 SEQUENCE,第一个字段就是状态,后面的响应字节只有在状态为 successful 时才存在。因此 malformedRequest、internalError、tryLater、sigRequired、unauthorized 都是五六个字节的完整响应:没有签名,没有 producedAt,也没有提到任何证书。其中 tryLater 是响应方繁忙时的回答,客户端应当重试而不是当作校验失败。如果你在为 stapling 缓存响应,缓存到这种响应本身就是缺陷,下游从中学不到任何东西。
- CertID 为什么还在用 SHA-1?这是弱点吗?
- 因为它用于标识而不是认证。CertID 由签发者名称哈希、签发者公钥哈希和证书序列号组成,只是一个查找键,让响应方找到正确的记录;保护这份答复的是对整个响应的签名,而不是这些哈希。要做碰撞攻击,需要另一个签发者的名称哈希、密钥哈希乃至序列号都相同,攻击者由此得到的东西并不比别的途径更多。这就是 RFC 6960 在这里仍保留 SHA-1 的原因。反过来,如果响应本身用 SHA-1 签名,那才是真问题,本解码器会单独提示。
- 响应里没有 nextUpdate,那什么时候过期?
- 形式上不会过期。RFC 6960 规定,缺少 nextUpdate 意味着任何时刻都有更新的信息可用,该响应在被取代之前都可以依赖。实际中客户端会自设上限,但不少实现只要能解析就一直接受,而这正是重放攻击盯上的窗口。nonce 的意义也在这里:有了它,被截获的响应无法拿去回答后来的查询,因为答案绑定在客户端选定的值上。
- 响应方把我的 nonce 丢了,这份响应无效吗?
- 并非无效,这是调试时最常见的意外。大型公共 CA 会批量预生成响应并由 CDN 分发,这与逐个请求回送不同 nonce 的做法天然冲突,于是干脆省略;RFC 8954 甚至允许响应方忽略该扩展。响应依然有效,只是失去了"这是为我的查询而生成"的凭据,新鲜度只能依靠 thisUpdate 与 nextUpdate。把请求粘贴进来,本工具会告诉你 nonce 是回送了、被丢弃了,还是回送了另一个值——最后一种情况才真的意味着你看到的是别人查询的答案。
- unknown 和什么都没说的响应有什么区别?
- unknown 是一个明确的回答:这个响应方没有该序列号的记录,通常是因为证书由 CertID 所指之外的另一家 CA 签发,或者根本不存在。它不等于 good,客户端也不该那样处理。它同样不等于 unauthorized——后者表示响应方根本不为该证书作答。如果响应带有 extended-revoke 扩展,含义还会更窄:这样的响应方对从未签发的证书也返回 revoked(吊销时间为 1970 年初),因此它给出的 unknown 更接近"不在我的范围内"。
- 这个工具能告诉我响应对应哪张证书,或者验证签名吗?
- 前者做不到,后者刻意不做。CertID 是若干哈希加一个序列号,而哈希不可逆,所以要把响应和证书对上,只能对那张证书的签发者名称与公钥求哈希再比对——前提是你手上已经有证书。验证签名需要签发者公钥,本页面既不持有也不去获取,因此这里给出的是对字节的忠实解读,而不是信任结论。仅凭字节能确定的是签名者:对随附证书的公钥求哈希,与 CertID 的 issuerKeyHash 比对,就能区分是签发 CA 还是受委派的响应方。
相关工具
HTTP 状态码参考
可搜索的全部 HTTP 状态码(1xx-5xx)参考 — 含概要、RFC、使用时机与常见陷阱。
CRL 解码器 (X.509)
在浏览器中读取证书吊销列表:签发者、CRL 编号、有效区间、每个被吊销序列号及其原因,以及签名校验。
CSR 解码器 (PKCS#10)
在提交证书签名请求之前读懂它:主体、SAN、密钥长度、签名算法,以及自签名能否通过校验。
ASN.1 / DER 解码器
粘贴任意 DER 结构——PEM、base64 或 hex——即可查看它的 ASN.1 树:偏移量、标签、长度和解码后的值。
CAA 记录构建器 (DNS 证书颁发机构授权)
生成 DNS CAA (Certificate Authority Authorization) 记录,让只有你信任的 CA 才能为你的域名签发 TLS 证书。
PKCS#12 密钥库检查器
在浏览器里打开 .p12 / .pfx:输入密码前先看 MAC 和加密算法,输入后查看证书链、私钥,以及私钥与证书是否匹配。