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

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.

Leave a Comment