4

I am trying to connect to a service that has a self signed certificate from an internal testing environment that will only exist during prototyping. The Ktor client fails with

javax.net.ssl.SSLHandshakeException: PKIX path building failed:
 sun.security.provider.certpath.SunCertPathBuilderException:
 unable to find valid certification path to requested target

How can I disable certificate verification in this case?

hanzo2001
  • 1,338
  • 1
  • 10
  • 24

2 Answers2

5

Here's my solution for CIO engine.

val client = HttpClient(CIO) {
    engine {
        https {
            trustManager = object: X509TrustManager {
                override fun checkClientTrusted(p0: Array<out X509Certificate>?, p1: String?) { }

                override fun checkServerTrusted(p0: Array<out X509Certificate>?, p1: String?) { }

                override fun getAcceptedIssuers(): Array<X509Certificate>? = null
            }
        }
    }
}
itachi
  • 3,389
  • 2
  • 24
  • 29
2

WARNING! do not use this in any production environment. I have done this for an isolated test environment where nothing is sensitive

Following the instructions from the first answer on Java: Overriding function to disable SSL certificate check (specifically: https://stackoverflow.com/a/19723687/2733184)

I found that I could add my own implementation of the TrustAll manager:

import java.security.cert.X509Certificate
import javax.net.ssl.X509TrustManager

class TrustAllX509TrustManager : X509TrustManager {
    override fun getAcceptedIssuers(): Array<X509Certificate?> = arrayOfNulls(0)

    override fun checkClientTrusted(certs: Array<X509Certificate?>?, authType: String?) {}

    override fun checkServerTrusted(certs: Array<X509Certificate?>?, authType: String?) {}
}

To add this to the Ktor client we need to configure the engine. I am using the Apache engine at the moment so you may need to change the setter to suit your chosen engine.

import io.ktor.client.*
import io.ktor.client.engine.apache.*
import java.security.SecureRandom
import javax.net.ssl.SSLContext

val client = HttpClient(Apache) {
    engine {
        sslContext = SSLContext.getInstance("TLS")
            .apply {
                init(null, arrayOf(TrustAllX509TrustManager()), SecureRandom())
            }
    }
    // install other features ....
}

I encourage anyone who finds how to do this for the other engines to add their own answer, or, if you add it as a comment, I will try to keep this answer updated

hanzo2001
  • 1,338
  • 1
  • 10
  • 24
  • For `HttpClient(Android)`, you do ```engine { sslManager = { httpsURLConnection -> httpsURLConnection.sslSocketFactory = SSLContext.getInstance("TLS").apply{}.socketFactory }``` – Sam Mar 09 '23 at 02:45