0

Using HttpsUrlConnection on Android, if I connect to a server with an untrusted certificate, most likely a self signed one, I'll get an error. When something similar happens in a browser for instance, I get the option to accept that certificate anyway.

  1. The plan is to run the URL connection as normal.
  2. If an certificate error occurs, rerun it with the Dummy "trust all" settings, while of course still breaking the connection as soon at the certificates have been received (in the X509TrustManager and then the HostNameVerifier). Returning false in the HostNameVerifier does that trick quite nicely.
  3. Ask the user if they really want to use this certificate.

Now, how do I add this certificate to the application's store, for it to be used next time a connection is made to that server?

Or do I need to cook my own X509TrustManager/HostNameVerifier, and compare the incoming certificate data to the one stored, while maintaining normal function for all CA signed certificates.

In other words.

  1. Retrive the public certificate from the server (done)
  2. Ask the user if they want to use it anyway.
  3. IMPORT that public certificate somewhere in the app's own store for use in future connections.
  4. fallback to the regular trust chain for all CA trusted certificates.

Because I've seen this with all other questions asking something similar to this, where people start offering all the wrong solutions. I do NOT want an AcceptAllVerifier. I can NOT use anything that requires me to import the certificate manually.

A.Grandt
  • 2,242
  • 2
  • 20
  • 21

1 Answers1

0

If I correctly understand your issue, then you don't have to AcceptAllVerifier as in your question.

The following code is an example I think you can refer:

Let's assume your server app is hosting inside a server machine which has a server certificate in which "Issued to" is "localhost", for example. Then, inside verify method you can verify "localhost".

     HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
     urlConnection.setSSLSocketFactory(getSSLSocketFactory());
     urlConnection.setHostnameVerifier(new HostnameVerifier() {
               @Override
                    public boolean verify(String hostname, SSLSession session) {
                        HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
                        return hv.verify("localhost", session);
                    }
                });

More about cert file, getSSLSocketFactory... you can refer to the following questions (of course they can be applied for HttpsUrlConnection):

Does Android Volley support SSL?

Volley SSL - Hostname was not verified

Hope this helps!

Community
  • 1
  • 1
BNK
  • 23,994
  • 8
  • 77
  • 87
  • You also need the TrustManager. For the moment I'm playing with having a custom X509TrustManager using the system keystore, and with another custom X509TrustManager inside that using my own keystore, in the verify methods I then catch the error if the "global" keystore can't verify, and then call the inner TrustManager testing against my own KeyStore. If that fails, the connection is untrusted, and I can them pull the received certificate chain from the custom TrustManager and ask the user, adding the certificates to my own keystore – A.Grandt Oct 05 '15 at 12:23
  • Sorry I don't understand much about your comment. Looks like that you have already had your own solution, what are you looking for with your question? – BNK Oct 05 '15 at 13:40