Используя com.squareup.okhttp:okhttp:2.4.0
с com.squareup.retrofit:retrofit:1.9.0
в приложении для Android, пытайтесь установить связь с сервером REST API через HTTPS, который использует самоподписанный сертификат.
У сервера keystore есть закрытый ключ и 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()
он выбрасывается при com.squareup.okhttp.internal.http.SocketConnector
, даже до CertificatePinner
используется для проверки полученных сертификатов.
Я убедился, что сервер правильно установил сертификаты, используя openssl
и curl --cacert root.pem
.
Итак, почему OkHttp генерирует исключение, прежде чем пытаться проверить, соответствуют ли сертификаты?