Okhttp3 - Accept all certificates and use a certificatePinner

后端 未结 2 1238
迷失自我
迷失自我 2021-01-01 07:00

I\'m trying to pin my server\'s self-signed certificate. My OkHttpClient takes two parameters, the first one is the ssl Socket Factory :

final TrustManager[]         


        
相关标签:
2条回答
  • 2021-01-01 07:39
    private static OkHttpClient getUnsafeOkHttpClient() {
      try {
        // Create a trust manager that does not validate certificate chains
        final TrustManager[] trustAllCerts = new TrustManager[] {
            new X509TrustManager() {
              @Override
              public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
              }
    
              @Override
              public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
              }
    
              @Override
              public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return new java.security.cert.X509Certificate[]{};
              }
            }
        };
    
        // Install the all-trusting trust manager
        final SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
        // Create an ssl socket factory with our all-trusting manager
        final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
    
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.sslSocketFactory(sslSocketFactory, (X509TrustManager)trustAllCerts[0]);
        builder.hostnameVerifier(new HostnameVerifier() {
          @Override
          public boolean verify(String hostname, SSLSession session) {
            return true;
          }
        });
    
        OkHttpClient okHttpClient = builder
            .connectTimeout(15, TimeUnit.SECONDS)
            .writeTimeout(15, TimeUnit.SECONDS)
            .readTimeout(15, TimeUnit.SECONDS)
            .build();
        return okHttpClient;
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }
    
    0 讨论(0)
  • 2021-01-01 07:50

    The TrustManager, CertificatePinner and Hostname verification all do different but important things. If you want to use self-signed certificates but still have security, as opposed to self-signed certificates purely for ease of local development then you probably want to create a valid TrustManager.

    e.g. https://github.com/yschimke/oksocial/blob/3757196cde420b9d0fe37cf385b66f4cdafb1ae1/src/main/java/com/baulsupp/oksocial/security/CertificateUtils.java#L19

      public static X509TrustManager load(List<File> serverCerts)
          throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException {
        return trustManagerForKeyStore(keyStoreForCerts(serverCerts));
      }
    
      public static X509TrustManager trustManagerForKeyStore(KeyStore ks)
          throws NoSuchAlgorithmException, KeyStoreException {
        TrustManagerFactory tmf =
            TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    
        tmf.init(ks);
    
        return (X509TrustManager) tmf.getTrustManagers()[0];
      }
    
      public static KeyStore keyStoreForCerts(List<File> serverCerts)
          throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException {
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
    
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(null);
    
        for (int i = 0; i < serverCerts.size(); i++) {
          try (InputStream is = new FileInputStream(serverCerts.get(i))) {
            X509Certificate caCert = (X509Certificate) cf.generateCertificate(is);
            ks.setCertificateEntry("cacrt." + i, caCert);
          }
        }
        return ks;
      }
    

    This will start off with the system certificates loaded, so your client can still be used to load externally hosted images etc.

    Then on top of that you can use CertificatePinner to require that only your trusted self-signed certificates are used for your domain.

    0 讨论(0)
提交回复
热议问题