Как заставить 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" в первой строке выше, btw.
Я понимаю, что это может иметь какое-то отношение к этой проблеме, и я прочитал этот (еще не отвеченный) вопрос и статьи, подобные этому, но они, похоже, не попадают в точку - решения Я видел, что все, похоже, полагаются на SSLSocket, а не на SSLEngine.
Большое спасибо за любые знания, которые вы можете потерять.
ОБНОВЛЕНИЕ 6/23/14 10AMEDT
Итак, я нашел SSLEngine.setSSLParameters
, который, я надеялся, позволил мне передать SSLParameters, который я получил из SSLContext.getSupportedSSLParameters()
, но когда я вызываю это, я получаю исключение, которое утверждает, что набор шифров не поддерживается, поэтому он похоже, что setSSLParameters() делает то же самое, что и setEnabledCipherSuites(), и движок уже находится в состоянии, когда он не распознает протокол/пакеты TLS 1.2 как поддерживаемый.
Ответы
Ответ 1
Документы Android API правильно указывают, что TLSv1.2 поддерживается только для SSLEngine в API уровня 20 или более поздней версии (Lollipop), в то время как SSLSocket поддерживает его начиная с уровня 16.
Использование SSLSocket или требование API 20 не было вариантом для нашего проекта, и ни один из них не менял код сервера, чтобы разрешить TLSv1 или SSLv3. Нашим решением было установить более нового поставщика безопасности, используя Службы Google Play:
ProviderInstaller.installIfNeeded(getApplicationContext());
Это эффективно дает вашему приложению доступ к более новой версии OpenSSL и Java Security Provider, которая включает поддержку 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
.
Ответ 2
Вот как это сделать с 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, похоже, работает.
Ответ 3
Попробуйте это решение, если вы используете okHttp.
Решение для включения TLSv1.2 на Android 4.4
Была ли та же проблема на Android < 5,0 (16 <= API < 20). Благодаря вашим сообщениям я смог сделать эту работу, поэтому для тех, кто попадает сюда, это готовое решение. На момент написания этой статьи я использую OkHttp 3.4.1.
Теги: невозможно найти приемлемые протоколы, javax.net.ssl.SSLProtocolException: SSL-рукопожатие отменено: