最近在配置Android客户端的Https时,发现运维同事给我的公钥证书的有效期只有3个月,如果直接使用这个证书对Https进行配置,那么三个月以后,线上的App就会因为证书过期,造成所有Https请求失败,进而无法从服务器获取数据,这是完全不能接受的。
可能这个问题不是很普遍,其一,运维同事提供给你的证书可能有效期很长;其二,如果给你的是中间证书或者根证书,这些证书有效期本身就比较长,但是毕竟我遇到了,还是准备和大家分享一下,帮助遇到此坑的同学成功爬坑。
文章以问答的形式展开,总共涉及三个问题。因为这块其实涉及的知识面很广,我还没有完全掌握,有些地方也只是了解的程度,所以有说的不对的地方,还望指正。但是按照文章进行配置,成功解决上面的问题还是没问题的。
一、为什么App需要在本地对Https做单独的证书配置?
在SSL/TLS握手的过程中,需要对服务器发送过来的公钥证书进行校验,判断证书是否有效。
按道理,如果这个证书是一个被广泛认可的CA机构签发的证书,因为该机构的“根”证书可能已经存储在Android系统中,那么在证书验证的过程中,通过证书链链接到对应的根证书,就可以完成验证。这种情况不需要自己在app本地配置证书。
那在什么情况下需要在App本地配置证书呢?
目前我遇到的情况有两种:
- 服务器公钥证书使用的是自签名证书
- 服务器公钥证书使用的是根证书未被浏览器接受的CA机构签发的证书(比如Let's encrypt)
为什么在这两种情况下需要在App本地配置证书呢?
简单来说,这两种情况如果不在App本地配置证书,HTTPS的SSL/TLS握手过程就不会成功,HTTPS连接就不能够建立。那么为什么握手不能成功呢?因为签发这两种证书的CA机构,其根证书并不在公认的可信任范围内,所以其根证书并不会默认存储在Android系统中。在SSL/TLS握手过程中,当服务器将其公钥证书发送给App后,这个公钥证书在证书链验证过程中,由于不能链接到系统自带的根证书,从而造成证书校验失败,进而造成SSL/TLS握手失败。
所以在上面两种情况下,就需要在App本地配置“证书”,协助完成握手过程中的证书校验。
二、如何配置以及为什么这么配置?
配置其实很简单,网上有不少文章,这里就不详细介绍了,推荐张鸿洋的文章: 。
公钥证书我了解的有两种验证方式。一种是证书链校验,通过该公钥证书链接到系统保存的根证书,说明证书有效;另一种是对比App本地存储证书的编码与服务器发送证书的编码,如果一致,说明证书有效。
关于第二种验证方式,读过源码,不过因为实在涉及的知识面太广了,没能整的太明白,有兴趣的同学可以看看JDK中PKIXValidator
这个类,它里面有个方法叫
engineValidate()
, 其中有一个if (trustedCerts.contains(cert) ...
语句。 综上一和二所述,自签名证书和“小”CA机构(其实一点都不小,有的很大)签发的证书,为了验证其有效性,必须在App本地为校验过程提供所需的证书。
三、解决证书有效期短的问题
按照上面第二个问答的说法,我们分两种情况进行分析。假设App本地保存的证书为A,服务器在握手阶段发送给App的证书为B,证书B到其根证书链路上的证书为C。
第一种 通过证书编码对比进行证书校验
这种方式下,如果证书A有效期较短,就会遇到与我一样的问题。那么很简单,我们只要使用一个有效期长一点的证书替换即可。
但是问题来了,编码比对方式下,App本地保存的证书A只能是与服务器在握手阶段发送给App的证书B相同的证书,即A必须与B是同一个证书,这就限制了可用证书的数量,如果B有效期短,我们就没有办法将A替换为一个有效期长的证书。
第二种 通过证书链进行证书校验
这种方式下,因为只要App本地保存的证书是证书B到其根证书链路上的任意一个证书,在SSL/TLS握手阶段都能成功完成证书校验,所以App本地保存的证书有很多个可选,只要找到其中一个有效期够长的即可。一般选择中间证书或根证书比较合理。
综上所述,其实只要按照网上配置Https证书的文章进行正常配置,然后选择一个有效期长的证书放到App中即可解决问题。
四、结语
像我们公司使用CA机构的是LetsEncrypt,按道理只要将LetsEncrypt的根证书放到App本地即可,但是实际操作过程中发现网络请求因为没找到根证书失败了,真是邪门了。仔细分析后发现,因为LetsEncrypt的根证书在浏览器中是不被默认支持的,所以我们的公钥证书并不是直接使用LetsEncrypt的根证书或中间证书(使用LetsEncrypt的根证书进行签名版本)进行签名的,而是使用的LetsEncrypt颁发的由机构IdenTrust交叉签名的中间证书。在我把这个中间证书放到App中后,网络请求ok,有效期短的问题解决。
LetsEncrypt根证书和中间证书的下载地址:
希望通过这个文章,能够给第一次做相关工作的朋友提供一些帮助。