Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 23 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save Karewan/4b0270755e7053b471fdca4419467216 to your computer and use it in GitHub Desktop.
Save Karewan/4b0270755e7053b471fdca4419467216 to your computer and use it in GitHub Desktop.
Android: TLS 1.3 with OkHttp and Conscrypt on all Android versions (Tested on 4.1+)
// Android 4.1+
dependencies {
implementation 'com.squareup.okhttp3:okhttp:3.12.13'
implementation 'org.conscrypt:conscrypt-android:2.5.2'
}
// Android 5.0+
dependencies {
implementation 'com.squareup.okhttp3:okhttp:4.10.0'
implementation 'org.conscrypt:conscrypt-android:2.5.2'
}
// Init Conscrypt
Provider conscrypt = Conscrypt.newProvider();
// Add as provider
Security.insertProviderAt(conscrypt, 1);
// Init OkHttp
OkHttpClient.Builder okHttpBuilder = new OkHttpClient()
.newBuilder()
.connectionSpecs(Collections.singletonList(ConnectionSpec.RESTRICTED_TLS));
// OkHttp 3.12.x
// ConnectionSpec.COMPATIBLE_TLS = TLS1.0
// ConnectionSpec.MODERN_TLS = TLS1.0 + TLS1.1 + TLS1.2 + TLS 1.3
// ConnectionSpec.RESTRICTED_TLS = TLS 1.2 + TLS 1.3
// OkHttp 3.13+
// ConnectionSpec.COMPATIBLE_TLS = TLS1.0 + TLS1.1 + TLS1.2 + TLS 1.3
// ConnectionSpec.MODERN_TLS = TLS1.2 + TLS 1.3
// ConnectionSpec.RESTRICTED_TLS = TLS 1.2 + TLS 1.3
try {
X509TrustManager tm = Conscrypt.getDefaultX509TrustManager();
SSLContext sslContext = SSLContext.getInstance("TLS", conscrypt);
sslContext.init(null, new TrustManager[] { tm }, null);
okHttpBuilder.sslSocketFactory(new InternalSSLSocketFactory(sslContext.getSocketFactory()), tm);
} catch (Exception e) {
e.printStackTrace();
}
// Build OkHttp
OkHttpClient okHttpClient = okHttpBuilder.build();
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
public final class InternalSSLSocketFactory extends SSLSocketFactory {
private final SSLSocketFactory mSSLSocketFactory;
public InternalSSLSocketFactory(SSLSocketFactory sslSocketFactory) {
this.mSSLSocketFactory = sslSocketFactory;
}
@Override
public String[] getDefaultCipherSuites() {
return mSSLSocketFactory.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return mSSLSocketFactory.getSupportedCipherSuites();
}
@Override
public Socket createSocket() throws IOException {
return enableTLSOnSocket(mSSLSocketFactory.createSocket());
}
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
return enableTLSOnSocket(mSSLSocketFactory.createSocket(s, host, port, autoClose));
}
@Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
return enableTLSOnSocket(mSSLSocketFactory.createSocket(host, port));
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
return enableTLSOnSocket(mSSLSocketFactory.createSocket(host, port, localHost, localPort));
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return enableTLSOnSocket(mSSLSocketFactory.createSocket(host, port));
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return enableTLSOnSocket(mSSLSocketFactory.createSocket(address, port, localAddress, localPort));
}
private Socket enableTLSOnSocket(Socket socket) {
//if(socket instanceof SSLSocket) ((SSLSocket) socket).setEnabledProtocols(new String[] {"TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"});
if(socket instanceof SSLSocket) ((SSLSocket) socket).setEnabledProtocols(new String[] {"TLSv1.2", "TLSv1.3"});
return socket;
}
}
Request request = new Request.Builder()
.url("https://tls13.1d.pw") // You can try another TLS 1.3 capable HTTPS server
.build();
okHttpClient.newCall(request)
.enqueue(new Callback() {
@Override
public void onFailure(final Call call, IOException e) {
e.printStackTrace();
Log.d(LOG, "onFailure()");
}
@Override
public void onResponse(Call call,final Response response) throws IOException {
Log.d(LOG, "onResponse() tlsVersion=" + response.handshake().tlsVersion());
Log.d(LOG, "onResponse() cipherSuite=" + response.handshake().cipherSuite().toString());
// D/TestApp##: onResponse() tlsVersion=TLS_1_3
// D/TestApp##: onResponse() cipherSuite=TLS_AES_256_GCM_SHA384
}
});
@mendhak
Copy link

mendhak commented Jun 16, 2022

For the SSLContext I had to use the .newProvider() method rather than the string "Conscrypt". Like so:

SSLContext sslContext = SSLContext.getInstance("TLS", Conscrypt.newProvider());

When using just the string I was getting NoSuchProviderException: Conscrypt

@zedxxx
Copy link

zedxxx commented Nov 14, 2022

Thanks a lot! Works great on Android 4.1.

@CyxouD
Copy link

CyxouD commented Oct 19, 2023

It doesn't work in my case on my specific API 19 device, but works in emulator

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment