javaandroidamazon-ec2httpsurlconnectionself-signed-certificate

Android HttpsURLConnection works with self-signed certificate on emulator but not on real device


I used this command to create a self-signed certificate for a nginx server running on EC2 instance

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/selfsigned.key -out /etc/ssl/certs/selfsigned.crt

As a common name (e.g. server FQDN or YOUR name) I used Public DNS of EC2 instance that is something like ec2-somenumber.region.compute.amazonaws.com

I use this code to resolve the trust issues, I copied the selfsigned.crt to the application raw folder and used it in this way:

CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = getResources().openRawResource(R.raw.selfsigned);
Certificate ca = cf.generateCertificate(caInput);

// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);

// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);

// Create an SSLContext that uses our TrustManager
SSLContext _sslContext = SSLContext.getInstance("TLS");
_sslContext.init(null, tmf.getTrustManagers(), null);

URL url = new URL("https://ec2-somenumber.region.compute.amazonaws.com");
HttpsURLConnection connection = (HttpsURLConnection)url.openConnection();
connection.setSSLSocketFactory(_sslContext.getSocketFactory());

Now it's perfectly working on emulator but when I try to debug it on the real device it gives me this error:

 javax.net.ssl.SSLPeerUnverifiedException: Hostname ec2-somenumber.region.compute.amazonaws.com not verified

I read a lot of questions here on stackoverlow and I actually don't want to override hostnameVerifier, until I understand why it works on emulator but not on real device.

Do you have any suggestions?

Thanks


Solution

  • If you have the same problem please refer to this link for certificate generation.

    To make a self-signed certificate work on real device I needed to specify the Subject Alternative Name like this in the ssl.conf file that I used for the certificate creation

    [alt_names]
    DNS.1   = ec2-somenumber.region.compute.amazonaws.com