如何在Android(4.4.2)上使用TLSv1.2使SSLEngine生效?

26

大家好,我希望我错过了一些显而易见的东西,希望有人能够给予一些指导。我正在尝试在SSL + NIO上下文(使用AndroidAsync库)中启用TLSv1.2,因此我尝试通过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 "Protocol TLSv1.2 is not supported."的错误信息。
我可以看到上下文声称支持TLSv1.2,但是我从该上下文中创建的引擎却不支持?这是怎么回事?顺便说一下,在上面的第一行中,如果我使用"TLS"而不是"TLSv1.2",则所有内容都不会改变。
我猜想这可能与此问题有关,我已经阅读了这个(尚未回答)的问题像这样的文章,但它们似乎没有完全解决问题——我看到的解决方案似乎都依赖于SSLSocket而不是SSLEngine。
非常感谢您能提供的任何知识。

更新 6/23/14 10:00AM EDT

我找到了 SSLEngine.setSSLParameters,我希望可以通过它传递一个从 SSLContext.getSupportedSSLParameters() 获取的 SSLParameters,但是当我调用它时,会抛出一个异常,声称不支持密码套件,因此看起来 setSSLParameters() 只是做与 setEnabledCipherSuites() 相同的事情,并且引擎已经处于一种状态,在该状态下它不识别 TLS 1.2 协议 / 套件作为受支持的。


当您执行 sslContext.setEnabledProtocols(new String[] { "TLSv1.2" }),然后执行 sslContext.createSSLEngine(); 会发生什么? - Martin Konecny
SSLContext没有setEnabledProtocols() API。然而,我刚刚发现了SSLEngine.setSSLParameters()。即将编辑问题。 - Glen
嗨,格伦,我在这个问题上卡住了,你能帮我吗?https://stackoverflow.com/questions/49946350/okhttp-android-websocket-and-jetty-server-connection-with-ssl - Firnaz
3个回答

64

Android API文档正确说明,仅支持API Level 20或更高版本(Lollipop)的SSLEngine使用TLSv1.2,而SSLSocket从Level 16起就支持它。

对于我们的项目,使用SSLSocket或要求API 20都不是一个选项,改变服务器代码以允许TLSv1或SSLv3也不行。我们的解决方案是安装一个更新的安全提供程序,使用Google Play服务

    ProviderInstaller.installIfNeeded(getApplicationContext());

这实际上让您的应用程序可以访问新版本的OpenSSL和Java安全提供程序,其中包括SSLEngine中对TLSv1.2的支持。安装新的提供程序后,您可以按照通常的方式创建支持SSLv3、TLSv1、TLSv1.1和TLSv1.2的SSLEngine:

    SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
    sslContext.init(null, null, null);
    SSLEngine engine = sslContext.createSSLEngine();

或者,您可以使用 engine.setEnabledProtocols 来限制启用的协议。


嘿,感谢你的回答!这是我们尚未尝试过的事情,我们将在接下来的几天尝试一下,然后标记为已接受。 - Glen
1
嗨!我们如何在Android上使用HttpsUrlConnection? - source.rar
伙计,你真棒!ProviderInstaller.installIfNeeded(getApplicationContext()); 这就是为什么我的应用在 Android 4.0 上无法工作的原因。 - Ossir
你知道是否有任何方法可以在AVD上进行测试,例如使用api 18?我已经创建了一个带有api 18 + Google Apis的AVD。在这种情况下,我只能看到具有TLS v1和3的SSLEngine。当我添加“ProviderInstaller”和谷歌服务依赖项时,我会得到安装升级的对话框,但由于它是AVD,我无法通过该屏幕。 - Juan
嘿,你真的救了我:),非常感谢! - Amal Kronz
你用了 Google Play 服务中的哪个实际包?一共有大约20个包可供选择。 - lxknvlk

7

如果您正在使用okHttp,请尝试此解决方案。 在Android 4.4上启用TLSv1.2的解决方案

在Android < 5.0(16 <= API < 20)上遇到了同样的问题。感谢您的帖子,我能够使其正常工作,所以对于任何到达这里的人,这是开箱即用的解决方案。在撰写本文时,我使用的是OkHttp 3.4.1。

标签:无法找到可接受的协议,javax.net.ssl.SSLProtocolException:SSL握手中止:


哇!太棒了,它解决了我的问题,我已经被卡了4天了,谢谢Wolfgang Profer。 - Shoaib Anwar

3

以下是使用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作为中间件似乎有效。


1
最好解释一下为什么这个解决方案有效,至少是你博客文章的转述。 - cryptic_star
@JordanRéjaud 上下文会从哪里传递进来? - user1744228
1
我认为在Ion中设置SSLContext可能更好:Ion.getDefault(this).getHttpClient().getSSLSocketMiddleware().setSSLContext(sslContext); - Raanan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接