2017-02-17 7 views
1

サーバーの自己署名証明書を固定しようとしています。Okhttp3 - すべての証明書を受け入れ、証明書を使用してください。

new CertificatePinner.Builder() 
    .add("bogus.com", "sha1/BOGUS") 
    .build() 

注:

final TrustManager[] trustAllCerts = new TrustManager[] { 
     new X509TrustManager() { 
      @SuppressLint("TrustAllX509TrustManager") 
      @Override 
      public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {} 

      @SuppressLint("TrustAllX509TrustManager") 
      @Override 
      public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {} 

      @Override 
      public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
        return new X509Certificate[0]; 
      } 
     } 
    }; 

// Install the all-trusting trust manager 
SSLContext sslContext; 
try { 
    sslContext = SSLContext.getInstance("SSL"); 
    sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); 
} catch (NoSuchAlgorithmException | KeyManagementException e) { 
    e.printStackTrace(); 
    FirebaseCrash.report(e); 
    return null; 
} 

// Create an ssl socket factory with our all-trusting manager 
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); 

第二には、証明書のピンナです:私は、その後、すべての作品をcertificatePinnerを追加しない場合 私OkHttpClientは、2つのパラメータを取り、最初のものは、SSLソケットファクトリです良い。問題は、要求が実行されますと、CertificatePinner.check()が呼び出されるということです。

if (pins.isEmpty()) return; 

もちろん、私は(空でない)certificatePinnerを設定しない場合、方法はそこに停止しませんし、続行します。 "少なくとも私のホスト名に固定された証明書の1つが信頼できる証明書であることを確認します"

問題は、TrustManagerのgetAcceptedIssuersに空の配列を渡したことです。つまり、「getAcceptedIssues」で明示的に信頼されていないため、自己署名付き証明書が例外をトリガーします。 "getAcceptedIssuers"で明示的に信頼されていない証明書を固定するのは不可能なようです。

これを回避する方法はありますか?それは設計によるのですか?

これは私が私のOkHttpClientを構築する方法である:

OkHttpClient client = new OkHttpClient.Builder() 
    .sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]) 
    .certificatePinner(certPinner) 
    .readTimeout(10, TimeUnit.SECONDS) 
    .connectTimeout(10, TimeUnit.SECONDS) 
    .build(); 

答えて

2

のTrustManager、CertificatePinnerとホスト名の検証すべてが異なるが、重要なことを行います。純粋にローカル開発を容易にするために自己署名証明書を使用するのではなく、自己署名証明書を使用したいがセキュリティを持っている場合は、有効なTrustManagerを作成したいと思うかもしれません。

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; 
    } 

あなたのクライアントはまだ外部からロードするために使用することができますので、これは、ロードされたシステム証明書でオフを開始しますが、画像を催しなど

そして、その上に、あなたはそれだけで、あなたの必要とするCertificatePinnerを使用することができます信頼できる自己署名証明書がお客様のドメインで使用されています。

+0

あなたが提供したコードは、私の元の質問に正確には答えていませんが、間違いなく助けてくれました。あなたの助けを借りて、有効なTrustManagerを作成しました。 – geecko

+0

ええ、私はあなたがしようと思っていたことに答えようとしていました。自分で署名した証明書を追加して、安全な接続を確立しました。すべての証明書を受け入れてから固定しようとするのは、典型的な使用例のようではありません。 –

1
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

この回答はおそらく正確で有用なものですが、問題の解決に役立つ方法を説明するためには[http://meta.stackexchange.com/q/114762/159034] [あなたにそれに沿って説明を含める]ことをお勧めします。これは、将来的には、それが機能しなくなり、読者が以前にどのように働いていたかを理解する必要がある変更(無関係かもしれない)がある場合に特に有用になります。 –

+0

@KevinBrownあなたは正しいですが、ただ助けたいと思っていましたが、実際にここの人たちの動揺になりました。 – samcpp

+2

には、OkHttp3のサンプルコードが必要です – Lunatikul

関連する問題