Last active
September 19, 2024 10:55
-
-
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+)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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' | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
}); |
Thanks a lot! Works great on Android 4.1.
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
For the SSLContext I had to use the .newProvider() method rather than the string
"Conscrypt"
. Like so:When using just the string I was getting
NoSuchProviderException: Conscrypt