Я тестирую свое приложение на старых устройствах, так как мы нацелены на развивающийся рынок и ожидаем, что пользователи будут иметь более старые устройства до леденцов.
Я использую 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}")
}
}
}
Так что я думаю, что у меня есть все, что мне нужно, и это должно работать. У кого-нибудь есть предложения относительно того, что я могу попробовать или чего мне не хватает?
Спасибо