Coil: SSLHandshakeException: Handshake failed

Created on 30 Mar 2020  路  7Comments  路  Source: coil-kt/coil

Hi,

I'm getting a handshake failed error when trying to load images from our server.

i.e. this image

I know this is more of a OkHttp issue, but I guess someone must have encountered this before. It used to work just fine with Glide.

Any idea what I should set to Coil's okHttpClient?

question

Most helpful comment

@minarja1 Glide by default uses HttpUrlConnection for networking, which has laxe security settings, which might be why it's working. To fix this I'd check out the Google Play Services Security Provider. It smooths over a lot of device specific networking issues. You could do something like the following to build your ImageLoader:

ImageLoader(context) {
    okHttpClient {
        // Initialized lazily on a background thread.
        ProviderInstaller.installIfNeeded(context)

        OkHttpClient.Builder()
            .cache(CoilUtils.createDefaultCache(context))
            .build()
    }
}

If that doesn't work you can try enabling all TLS versions and cipher suites, though I would only do this for the specific device as it's a security risk:

ImageLoader(context) {
    okHttpClient {
        OkHttpClient.Builder()
            .cache(CoilUtils.createDefaultCache(context))
            .connectionSpecs(listOf(ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
                .allEnabledTlsVersions()
                .allEnabledCipherSuites()
                .build()))
            .build()
    }
}

Ultimately, though this a device-specific networking issue so there's no action to take on Coil.

All 7 comments

Hey there @minarja1 , I added your url into the Coil sample app and it works just fine. Can you try the same and see what result you get? It might be an issue specific to your phone or something. To try it out, just change the jpgs.json first item in the list to be your URL for all the fields, ie. raw, full, regular, etc.

I guess you're right!

I tried it on 3 devices and it only does not work on a Xiaomi Redmi Note 4 with Android 7. We need this app to go into production soon though and this is the only issue we're having after migrating from Glide. Where should I be reporting this? Is this an OkHttp issue?

It's hard to know without seeing the full stack trace. You're saying that Glide has no issues loading an image on the Redmi Note 4? Can you paste the full stack trace in here?

2020-03-30 18:50:13.111 15327-15327/coil.sample E/RealImageLoader: javax.net.ssl.SSLHandshakeException: Handshake failed at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:429) 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) at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:257) at okhttp3.RealCall$AsyncCall.execute(RealCall.java:201) at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) at java.lang.Thread.run(Thread.java:760) Caused by: javax.net.ssl.SSLProtocolException: SSL handshake terminated: ssl=0x7f7998aa00: Failure in SSL library, usually a protocol error error:10000410:SSL routines:OPENSSL_internal:SSLV3_ALERT_HANDSHAKE_FAILURE (external/boringssl/src/ssl/s3_pkt.c:610 0x7f60a38a40:0x00000001) error:1000009a:SSL routines:OPENSSL_internal:HANDSHAKE_FAILURE_ON_CLIENT_HELLO (external/boringssl/src/ssl/s3_clnt.c:764 0x7f74551f76:0x00000000) at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method) at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357) ... 23 more

You could try providing your own OkHttpClient to Coil. You can find out how to do so here: https://coil-kt.github.io/coil/image_loaders/#caching. Maybe it will work with a custom one, since this seems to be something specifically with the Redmi Note 4 and the server you are fetching the image from.

@minarja1 Glide by default uses HttpUrlConnection for networking, which has laxe security settings, which might be why it's working. To fix this I'd check out the Google Play Services Security Provider. It smooths over a lot of device specific networking issues. You could do something like the following to build your ImageLoader:

ImageLoader(context) {
    okHttpClient {
        // Initialized lazily on a background thread.
        ProviderInstaller.installIfNeeded(context)

        OkHttpClient.Builder()
            .cache(CoilUtils.createDefaultCache(context))
            .build()
    }
}

If that doesn't work you can try enabling all TLS versions and cipher suites, though I would only do this for the specific device as it's a security risk:

ImageLoader(context) {
    okHttpClient {
        OkHttpClient.Builder()
            .cache(CoilUtils.createDefaultCache(context))
            .connectionSpecs(listOf(ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
                .allEnabledTlsVersions()
                .allEnabledCipherSuites()
                .build()))
            .build()
    }
}

Ultimately, though this a device-specific networking issue so there's no action to take on Coil.

For anyone having similar issues,

ProviderInstaller.installIfNeeded(context)

did the trick! Thanks for your help!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

GeniusRUS picture GeniusRUS  路  4Comments

wooldridgetm picture wooldridgetm  路  3Comments

billyjoker picture billyjoker  路  5Comments

cioccarellia picture cioccarellia  路  3Comments

ghost picture ghost  路  4Comments