8

Recently I work on the project that has implemented the SSL.

The SSL cert is expire once per year. And it throw exception in android after I renew the cert on the server.

06-13 11:20:27.709: D/allenj(30076): javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

After I looking through the project code, I saw there is a bks file, so , does it mean I have to update the bks file once per year, and I have to re-upload the app to google play as well.

The problem is what is the standard way to cope with the renewal of the SSL cert? Thanks for helping.

Code extract

nnable Register_runnable = new Runnable(){
        @Override
        public void run() {
            EditText emailText = (EditText) findViewById(R.id.editText1regist);

            EditText pwText = (EditText) findViewById(R.id.editText2registpw);

            String end = "\r\n";
            String twoHyphens = "--";
            String boundary = "*****";
            try {
                KeyStore keyStore = KeyStore.getInstance("BKS");
                InputStream in =  
                getResources().openRawResource(R.raw.ballooncardbks);
                keyStore.load(in, "".toCharArray());
                TrustManagerFactory tmf = 
                TrustManagerFactory.getInstance("X509");
                tmf.init(keyStore);

                SSLContext context = SSLContext.getInstance("TLS");
                context.init(null, tmf.getTrustManagers(), null);

                String actionUrl = "https://app.ballooncard.com/api/client/register/format/json";
                URL url = new URL(actionUrl);
                HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
             //   con.setDoInput(true);
                con.setDoOutput(true);
                con.setUseCaches(false);
                con.setRequestMethod("POST");

                con.setSSLSocketFactory(context.getSocketFactory());

                con.setRequestProperty("Connection", "Keep-Alive");
                con.setRequestProperty("Charset", "UTF-8");
                con.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
user782104
  • 13,233
  • 55
  • 172
  • 312
  • Can I prevent the above exception after renew the cert? Thanks – user782104 Jun 13 '14 at 03:26
  • The certificate pinning is a great security control. *Before* you take the advice to abandon it, you should talk to some security folks who understand the web security model and PKIX. If I was your security guy, I would deny the request and tell you to update the pinned certificate in the client. – jww Jun 13 '14 at 09:28
  • And you don't need to store the certificate in a KeyStore (hidden away like it is). You can store it plain text as a file resource, and you can even hard code it into your app as a string. See, for example, [Options for Programatically Adding Certificates to Java KeyStore](https://stackoverflow.com/questions/24043397/options-for-programatically-adding-certificates-to-java-keystore). – jww Jun 13 '14 at 09:30
  • By the way.... This *will* return an SSL context (and not a TLS exclusive context): `SSLContext.getInstance("TLS")`. There's hardening that should be applied to it, too - both protocol hardening and cipher suite hardening. For example, SSLv3 will be enabled, and TLS 1.1 and 1.2 will be disabled. See, for example, [Which Cipher Suites to enable for SSL Socket?](https://stackoverflow.com/questions/1037590/which-cipher-suites-to-enable-for-ssl-socket). – jww Jun 13 '14 at 09:32
  • Be careful if storing certificate as String, as suggested, since users could extract the certificate from app. – Don G. Feb 20 '23 at 20:11

2 Answers2

3

Looks like the app is using "certificate pinning", which means that a certificate has been hardcoded into the app, and the app has been instructed to accept only that certificate and no other.

This increases security at the expense that you need to update your app when (ideally before) the certificate expires. You can following the instructions from a post I created here:

https://stackoverflow.com/a/24007536/276949

to generate a new .bks file from your certificate. Once this is done, overwrite your old .bks file and your app should successfully connect via SSL.

Community
  • 1
  • 1
Martin Konecny
  • 57,827
  • 19
  • 139
  • 159
  • Thanks for your suggestion. Sorry I am just to take over the project and never implement SSL stuff before. I have searched for a while and there is some approach for paying to renew , and the "pinning" is the best apporach if I don't want to pay? – user782104 Jun 13 '14 at 03:41
  • 2
    Yes you can use this method to create a "self-signed" certificate which means you won't have to pay. However you can also get an "official" certificate for free from https://www.startssl.com/ – Martin Konecny Jun 13 '14 at 03:43
  • Because that means I have to update the app once per year and are there any workaround for that ? Is my current situation like that : Not using SSL / using SSL then I need to update once per year / pay for it – user782104 Jun 13 '14 at 03:43
  • 1
    Using the StartSSL free certificate, you won't have to re-release once a year. Simply updating the certificate on your server will be enough. However in this case, remove the `.bks` custom certificate code from your app. – Martin Konecny Jun 13 '14 at 03:44
  • it seems my boss has already purchased the ssl cert (renewal the cert), what is the difference between using that one and the one in StartSSL? That means if I use that one so I need to update once per year? Thanks for your patient – user782104 Jun 13 '14 at 03:47
  • 1
    There's no difference really. StartSSL gives them out for free but charges money if you want to revoke it (they reversed the standard business model). All certificates expire so you will always eventually need to update your certificate server side. You will need to update the app only if it's hardcoded to accept a specific certificate and no other. If the certificate is an "official" one, and you don't hardcode it into your app, the app will still recognize it. – Martin Konecny Jun 13 '14 at 03:51
  • So, after I remove the bks file, those bks revelant code I still have the SSL protection as long as I use the link "https"? – user782104 Jun 13 '14 at 03:57
  • 1
    Yes exactly. There are over 30 companies that can issue SSL certificates. There's a small risk that an attacker could hack one of them and create another valid SSL certificate for your domain (which is what certificate pinning addresses). However if you're not worried about this (and most people aren't except big companies like Google, Microsoft etc.), then go ahead and remove it. – Martin Konecny Jun 13 '14 at 04:04
  • besides the android code , so I also need to remove some code on the server side PHP that relevant to the bks? thanks – user782104 Jun 13 '14 at 04:13
  • 1
    No there shouldn't be any code that you need to touch server-side. – Martin Konecny Jun 13 '14 at 04:14
0

Apps by default trust the pre-installed system Certificate Authorities (CA), like this example: https://www.digitalocean.com/community/tutorials/retrofit-android-example-tutorial

Check if you really need to use certificate pinning (https://owasp.org/www-community/controls/Certificate_and_Public_Key_Pinning) in your application.

In case you want to disable Certificate Pinning, delete android:networkSecurityConfig line from AndroidManifest.xml and/or comment domain-config block from network_security_config.xml

Don G.
  • 117
  • 6