Android 4.2缓慢的SSL/TLS [英] Android 4.2 slow SSL/TLS

查看:90
本文介绍了Android 4.2缓慢的SSL/TLS的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用TLS 1.2和可信任证书的交换将我的Android(4.2)HTTP客户端连接到Jetty(9.1.3)-服务器在客户端受信任,客户端在服务器受信任.我正在握手,客户端读取了数据,但最多需要6秒钟.某些类来自适用于Android 4.3.5(GA)的Apache HttpClient.

I am trying to connect my Android (4.2) HTTP client to Jetty (9.1.3), using TLS 1.2 and with exchange of trusted certificates - server's is trusted on client's side, and client's is trusted on server's side. I am receiving a handshake and data is read by client but it takes up to 6 seconds. Some classes are from Apache HttpClient for Android 4.3.5 (GA).

读取密钥存储区(在扩展Application的Program类中):

Reading the key store (in Program class which extends Application):

private javax.net.ssl.SSLContext sslContext;

private org.apache.http.client.CredentialsProvider credentialsProvider;

public void createSSLContext(String pin) {
    InputStream store = null;
    try {
        String password = getPassword();
        store = getResources().openRawResource(R.raw.key_store);

        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(store, password.toCharArray());

        KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        keyFactory.init(keyStore, password.toCharArray());
        trustFactory.init(keyStore);

        String cn = null;
        List<String> aliases = Collections.list(keyStore.aliases());
        for (String alias : aliases) {
            if (!alias.equalsIgnoreCase("server")) {
                cn = alias;
                break;
            }
        }

        sslContext = SSLContext.getInstance("TLSv1.2");
        sslContext.init(keyFactory.getKeyManagers(), trustFactory.getTrustManagers(), null);

        credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(String.format("%s:%s", cn, pin)));
    } catch (Throwable t) {
        Log.e(Program.TAG, t.getMessage(), t);
        throw new RuntimeException(t.getMessage(), t);
    } finally {
        if (store != null) {
            try {
                store.close();
            } catch (IOException e) {
                Log.e(Program.TAG, e.getMessage(), e);
            }
        }
    }
}

public SSLContext getSSLContext() {
    return sslContext;
}

public HttpContext getHttpContext() {
    HttpClientContext httpContext = HttpClientContext.create();
    httpContext.setCredentialsProvider(credentialsProvider);

    return httpContext;
}

和一个客户端类:

public final class Client {

    private Context context;

    public Client(Context context) {
        this.context = context;
    }

    public void execute() {
        Program program = (Program) context.getApplicationContext();

        CloseableHttpClient client =
                HttpClients.custom()
                        .setSSLSocketFactory(
                                new SSLConnectionSocketFactory(program.getSSLContext(), new AllowAllHostnameVerifier()))
                        .build();
        HttpContext httpContext = program.getHttpContext();

        CloseableHttpResponse response = null;
        HttpEntity entity = null;

        try {
            HttpGet get = new HttpGet("https://10.1.5.195:8088/application/Application");
            response = client.execute(get, httpContext);

            entity = response.getEntity();

            String r = EntityUtils.toString(entity);
            System.out.println(r);
        } catch (Throwable t) {
            Log.e(Program.TAG, t.getMessage(), t);
        } finally {
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    Log.e(Program.TAG, e.getMessage(), e);
                }
            }
            if (entity != null) {
                try {
                    entity.consumeContent();
                } catch (IOException e) {
                    Log.e(Program.TAG, e.getMessage(), e);
                }
            }
            try {
                client.close();
            } catch (IOException e) {
                Log.e(Program.TAG, e.getMessage(), e);
            }
        }
    }
}

Android应用程序在移动设备(三星Galaxy S3,Cyanogenmod 11)上运行.移动设备和服务器都在同一网络中(在wi-fi上工作).

Android application is run on mobile device (Samsung Galaxy S3, Cyanogenmod 11). Both mobile device and server are in the same network (working on wi-fi).

在AVD上进行测试时,一切正常.

When testing on AVD everything works fine.

我应该怎么做才能使其更快?我试图设置HTTP版本1.1参数,没有延迟地启用tcp,但是它没有任何改变.

What should I do to make it faster? I have tried to set http version 1.1 param, enable tcp no delay but it didn't change anything.

在Java SE客户端中使用几乎相同的类时,接收数据大约需要400毫秒.

When using almost same classes in Java SE client, it takes about 400ms to receive data.

推荐答案

万一有人陷入类似的问题,只需阅读一些Jetty文档:

In case someone else would get stucked with similar problem just read some Jetty doc:

SslContextFactory.html#newSSLEngine

如果getNeedClientAuth()为true,则将主机名传递给newSSLEngine(String,int),可能会导致反向DNS查找,这需要花费时间并可能挂起选择器(因为此方法通常由选择器调用)线程).

If getNeedClientAuth() is true, then the host name is passed to newSSLEngine(String, int), possibly incurring in a reverse DNS lookup, which takes time and may hang the selector (since this method is usually called by the selector thread).

因此解决方案是在服务器端使用

So the solution is to use on server's side SslContextFactory.html#setWantClientAuth instead of SslContextFactory.html#setNeedClientAuth.

这篇关于Android 4.2缓慢的SSL/TLS的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆