Android TLS 版本过低造成的问题

由于集成的 SSL 库版本不同,不同 Android 版本的默认 SSL/TLS 版本配置如下表:

Protocol Supported (API Levels) Enabled by default (API Levels)
SSLv3 1–TBD 1–22
TLSv1 1+ 1+
TLSv1.1 20+ 20+
TLSv1.2 20+ 20+

Android 版本与 API Level 之间的对应关系则如下表:

Platform Version API Level VERSION_CODE Notes
Android 7.1.1 Android 7.1 25 N_MR1 Platform Highlights
Android 7.0 24 N Platform Highlights
Android 6.0 23 M Platform Highlights
Android 5.1 22 LOLLIPOP_MR1 Platform Highlights
Android 5.0 21 LOLLIPOP Platform Highlights
Android 4.4W 20 KITKAT_WATCH KitKat for Wearables Only
Android 4.4 19 KITKAT Platform Highlights
Android 4.3 18 JELLY_BEAN_MR2 Platform Highlights
Android 4.2, 4.2.2 17 JELLY_BEAN_MR1 Platform Highlights
Android 4.1, 4.1.1 16 JELLY_BEAN Platform Highlights
Android 4.0.3, 4.0.4 15 ICE_CREAM_SANDWICH_MR1 Platform Highlights
Android 4.0, 4.0.1, 4.0.2 14 ICE_CREAM_SANDWICH Platform Highlights
Android 3.2 13 HONEYCOMB_MR2
Android 3.1.x 12 HONEYCOMB_MR1 Platform Highlights
Android 3.0.x 11 HONEYCOMB Platform Highlights
Android 2.3.4 Android 2.3.3 10 GINGERBREAD_MR1 Platform Highlights
Android 2.3.2 Android 2.3.1 Android 2.3 9 GINGERBREAD Platform Highlights
Android 2.2.x 8 FROYO Platform Highlights
Android 2.1.x 7 ECLAIR_MR1 Platform Highlights
Android 2.0.1 6 ECLAIR_0_1 Platform Highlights
Android 2.0 5 ECLAIR Platform Highlights
Android 1.6 4 DONUT Platform Highlights
Android 1.5 3 CUPCAKE Platform Highlights
Android 1.1 2 BASE_1_1
Android 1.0 1 BASE

可穿戴设备的 KitKat Android 4.4W 占用了 API Leve 20。也就是说,对于 Android 手机/平板 等设备,在 Android 5.0 之前,最高支持的 SSL/TLS 版本为 TLSv1,而这个版本实际上是一个安全性并不是太好的版本,当前已经有许多网站配置为不再支持这种老版本的 SSL/TLS 。在用 Android 5.0 之前的设备,访问一些不再支持 TLSv1 及之前 SSL/TLS 版本的网站的时候,就会出现一些问题。

Android 4.4.4 的设备与支持 TLSv1 的 HTTP 服务器建立连接时,其 Client Hello 消息如下:

SSL/TLS 握手可以正常完成,连接能够建立成功,并顺利完成数据传输。

Android 4.4.4 的设备与最低支持 TLSv1.1 的 HTTP 服务器建立连接时,其网络包的交互则像下面这样:

第 4 号包是 TCP 连接建立完成后, Android 客户端发向服务器的 Client Hello 消息,但服务器立即就回了一个 Alert 消息,并关闭了 TCP 连接。此时,用于执行 HTTP 请求的 OkHttp 库也将抛出异常并退出,异常为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0xb7f24d78: Failure in SSL library, usually a protocol error
error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version (external/openssl/ssl/s23_clnt.c:741 0x96ff8926:0x00000000)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:448)
at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:267)
at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:237)
at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:148)
at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:186)
at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:121)
at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:100)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:120)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at com.netease.netlib.OkHttp3Utils$MyInterceptor.intercept(OkHttp3Utils.java:29)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:179)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:129)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
Suppressed: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0xb7f24d78: Failure in SSL library, usually a protocol error
error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version (external/openssl/ssl/s23_clnt.c:741 0x96ff8926:0x00000000)
... 27 more
Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0xb7f24d78: Failure in SSL library, usually a protocol error
error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version (external/openssl/ssl/s23_clnt.c:741 0x96ff8926:0x00000000)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:405)
... 26 more
Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0xb7f24d78: Failure in SSL library, usually a protocol error
error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version (external/openssl/ssl/s23_clnt.c:741 0x96ff8926:0x00000000)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:405)
... 26 more

在 Android 4.3、Android 4.2.2 和 Android 4.1.1 上,用相同版本的 OkHttp 访问前面配置为最低支持 TLSv1.1 的 HTTP 服务器时,抛出了完全相同的异常。

客户端版本低于服务器支持的最低 SSL/TLS 版本时,HTTPS 连接会在握手阶段失败。

参考文档

SSLEngine

坚持原创技术分享,您的支持将鼓励我继续创作!