I'm having trouble with getting Android to connect to a simple OpenSSL
server using the HttpsUrlConnection
object (I've combed through StackOverflow and a bunch of online tutorials, and followed the examples pretty much line for line and I still can't figure out why mine is broken when I use my local truststore).
I currently have an Android activity that attempts to connect to a simple OpenSSL server
(I can connect to my server using a OpenSSL client), once the HttpsUrlConnection.connect()
is called I receive a "javax.net.ssl.SSLException: Connection closed by peer" error during the SSL handshake.
Perhaps I am setting up my sample server incorrectly?
Things to note:
- no client authorization at the moment
- am able to connect to https://www.google.com when loading default trust store
- am not able to connect to server on localhost with self-signed certificate
- do not want to trust all certificates
- do not want to use Apache HttpClient
- want to use local truststore only
- created local truststore with bouncy castle
- am able to correctly load truststore into
- behind a proxy firewall, proxy is set on my android virtual device
- AVD set to
Android 4.1 API 16
.
Things I have already tried:
- connecting to both
127.0.0.1 and 10.0.2.2
- using a new
SecureRandom() with the SSLContext.init()
- creating the URL with
'URL u = new URL("https", "10.0.2.2", 443, "/");'
- using
TrustManagerFactory.getDefaultAlgorithms()
instead of the "X509"- gives
"Unexpected response code error 503"
instead of "Connection closed by peer"
- gives
Thank you in advance for taking the time to review my question!
Simple server started with command:
$ sudo openssl s_server -accept 443 -cert server-cert.pem -key server-key.pem -pass file:passphrase.txt -state -www -verify 0
Client connection tested with command:
$ openssl s_client -connect 127.0.0.1:443
Android activity code (edited to remove complete running code for simplification - please let me know if more code is needed) - error output is below the code.
try { TrustManagerFactory tmf; // local trust store tmf = TrustManagerFactory.getInstance("X509"); tmf.init(loadLocalKeyStore(getApplicationContext())); // default trust store - works for https://www.google.com // tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); // tmf.init((KeyStore) null); SSLContext context = SSLContext.getInstance("TLS"); context.init(null, tmf.getTrustManagers(), null); HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.STRICT_HOSTNAME_VERIFIER; URL u = new URL("https://10.0.2.2"); HttpsURLConnection urlConnection = (HttpsURLConnection) u.openConnection(); urlConnection.setSSLSocketFactory(context.getSocketFactory()); urlConnection.setHostnameVerifier(hostnameVerifier); urlConnection.connect(); System.out.println("Response Code: " + urlConnection.getResponseCode()); System.out.println("Response Code: " + urlConnection.getCipherSuite()); } ... private KeyStore loadLocalKeyStore(Context context) { InputStream in = context.getResources().openRawResource(R.raw.newserverkeystore); KeyStore trusted = null; try { trusted = KeyStore.getInstance("BKS"); trusted.load(in, "thisisasecret".toCharArray()); } finally { in.close(); } return trusted; }
Output when connecting correctly to https://www.google.com:
09-09 21:58:09.947: I/System.out(669): Response Code: 200 09-09 21:58:09.947: I/System.out(669): Response Code: TLS_ECDHE_RSA_WITH_RC4_128_SHA
Output when trying to connect to my server with self-signed certificate:
09-09 22:03:23.377: D/HttpsProxy(717): Https Request error 09-09 22:03:23.377: D/HttpsProxy(717): javax.net.ssl.SSLException: Connection closed by peer 09-09 22:03:23.377: D/HttpsProxy(717): at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method) 09-09 22:03:23.377: D/HttpsProxy(717): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:395) 09-09 22:03:23.377: D/HttpsProxy(717): at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:210) 09-09 22:03:23.377: D/HttpsProxy(717): at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:478) 09-09 22:03:23.377: D/HttpsProxy(717): at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:442) 09-09 22:03:23.377: D/HttpsProxy(717): at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:289) 09-09 22:03:23.377: D/HttpsProxy(717): at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:239) 09-09 22:03:23.377: D/HttpsProxy(717): at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:80) 09-09 22:03:23.377: D/HttpsProxy(717): at libcore.net.http.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:165) 09-09 22:03:23.377: D/HttpsProxy(717): at com.example.myfirstapp.HttpsUrlConnectionActivity$3.doInBackground(HttpsUrlConnectionActivity.java:257) 09-09 22:03:23.377: D/HttpsProxy(717): at com.example.myfirstapp.HttpsUrlConnectionActivity$3.doInBackground(HttpsUrlConnectionActivity.java:1) 09-09 22:03:23.377: D/HttpsProxy(717): at android.os.AsyncTask$2.call(AsyncTask.java:287) 09-09 22:03:23.377: D/HttpsProxy(717): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) 09-09 22:03:23.377: D/HttpsProxy(717): at java.util.concurrent.FutureTask.run(FutureTask.java:137) 09-09 22:03:23.377: D/HttpsProxy(717): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230) 09-09 22:03:23.377: D/HttpsProxy(717): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076) 09-09 22:03:23.377: D/HttpsProxy(717): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569) 09-09 22:03:23.377: D/HttpsProxy(717): at java.lang.Thread.run(Thread.java:856)
Thanks again!!