对于 HTTPS 服务器证书过期的问题,由于 Android 安全库的不断更新,尽管在证书验证的时候抛出的异常大同小异,但还是有一定的区别的。某些系统之间抛出的异常完全相同,另外的一些系统之间,抛出的异常则不太一样。
Android 4.1.1 、4.2.2、4.3
在 Android 4.1.1 、4.2.2、4.3 平台上,使用 OkHttp 3.4,访问一个 HTTPS 证书过期的网站时,OkHttp 将报出如下的异常:
|
|
在这几个 Android 版本上,遇到过期 HTTPS 证书时,OkHttp 抛出异常 javax.net.ssl.SSLHandshakeException: com.android.org.bouncycastle.jce.exception.ExtCertPathValidatorException: Could not validate certificate: current time: Wed Jun 07 23:08:11 EDT 2017, expiration time: Sun Jan 22 20:12:00 EST 2017
,在错误信息中会明确地指出是证书验证失败,并包含当前时间和证书的过期时间。
而这个过程,所有的网络包交互如下:
整个过程,包括 TCP 连接建立,SSL/TLS 握手,TCP ACK 以及 TCP 连接断开,总共只有 16 个包。
Android 4.4.4
在 Android 4.4.4 上,与前面执行相同的操作,将报出如下的异常:
|
|
在 Android 4.4.4 上,遇到过期 HTTPS 证书时,OkHttp 抛出异常 javax.net.ssl.SSLHandshakeException: com.android.org.bouncycastle.jce.exception.ExtCertPathValidatorException: Could not validate certificate: null
,与 Android 4.1.1 、4.2.2、4.3 的异常大体相同,同样指出了异常是由于证书验证失败引起的,但其中包含的错误信息反而更少了,没有了当前时间和证书的过期时间。
由于支持的 SSL/TLS 版本相同,网络包的交互过程与 Android 4.1.1 、4.2.2、4.3 相同。
Android 5.0.0、Android 5.1.0、6.0.0、
如果是在 Android 5.0.0、Android 5.1.0 、6.0.0 上执行相同的操作,则抛出的异常与 Android 4.1.1 、 4.2.2 和 4.3 上的更类似:
在异常的错误消息中指出了异常是由证书验证失败引起的,并大体指明了证书的过期时间和当前时间。但用 Wireshark 抓到的包来看,区别要大一点:
从 Android 5.0.0 开始,提供了对 TLSv1.2 的支持,整个过程都会用 TLSv1.2 来完成。服务器发送的几个 SSL/TLS 消息 Server Hello,Certificate,Server Key Exchange,Server Hello Don 被放在了一个 TCP 包里,第 6 号包,因而,整个握手过程用了更少的包,
Android 7.0.0 、Android 7.1.0
执行相同的操作,在 Android 7.0.0 和 Android 7.1.0 上,则抛出了如下的异常:
抛出的异常的类型依然为 javax.net.ssl.SSLHandshakeException
,但异常的消息里仅指明了异常是由证书链验证失败引起的。从直接异常的多层源异常中才能看出来是由于证书过期引起的。从异常的堆栈中可以看出来,自 Android 7.0.0 开始,证书验证的部分还是有比较大的改动的。
这个握手失败的过程,同样包含 16 个网络包:
[Done]