聊一聊openssl校验证书链的流程


简单描述下业务场景,我们期望使用X.509证书来实现对终端设备的授权。
首先在终端设备内置根证书,当终端收到服务端下发的授权证书后,使用内置根证书对授权证书进行验证,验证通过即代表授权证书是由服务端所颁发。
在根证书和授权证书中间也可能存在多个中间证书,有多个证书的情况下对证书进行合并后下发。

假设已有证书的签发顺序如下:

根证书root.pem -> server.pem -> device.pem

第一轮尝试验证

// 合并证书服务证书与终端授权证书
cat server.pem device.pem > app.pem
// 使用根证书对授权证书链进行验证
openssl verify -CAfile root.pem app.pem
// 输出
app.pem: OK

得到的结果是验证通过,看上去符合预期的结果。

但是,随着继续测试问题就出现了

// 合并一个完全不相干证书作为三级证书
cat server.pem other.pem > app.pem
// 再次使用根证书进行验证
openssl verify -CAfile root.pem app.pem
// 输出
app.pem: OK

得到的结果依然是通过验证。。。
最终经过几次测试得出结论,验证合并的多张证书时,其实还是只验了证书链中的第一个证书。
这很显然不符合我们的需求。

预期的流程图如下,但灰色部分并未执行

第二轮尝试验证

我又做了些尝试,这次使用合并后的证书作为CAfile,去验证device证书,如下:

// 合并服务器证书与根证书
cat server.pem root.pem > ca.pem
// 使用合并后的CA验证终端授权证书
openssl verify -CAfile ca.pem device.pem
// 输出
device.pem: OK

得到的结果是通过,符合预期。
紧接着我又又测试了

// 合并一个毫不相干的证书到CA证书链顶部
cat other.pem server.pem root.pem > ca.pem
// 测试验证终端授权证书
openssl verify -CAfile ca.pem device.pem
// 输出
device.pem: OK

得到的结果依然是通过,这。。。
再经过多次测试后,发现ca.pem中的证书集合在验证时,如果其中任何一个验证成功,则直接返回,不再对后续证书进行验证,因为这时已经可以确认device与root的关系。

流程如下图:

每次在CA证书链对授权证书进行验证时,都需要先对自身链上证书进行校验,通过后再对授权证书进行校验;
第1、3、5步,任何一步校验失败,则说明CA证书链有问题,直接返回失败;
第2、4、6步,任何一步校验成功,则说明在证书链找到了device的签发者,直接返回成功。

我们的目标是保证从根证书到授权证书这条线的安全,目前已经基本满足了需求。
在测试的过程中还发现一些其他问题,比如说如果未设置basic constraints属性,在Ubuntu系统下会报error 24 at 1 depth,Ubuntu对证书的算法也要求严格,需要使用SHA256等等。

声明:不知|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - 聊一聊openssl校验证书链的流程


If it hurts, do it more often.