SSLProtocolException with HTTPs on Retrofit2

折月煮酒 提交于 2021-02-18 12:45:09

问题


I am running into an issue on Android 4.4 phones (specifically, Galaxy S4, although I believe it's not the fault of the phone itself). While using Retrofit2.Http I receive the following error while connecting on HTTPS:

javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x737510d0: Failure in SSL library, usually a protocol error
error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:741 0x727fb7d0:0x00000000)

I have found several resources that indicate this is a bug on Android 4.4(1), but the examples given always assume use of the HttpsUrlConnection class, which I am not using.

I did find some answers here about setting specific ConnectionSpec instances for the connection, which seemed promising because it was Retrofit-specific(2). Unfortunately, this made no difference in the error. An example of my code (I tried both MODERN_TLS and COMPATIBLE_TLS):

return new OkHttpClient.Builder()
                .addInterceptor(interceptor)
                .connectionSpecs(Collections.singletonList(ConnectionSpec.MODERN_TLS))
                .build();

Switching to "http" does work, but that is not an option for the final release. A secure, encrypted connection is absolutely required, so any solution that completely disables HTTPS or blindly accepts any certificate is not likely to be acceptable.

Thanks in advance!

(1) Javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: Failure in SSL library, usually a protocol error

(2) Retrofit OkHttp SSLHandshakeException

Edit:

Running openssl gives the following:

[[my_computer]]$ ./openssl s_client -connect [[server_hidden_by_me]]:443 -tls1


CONNECTED(00000003)
depth=2 /C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
 0 s:/OU=Domain Control Validated/OU=PositiveSSL/CN=[hidden_by_me]
   i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA
 1 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA
   i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
 2 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
   i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
---
Server certificate
-----BEGIN CERTIFICATE-----
[snip certificate for brevity]
-----END CERTIFICATE-----
subject=/OU=Domain Control Validated/OU=PositiveSSL/CN=[hidden_by_me]
issuer=/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA
---
No client certificate CA names sent
---
SSL handshake has read 5449 bytes and written 426 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-SEED-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : DHE-RSA-SEED-SHA
    Session-ID: A4D84E2A0A16DB03082172695141BE1BB562F920ED4E4F6A9139733D9CAB7A54
    Session-ID-ctx: 
    Master-Key: 119C10E5CC34297D1717E4AEAB8BF1CAA8BA012C125B10513FBFE0854B6AB0E9E65536F801990CA3C992FEB69ADBE279
    Key-Arg   : None
    TLS session ticket lifetime hint: 300 (seconds)
    TLS session ticket:
    0000 - 5c 21 2c ac 68 a9 ef 71-8c 69 2a 86 0c da 6c cd   \!,.h..q.i*...l.
    [snipped for brevity]

    Start Time: 1464109807
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
---

回答1:


Had similar issue with Nexus 7 (Android 4.4.4). Found that it tries to connect via TLSv1 which was not enabled by default on my server. Fixed by enabling it =)

You can test your server with openssl: openssl s_client -connect google.com:443 -tls1

Update:

This code forces TLSv1 on my device, btw it supports only SSLv3, TLSv1. Tested with okhttp:3.3.0

ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
        .tlsVersions(TlsVersion.TLS_1_0)
        .allEnabledCipherSuites()
        .build();

OkHttpClient client = new OkHttpClient.Builder()
        .connectionSpecs(Collections.singletonList(spec))
        .build();

Request request = new Request.Builder()
        .url("https://192.168.0.19:44330")
        .build();

try {
    client.newCall(request).execute();
} catch (IOException e) {
    e.printStackTrace();
}

Used openssl server to see which protocol version it really uses, you will need certificate and key files:

openssl s_server -key key.pem -cert cert.cer -accept 44330 -www -msg

Hope this helps!



来源:https://stackoverflow.com/questions/37417400/sslprotocolexception-with-https-on-retrofit2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!