Androidアプリで_com.squareup.okhttp:okhttp:2.4.0
_と_com.squareup.retrofit:retrofit:1.9.0
_を使用し、サーバーと通信しようとしていますREST API over HTTPS、自己使用署名された証明書。
サーバーキーストアには、秘密鍵と2つの証明書、サーバーとルート証明書があります。 _openssl s_client
_出力-
_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]
_
Androidアプリでは、OkHttpはルート証明書のSHA1署名で初期化されます-
_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();
_
しかし、リクエストを送信しようとすると、例外が発生して失敗します-
_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()
を試行すると、受信した証明書をチェックするためにCertificatePinner
が使用される前であっても、_com.squareup.okhttp.internal.http.SocketConnector
_でスローされます。
openssl
と_curl --cacert root.pem
_を使用して、サーバーに証明書が正しくインストールされていることを確認しました。
では、提供された証明書に問題がないかどうかを確認する前に、OkHttpが例外をスローするのはなぜですか?
OkHttpは自己署名証明書をサポートしていません。
既知のCAによって署名された証明書を使用する場合、ハンドシェイクは成功し、CertificatePinner
は、証明書チェーンに提供された署名の少なくとも1つが含まれていることを確認します。何も表示されない場合は、例外がスローされ、リクエストが停止します。
したがって、既知のCAによって署名された証明書を使用し、証明書の1つを固定して、適切なサーバーと通信していることを確認することができます。
OkHttpは自己署名証明書をサポートします。
証明書のみを信頼するSslSocket
を作成する方法については、 この回答 を確認してください。