Skip to content

Instantly share code, notes, and snippets.

@ankushg
Created August 3, 2018 19:19
Show Gist options
  • Star 22 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save ankushg/8c0c3144318b1c17abb228d6211ba996 to your computer and use it in GitHub Desktop.
Save ankushg/8c0c3144318b1c17abb228d6211ba996 to your computer and use it in GitHub Desktop.
/**
* Implementation of [SSLSocketFactory] that adds [TlsVersion.TLS_1_2] as an enabled protocol for every [SSLSocket]
* created by [delegate].
*
* [See this discussion for more details.](https://github.com/square/okhttp/issues/2372#issuecomment-244807676)
*
* @see SSLSocket
* @see SSLSocketFactory
*/
class Tls12SocketFactory(private val delegate: SSLSocketFactory) : SSLSocketFactory() {
companion object {
/**
* @return [X509TrustManager] from [TrustManagerFactory]
*
* @throws [NoSuchElementException] if not found. According to the Android docs for [TrustManagerFactory], this
* should never happen because PKIX is the only supported algorithm
*/
private val trustManager by lazy {
val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
trustManagerFactory.init(null as KeyStore?)
trustManagerFactory.trustManagers
.first { it is X509TrustManager } as X509TrustManager
}
/**
* If on [Build.VERSION_CODES.LOLLIPOP] or lower, sets [OkHttpClient.Builder.sslSocketFactory] to an instance of
* [Tls12SocketFactory] that wraps the default [SSLContext.getSocketFactory] for [TlsVersion.TLS_1_2].
*
* Does nothing when called on [Build.VERSION_CODES.LOLLIPOP_MR1] or higher.
*
* For some reason, Android supports TLS v1.2 from [Build.VERSION_CODES.JELLY_BEAN], but the spec only has it
* enabled by default from API [Build.VERSION_CODES.KITKAT]. Furthermore, some devices on
* [Build.VERSION_CODES.LOLLIPOP] don't have it enabled, despite the spec saying they should.
*
* @return the (potentially modified) [OkHttpClient.Builder]
*/
@JvmStatic
fun OkHttpClient.Builder.enableTls12() = apply {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
try {
val sslContext = SSLContext.getInstance(TlsVersion.TLS_1_2.javaName())
sslContext.init(null, arrayOf(trustManager), null)
sslSocketFactory(Tls12SocketFactory(sslContext.socketFactory), trustManager)
} catch (e: Exception) {
Timber.e(e, "Error while setting TLS 1.2 compatibility")
}
}
}
}
/**
* Forcefully adds [TlsVersion.TLS_1_2] as an enabled protocol if called on an [SSLSocket]
*
* @return the (potentially modified) [Socket]
*/
private fun Socket.patchForTls12(): Socket {
return (this as? SSLSocket)?.apply {
enabledProtocols += TlsVersion.TLS_1_2.javaName()
} ?: this
}
override fun getDefaultCipherSuites(): Array<String> {
return delegate.defaultCipherSuites
}
override fun getSupportedCipherSuites(): Array<String> {
return delegate.supportedCipherSuites
}
@Throws(IOException::class)
override fun createSocket(s: Socket, host: String, port: Int, autoClose: Boolean): Socket? {
return delegate.createSocket(s, host, port, autoClose)
.patchForTls12()
}
@Throws(IOException::class, UnknownHostException::class)
override fun createSocket(host: String, port: Int): Socket? {
return delegate.createSocket(host, port)
.patchForTls12()
}
@Throws(IOException::class, UnknownHostException::class)
override fun createSocket(host: String, port: Int, localHost: InetAddress, localPort: Int): Socket? {
return delegate.createSocket(host, port, localHost, localPort)
.patchForTls12()
}
@Throws(IOException::class)
override fun createSocket(host: InetAddress, port: Int): Socket? {
return delegate.createSocket(host, port)
.patchForTls12()
}
@Throws(IOException::class)
override fun createSocket(address: InetAddress, port: Int, localAddress: InetAddress, localPort: Int): Socket? {
return delegate.createSocket(address, port, localAddress, localPort)
.patchForTls12()
}
}
@georgiecasey
Copy link

to add it to your chain you need something like OkHttpClient httpClient = enableTls12(new OkHttpClient.Builder()) .addInterceptor(new SignatureInterceptor()) .connectionSpecs(Arrays.asList(requireTls12)) .build();

handy code from OP but i don't know why he didn't tell us that line! it wasn't obvious to me

@CoolMind
Copy link

CoolMind commented Jun 3, 2020

@georgiecasey, thanks! It looks like

val okHttpClient = OkHttpClient().newBuilder()
            .enableTls12()
            ...
            .build()

Where did you get SignatureInterceptor? Also requireTls12 is unresolved. As I understood, those classed in Glide and OkHttp are deprecated.

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