1

My Server is using Self-Signed certificate. I am using Okhttp + Retrofit for api calls. I have got crt file and public key [SHA-256] from the server. Following this and this links from Google docs, I have created a network_security_config file in xml folder and added my crt file in raw folder and added it in manifest file as

android:networkSecurityConfig="@xml/network_security_config"

Here is my network config file as per Google docs:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
    <domain includeSubdomains="true">2.48.3.66:</domain>
    <pin-set>
        <pin digest="SHA-256">ofJqMSD8j9q3w5myKalxjJO5OklHyBqgkwgHjqcOhds=</pin>
    </pin-set>
    <trust-anchors>
        <certificates src="@raw/ssl_certificate"/>
    </trust-anchors>
</domain-config>
</network-security-config>

I get following exception when calling an api

Response Failure: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
W/System.err: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
W/System.err:     at com.android.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(ConscryptFileDescriptorSocket.java:231)
W/System.err:     at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.kt:367)
W/System.err:     at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.kt:325)
W/System.err:     at okhttp3.internal.connection.RealConnection.connect(RealConnection.kt:197)
W/System.err:     at okhttp3.internal.connection.ExchangeFinder.findConnection(ExchangeFinder.kt:249)
W/System.err:     at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:108)
W/System.err:     at okhttp3.internal.connection.ExchangeFinder.find(ExchangeFinder.kt:76)
W/System.err:     at okhttp3.internal.connection.RealCall.initExchange$okhttp(RealCall.kt:245)
W/System.err:     at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:32)
W/System.err:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100)
W/System.err:     at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:96)
W/System.err:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100)
W/System.err:     at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83)
W/System.err:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100)
W/System.err:     at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76)
W/System.err:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100)
W/System.err:     at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.kt:219)
W/System.err:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:100)
W/System.err:     at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:197)
W/System.err:     at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:502)
W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
W/System.err:     at java.lang.Thread.run(Thread.java:919)

So following are my queries:

  1. Is this the right way to implement Self-Signed certificate pinning? Because google clearly mentions in their docs that "Fortunately, you can teach your application to trust custom CAs by configuring your application's Network Security Config, without needing to modify the code inside your application."

  2. If network_security_config is correct then how to check if there is any issue with server configurations (crt file + public key)

  3. Do i manually need to load crt file and then use keystore + sslfactory to configure ssl pinning as mentioned in this link

Note: For now just to run the apis, I am using a trust manager that does not validate certificate chains as follow:

try {
            val trustAllCerts:  Array<TrustManager> = arrayOf(object : X509TrustManager {
                override fun checkClientTrusted(chain: Array<out java.security.cert.X509Certificate>?, authType: String?) {

                }

                override fun checkServerTrusted(chain: Array<out java.security.cert.X509Certificate>?, authType: String?) {

                }

                override fun getAcceptedIssuers(): Array<out java.security.cert.X509Certificate>? = arrayOf()
            })

            // Install the all-trusting trust manager
            val  sslContext = SSLContext.getInstance("SSL")
            sslContext.init(null, trustAllCerts, SecureRandom())

            // Create an ssl socket factory with our all-trusting manager
            val sslSocketFactory = sslContext.socketFactory
            if (trustAllCerts.isNotEmpty() &&  trustAllCerts.first() is X509TrustManager) {
                builder.sslSocketFactory(sslSocketFactory, trustAllCerts.first() as X509TrustManager)
                builder.hostnameVerifier { hostname, session -> true }
            }
        } catch (e: Exception) {
        }
Nouman Bhatti
  • 1,777
  • 4
  • 28
  • 55

0 Answers0