Created
June 26, 2020 09:21
-
-
Save cdongieux/08a96321e25d81f80fd32c68e7e430b8 to your computer and use it in GitHub Desktop.
OkHttpClient for Android API 19 (maybe 21?) devices having issues with SSL certificates
This file contains hidden or 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
private fun createOkHttpClient(): OkHttpClient { | |
return OkHttp.Builder().apply { | |
createSocketFactoryForKitKatOrLollipop()?.let { socketFactory -> | |
sslSocketFactory(socketFactory) | |
} | |
} | |
} | |
private fun createSocketFactoryForKitKatOrLollipop(): SSLSocketFactory? { | |
/** | |
* Typical stacktrace: | |
javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. | |
at com.google.android.gms.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(:com.google.android.gms@[email protected] (000700-316502805):25) | |
at com.google.android.gms.org.conscrypt.KitKatPlatformOpenSSLSocketImplAdapter.startHandshake(:com.google.android.gms@[email protected] (000700-316502805):0) | |
at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:320) | |
at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:284) | |
at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:169) | |
at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:258) | |
at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135) | |
at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:114) | |
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42) | |
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) | |
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) | |
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93) | |
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) | |
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) | |
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93) | |
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) | |
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:127) | |
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) | |
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) | |
... | |
Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. | |
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:282) | |
at com.android.org.conscrypt.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:202) | |
at java.lang.reflect.Method.invokeNative(Native Method) | |
at java.lang.reflect.Method.invoke(Method.java:515) | |
at com.google.android.gms.org.conscrypt.Platform.checkTrusted(:com.google.android.gms@[email protected] (000700-316502805):2) | |
at com.google.android.gms.org.conscrypt.Platform.checkServerTrusted(:com.google.android.gms@[email protected] (000700-316502805):3) | |
at com.google.android.gms.org.conscrypt.ConscryptFileDescriptorSocket.verifyCertificateChain(:com.google.android.gms@[email protected] (000700-316502805):6) | |
at com.google.android.gms.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method) | |
at com.google.android.gms.org.conscrypt.NativeSsl.doHandshake(:com.google.android.gms@[email protected] (000700-316502805):6) | |
at com.google.android.gms.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(:com.google.android.gms@[email protected] (000700-316502805):16) | |
... | |
Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. | |
*/ | |
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { | |
return null | |
} | |
// From: https://developer.android.com/training/articles/security-ssl#UnknownCa | |
// Load CAs from an InputStream | |
// (could be from a resource or ByteArrayInputStream or ...) | |
val cf: CertificateFactory = CertificateFactory.getInstance("X.509") | |
val caInput: InputStream = DiamondApplication.getInstance().applicationContext.resources.openRawResource(R.raw.ca) | |
val ca: X509Certificate = caInput.use { | |
cf.generateCertificate(it) as X509Certificate | |
} | |
// Create a KeyStore containing our trusted CAs | |
val keyStoreType = KeyStore.getDefaultType() | |
val keyStore = KeyStore.getInstance(keyStoreType).apply { | |
load(null, null) | |
setCertificateEntry(ca.subjectX500Principal.name, ca) | |
} | |
// Create a TrustManager that trusts the CAs inputStream our KeyStore | |
val tmfAlgorithm: String = TrustManagerFactory.getDefaultAlgorithm() | |
val tmf: TrustManagerFactory = TrustManagerFactory.getInstance(tmfAlgorithm).apply { | |
init(keyStore) | |
} | |
// Create an SSLContext that uses our TrustManager | |
val context: SSLContext = SSLContext.getInstance("TLS").apply { | |
init(null, tmf.trustManagers, null) | |
} | |
return context.socketFactory | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment