Заставить SSLEngine использовать TLSv1.2 на Android (4.4.2)?
Люди, я надеюсь, что есть что-то очевидное, что я упускаю, и я надеюсь, что кто-то сможет пролить немного света. Я пытаюсь запустить TLSv1.2 в контексте SSL + NIO (используя библиотеку AndroidAsync), поэтому я пытаюсь включить его через SSLEngine. Я могу запустить код так:
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, null, null);
String[] protocols = sslContext.getSupportedSSLParameters().getProtocols();
for (String protocol : protocols) {
Timber.d("Context supported protocol: " + protocol);
}
SSLEngine engine = sslContext.createSSLEngine();
String[] supportedProtocols = engine.getSupportedProtocols();
for (String protocol : supportedProtocols) {
Timber.d("Engine supported protocol: " + protocol);
}
И в итоге я вижу это на logcat:
06-22 21:56:27.715 1117-1117/? D/XXX﹕ Context supported protocol: SSLv3
06-22 21:56:27.715 1117-1117/? D/XXX﹕ Context supported protocol: TLSv1
06-22 21:56:27.725 1117-1117/? D/XXX﹕ Context supported protocol: TLSv1.1
06-22 21:56:27.725 1117-1117/? D/XXX﹕ Context supported protocol: TLSv1.2
06-22 21:56:27.735 1117-1117/? D/XXX﹕ Engine supported protocol: TLSv1
06-22 21:56:27.745 1117-1117/? D/XXX﹕ Engine supported protocol: SSLv3
Конечно, если я попытаюсь engine.setEnabledProtocols(new String[] { "TLSv1.2" })
Я получаю IllegalArgumentException "Протокол TLSv1.2 не поддерживается".
Я вижу контекстные утверждения для поддержки TLSv1.2, но тогда движок, который я создаю из этого контекста, не работает? Что тут происходит? Ничего из этого не изменится, если я использую "TLS" вместо "TLSv1.2" в первой строке выше, кстати.
Я полагаю, что это может быть как-то связано с этой проблемой, и я читал этот (пока еще без ответа) вопрос и статьи, подобные этой, но они, похоже, не достигли цели - решения, которые я видел, похоже, все полагаться на SSLSocket, а не SSLEngine.
Большое спасибо за любые знания, которые вы можете оставить.
ОБНОВЛЕНИЕ 23/23/14 10AMEDT
Итак, я нашел SSLEngine.setSSLParameters
, который я надеялся, позволил бы мне передать в SSLParameters, которые я получил от SSLContext.getSupportedSSLParameters()
, но когда я вызываю это, я получаю исключение, которое утверждает, что наборы шифров не поддерживаются, поэтому похоже, что setSSLParameters() просто делает то же самое, что и setEnabledCipherSuites(), и механизм уже находится в состоянии, в котором он не не распознает протокол / наборы TLS 1.2 как поддерживаемые.
3 ответа
Документы API Android правильно утверждают, что TLSv1.2 поддерживается только для SSLEngine в API уровня 20 или новее (Lollipop), а SSLSocket поддерживает его начиная с уровня 16.
Использование SSLSocket или требование API 20 не было вариантом для нашего проекта, и ни один из них не изменял код сервера, чтобы разрешить TLSv1 или SSLv3. Нашим решением было установить нового поставщика безопасности с помощью Google Play Services:
ProviderInstaller.installIfNeeded(getApplicationContext());
Это эффективно дает вашему приложению доступ к более новой версии OpenSSL и провайдера безопасности Java, который включает поддержку TLSv1.2 в SSLEngine. После установки нового провайдера вы можете создать SSLEngine, который поддерживает SSLv3, TLSv1, TLSv1.1 и TLSv1.2 обычным способом:
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, null, null);
SSLEngine engine = sslContext.createSSLEngine();
Или вы можете ограничить включенные протоколы, используя engine.setEnabledProtocols
,
Попробуйте это решение, если вы используете okHttp. Решение для включения TLSv1.2 на Android 4.4
Была такая же проблема на Android < 5.0 (16 <= API < 20). Благодаря вашим сообщениям я смог сделать эту работу, поэтому для всех, кто сюда попал, это готовое решение. На момент написания статьи я использовал OkHttp 3.4.1.
Теги: не удается найти приемлемые протоколы, javax.net.ssl.SSLProtocolException: SSL рукопожатие прервано:
Вот как это сделать с помощью AndroidAsync:
ProviderInstaller.installIfNeeded(context);
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(KeyManager[] km, TrustManager[] tm, SecureRandom rm);
SSLEngine engine = sslContext.createSSLEngine();
AsyncHttpClient.getDefaultInstance().insertMiddleware((AsyncHttpClientMiddleware) engine);
Обновление SSLEngine и вставка его как промежуточного ПО в AndroidAsync, похоже, работает.