Android KitKat не поддерживает TLSv1.2 - PullRequest
2 голосов
/ 01 апреля 2020

Я тестирую свое приложение на старых устройствах, так как мы нацелены на развивающийся рынок и ожидаем, что пользователи будут иметь более старые устройства до леденцов.

Я использую RetroFit (2.6.4) и OkHttp (3.12.4) для связи с REST-сервер, который размещен на Amazon. AWS поддерживает TLS 1.0, 1.1 и 1.2, но мы заблокировали его для TLSv1.2 на нашем NodeJS сервере.

Приложение работает для новых устройств, но я получаю следующую ошибку на KitKat:

<-- HTTP FAILED: java.net.UnknownServiceException: Unable to find acceptable protocols. isFallback=false, modes=[ConnectionSpec(cipherSuites=[TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, TLS_AES_128_CCM_SHA256, TLS_AES_256_CCM_8_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256], tlsVersions=[TLS_1_3, TLS_1_2], supportsTlsExtensions=true)], supported protocols=[SSLv3, TLSv1, TLSv1.2]

Если вы посмотрите в конце этого сообщения об ошибке, оно говорит:

, tlsVersions=[TLS_1_3, TLS_1_2], supportsTlsExtensions=true)], supported protocols=[SSLv3, TLSv1, TLSv1.2]

Так что я думаю, что у меня есть правильный код для включения TLSv1.2, но я его не использую правильно, и OKHttp пытается использовать SSLv3 или TLS1 вместо TLSv1.2.

Кроме того, я только что проверил наш сервер на SSLLabs, и он поддерживает следующие наборы шифров TLSv1.2:

# TLS 1.2 (suites in server-preferred order)
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)   ECDH secp256r1 (eq. 3072 bits RSA)   FS    128
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027)   ECDH secp256r1 (eq. 3072 bits RSA)   FS   WEAK 128
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)   ECDH secp256r1 (eq. 3072 bits RSA)   FS   WEAK    128
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)   ECDH secp256r1 (eq. 3072 bits RSA)   FS    256
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)   ECDH secp256r1 (eq. 3072 bits RSA)   FS   WEAK 256
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)   ECDH secp256r1 (eq. 3072 bits RSA)   FS   WEAK    256
TLS_RSA_WITH_AES_128_GCM_SHA256 (0x9c)   WEAK   128
TLS_RSA_WITH_AES_128_CBC_SHA256 (0x3c)   WEAK   128
TLS_RSA_WITH_AES_128_CBC_SHA (0x2f)   WEAK  128
TLS_RSA_WITH_AES_256_GCM_SHA384 (0x9d)   WEAK   256
TLS_RSA_WITH_AES_256_CBC_SHA256 (0x3d)   WEAK   256
TLS_RSA_WITH_AES_256_CBC_SHA (0x35)   WEAK  256

Полная трассировка стека:

java.net.UnknownServiceException: Unable to find acceptable protocols. isFallback=false, modes=[ConnectionSpec(cipherSuites=[TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, TLS_AES_128_CCM_SHA256, TLS_AES_256_CCM_8_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256], tlsVersions=[TLS_1_3, TLS_1_2], supportsTlsExtensions=true)], supported protocols=[SSLv3, TLSv1, TLSv1.2]
    at okhttp3.internal.connection.ConnectionSpecSelector.configureSecureSocket(ConnectionSpecSelector.java:74)
    at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:313)
    at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:284)
    at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:169)
    at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:258)
    at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135)
    at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:114)
    at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:127)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:225)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:250)
    at okhttp3.RealCall.execute(RealCall.java:93)
    at retrofit2.OkHttpCall.execute(OkHttpCall.java:188)
    at retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall.execute(DefaultCallAdapterFactory.java:104)

Я использую собственную SocketFactory, которую я нашел в этом сообщении в блоге: https://ankushg.com/posts/tls-1.2-on-android/

и использую ее так:

fun getHttpClientBuilder(enableLogging: Boolean = BuildConfig.DEBUG, vararg customInterceptors: Interceptor): OkHttpClient.Builder {
    val timeoutSecs = if (BuildConfig.DEBUG) 0 else TIMEOUT_SECONDS_RELEASE
    val httpClientBuilder = OkHttpClient.Builder()
        .connectTimeout(timeoutSecs.toLong(), TimeUnit.SECONDS)
        .readTimeout(timeoutSecs.toLong(), TimeUnit.SECONDS)
        .writeTimeout(timeoutSecs.toLong(), TimeUnit.SECONDS)
        .connectionSpecs(listOf(ConnectionSpec.RESTRICTED_TLS)) //  Restrict to TLS 1.2 and 1.3

    for (customInterceptor in customInterceptors) {
        httpClientBuilder.addInterceptor(customInterceptor)
    }

    val logger = HttpLoggingInterceptor()
    logger.level = if (enableLogging) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.BASIC
    httpClientBuilder.addInterceptor(logger)

    return httpClientBuilder
}

fun buildHttpClient(enableLogging: Boolean = BuildConfig.DEBUG, vararg customInterceptors: Interceptor): OkHttpClient {
    return getHttpClientBuilder(enableLogging, *customInterceptors)
        .enableTls12() //This calls the custom socket factory
        .build()
}

Вызов функции enableTls12() вызывает этот код:

  @JvmStatic
    fun OkHttpClient.Builder.enableTls12() = apply {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
            try {
                val sslContext = SSLContext.getInstance(TlsVersion.TLS_1_2.javaName())
                sslContext.init(null, arrayOf(trustManager), null)

                sslSocketFactory(Tls12SocketFactory(sslContext.socketFactory), trustManager)
            } catch (e: Exception) {
                println("Error while setting TLS 1.2 compatibility:: ${e.localizedMessage}")
            }
        }
    }

Так что я думаю, что у меня есть все, что мне нужно, и это должно работать. У кого-нибудь есть предложения относительно того, что я могу попробовать или чего мне не хватает?

Спасибо

1 Ответ

0 голосов
/ 01 апреля 2020

Похожая проблема с этой ссылкой ниже, проверьте реализацию Tls12SocketFactory

Android 4.1 до 4.4 KitKat - Включить TLS 1.2 для API

...