Как добавить SSL-сертификаты в okHttp взаимное соединение TLS? - PullRequest
1 голос
/ 14 февраля 2020

У меня уже есть файлы .pem и .key, которые я не хочу устанавливать / импортировать локально, просто скажите моему клиенту использовать их, возможно ли это? это не самозаверяющий сертификат

По сути, в моем завитке я делаю что-то вроде этого:

curl --key mykey.key --cert mycert.pem https://someurl.com/my-endpoint

Я проверил этот ответ

Как сделать https запрос с сертификатом ssl в Retrofit

также это https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/CustomTrust.java (но может не иметь смысла, так как я не получаю объект нужного мне типа)

В основном у меня есть мой okHttpClient

val okHttpClient = OkHttpClient.Builder()
    .sslSocketFactory(?, ?) //here I tried to call sslSocketFactory, trustManager following the example from the CustomTrust.java
    .build()

Есть идеи для решения?

Также проверил эту документацию, но снова ssl-часть не завершена, ни в примерах

https://square.github.io/okhttp/https/#customizing -trusted-Certificates-KT- java

Поэтому я попытался сделать это (на основе образцов Okhttp)

private fun trustedCertificatesInputStream(): InputStream {
        val comodoRsaCertificationAuthority = (""
            + "-----BEGIN CERTIFICATE-----\n" +
            "-----END CERTIFICATE-----")
        return Buffer()
            .writeUtf8(comodoRsaCertificationAuthority)
            .inputStream()
    }


    val loggingInterceptor = HttpLoggingInterceptor().apply {
        level = HttpLoggingInterceptor.Level.BODY
    }


    fun createClient() : OkHttpClient {

        val trustManager: X509TrustManager
        val sslSocketFactory: SSLSocketFactory
        try {
            trustManager = trustManagerForCertificates(trustedCertificatesInputStream())
            val sslContext = SSLContext.getInstance("TLS")
            sslContext.init(null, arrayOf<TrustManager>(trustManager), null)
            sslSocketFactory = sslContext.socketFactory



        } catch (e: GeneralSecurityException) {
            throw RuntimeException(e)
        }
        return OkHttpClient.Builder()
            .sslSocketFactory(sslSocketFactory, trustManager)
            .connectTimeout(45, TimeUnit.SECONDS)
            .readTimeout(45, TimeUnit.SECONDS)
            .protocols(listOf(Protocol.HTTP_1_1))
            .addInterceptor(loggingInterceptor)
            .build()
    }


    @Throws(GeneralSecurityException::class)
    private fun trustManagerForCertificates(input: InputStream): X509TrustManager {
        val certificateFactory: CertificateFactory = CertificateFactory.getInstance("X.509")
        val certificates: Collection<Certificate?> = certificateFactory.generateCertificates(input)
        val password = "password".toCharArray() // Any password will work.
        val keyStore = newEmptyKeyStore(password)

        for ((index, certificate) in certificates.withIndex()) {
            val certificateAlias = index.toString()
            keyStore.setCertificateEntry(certificateAlias, certificate)
        }
        // Use it to build an X509 trust manager.
        val keyManagerFactory: KeyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
        keyManagerFactory.init(keyStore, password)

        val trustManagerFactory: TrustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
        trustManagerFactory.init(keyStore)

        val trustManagers: Array<TrustManager> = trustManagerFactory.getTrustManagers()
        return trustManagers[0]!! as X509TrustManager
    }

    @Throws(GeneralSecurityException::class)
    private fun newEmptyKeyStore(password: CharArray): KeyStore {
        return try {
            val keyStore = KeyStore.getInstance(KeyStore.getDefaultType())
            val inputStream: InputStream? = null // By convention, 'null' creates an empty key store.
            keyStore.load(inputStream, password)
            keyStore
        } catch (e: IOException) {
            throw AssertionError(e)
        }

    }

и я получаю ошибка

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

при поиске ошибки кажется, что я должен установить SSL локально, чего следует избегать, так как я не могу установить его таким образом на сервере, есть ли способ сделать это Работа?

1 Ответ

1 голос
/ 14 февраля 2020

Полагаю, вы хотите настроить взаимную аутентификацию TLS, и для этого и нужен ключ?

Взгляните на okhttp-tls , в котором есть API для превращения сертификата и закрытых ключей в соответствующие Java объекты.

...