Using self signed certificates with Android
Updated in AndroidWhen using https on Android the operating system requires that the server certificate has been signed by trusted third party vendor. In some cases this a test server, for example, might have a self signed certificate which leads to failing https connections.
Luckily in Android, and in Java, this requirement can be circumvented. Word of warning though, this is something you should only do in development code and it should be removed when the application is published!
Basics
To use self signed certificates you need to create a trust manager. The trust manager handles the validation of certificates and that’s the part of the program that throws SSLHandshakeException when your server certificate is not signed by a trusted party. Using a custom trust manager you have the ability choose which certificates are trusted and which are not, i.e. you can choose to trust or not to trust any certificate you like.
The example below shows how to create a dummy TrustManager instance which trusts all certificates.
As noted earlier this should only be used for testing and development and never in production!
Example
public class SelfSignedCertActivity extends AppCompatActivity {
private static final String TAG = "SelfSignedCertActivity";
// Verifier that verifies all hosts
private static final HostnameVerifier DUMMY_VERIFIER = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_self_signed_cert);
}
public void onOpenConnectionClick(View view) {
new OpenConnectionTask().execute();
}
private class OpenConnectionTask extends AsyncTask<Void, Void, Boolean> {
@Override
protected void onPreExecute() {
super.onPreExecute();
// Dummy trust manager that trusts all certificates
TrustManager localTrustmanager = new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
@Override
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
};
// Create SSLContext and set the socket factory as default
try {
SSLContext sslc = SSLContext.getInstance("TLS");
sslc.init(null, new TrustManager[]{localTrustmanager},
new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslc
.getSocketFactory());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
}
@Override
protected Boolean doInBackground(Void... params) {
try {
URL url = new URL("https://selfsigned.tanelikorri.com/");
HttpsURLConnection connection = (HttpsURLConnection) url
.openConnection();
connection.setHostnameVerifier(DUMMY_VERIFIER);
// Log the server response code
int responseCode = connection.getResponseCode();
Log.i(TAG, "Server responded with: " + responseCode);
// And if the code was HTTP_OK then return true
if (responseCode == HttpURLConnection.HTTP_OK) {
return true;
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
// Hide progressbar
setProgressBarIndeterminateVisibility(false);
if (result != null) {
// Create a dialog
Builder builder = new Builder(SelfSignedCertActivity.this);
if (result) {
builder.setMessage("Connection was opened successfully");
} else {
builder.setMessage("Connection failed");
}
builder.setPositiveButton("OK", null);
// and show it
builder.create().show();
}
}
}
}
Screenshots
Source code
Source code for the whole example project is available here