简体   繁体   English

使用 okHttp 进行证书固定

[英]Certificate pinning with okHttp

This question can be a duplicate of How can I pin a certificate with Square OKHTTP?此问题可能与如何使用 Square OKHTTP 固定证书? But since it's not clear I'm asking again.但因为不清楚,所以我再问一次。 I have to attach SSL certificate to my http client.我必须将 SSL 证书附加到我的 http 客户端。 I'm using retrofit version 2.2.0 and okHttp version 3.6.0我正在使用改造版本2.2.0和 okHttp 版本3.6.0

I have a certificate in .crt format.我有一个.crt格式的证书。 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?使用 okHttp 固定.crt证书是正确的方法吗? 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我看到了一些这样的样本和文档https://medium.com/@deelodroid/android-ssl-pinning-using-okhttp-ca1239065616

but it is entirely different from what I have implemented.但这与我实施的完全不同。 Nowhere they have used a crt file.他们在任何地方都没有使用过crt文件。

If someone could share a better explanation about certificate pinning and how it can be done in okHttp , it would be very helpful.如果有人可以分享有关证书固定以及如何在 okHttp 中完成的更好解释,那将非常有帮助。 Thanks in advance!!提前致谢!!

See examples here https://square.github.io/okhttp/https/#certificate-pinning-kt-java在此处查看示例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!提醒:未经服务器 TLS 管理员的许可,请勿使用证书锁定!

This is certificate pinning.这是证书固定。 It's the correct way.这是正确的方法。 You can test it using fiddler or charles by installing https certificate in phone.您可以通过在手机中安装https证书,使用fiddlercharles对其进行测试。 If request is not success, then pinning is working fine.如果请求不成功,则固定工作正常。 Test it by disabling ssl pinning as well.也可以通过禁用 ssl 固定来测试它。 In that case request will be successful and you will be able to see request + data in fiddler or charles在这种情况下,请求将成功,您将能够在 fiddler 或 charles 中看到请求 + 数据

You could also use public key pinning which will pin sha of public key inside certificate您还可以使用公钥固定,这将在证书内固定公钥的 sha

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());

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 :)快乐编码:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM