首页 >> 大全

引 - 我也没想到在神策数据这大半年能遇到好几次和证书相关的问题。

2023-12-20 大全 20 作者:考证青年

由于证书总是由某个证书颁发机构( ,或 ,简写成 CA)签发的,如果我们事先将一批可信的证书颁发机构存储在本地,就可以在发起请求的时候判断证书是否可信了。

有时情况会更复杂一些:某些机构不在我们的列表里,但他的证书是由我们信任的某个机构颁发的,我们也认为他是可信的,因此他颁发的证书也是可信的。

于是这就构成了一个信任链,链的末端是「根证书颁发机构」(Root CA),这些机构通常是国际上公认可靠的大型机构,或者国家权威机关背书的机构。

理解了这点,就可以推测,应当是我们服务器上的机构列表没有及时更新;只要把该客户证书的颁发机构加入本地的列表就应该能解决该问题。

- 解 -

再细看上面curl 命令的输出,有一行: /etc/pki/tls/certs/ca-.crt,这就是 curl 使用到的证书颁发机构列表。

以为例,我们可以通过如下命令获取客户证书的信任链:

$ openssl s_client -showcerts -servername server -connect www.baidu.com:443 > cacert.pem

在得到的.pem中,我们可以看到如下内容(略作简化):

Certificate chain0 s:/CN=baidu.comi:/CN=GlobalSign Organization Validation CA-----BEGIN CERTIFICATE-----
MIIKQDCCCSigAwIBAgIM...o93DCwUAMGYxCzAJ
...(略)...
n3XcFtwQLBY9Iuqh8M...hZcFBCBAeUoRhDC
-----END CERTIFICATE-----1 s:/CN=GlobalSign Organization Validation CAi:/OU=Root CA/CN=GlobalSign Root CA-----BEGIN CERTIFICATE-----
MIIEaTCCA1GgAwIBAgILB...ELBQAwVzELMAkG
...(略)...
K1pp74P1S8SqtCr4f...yHDPSsQPhZSZg=
-----END CERTIFICATE-----...(略)...

可以看到里面有两段用--BEGIN --和--END --包起来的 编码字符串,这就是被编码为 PEM 格式( Mail)的证书了(有时也会用 .crt 作为扩展名)。

在 BEGIN 前面有一些摘要,可以帮助我们了解证书的内容,比如s:/CN=表示这个证书的主体(s 即 )是 (CN 即 name),i:/CN=表示它的颁发机构(i 即 )是 。

因此可以看到,这个.pem实际上包含了两个证书,一个是百度使用的证书,另一个是颁发该证书的 这个机构(CA)自己的证书。

通过curl -- .pem 我们可以确认,这个信任链能用来验证 的证书(实际上我们只需要里面第二个证书,将第一个证书删除,不影响 curl 的执行)。

回到该客户的情况,我们用相同的方法取得客户证书颁发机构的证书,将它放到/etc/pki/ca-trust///目录,执行-ca-trust将其加入到证书列表中,就可以正常使用 curl 命令来请求了。

- 然 -

没有「但是」的文章不是好文章。

引 - 我也没想到在神策数据这大半年能遇到好几次和证书相关的问题。_引 - 我也没想到在神策数据这大半年能遇到好几次和证书相关的问题。_

curl 正常了,但是我们的 Java 代码依然报错,这说明 java 和 curl 使用了不同的 CA 列表。

问题倒是好解决,简单搜索一下,就了解到 jre 的证书是存放在$/jre/lib//这个文件里,需要使用专门的 工具来更新它:

$ keytool -import -trustcacerts -file cacert.pem -alias 证书颁发机构的名称 -keystore $JAVA_HOME/jre/lib/security/cacertsEnter keystore password:  changeit (这是jre自带的默认密码)Certificate was added to keystore

再次验证,Java 代码就可以正常运行了。

注:如果想要单独验证某个证书,可以这样

先创建一个空的 (密码为 ):

$ keytool -genkeypair -alias boguscert -storepass storePassword -keypass secretPassword -keystore keystore -dname "CN=Developer"
$ keytool -delete -alias boguscert -storepass storePassword -keystore emptyStore.keystore

添加证书到该 :

$ keytool -import -trustcacerts -file cacert.pem -alias 机构名称 -keystore keystore

指定 启动 java 程序:

$ java -Djavax.net.ssl.trustStore=keystore -Djavax.net.ssl.trustStorePassword=storePassword -cp $CLASS_PATH CLASS_NAME

- 劫 -

不巧的是,这周又遇到了一个证书信任的问题,这次是客户的环境向我们的服务器发起请求,报了相同的错误。

有了前车之鉴,上面这些命令执行起来可谓得心应手,但是这次却不灵了。

排查过程比较琐碎,也因为陷入思维定势而走了一些弯路,但其实原因很简单,这里就不卖关子了。

这家客户是一家泛金融类的企业,其生产环境的网络安全级别非常高,不仅有严格的外网访问限制,而且针对所有 https 请求都会默认劫持,用一个自签名证书返回错误信息。

引 - 我也没想到在神策数据这大半年能遇到好几次和证书相关的问题。__引 - 我也没想到在神策数据这大半年能遇到好几次和证书相关的问题。

经过与客户沟通,将神策数据的域名添加到白名单后,问题得以解决。

- 故事 -

讲完了事故,再讲讲故事。

非对称加密、证书、信任链这一系列发明,构成了现在 web 通信安全的基石,很难想象如果没有这些基础设施,现在互联网还能做些什么。

但是这里隐藏了一个大bug:我们凭什么相信本地这些证书颁发机构是可信的?

至少有三种情况会打破这个假设:

1. 本地 CA 列表被污染

可能你的电脑/手机被病毒导入了 CA 证书;或者你自己可能就做过这个事情,比如公司网管要求添加公司的自签名证书,又或者你为了能使用 来抓 https 请求,导入了它自签名的 Root CA 证书。

2. 机构的私钥泄漏

我没有在公开渠道查到相关的事故(倒是有一个代理商把客户证书的私钥给泄漏了);如果某个机构的私钥泄漏,这家机构应该离倒闭也不远了。

3. 看起来正经的机构也可能不正经

各国政府控制的 CA 机构大概都干过些「不干净」的事情(至少有这种冲动),有一些被发现了,有一些还没有。出于本文的安全考虑,这里就不展开细节了。此外,「不被政府控制」的那些机构,就一定干净么?说到底,机构总是被所在国管辖的,当遇到政府行政命令的时候,不一定有反抗的能力。

综上,理论上并不存在 100% 可靠的通信安全方案。

如果你的应用对通信安全要求非常严格,连本地的 CA 列表都不相信,可以考虑加入更多的手段来提高通信的安全等级。

简单一点的场景(例如 app 不想被抓包破解协议),可以自己校验服务器的证书(证书指纹,或者自己指定证书颁发机构列表);要求更高的场景(例如需要访问内部控制系统),可以给客户端颁发证书,浏览器会在请求时提供证书用于校验,感兴趣的话可以参考这个不太完善的项目:

- 收 -

结尾照例做一个小结:

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了