通过ocsp验证指定cert的流程

5 阅读4分钟

通过ocsp验证指定cert的流程

ocsp_verify(目标证书)流程

我想通过ocsp去验证一个证书的吊销状态,我对这个证书使用ocsp_verify(目标证书)这个流程,我只聚焦其中一部分我认为重点的验证过程,同时忽略一些常规验证。

ocsp_verify(目标证书)流程:

发起ocsp,获得response。

一些快速验证:

如果验证不通过则立即向调用者返回结果

验证id-pkix-ocsp-nonce:

如果验证不通过则立即向调用者返回结果

验证thisUpdate/nextUpdate/producedAt:

如果验证不通过则立即向调用者返回结果

验证responderID对应的证书:

首先用responderID从“certs+本地”范围中匹配response的签名证书出来,然后看这个证书:

  1. 情况 A(CA 亲自签名):该证书的公钥与目标证书的 Issuer的公钥完全一致(CA的原版/交叉签名版证书)。
  2. 情况 B(CA 委派签名):该证书由目标证书的Issuer直接签署,且该证书带有 id-kp-OCSPSigning 扩展。
  3. 其他情况:一律表示验证失败,向调用者返回结果。

接着使用“边构建边验签”的方式进行候选链构建:

对于候选链,我们从trust anchor的下一级证书开始逐一向下验证吊销状态:

  1. 在本地就能得出证书的吊销状态
  2. 需要发起ocsp请求来验证,于是挂起当前验证流程,执行ocsp_verify(当前验证证书),并等待其返回结果。

在当前ocsp_verify()流程下,如果发生“某个证书得出被吊销的结果”或者其他错误时,可以尝试从dfs拿下一条候选链,再次进行吊销验证。如果可用候选链中 没有任何一条得出“未吊销”的结论,则将验证结果(吊销或者其他错误)返回给调用者。

否则继续验证下级证书。如果整个链验证通过,则将未吊销的结果返回调用者。调用者会继续它的验证流程。

内部调用的ocsp_verify()会将结果依次返回到最外层的ocsp_verify(),于是我们此时可以根据结果判断:

  1. 证书吊销
  2. 证书未吊销
  3. 验证失败

证书循环检测:

“dfs边构建边验证签名”这个流程中包含证书循环检测

本地验证:

  1. 通过本地手段获取证书吊销状态;例如缓存/本地下载好的CRL/CRLSets/OneCRL
  2. 本次验证(验证最开始那个证书)中共享的证书信任状态

ocsp_verify()流程的递归执行:

观察ocsp_verify()流程可知,当某个ocsp候选链中的证书不能在本地得出吊销状态,我们得挂起当前链的验证,为这个证书发起ocsp_verify()流程 (为了验证ocsp链1中的A证书,我得先验证ocsp链2)。在ocsp链2中也可能会发生递归情况。

如果一个验证证书的吊销状态不需要发起ocsp请求,那么可能是如下几种情况:

  1. 这是一个ocsp证书,并且带有nocheck扩展;或者,
  2. 本地就能得出吊销结论;或者,
  3. 需要发起ocsp请求,但是被约束阻止(例如全局扩展计算器或者其他类似的约束)
  4. trust anchor

ocsp_verify()流程内部会递归自身,它的终止条件是:

  1. 整个ocsp链验上的每个证书都被验证过,得出最终结论(吊销/未吊销)
  2. 在验证过程中发生错误,需要停止当前链验证
  3. 约束导致的验证停止
  4. 如果当前证书是trust anchor,停止对它的验证流程。

nocheck扩展解释:

【主链验证】
Trust Anchor -> CA1证书 -> CA2证书 -> 目标证书(EE)
                  │
                  └─► 签发 【OCSP签名证书】(带有nocheck扩展)

nocheck扩展只能在ocsp证书中使用,它表示这个ocsp证书不用进行吊销验证;对于链上的其他证书(如CA1证书/CA2证书),依然需要被吊销验证(本地或者ocsp)。

ocsp候选链上证书的验证顺序:

关于吊销状态,rfc 5280中没有规定候选链上证书吊销状态的验证顺序,但是在实践中采用自顶向下的顺序

证书链吊销验证方向

  • rfc规定从trust anchor的下一级证书开始向下验证吊销状态
  • 实践中可能会出现从底部开始依次向上验证吊销状态的情况