Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create SSL-Socket on Android with self-signed certificate

Tags:

java

android

ssl

I'm trying to connect an Android app to a SSL-enabled server, which uses a self-signed certificate. I've already read through dozens of tutorials and the app is now accepting the certificate & connecting to the server, but I never get any data back.

The original code i used to initialize the socket is this:

//passphrase for keystore
char[] keystorePass="password".toCharArray();

//load own keystore (MyApp just holds reference to application context)
KeyStore keyStore=KeyStore.getInstance("BKS");
keyStore.load(MyApp.getStaticApplicationContext().getResources().openRawResource(R.raw.keystore),keystorePass);

//create a factory
TrustManagerFactory     trustManagerFactory=TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);

//get context
SSLContext sslContext=SSLContext.getInstance("TLS");

//init context
sslContext.init(
    null,
    trustManagerFactory.getTrustManagers(), 
    new SecureRandom()
);

//create the socket
Socket socket=sslContext.getSocketFactory().createSocket("hostname",443);
socket.setKeepAlive(true);

Afterwards, the run loop of the receiver thread uses socket.getInputStream() to access the input stream. As long as I use an unencrypted connection, this works without a problem. But the secure connection does not retrieve any data from the socket. I've verified this by adding log messages to the receive loop and even used OpenSSL's s_server to check. I retrieved data from the client, but the client never received anything I sent to it.

As a last test, I tried to open a connection to www.google.com:443 like this:

javax.net.SocketFactory fact=SSLSocketFactory.getDefault();
Socket socket=fact.createSocket(_config.getUri().getHost(), _config.getUri().getPort());

Still the same result, connection works but using the InputStream I receive nothing from the server.

Anybody got any ideas?

EDIT:

I'm currently not allowed to answer my own question, but here's the answer: Well, turns out the problem WAS the receive loop. I relied on InputStream.available() to get the number of bytes to read, but didn't realize it was rather unreliable (always returns 0 for SSL socket). So I switched the receive loop to use the blocking read() instead.

like image 290
mistalee Avatar asked Jan 02 '12 08:01

mistalee


People also ask

How can I take self signed certificate in Android?

Go to Settings / Security / Credential storage and select “Install from device storage”. The . crt file will be detected and you will be prompted to enter a certificate name. After importing the certificate, you will find it in Settings / Security / Credential storage / Trusted credentials / User.

Can you use self signed certificate with SSL?

When using the SSL for non-production applications or other experiments you can use a self-signed SSL certificate. Though the certificate implements full encryption, visitors to your site will see a browser warning indicating that the certificate should not be trusted.

Is SSL pinning applicable to Android?

Caution: Certificate Pinning is not recommended for Android applications due to the high risk of future server configuration changes, such as changing to another Certificate Authority, rendering the application unable to connect to the server without receiving a client software update.


1 Answers

As mentioned above: Turns out the problem WAS the receive loop. I relied on InputStream.available() to get the number of bytes to read, but didn't realize it was rather unreliable (always returns 0 for SSL socket). So I switched the receive loop to use the blocking read() instead.

like image 156
mistalee Avatar answered Nov 15 '22 12:11

mistalee