Доверие / белый список сертификата в OkHttp (доверенный якорь для пути сертификации не найден) - PullRequest
0 голосов
/ 24 января 2019

У меня проблема с устройствами Android 4, которые получают следующее исключение при подключении к серверу:

java.security.cert.CertPathValidatorException: доверенная привязка для путь сертификации не найден. на com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake (OpenSSLSocketImpl.java:410) по адресу okhttp3.internal.connection.RealConnection.connectTls (SourceFile: 319) по адресу okhttp3.internal.connection.RealConnection.establishProtocol (SourceFile: 283) по адресу okhttp3.internal.connection.RealConnection.connect (SourceFile: 168) в okhttp3.internal.connection.StreamAllocation.findConnection (SourceFile: 257) в okhttp3.internal.connection.StreamAllocation.findHealthyConnection (SourceFile: 135) в okhttp3.internal.connection.StreamAllocation.newStream (SourceFile: 114) по адресу okhttp3.internal.connection.ConnectInterceptor.intercept (SourceFile: 42) по адресу okhttp3.internal.http.RealInterceptorChain.proceed (SourceFile: 147) в okhttp3.internal.http.RealInterceptorChain.proceed (SourceFile: 121) на okhttp3.internal.cache.CacheInterceptor.intercept (SourceFile: 93) по адресу okhttp3.internal.http.RealInterceptorChain.proceed (SourceFile: 147) в okhttp3.internal.http.RealInterceptorChain.proceed (SourceFile: 121) по адресу okhttp3.internal.http.BridgeInterceptor.intercept (SourceFile: 93) по адресу okhttp3.internal.http.RealInterceptorChain.proceed (SourceFile: 147) в okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept (SourceFile: 126) по адресу okhttp3.internal.http.RealInterceptorChain.proceed (SourceFile: 147) в okhttp3.internal.http.RealInterceptorChain.proceed (SourceFile: 121) в okhttp3.RealCall.getResponseWithInterceptorChain (SourceFile: 254) по адресу okhttp3.RealCall.execute (SourceFile: 92)

Сертификат сервера от Cloudflare, я проверил его с помощью нескольких инструментов, таких как https://www.digicert.com/help/, и, похоже, все в порядке.

Но по какой-то причине я не понимаю, что он начал давать сбой в версиях Android 4.

Попробовал решение доверять всем сертификатам [LINK] , и это работает, но это, очевидно, имеет проблемы с безопасностью, такие как подвергание вашего приложения атаке "человек посередине"

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[]{};
            }
        }
};
final SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
okHttpBuilder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);

Как я могу реализовать TrustManager с поведением по умолчанию, но в белый список входит только сертификат сервера.

Спасибо

Редактировать: по примеру OkHttp @ CustomTrust (Спасибо CommonsWare)

Использовал команду:

openssl s_client -showcerts -servername www.serverdomain.com -connect www.serverdomain.com:443

В цепочке сертификатов дали мне два сертификата в формате:

-----BEGIN CERTIFICATE-----
....
-----END CERTIFICATE-----

Заменил URL и сертификаты в примере на полученные, но он все еще не работает, есть идеи?

1 Ответ

0 голосов
/ 24 января 2019

Вам нужно сохранить ваш сертификат в сырой папке, затем:

CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream instream = context.getResources().openRawResource(R.raw.gtux_cert);
Certificate ca;
try {
    ca = cf.generateCertificate(instream);
} finally {
    caInput.close();
}

KeyStore kStore = KeyStore.getInstance(KeyStore.getDefaultType());
kStore.load(null, null);
kStore.setCertificateEntry("ca", ca);

TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm(););
tmf.init(kStore);

SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);

okHttpClient.setSslSocketFactory(context.getSocketFactory());

Больше информации здесь: Безопасность SSL

...