Search code examples
javaandroidkotlinkotlin-android-extensionskotlin-extension

kotlin connect to self-signed https server


I have the following kotlin code:

val urlPath = "https://10.0.2.2:8080"
var data: String
try {
    data = URL(urlPath).readText()
} catch (e: Exception) {
    Log.e("doInBackground", "Exception caught: ${e.localizedMessage}")
    error = when (e) {
        is MalformedURLException -> "Invalid URL"
        is IOException -> "Network Error"
        else -> {
            "Network error: ${e.localizedMessage}"
        }
    }
}

If I use the above code to connect to a http server, the above code works. However when I try to connect to a https server with a self-signed certificate, it fails. Is there a way to allow https connections on localhost (only), even when the certificates are self-signed ?


Solution

  • Here's an example that reads from https://google.com using JSSE, it trusts literally every certificate and shouldn't be used productively.

    fun main(args: Array<String>) {
        val urlPath = "https://google.com"
        try {
            (URL(urlPath).openConnection() as HttpsURLConnection).apply {
                sslSocketFactory = createSocketFactory(listOf("TLSv1.2"))
                hostnameVerifier = HostnameVerifier { _, _ -> true }
                readTimeout = 5_000
            }.inputStream.use {
                it.copyTo(System.out)
            }
        } catch (e: Exception) {
            TODO()
        }
    }
    
    
    private fun createSocketFactory(protocols: List<String>) =
        SSLContext.getInstance(protocols[0]).apply {
            val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
                override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
                override fun checkClientTrusted(certs: Array<X509Certificate>, authType: String) = Unit
                override fun checkServerTrusted(certs: Array<X509Certificate>, authType: String) = Unit
            })
            init(null, trustAllCerts, SecureRandom())
        }.socketFactory
    

    I've got a little library for these kinds of things here, which is neither up-to-date nor published. Nevertheless, it provides a simple DSL for setting up TLS/SSL sockets and provides means for https connections.