JJaviMS
JJaviMS

Reputation: 422

SSL connection error on valid certificate

I got an javax.net.ssl.SSLHandshakeException: Chain validation failed, when I´m trying to connect to my API server, the certificate is valid nowdays, and in the stack trace I got Caused by: java.security.cert.CertPathValidatorException: Response is unreliable: its validity interval is out-of-date, the certificate is valid and it´s working on iOS and in the website, the problem is only in Android.

I´m using Retrofit, here is the clitent generation

fun generateClient(): OkHttpClient {
        val client = OkHttpClient.Builder()
        client.addInterceptor {
            val request = it.request()
            val url = request.url().newBuilder()
                .build()
            val newRequest = it.request().newBuilder().url(url).build()
            it.proceed(newRequest)
        }
        client.connectTimeout(10, TimeUnit.SECONDS)
        client.readTimeout(30, TimeUnit.SECONDS)
        return client.build()
    }

And the full trace is this

javax.net.ssl.SSLHandshakeException: Chain validation failed
    at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:361)
    at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:302)
    at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:270)
    at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:162)
    at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:257)
    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:126)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at es.app.webservice.WebService$Companion$generateClient$1.intercept(WebService.kt:67)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:200)
    at okhttp3.RealCall.execute(RealCall.java:77)
    at retrofit2.OkHttpCall.execute(OkHttpCall.java:180)
    at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall.execute(ExecutorCallAdapterFactory.java:91)
    at es.app.bd.cacheDb.databseRepositories.SplashActivityRepository$getVersions$1.invoke(SplashActivityRepository.kt:28)
    at es.app.bd.cacheDb.databseRepositories.SplashActivityRepository$getVersions$1.invoke(SplashActivityRepository.kt:17)
    at kotlin.concurrent.ThreadsKt$thread$thread$1.run(Thread.kt:30)
 Caused by: java.security.cert.CertificateException: Chain validation failed
    at com.android.org.conscrypt.TrustManagerImpl.verifyChain(TrustManagerImpl.java:788)
    at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:612)
    at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:633)
    at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:678)
    at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:499)
    at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:422)
    at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:343)
    at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94)
    at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:88)
    at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:203)
    at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:607)
    at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
    at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357)
    at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:302) 
    at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:270) 
    at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:162) 
    at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:257) 
    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:126) 
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) 
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) 
    at es.app.bd.cacheDb.webservice.WebService$Companion$generateClient$1.intercept(WebService.kt:67) 
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) 
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) 
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:200) 
    at okhttp3.RealCall.execute(RealCall.java:77) 
    at retrofit2.OkHttpCall.execute(OkHttpCall.java:180) 
    at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall.execute(ExecutorCallAdapterFactory.java:91) 
    at es.app.bd.cacheDb.databseRepositories.SplashActivityRepository$getVersions$1.invoke(SplashActivityRepository.kt:28) 
    at es.app.bd.cacheDb.databseRepositories.SplashActivityRepository$getVersions$1.invoke(SplashActivityRepository.kt:17) 
    at kotlin.concurrent.ThreadsKt$thread$thread$1.run(Thread.kt:30) 
 Caused by: java.security.cert.CertPathValidatorException: Response is unreliable: its validity interval is out-of-date
E/AndroidRuntime:     at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:133)
    at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:225)
    at sun.security.provider.certpath.PKIXCertPathValidator.validate(PKIXCertPathValidator.java:143)
    at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:79)
    at com.android.org.conscrypt.DelegatingCertPathValidator.engineValidate(DelegatingCertPathValidator.java:44)
    at java.security.cert.CertPathValidator.validate(CertPathValidator.java:301)
    at com.android.org.conscrypt.TrustManagerImpl.verifyChain(TrustManagerImpl.java:784)
        ... 39 more
 Caused by: java.security.cert.CertPathValidatorException: Response is unreliable: its validity interval is out-of-date
    at sun.security.provider.certpath.OCSPResponse.verify(OCSPResponse.java:619)
    at sun.security.provider.certpath.RevocationChecker.checkOCSP(RevocationChecker.java:709)
    at sun.security.provider.certpath.RevocationChecker.check(RevocationChecker.java:363)
    at sun.security.provider.certpath.RevocationChecker.check(RevocationChecker.java:337)
    at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:125)
        ... 45 more
    Suppressed: java.security.cert.CertPathValidatorException: Could not determine revocation status
    at sun.security.provider.certpath.RevocationChecker.buildToNewKey(RevocationChecker.java:1092)
    at sun.security.provider.certpath.RevocationChecker.verifyWithSeparateSigningKey(RevocationChecker.java:910)
    at sun.security.provider.certpath.RevocationChecker.checkCRLs(RevocationChecker.java:577)
    at sun.security.provider.certpath.RevocationChecker.checkCRLs(RevocationChecker.java:465)
    at sun.security.provider.certpath.RevocationChecker.check(RevocationChecker.java:394)
            ... 47 more

Update 1: If I access the webpage from Chrome on the phone it works, but the app is still crashing.

Upvotes: 2

Views: 5879

Answers (3)

kojak
kojak

Reputation: 1

In my case, I had to add this sentence to AndroidManifest.xml:

android:usesCleartextTraffic="true"

as shown in context here:

A screenshot showing this line of code in context in my AndroidManifest.xml file.

Upvotes: 0

Vit Khudenko
Vit Khudenko

Reputation: 28418

In my case it was enought to just set proper system time on device ('Settings' > 'System' > 'Date & Time' > 'Automatic date & time').

Upvotes: 8

Caroline
Caroline

Reputation: 406

Looking at line Suppressed: java.security.cert.CertPathValidatorException: Could not determine revocation status suggests that the failure occurs at the revocation validation step which relies on the OCSP Protocol.

What might happen here, is that your device is not connected to the internet and can't contact the authority server in order to check the validity of your certificate (it's only a guess).

If you don't want your application to have access to the authority server, you should activate "OCSP stappling" on your server. This means that your server is going to send the OCSP validation receipt as well as the certificate.

Upvotes: 3

Related Questions