2
votes

I'm trying to make a request with OKHttp and Retrofit 2. This request should be done by sending a certificate (it must be a p12 or a crt). We've tried different ways, but no one allows me to succeed. I am testing with badssl.com, which allows me to make request to this URL: https://client.badssl.com with a certificate that you can find here: https://badssl.com/download/

I've tried to include the p12 and the crt in the assets folder and in the raw folder of the project and creating a Keystore, SSLSocketFactory and TrustManager. Since this wasn't working, I've also tried to create an unsafe OkHttpClient that can make any request, but I didn't succeed. In both the cases, I've got: "javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found"

public static SSLContext getSSLConfig(Context context) throws CertificateException, IOException,
            KeyStoreException, NoSuchAlgorithmException, KeyManagementException {

        // Loading CAs from an InputStream
        CertificateFactory cf = null;
        cf = CertificateFactory.getInstance("X.509");

        Certificate ca;
        // I'm using Java7. If you used Java6 close it manually with finally.
        try (InputStream cert = context.getResources().openRawResource(R.raw.somecert)) {
            ca = cf.generateCertificate(cert);
        }

        // Creating a KeyStore containing our trusted CAs
        String keyStoreType = KeyStore.getDefaultType();
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);

        // Creating a TrustManager that trusts the CAs in our KeyStore.
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);

        // Creating an SSLSocketFactory that uses our TrustManager
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, tmf.getTrustManagers(), null);

        return sslContext;
    }
val client: OkHttpClient = OkHttpClient.Builder()
            .sslSocketFactory(SSLConfigUtils.getSSLConfig(MyClass.getContext()).socketFactory)
            .hostnameVerifier { _, _ -> true }
            .build()

            val retrofit = Retrofit.Builder()
                .addCallAdapterFactory(
                    RxJava2CallAdapterFactory.create())
                .addConverterFactory(
                    GsonConverterFactory.create(gson))
                .baseUrl("https://client.badssl.com/")
                .client(client)
                .build()

I expect to make correctly Retrofit requests, but every request returns me this error:

    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] (100700-245988633):43)
        at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:319)
        at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:283)
        at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:168)
        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 okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:254)
        at okhttp3.RealCall.execute(RealCall.java:92)
        at retrofit2.OkHttpCall.execute(OkHttpCall.java:186)
        at retrofit2.adapter.rxjava2.CallExecuteObservable.subscribeActual(CallExecuteObservable.java:41)
        at io.reactivex.Observable.subscribe(Observable.java:12267)
        at retrofit2.adapter.rxjava2.BodyObservable.subscribeActual(BodyObservable.java:34)
        at io.reactivex.Observable.subscribe(Observable.java:12267)
        at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96)
        at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:578)
        at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)
        at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:919)
     Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
        at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:656)
        at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:615)
        at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:505)
        at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:424)
        at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:352)
        at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94)
        at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:89)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.google.android.gms.org.conscrypt.Platform.checkTrusted(:com.google.android.gms@[email protected] (100700-245988633):2)
2019-05-23 11:37:15.389 5640-5640/it.sogetel.agtcs E/Errore:     at com.google.android.gms.org.conscrypt.Platform.checkServerTrusted(:com.google.android.gms@[email protected] (100700-245988633):1)
        at com.google.android.gms.org.conscrypt.ConscryptFileDescriptorSocket.verifyCertificateChain(:com.google.android.gms@[email protected] (100700-245988633):12)
        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] (100700-245988633):7)
        at com.google.android.gms.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(:com.google.android.gms@[email protected] (100700-245988633):14)
            ... 33 more
     Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
            ... 47 more
1
Please check thisRobbit

1 Answers

0
votes

There’s a test case in OkHttp that configures client authentication. It might need useful as an example, though you should note that it generates certificates in memory rather than loading them from a file.

The relevant code is in the okhttp-tls module.

Also note that your TrustManager must include the server’s certificate, or one of the certificate authority root certificates that signed it.