前情回顾
近日在帮用户配置某协同办公软件内的SSO登陆页时,发现一个有趣的事情,在iOS以及PC端都可以打开的登陆页,却在安卓设备上出现了白屏的现象。
客户端的报错信息如下:
{... "Ssl_Err_Info": {proceed: false, sslError=primary error: 3, ...} ...}
这个primary error: 3的魔术数字是什么???
咨询了安卓的同学得到的答复是,这是系统预置的。
可以看到错误信息表示这个证书并没有被信任,那么造成证书在安卓端不被信任的原因是什么呢?
概念补充
在Chrome浏览器中查看网站证书时,可以看到大多证书都是三级结构
1. DigiCert Global Root CA 根证书,会在我们的设备中存储
2. Encryption Everywhere DV TLS CA - G1 中级证书(Intermediate Certificate)
- 证书颁发机构(CA)不会直接使用根证书颁发服务器证书,因为这种行为是十分危险的,因为一旦发生错误颁发或者需要撤销root,则使用root签名的每个证书都会被撤销信任。 于是,为了保护根证书,CA机构会颁发中级证书,使中级证书也受到信任。接着,CA机构使用中级证书颁发终端用户的服务器SSL证书。
3. *.juejin.cn 服务器SSL证书
- 通常ngnix会配置后缀为pem的证书文件,格式以“-----BEGIN CERTIFICATE-----”开头,以“-----END CERTIFICATE-----”结尾。
校验规则
在我们访问 https 的站点资源时,虽然服务器已经配置好了相关的证书,但浏览器如何能够验证该证书的有效性呢?浏览器会收到证书本身以及与证书关联的公共密钥。它使用公钥验证数字签名,并查看签名者是由什么证书签名,并且超上一个链接移动,继续对上一个签名进行身份验证,并跟踪签名它的证书的链——直到最终它到达浏览器信任库中的根证书之一。如果无法将证书链接回其受信任的根目录之一,则它将不信任该证书。
整个过程就是一个证书链。
即 Server certificate -> Intermediate certificate(中级证书, 这中间可能会链接到另一个中级证书)-> Root certificate 。
根证书都会在我们的设备里/浏览器预置,那么中级证书的来源是哪里呢?一般来说,在我们配置服务器中的证书中,就会包含中级证书的信息。详细解释可以参考阿里云的证书格式说明。
但如果配置的证书里没有包含中级证书信息(也就是证书链不完整)会出现什么情况呢?以下会分两种情况说明。 这里有一个网站 incomplete-chain.badssl.com/ 就是一个未配置完整证书链的样例。
AIA fetching / 浏览器缓存
我们会注意到如果用Chrome浏览器打开 incomplete-chain.badssl.com/ ,浏览器并不会报出此网站证书不受信任,也就是说浏览器校验通过了该网站的整条证书链。
那么浏览器是怎么校验到中级证书的呢?我们可以把该网站的证书下载下来,通过以下工具来查看证书信息。
openssl x509 -inform der -in \*.badssl.com.cer -noout -text
这里的Authority Information Access是SSL证书中的特殊扩展,其中包含有关证书签发人的信息。浏览器通过这里的信息就可以获取到中级证书,从而补全整个证书链通过校验。如果浏览器之前有下载过同样的中级证书,也会缓存下来以便之后校验。
证书链不完整而导致服务器的证书不受信
postman警告
还是同样的网站 incomplete-chain.badssl.com/ ,如果我们用postman发送GET请求会是什么样的呢?
postman对于该域名的响应给出了Unable to verify the first certificate的警告。
安卓webview白屏
上边提到安卓客户端内打不开时,iOS和PC端都是可以打开的,这样的差异是因为不同客户端上对于权限信息访问(AIA)的处理策略不同。像大部分浏览器都会根据证书内AIA extension信息去下载证书完成证书链的校验,但不同于其他平台,Android 客户端默认是不会通过 AIA Extension 去做证书链的校验。
如何修复
这里推荐一个检查网站安全性的工具 myssl.com/
在这里输入网站域名后,如果证书链不完整,则会有以下提示。
继续往下流览,我们可以看到中级证书的信息是缺失的
因为证书信息都是公开的,点击右上角的下载证书链,一份包含中级证书的完整证书信息就会自动生成出来。可以用此证书信息替换掉服务器上配置的证书信息,一条完整的证书链就被补充好了。
小结
- 在配置服务器的SSL证书时,将中级证书信息也添加进去,构成完整的证书链
- AIA fetching 可以将不完整的证书链补全,从而通过校验
- 安卓系统webview默认不会通过AIA extension去做证书链的校验