2015-08-30 48 views
14

Bir Android uygulamasında com.squareup.retrofit:retrofit:1.9.0 ile com.squareup.okhttp:okhttp:2.4.0'u kullanarak, kendinden imzalı bir sertifika kullanan HTTPS üzerinden bir sunucu REST API'siyle iletişim kurmaya çalışıyorsunuz.Sertifika Android'de OkHttp ile çalışmayan sertifika

Sunucu anahtar deposunda özel bir anahtar ve 2 sertifika, sunucunun ve bir kök sertifikası vardır. openssl s_client çıktı - Android uygulaması At

Certificate chain 
0 s:/C=...OU=Dev/CN=example.com 
    i:/C=... My CA/[email protected] 
1 s:/C=... My CA/[email protected] 
    i:/C=... My CA/[email protected] 

, OkHttp kök sertifikanın SHA1 imzasıyla başlatıldığını -

CertificatePinner certificatePinner = new CertificatePinner.Builder() 
     .add("example.com", "sha1/5d...3b=") 
     .build(); 

OkHttpClient client = new OkHttpClient(); 
client.setCertificatePinner(certificatePinner); 

RestAdapter restAdapter = new RestAdapter.Builder() 
     .setEndpoint("https://example.com") 
     .setClient(new OkClient(client)) 
     .build(); 

Ama bir istek göndermeye çalışırken durumla başarısız -

retrofit.RetrofitError: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. 
     at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:395) 
     at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:240) 
     at java.lang.reflect.Proxy.invoke(Proxy.java:397) 
     at $Proxy1.report(Unknown Source) 
     ... 
     at android.os.AsyncTask$2.call(AsyncTask.java:288) 
     at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) 
     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
     at java.lang.Thread.run(Thread.java:818) 
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. 
     at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:306) 
     at com.squareup.okhttp.internal.http.SocketConnector.connectTls(SocketConnector.java:103) 
     at com.squareup.okhttp.Connection.connect(Connection.java:143) 
     at com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java:185) 
     at com.squareup.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:128) 
     at com.squareup.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:341) 

sslSocket.startHandshake() çalışırken com.squareup.okhttp.internal.http.SocketConnector adresinden atılır, CertificatePinner alınan sertifikaları kontrol etmek için kullanılır ficates.

Sunucunun openssl ve curl --cacert root.pem ile doğru şekilde yüklenmiş sertifikalarının olduğundan emin oldum.

Peki neden sağlanan sertifikaların iyi olup olmadığını kontrol etmeye çalışan OkHttp neden bir istisna atar?

cevap

5

OkHttp, kendinden imzalı sertifikaları desteklemez.

Bilinen bir CA tarafından imzalanmış bir sertifikayı kullanırken, el sıkışmaları başarılı olur ve CertificatePinner sertifika zincirinin sağlanan imzalardan en az birini içerdiğinden emin olur. Hiçbiri görünmez, isteği keserek bir istisna atar.

Bu nedenle, bilinen bir CA tarafından imzalanmış bir sertifikayı kullanmak ve doğru sunucuyla konuştuğumuzdan emin olmak için sertifikalardan birini sabitlemek mümkündür.

+2

Yup. Sertifika sabitleme mevcut sertifika doğrulamasının yerini almaz; onu tamamlar. Müşterinizi sertifikanıza güvenecek şekilde yapılandırmanız gerekir; Testlerde bolca örnek var! –

+0

@JesseWilson and @Kof: Bir soru sorabilir miyim, bilinen bir CA, Android telefonunda başarılı bir şekilde yüklenmiş bir CA anlamına gelir ('Güvenilir kimlik bilgileri - Kullanıcı 'bölümünde görebilirim? Teşekkürler – BNK

+0

Muhtemelen bir CA Cihazın güvenilen CA veritabanında imzası var – Kof

3

OkHttp, kendinden imzalı sertifikaları destekliyor.

Yalnızca sertifikanıza güvenen bir SslSocket oluşturmayı öğrenmek için lütfen this answer numarasını kontrol edin.

+2

Örnek kodun görülebileceği başka bir yer de OkHttp tarifindeki repo: [CustomTrust.java] (https://github.com/square/okhttp/blob/master/samples/guide /src/main/java/okhttp3/recipes/CustomTrust.java) Daha genel bir çalışma kodu sağlar. – Anonsage