通过ocsp验证指定cert的流程
ocsp_verify(目标证书)流程
我想通过ocsp去验证一个证书的吊销状态,我对这个证书使用ocsp_verify(目标证书)这个流程,我只聚焦其中一部分我认为重点的验证过程,同时忽略一些常规验证。
ocsp_verify(目标证书)流程:
发起ocsp,获得response。
一些快速验证:
如果验证不通过则立即向调用者返回结果
验证id-pkix-ocsp-nonce:
如果验证不通过则立即向调用者返回结果
验证thisUpdate/nextUpdate/producedAt:
如果验证不通过则立即向调用者返回结果
验证responderID对应的证书:
首先用responderID从“certs+本地”范围中匹配response的签名证书出来,然后看这个证书:
- 情况 A(CA 亲自签名):该证书的公钥与目标证书的 Issuer的公钥完全一致(CA的原版/交叉签名版证书)。
- 情况 B(CA 委派签名):该证书由目标证书的Issuer直接签署,且该证书带有 id-kp-OCSPSigning 扩展。
- 其他情况:一律表示验证失败,向调用者返回结果。
接着使用“边构建边验签”的方式进行候选链构建:
对于候选链,我们从trust anchor的下一级证书开始逐一向下验证吊销状态:
- 在本地就能得出证书的吊销状态
- 需要发起ocsp请求来验证,于是挂起当前验证流程,执行ocsp_verify(当前验证证书),并等待其返回结果。
在当前ocsp_verify()流程下,如果发生“某个证书得出被吊销的结果”或者其他错误时,可以尝试从dfs拿下一条候选链,再次进行吊销验证。如果可用候选链中 没有任何一条得出“未吊销”的结论,则将验证结果(吊销或者其他错误)返回给调用者。
否则继续验证下级证书。如果整个链验证通过,则将未吊销的结果返回调用者。调用者会继续它的验证流程。
内部调用的ocsp_verify()会将结果依次返回到最外层的ocsp_verify(),于是我们此时可以根据结果判断:
- 证书吊销
- 证书未吊销
- 验证失败
证书循环检测:
“dfs边构建边验证签名”这个流程中包含证书循环检测
本地验证:
- 通过本地手段获取证书吊销状态;例如缓存/本地下载好的CRL/CRLSets/OneCRL
- 本次验证(验证最开始那个证书)中共享的证书信任状态
ocsp_verify()流程的递归执行:
观察ocsp_verify()流程可知,当某个ocsp候选链中的证书不能在本地得出吊销状态,我们得挂起当前链的验证,为这个证书发起ocsp_verify()流程 (为了验证ocsp链1中的A证书,我得先验证ocsp链2)。在ocsp链2中也可能会发生递归情况。
如果一个验证证书的吊销状态不需要发起ocsp请求,那么可能是如下几种情况:
- 这是一个ocsp证书,并且带有nocheck扩展;或者,
- 本地就能得出吊销结论;或者,
- 需要发起ocsp请求,但是被约束阻止(例如全局扩展计算器或者其他类似的约束)
- trust anchor
ocsp_verify()流程内部会递归自身,它的终止条件是:
- 整个ocsp链验上的每个证书都被验证过,得出最终结论(吊销/未吊销)
- 在验证过程中发生错误,需要停止当前链验证
- 约束导致的验证停止
- 如果当前证书是trust anchor,停止对它的验证流程。
nocheck扩展解释:
【主链验证】
Trust Anchor -> CA1证书 -> CA2证书 -> 目标证书(EE)
│
└─► 签发 【OCSP签名证书】(带有nocheck扩展)
nocheck扩展只能在ocsp证书中使用,它表示这个ocsp证书不用进行吊销验证;对于链上的其他证书(如CA1证书/CA2证书),依然需要被吊销验证(本地或者ocsp)。
ocsp候选链上证书的验证顺序:
关于吊销状态,rfc 5280中没有规定候选链上证书吊销状态的验证顺序,但是在实践中采用自顶向下的顺序
证书链吊销验证方向
- rfc规定从trust anchor的下一级证书开始向下验证吊销状态
- 实践中可能会出现从底部开始依次向上验证吊销状态的情况