support enabling TLSv1.2 on Android 4.1-4.4.
See original GitHub issueOur lawyers and security consultants claim that for PCI compliance*, we must disable TLS 1.0 and 1.1 on our servers. For some confusing reason, Android has supported TLS 1.2 since API 16 (android 4.1) but enabled it by default only since API 20 (android “4.4W”).
With okhttp 2.6, we were able to force use of TLS 1.2 with:
OkHttpClient cli = new OkHttpClient();
SSLContext sc = SSLContext.getInstance("TLSv1.2");
sc.init(null, null, null);
cli.setSslSocketFactory(new Tls12SocketFactory(sc.getSocketFactory()));
ConnectionSpec cs = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_2)
.build();
cli.setConnectionSpecs(ImmutableList.of(cs));
where Tls12SocketFactory
is this.
However, okhttp 3.1 uses some kind of reflection on internal implementation details of the SSLSocketFactory
, so the above implementation no longer works. And, indeed, it’s a bit silly to make callers write so much code anyway. Specifying TLS_1_2
in the ConnectionSpec
should be enough to get TLSv1.2 whenever it is supported.
As far as I can tell, the only reason why the custom socket factory is needed in the first place is that ConnectionSpec.supportedSpec()
calls SSLSocket.getEnabledProtocols()
to learn the list of protocols supported by the system, so on Android 4.x where TLS 1.2 is supported but not enabled by default, OkHttp thinks 1.2 is not supported at all.
Sorry for this long bug report: I think the fix is as simple as changing getEnabledProtocols()
above to getSupportedProtocols()
but wanted to submit this bug for discussion before making a PR with such a change, in case there is some affirmative reason why it’s the other way now.
* Originally I understood the PCI compliance deadline to be June 2016; however, it seems like it has since been changed to be June 2018. Regardless, OkHttp should support this change for users that want it.
Issue Analytics
- State:
- Created 8 years ago
- Reactions:3
- Comments:63 (7 by maintainers)
Top GitHub Comments
Had the same issue on Android < 5.0 (16 <= API < 20). Thanks to your posts, I was able to make this work, so for anyone who gets here, this is the out-of-the-box solution. At the time of this writing, I’m using
OkHttp 3.4.1
.Edit: I’ve done some tests and the same issue also happens on some Samsung devices with API 21. Solved by applying the solution also for API 21
Add
Tls12SocketFactory.java
with the following content:Then, add this method somewhere in your code:
And when you create your
OkHttp
instance, use it for example like this:Also, be sure to use well known CAs for your server side certificates when targeting older Androids.
Credits to @StuStirling and @techiebrij:
To check your server side certificates: https://developer.android.com/reference/javax/net/ssl/SSLEngine.html
Or: https://gist.github.com/gotev/f1a8a221e2d1d09bcb93e823b8e5a05a
For anyone else that may be struggling with this, the thing that fixed mine was to install the latest security fixes that are bundled with Google Play Services.
After doing this, the solution for enabling TLS1.2 worked.
https://square.github.io/okhttp/3.x/okhttp/okhttp3/OkHttpClient.Builder.html#sslSocketFactory-javax.net.ssl.SSLSocketFactory-javax.net.ssl.X509TrustManager-