How can I pin a certificate with Square OKHTTP?

前端 未结 5 1463
生来不讨喜
生来不讨喜 2020-11-30 17:04

I think I need to create a new SSL Socket Factory? Also, I don\'t want to use the global SSL Context (https://github.com/square/okhttp/issues/184) for obvious reasons.

5条回答
  •  旧巷少年郎
    2020-11-30 17:43

    I found the example mentioned in Unknown certificate authority section of this link developer.android.com/training/articles/security-ssl very useful.

    The SSLSocketFactory returned in context.getSocketFactory() can be then used to set to OkHttpClient in setSslSocketFactory() method.

    Note : The Unknown certificate authority section also mentions the link to download a cert file to use and check this code.

    Here is the sample method I've written to obtain the SSLSocketFactory

    private SSLSocketFactory getSslSocketFactory() {
        try {
            // Load CAs from an InputStream
            // (could be from a resource or ByteArrayInputStream or ...)
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            // From https://www.washington.edu/itconnect/security/ca/load-der.crt
            InputStream caInput = getApplicationContext().getResources().openRawResource(R.raw.loadder);
            Certificate ca = null;
            try {
                ca = cf.generateCertificate(caInput);
                System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
            } catch (CertificateException e) {
                e.printStackTrace();
            } finally {
                caInput.close();
            }
    
            // Create a KeyStore containing our trusted CAs
            String keyStoreType = KeyStore.getDefaultType();
            KeyStore keyStore = KeyStore.getInstance(keyStoreType);
            keyStore.load(null, null);
            if (ca == null)
                return null;
            keyStore.setCertificateEntry("ca", ca);
    
            // Create a TrustManager that trusts the CAs in our KeyStore
            String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
            tmf.init(keyStore);
    
            // Create an SSLContext that uses our TrustManager
            SSLContext context = SSLContext.getInstance("TLS");
            context.init(null, tmf.getTrustManagers(), null);
    
            return context.getSocketFactory();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    

    Later I'm just setting this to OkHttpClient like this

    httpClient.setSslSocketFactory(sslSocketFactory);
    

    and then make the https call

    httpClient.newCall(requestBuilder.build()).enqueue(callback);
    

提交回复
热议问题