2

This question can be a duplicate of How can I pin a certificate with Square OKHTTP? But since it's not clear I'm asking again. I have to attach SSL certificate to my http client. I'm using retrofit version 2.2.0 and okHttp version 3.6.0

I have a certificate in .crt format. Currently I'm doing the certificate pinning as shown here. But I don't know its proper or not. Following is my code

       static void pinCertificate(Context context, OkHttpClient.Builder builder) {
            try {
                CertificateFactory cf = CertificateFactory.getInstance("X.509");
                InputStream cert = context.getResources().openRawResource(R.raw.certificate);
                Certificate ca;
                ca = cf.generateCertificate(cert);

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


                String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
                TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
                tmf.init(keyStore);


                SSLContext sslContext = SSLContext.getInstance("TLS");
                sslContext.init(null, tmf.getTrustManagers(), null);
                builder.sslSocketFactory(sslContext.getSocketFactory());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

Is it the proper way to pin a .crt certificate with okHttp? How can we test if it is doing the handshake properly? If it is wrong can anyone show a sample code to pin the certificate properly? I saw some samples and documenst like this https://medium.com/@develodroid/android-ssl-pinning-using-okhttp-ca1239065616

but it is entirely different from what I have implemented. Nowhere they have used a crt file.

If someone could share a better explanation about certificate pinning and how it can be done in okHttp , it would be very helpful. Thanks in advance!!

  • 2
    Your code is for supporting a self-signed certificate, which requires more than pinning. If you want certificate pinning of an ordinary certificate from a certificate authority, the Medium post that you link to is fine. – CommonsWare Oct 26 '17 at 12:20
  • `crt` file means its a self signed certificate? –  Oct 26 '17 at 12:37
  • Not necessarily. Ask whoever is maintaining your Web site whether that is a self-signed certificate or not. – CommonsWare Oct 26 '17 at 12:39

3 Answers3

1

See examples here https://square.github.io/okhttp/https/#certificate-pinning-kt-java

  private val client = OkHttpClient.Builder()
      .certificatePinner(
          CertificatePinner.Builder()
              .add("publicobject.com", "sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=")
              .build())
      .build()

Reminder: Do not use certificate pinning without the blessing of your server’s TLS administrator!

Yuri Schimke
  • 12,435
  • 3
  • 35
  • 69
-1

This is certificate pinning. It's the correct way. You can test it using fiddler or charles by installing https certificate in phone. If request is not success, then pinning is working fine. Test it by disabling ssl pinning as well. In that case request will be successful and you will be able to see request + data in fiddler or charles

You could also use public key pinning which will pin sha of public key inside certificate

I have implemented the following way

            InputStream cert = context.getResources().openRawResource(R.raw.certificate);            
            CertificateFactory cf=CertificateFactory.getInstance("X.509", "BC");
            InputStream caInput = new BufferedInputStream(cert);
            X509Certificate ca = (X509Certificate) cf.generateCertificate(caInput);
            caInput.close();
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null);
            keyStore.setCertificateEntry(ca.getSubjectX500Principal().getName(), ca);
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
            kmf.init(keyStore, null);
            KeyManager[] keyManagers = kmf.getKeyManagers();
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            tmf.init(keyStore);
            SSLContext context1 = SSLContext.getInstance("TLS");
            context1.init(keyManagers, tmf.getTrustManagers(), null);
            builder.sslSocketFactory(context1.getSocketFactory());
Sangeet Suresh
  • 2,527
  • 1
  • 18
  • 19
  • _**This is certificate pinning. It's the correct way**_ you mean the code I pasted? –  Oct 26 '17 at 12:27
  • 1
    "This is certificate pinning" -- the developers of OkHttp disagree. [**This** is certificate pinning](https://github.com/square/okhttp/wiki/HTTPS#certificate-pinning). What you have is [replacing the platform's trusted certificates with your own](https://github.com/square/okhttp/wiki/HTTPS#customizing-trusted-certificates). – CommonsWare Oct 26 '17 at 12:40
  • @CommonsWare there any issue by doing so? Do I need to change anything? –  Oct 26 '17 at 12:45
  • 1
    @Jrd: If your certificate is a self-signed certificate, code like what you have in your question, or what appears in this answer, is fine, so long as you are not planning on making requests of any other servers using this `OkHttpClient` instance. If your certificate is an ordinary SSL certificate, signed by a certificate authority, you can use the simpler certificate pinning code from the Medium post and [the OkHttp documentation](https://github.com/square/okhttp/wiki/HTTPS#certificate-pinning). – CommonsWare Oct 26 '17 at 12:48
  • @CommonsWare Terminologies may differ. Someone will prefer certificate pinning and public key pinning. Certificate pinning means pinning certificate. Public key pinning means pinning only public key part of certificate. You can go through this blog https://medium.com/@appmattus/android-security-ssl-pinning-1db8acb6621e – Sangeet Suresh Oct 26 '17 at 13:09
-1

The way you are doing is the proper way. I did this too in the same way you are implementing. Its good to go with it. Happy Coding :)

Muhammad Saad Rafique
  • 3,158
  • 1
  • 13
  • 21