Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Self-signed SSL acceptance on Android

How do I accept a self-signed certificate in Java on Android?

A code sample would be perfect.

I've looked everywhere on the Internet and while some people claim to have found the solution, it either does not work or there is no sample code to back it up.

like image 972
Faisal Abid Avatar asked Aug 01 '09 18:08

Faisal Abid


People also ask

How do I trust a self-signed certificate in Android?

Inside your Android device, Settings > Security > Install from storage. It should detect the certificate and let you add it to the device. Browse to your development site. The first time it should ask you to confirm the security exception.


2 Answers

I have this functionality in exchangeIt, which connects to Microsoft exchange via WebDav. Here's some code to create an HttpClient which will connect to self signed cert's via SSL:

SchemeRegistry schemeRegistry = new SchemeRegistry(); // http scheme schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); // https scheme schemeRegistry.register(new Scheme("https", new EasySSLSocketFactory(), 443));  HttpParams params = new BasicHttpParams(); params.setParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 30); params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, new ConnPerRouteBean(30)); params.setParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, false); HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);  ClientConnectionManager cm = new ThreadSafeClientConnManager(params, schemeRegistry); 

The EasySSLSocketFactory is here, and the EasyX509TrustManager is here.

The code for exchangeIt is open source, and hosted on googlecode here, if you have any issues. I'm not actively working on it anymore, but the code should work.

Note that since Android 2.2 the process has changed a bit, so check this to make the code above work.

like image 55
Brian Yarger Avatar answered Sep 21 '22 07:09

Brian Yarger


As EJP correctly commented, "Readers should note that this technique is radically insecure. SSL is not secure unless at least one peer is authenticated. See RFC 2246."

Having said that, here's another way, without any extra classes:

import java.security.SecureRandom; import java.security.cert.CertificateException; import java.security.cert.X509Certificate;  import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.X509TrustManager;  private void trustEveryone() {     try {         HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier(){                 public boolean verify(String hostname, SSLSession session) {                     return true;                 }});         SSLContext context = SSLContext.getInstance("TLS");         context.init(null, new X509TrustManager[]{new X509TrustManager(){             public void checkClientTrusted(X509Certificate[] chain,                     String authType) throws CertificateException {}             public void checkServerTrusted(X509Certificate[] chain,                     String authType) throws CertificateException {}             public X509Certificate[] getAcceptedIssuers() {                 return new X509Certificate[0];             }}}, new SecureRandom());         HttpsURLConnection.setDefaultSSLSocketFactory(                 context.getSocketFactory());     } catch (Exception e) { // should never happen         e.printStackTrace();     } } 
like image 32
Chris Boyle Avatar answered Sep 21 '22 07:09

Chris Boyle