Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTTPS GET (SSL) with Android and self-signed server certificate

Tags:

java

android

ssl

I have looked into various posts about how to retrieve something via HTTPS on Android, from a server that uses a self-signed certificate. However, none of them seem to work - they all fail to remove the

javax.net.ssl.SSLException: Not trusted server certificate message.

It is not an option to modify the server to have a trusted certificate, and it is also not an option to make the server certificate match the server's IP address.

Note, that the server will not have a DNS name, it will only have an IP-address. The GET request looks something like this:

 https://username:password@anyIPAddress/blabla/index.php?param=1&param2=3 

I am fully aware that this solution is prone to man-in-the-middle attacks etc.

So, the solution must ignore the lack of trust in the certificate, and ignore the hostname mismatch.

Does anybody know the code, that does this, using Java for Android?

There are plenty of attempts to explain this on stackoverflow.com, and plenty of code snippets, but they don't seem to work, and nobody has provided one block of code that solves this, as far as I can see. It would be interesting to know if somebody really solved this, or if Android simply blocks certificates that are not trusted.

like image 348
Lars D Avatar asked Sep 21 '10 15:09

Lars D


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.


1 Answers

As you correctly point out, there are two issues: a) the certificate isn't trusted, and b) the name on the certificate doesn't match the hostname.

WARNING: for anybody else arriving at this answer, this is a dirty, horrible hack and you must not use it for anything that matters. SSL/TLS without authentication is worse than no encryption at all - reading and modifying your "encrypted" data is trivial for an attacker and you wouldn't even know it was happening.

Still with me? I feared so...

a) is solved by creating a custom SSLContext whose TrustManager accepts anything:

SSLContext ctx = SSLContext.getInstance("TLS"); ctx.init(null, new TrustManager[] {   new X509TrustManager() {     public void checkClientTrusted(X509Certificate[] chain, String authType) {}     public void checkServerTrusted(X509Certificate[] chain, String authType) {}     public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[]{}; }   } }, null); HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory()); 

and b) by creating a HostnameVerifier which allows the connection to proceed even though the cert doesn't match the hostname:

HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {   public boolean verify(String hostname, SSLSession session) {     return true;   } }); 

Both must happen right at the beginning of your code, before you start messing around with HttpsURLConnections and so on. This works both in Android and the regular JRE. Enjoy.

like image 160
SimonJ Avatar answered Oct 17 '22 22:10

SimonJ