Certificate pinning Android with Retrofit

1.3k views Asked by At

I am implementing ssl pinning in my app and i use leaf node certificate which is for my website in certificate hierarchy.

 val certificatePinner = CertificatePinner.Builder()
        .add(
            BuildConfig.DOMAIN,
            Constants.SHA256_HASH
        )
    okHttpClientBuilder.certificatePinner(certificatePinner.build())
        .build()

This works perfect until the certificate remains the same. but the main problem is keeping the app up to date with SHA256 hash as the certificate expires every 3 months. If i miss on updating the new SHA256 hash, app stops working due to certificate mismatch. Is there any way to avoid this situation. Thanks in advance.

2

There are 2 answers

0
Mahesh On BEST ANSWER

using SHA hash of Root certificate solved my problem as it has a longer life

5
xcesco On

I had to manage a similar situation: I had to implement certificate pinning and I don't want to synchronize app release with certificate expiration.

The solution (is a compromise I know) I implemented works in this way: if certificate app use is still valid, the app applies the certificate pinning. If the certificate is expired, the app does not use certificate pinning. In this way, the app is "exposed with no certificate pinning" between the certificate expiration date and app update (with new certificate hashcode). During this period the app is exposed, but it continues to work!!

The code:

public abstract class CertificatePinnerManager {

    private CertificatePinnerManager() {

    }

    public static final String DATE_FORMAT="dd/MM/yyyy";
    public static final String CERTIFICATE_PINNING_END_CHECK = "12/09/2021";
    public static final String CERTIFICATE_SHA_256 = "sha256/zzz/yyy/xxxx";

    public static CertificatePinner generateCertificatePinner() {
        @SuppressLint("SimpleDateFormat") SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
        Date strDate = null;
        try {
            strDate = sdf.parse(CERTIFICATE_PINNING_END_CHECK);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        if (new Date().before(strDate)) {
            // Certificate pinning enabled
            return new CertificatePinner.Builder()
                    // domain to check
                    .add("dummy.com", CERTIFICATE_SHA_256)
                    .build();

        } else {
            // disable certificate pinning
            return new CertificatePinner.Builder().build();
        }

    }
}
// create okhttp client
OkHttpClient httpClient = new OkHttpClient.Builder()
  .certificatePinner(CertificatePinnerManager.generateCertificatePinner())
  .build()

I think it would a better solution manage certificate SHA with remote config, but for the moment, this is my solution. :D

I hope it will help you.