I am trying to connect my Android (4.2) HTTP client to Jetty (9.1.3) using TLS 1.2 and with the exchange of trusted certificates - the server is trusted on the client side, and the client is trusted on the server side. I get a handshake and the data is read by the client, but it takes up to 6 seconds. Some classes belong to Apache HttpClient for Android 4.3.5 (GA).
Reading the keystore (in the class of the program that extends the 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; }
And client class:
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); } } } }
The Android application runs on a mobile device (Samsung Galaxy S3, Cyanogenmod 11). Both the mobile device and the server are on the same network (running on Wi-Fi).
When testing on AVD, everything works fine.
What to do to make it faster? I tried to set the http option 1.1, enable tcp without delay, but didn't change anything.
When using almost the same classes in the Java SE client, it takes about 400 ms to get the data.