Не удается подключить SSLSocket к серверу даже с правильными сертификатами - PullRequest
0 голосов
/ 20 января 2020

Я пытаюсь подключиться с помощью SSLSocket с использованием TLS к серверу, который уже должен иметь правильные сертификаты. Но клиент продолжает падать.

Это проверка SSL на веб-сайте:

server verifies our domain

Пока это код (имя хоста и порт исправлен):

val SSLSocketFactory = SSLSocketFactory.getDefault() as SSLSocketFactory
val socket: SSLSocket = factory.createSocket(address, port) as SSLSocket
socket.startHandshake()

Когда код приходит на рукопожатие, он вылетает с этой ошибкой:

java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

Есть идеи, почему это может произойти? Другой HTTPS-вызов, который я делаю серверу с использованием TLS, работает отлично, поэтому я не думаю, что проблема в сервере (и все ответы, которые я видел, имеют такой тип ответа).

1 Ответ

0 голосов
/ 21 января 2020

Проблема заключалась в том, что мне нужно было закрепить сертификат в клиенте, открывающем соединение через сокет SSL.

Более подробное руководство c см. В этом руководстве о закреплении SSL на Android. Хотя это руководство относится к соединениям HTTPS, а не к Socket.

Для сокета я сделал следующее:

fun run() {
    val trustGodaddyCertificate = loadTrustManagers()

    val sslContext = SSLContext.getInstance("SSL")
    sslContext.init(null, trustGodaddyCertificate, SecureRandom())

    val socket = sslContext.socketFactory.createSocket(address, port)

    // use the socket
}

private fun loadTrustManagers(): Array<out TrustManager>? {
    val certificateFactory: CertificateFactory = CertificateFactory.getInstance("X.509")
    val caInput: InputStream = BufferedInputStream(resources.openRawResource(R.raw.server_godaddy_certificate))
    caInput.use {
        val certificate = certificateFactory.generateCertificate(caInput)

        val keyStoreType: String = KeyStore.getDefaultType()
        val keyStore: KeyStore = KeyStore.getInstance(keyStoreType)
        keyStore.load(null, null)
        keyStore.setCertificateEntry("ca", certificate)

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

        return trustManagerFactory.trustManagers
    }
}

Короче говоря, я сохранил сертификат .crt GoDaddy. в сырой куче ресурсов. Я загрузил его и создал TrustManager, который его использует. И я положил это в сертификат, разрешенный клиентом. Это заставляет все работать.

...