0

I'm using Retrofit2 with RxJava2 and OkHttp3 to make an HTTPS call to an internal server for testing a SSL certificate, but I always get an exception stating:

HTTP FAILED: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

According to the Google developer documentation, there are 3 reasons why this might occur (unknown CA, self signed certificate or server configuration is missing intermediate CA)

I cannot post the URL, as it is an internal testing server, but opening the URL in a browser on my computer or on my phone in Chrome works fine, this is what I can see from the certificate:

enter image description here

Therefore I think that it can't be option 1, because the browser recognises the certificate, only my app and OkHttp don't seem so and as it is no self signed certificate, option 2 also shouldn't be the cause.

And this is how my OkHttp client is provided by Dagger:

@Provides
@PerApplication
OkHttpClient provideOkHttpClient(@ApplicationContext Context context) {
    int cacheSize = 10 * 1024 * 1024; // 10 MiB

    File cacheDirectory = new File(context.getCacheDir().getAbsolutePath(), "HttpCache");

    ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
            .tlsVersions(TlsVersion.TLS_1_2)
            .cipherSuites(
                    CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
                    CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
                    CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
            .build();

    OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder()
            .connectionSpecs(Collections.singletonList(spec))
            .readTimeout(60, TimeUnit.SECONDS)
            .connectTimeout(10, TimeUnit.SECONDS)
            .cache(new Cache(cacheDirectory, cacheSize));

    if (BuildConfig.DEBUG) {
        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        httpClientBuilder.addInterceptor(loggingInterceptor);
    }

    return httpClientBuilder.build();
}

I added the CollectionSpec to define that I'm using TLS 1.2, but this makes no difference, I still receive the Trust anchor error.

Is there something else that I need to set in order to use the ssl certificate? Any ideas why the certificate is not accepted?

Eve
  • 1,153
  • 1
  • 15
  • 34
  • "Therefore I think that it can't be option 1, because the browser recognises the certificate" -- I would not assume that what Chrome accepts matches what Android SDK apps will accept in terms of a root certificate authority. – CommonsWare Mar 01 '17 at 12:23
  • You're right, that makes sense. – Eve Mar 01 '17 at 12:32
  • @Eve I faced the same and have answered http://stackoverflow.com/a/42392679/2870088. It is option 3 Missing intermediate certificate authority. Yes, browsers will cache intermediate certificates, and use them between different sites. Because of that, if you are missing the intermediate certificate, random users will receive a trust error, while others won't. http://superuser.com/questions/351516/do-intermediate-certificates-get-cached-in-firefox – Anurag Singh Mar 01 '17 at 12:57

1 Answers1

0

The problem solved itself, the URL of the server was not correct.

Eve
  • 1,153
  • 1
  • 15
  • 34