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:
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."
If network_security_config is correct then how to check if there is any issue with server configurations (crt file + public key)
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) {
}