Привязка доверия не найдена для Android SSL-соединения

185

Я пытаюсь подключиться к блоку IIS6, работающему с сертификатом godaddy 256bit SSL, и получаю сообщение об ошибке:

java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

Я пытался определить, что может быть причиной этого, но сейчас рисую пробелы.

Вот как я подключаюсь:

HttpsURLConnection conn;              
conn = (HttpsURLConnection) (new URL(mURL)).openConnection();
conn.setConnectTimeout(20000);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.connect();
String tempString = toString(conn.getInputStream()); 
Chrispix
источник

Ответы:

78

Решение @Chrispix опасно! Доверие всем сертификатам позволяет любому сделать человека в середине атаки! Просто отправьте ЛЮБОЙ сертификат клиенту, и он примет его!

Добавьте свой сертификат (сертификаты) в пользовательский диспетчер доверия, как описано в этом посте: Доверие всем сертификатам с использованием HttpClient через HTTPS

Хотя установить безопасное соединение с настраиваемым сертификатом немного сложнее, он обеспечит вам требуемую безопасность шифрования ssl без опасности попадания человека в центр атаки!

Матиас Б
источник
1
Это нормально для работы с самогенерируемым сертификатом, но для одного (например, OP), который имеет действительную цепочку к корневому CA, это просто обходной путь для плохо настроенного сервера - см. Мой ответ.
Стиви
4
@Stevie Принятие КАЖДОГО сертификата - это только вариант для проверки концепции, когда SSL-соединение не является частью, которую вы хотите проверить. В противном случае вам не нужно использовать SSL, если вы принимаете каждый сертификат, так как соединение небезопасно!
Матиас Б.
1
Ах, извините, я думаю, что есть недоразумение - я полностью согласен, что никто не должен принимать каждый сертификат! :) Мой комментарий касался вашего 2-го абзаца - предложения использовать настраиваемый менеджер доверия - который, по моему мнению, должен быть последним решением, а не рекомендуемым решением.
Стиви
2
Выступите на голову ... Я удалил «решение», которое я вставил в качестве обходного пути, чтобы не вызывать больше проблем, поскольку люди не воспринимали его как «временное решение».
Chrispix
7
@Chrispix, вы не должны были удалять частичное исправление, это хорошо только для тестирования
Уго Аллексис Кардона
224

Вопреки принятому ответу вам не нужен специальный менеджер доверия, вам нужно исправить конфигурацию вашего сервера!

Я столкнулся с той же проблемой при подключении к серверу Apache с неправильно установленным сертификатом dynadot / alphassl. Я подключаюсь с помощью HttpsUrlConnection (Java / Android), который бросал -

javax.net.ssl.SSLHandshakeException: 
  java.security.cert.CertPathValidatorException: 
    Trust anchor for certification path not found.

Фактическая проблема - неверная конфигурация сервера - протестируйте ее с http://www.digicert.com/help/ или подобной, и она даже скажет вам решение:

«Сертификат не подписан доверенным органом (проверка по отношению к корневому хранилищу Mozilla). Если вы купили сертификат в доверенном органе, вам, вероятно, просто нужно установить один или несколько промежуточных сертификатов . Обратитесь к поставщику сертификатов за помощью, выполнив это для вашего серверная платформа. "

Вы также можете проверить сертификат с помощью openssl:

openssl s_client -debug -connect www.thedomaintocheck.com:443

Вы, вероятно, увидите:

Verify return code: 21 (unable to verify the first certificate)

и ранее в выводе:

depth=0 OU = Domain Control Validated, CN = www.thedomaintocheck.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 OU = Domain Control Validated, CN = www.thedomaintocheck.com
verify error:num=27:certificate not trusted
verify return:1
depth=0 OU = Domain Control Validated, CN = www.thedomaintocheck.com
verify error:num=21:unable to verify the first certificate`

Цепочка сертификатов будет содержать только 1 элемент (ваш сертификат):

Certificate chain
 0 s:/OU=Domain Control Validated/CN=www.thedomaintocheck.com
  i:/O=AlphaSSL/CN=AlphaSSL CA - G2

... но следует ссылаться на право подписи в цепочке на доверенное Android (Verisign, GlobalSign и т. д.):

Certificate chain
 0 s:/OU=Domain Control Validated/CN=www.thedomaintocheck.com
   i:/O=AlphaSSL/CN=AlphaSSL CA - G2
 1 s:/O=AlphaSSL/CN=AlphaSSL CA - G2
   i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
 2 s:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
   i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA

Инструкции (и промежуточные сертификаты) для настройки вашего сервера обычно предоставляются органом, выдавшим ваш сертификат, например: http://www.alphassl.com/support/install-root-certificate.html.

После установки промежуточных сертификатов, предоставленных моим издателем сертификатов, у меня теперь нет ошибок при подключении с использованием HttpsUrlConnection.

Стиви
источник
3
Если у ОП есть доступ к конфигурации SSL серверов, к которой он подключается, это может быть решением. Но если он не является хостером службы, к которой он подключается, он должен решить проблему со своей стороны, то есть реализовать собственный менеджер доверия.
Матиас Б
9
Ваше решение работает, без вопросов, но разве вы не согласны с тем, что это обходной путь, а не исправление основной причины? Если мне нужно подключиться к серверу из 3-х клиентов (Android, iOS, Windows Mobile), тогда мне придется применить обходной путь ко всем 3, тогда как я могу исправить сервер один раз, и все они будут «просто работать».
Стиви
2
Спасибо, Стиви, у меня неправильно настроен сервер на 3 месяца, и только сейчас я это обнаружил! Теперь мое приложение для Android работает на 100%
jpros
2
@ Steve Я делаю много вызовов различным API, которые совместно используют один и тот же домен, но только с одним из них происходит сбой (javax.net.ssl.SSLHandshakeException) ... есть идеи, почему это может произойти? и, кстати, сертификат SSL не является доверенным. Итак, я подумал, что все вызовы должны завершаться с одним и тем же исключением.
честный игрок
1
@dvaey свяжись с кем-либо, кто владеет сервером, и скажи им, что их конфигурация сломана, а их https не работает должным образом - дайте им эту ссылку, чтобы доказать это digicert.com/help ... Я думаю, они будут благодарны и быстро разрешить. В противном случае вам придется предпринять один из обходных путей в других ответах, но затем вам придется либо не принимать никаких мер безопасности (игнорировать сертификаты), либо повторно развертывать приложения, когда срок действия сертификата истекает, а хранилище пользовательских трастов больше не соответствует новому. засвидетельствовано
Стиви
17

Вы можете доверять конкретному сертификату во время выполнения.
Просто скачайте его с сервера, вставьте ресурсы и загрузите так, используя ssl-utils-android :

OkHttpClient client = new OkHttpClient();
SSLContext sslContext = SslUtils.getSslContextForCertificateFile(context, "BPClass2RootCA-sha2.cer");
client.setSslSocketFactory(sslContext.getSocketFactory());

В приведенном выше примере я использовал, OkHttpClientно SSLContextможет быть использован с любым клиентом в Java.

Если у вас есть вопросы, не стесняйтесь спросить. Я автор этой маленькой библиотеки.

Klimat
источник
как насчет .pfx?
Холецкий
2
Разве это небезопасно, поскольку любой пользователь может получить доступ к папке ресурсов для приложения, если у него есть apk?
Патрис Андала
1
@PatriceAndala, корневые CA общедоступны, так что все в порядке
BekaBot
17

Обновление на основе последней документации Android (март 2017 года):

Когда вы получаете этот тип ошибки:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
        at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:374)
        at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:209)
        at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:478)
        at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:433)
        at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)
        at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)
        at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:282)
        at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177)
        at libcore.net.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:271)

проблема может быть одной из следующих:

  1. ЦС, выдавший сертификат сервера, был неизвестен
  2. Сертификат сервера не был подписан ЦС, но был самоподписан
  3. В конфигурации сервера отсутствует промежуточный ЦС

Решение состоит в том, чтобы научить HttpsURLConnectionдоверять определенному набору CA. Как? Пожалуйста, проверьте https://developer.android.com/training/articles/security-ssl.html#CommonProblems

Другие, которые используют AsyncHTTPClientиз com.loopj.android:android-async-httpбиблиотеки, пожалуйста, проверьте Setup AsyncHttpClient для использования HTTPS .

user1506104
источник
5
Что делать, если кто-то использует okhttp-клиент?
TheLearner
Пожалуйста, проверьте ответ @ mklimek.
user1506104
14

Если вы используете модернизацию, вам нужно настроить ваш OkHttpClient.

retrofit = new Retrofit.Builder()
                        .baseUrl(ApplicationData.FINAL_URL)
                        .client(getUnsafeOkHttpClient().build())
                        .addConverterFactory(GsonConverterFactory.create())
                        .build();

Полный код приведен ниже.

    public class RestAdapter {

    private static Retrofit retrofit = null;
    private static ApiInterface apiInterface;

    public static OkHttpClient.Builder 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;
                }
            });
            return builder;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static ApiInterface getApiClient() {
        if (apiInterface == null) {

            try {
                retrofit = new Retrofit.Builder()
                        .baseUrl(ApplicationData.FINAL_URL)
                        .client(getUnsafeOkHttpClient().build())
                        .addConverterFactory(GsonConverterFactory.create())
                        .build();

            } catch (Exception e) {

                e.printStackTrace();
            }


            apiInterface = retrofit.create(ApiInterface.class);
        }
        return apiInterface;
    }

}
Шихаб Уддин
источник
1
Я пытаюсь использовать код, но снова получаю следующую ошибку ...
Вишва Пратап
Это радикально небезопасно. Не используй.
Маркиз Лорн
Спасибо! Переписал метод getUnsafeOkHttpClient()в Котлине: stackoverflow.com/a/60507560/2914140 .
CoolMind
11

Отвечаю на очень старый пост. Но, возможно, это поможет какому-то новичку, и если ничего из вышеперечисленного не получится.

Объяснение: я знаю, что никто не хочет дерьма объяснения; скорее решение. Но в одном случае вы пытаетесь получить доступ к услуге с локального компьютера на удаленный компьютер, который не доверяет вашему компьютеру. Вы запрашиваете необходимость получить доверие от удаленного сервера.

Решение: в следующем решении предполагается, что выполнены следующие условия

  1. Попытка получить доступ к удаленному API с вашего локального компьютера.
  2. Вы создаете приложение для Android
  3. Ваш удаленный сервер находится под прокси-фильтрацией (вы используете прокси-сервер в настройках браузера для доступа к удаленной службе API, обычно к промежуточному серверу или серверу разработки)
  4. Вы тестируете на реальном устройстве

шаги:

Вам нужен файл расширения .keystore для регистрации вашего приложения. Если вы не знаете, как создать файл .keystore; затем следуют вместе со следующей секции Создать .keystore файл или в противном случае переходите к следующему разделу жестового Apk файл

Создать файл .keystore

Откройте Android Studio. Нажмите верхнее меню Build> Generate Signed APK. В следующем окне нажмите кнопку Создать новую ... кнопку. В новом окне, пожалуйста, введите данные во все поля. Помните, что поле «Два пароля», которое я рекомендую, должно иметь одинаковый пароль; не используйте другой пароль; а также помнить о пути сохранения на самом верхнее поле Key пути магазина: . После ввода всех полей нажмите кнопку ОК.

Подпишите файл Apk

Теперь вам нужно создать подписанное приложение с файлом .keystore, который вы только что создали. Следуй этим шагам

  1. Построить> Очистить проект, дождаться окончания очистки
  2. Построить> Создать подписанный APK
  3. Нажмите Choose existing...кнопку
  4. Выберите файл .keystore, который мы только что создали, в разделе « Создание файла .keystore ».
  5. Введите тот же пароль, который вы создали при создании в разделе Create .keystore file . Используйте один Key store passwordи тот же пароль для Key passwordполей и. Также введите псевдоним
  6. Нажмите кнопку Далее
  7. На следующем экране; которые могут отличаться в зависимости от ваших настроек в build.gradleфайлах, вам нужно выбрать Build Typesи Flavors.
  8. Для Build Typesвыбора releaseиз выпадающего
  9. Для Flavorsоднако это будет зависит от ваших настроек в build.gradleфайле. Выберите stagingиз этого поля. Я использовал следующие настройки в build.gradle, вы можете использовать так же, как у меня, но убедитесь, что вы измените на applicationIdимя вашего пакета

    productFlavors {
        staging {
            applicationId "com.yourapplication.package"
            manifestPlaceholders = [icon: "@drawable/ic_launcher"]
            buildConfigField "boolean", "CATALYST_DEBUG", "true"
            buildConfigField "boolean", "ALLOW_INVALID_CERTIFICATE", "true"
        }
        production {
            buildConfigField "boolean", "CATALYST_DEBUG", "false"
            buildConfigField "boolean", "ALLOW_INVALID_CERTIFICATE", "false"
        }
    }
  10. Нажмите два нижних Signature Versionsфлажка и нажмите Finishкнопку.

Почти готово:

Вся тяжелая работа сделана, теперь движение истины. Чтобы получить доступ к промежуточному серверу, резервное копирование которого осуществляется через прокси-сервер, необходимо выполнить некоторые настройки в реальных тестовых устройствах Android.

Настройка прокси в устройстве Android:

  1. Нажмите Настройка внутри телефона Android, а затем Wi-Fi
  2. Длительно нажмите на подключенный Wi-Fi и выберите Modify network
  3. Нажмите, Advanced optionsесли вы не видите Proxy Hostnameполе
  4. В Proxy Hostnameвъезжают в IP или имя вы хотите подключиться. Типичный промежуточный сервер будет называтьсяstg.api.mygoodcompany.com
  5. Для порта введите четырехзначный номер порта, например 9502
  6. Нажмите Saveкнопку

Одна последняя остановка:

Помните, что мы создали подписанный файл apk в разделе Sign APK File . Сейчас самое время установить этот APK-файл.

  1. Откройте терминал и перейдите в папку с подписанным файлом apk.
  2. Подключите устройство Android к вашей машине
  3. Удалите все предыдущие установленные apk-файлы с устройства Android
  4. Бегать adb install name of the apk file
  5. Если по какой-либо причине указанная выше команда возвращается с adb command not found. Введите полный путь какC:\Users\shah\AppData\Local\Android\sdk\platform-tools\adb.exe install name of the apk file

Я надеюсь, что проблема может быть решена. Если нет, пожалуйста, оставьте мне комментарий.

Салам!

HA S
источник
4

Сообщение об ошибке, которое я получал, было похоже, но причина в том, что самоподписанный сертификат истек. Когда была предпринята попытка клиента openssl, он дал мне причину, которая была упущена из виду, когда я проверял диалог сертификата из firefox.

Таким образом, в общем случае, если сертификат находится в хранилище ключей и имеет значение «VALID», эта ошибка исчезнет.

MPN
источник
1
Если срок действия сертификата истек, значит, он недействителен в соответствии с рядом стандартов. Можно использовать обычай TrustManagerи использовать другой набор критериев. Но из коробки с этим вы должны работать.
августа
4

У меня была такая же проблема при подключении от клиента Android к серверу Kurento. Сервер Kurento использует jks-сертификаты, поэтому мне пришлось конвертировать в него pem. В качестве входных данных для преобразования я использовал файл cert.pem, и это приводило к таким ошибкам. Но если вместо cert.pem использовать fullchain.pem - все в порядке.

V.Poddubchak
источник
3

Используйте https://www.ssllabs.com/ssltest/ для проверки домена.

Решение Шихаб Уддина в Котлине.

import java.security.SecureRandom
import java.security.cert.X509Certificate
import javax.net.ssl.*
import javax.security.cert.CertificateException

companion object {

    private val gson: Gson
    private val retrofit: Retrofit

    init {

        val okHttpClient = getUnsafeOkHttpClient() // OkHttpClient().newBuilder()
            .build()

        gson = GsonBuilder().setLenient().create()

        retrofit = Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .build()
    }

    private fun getUnsafeOkHttpClient(): OkHttpClient.Builder =
        try {
            // Create a trust manager that does not validate certificate chains
            val trustAllCerts: Array<TrustManager> = arrayOf(
                object : X509TrustManager {
                    @Throws(CertificateException::class)
                    override fun checkClientTrusted(chain: Array<X509Certificate?>?,
                                                    authType: String?) = Unit

                    @Throws(CertificateException::class)
                    override fun checkServerTrusted(chain: Array<X509Certificate?>?,
                                                    authType: String?) = Unit

                    override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
                }
            )
            // Install the all-trusting trust manager
            val sslContext: SSLContext = SSLContext.getInstance("SSL")
            sslContext.init(null, trustAllCerts, SecureRandom())
            // Create an ssl socket factory with our all-trusting manager
            val sslSocketFactory: SSLSocketFactory = sslContext.socketFactory
            val builder = OkHttpClient.Builder()
            builder.sslSocketFactory(sslSocketFactory,
                trustAllCerts[0] as X509TrustManager)
            builder.hostnameVerifier { _, _ -> true }
            builder
        } catch (e: Exception) {
            throw RuntimeException(e)
        }
}
CoolMind
источник
2

У меня была та же проблема, что я обнаружил, что файл сертификата .crt, который я предоставил, пропустил промежуточный сертификат. Поэтому я спросил все файлы .crt у администратора сервера, а затем объединил их в обратном порядке.

Ex. 1. Root.crt 2. Inter.crt 3. myCrt.crt

в окнах я выполнил копию Inter.crt + Root.crt newCertificate.crt

(Здесь я проигнорировал myCrt.crt)

Затем я предоставил файл newCertificate.crt в код через inputtream. Работа сделана.

Сахан Малдения
источник
У нас тоже была такая же проблема. Промежуточный сертификат отсутствовал
Нидин Чандран
1

Ошибка привязки доверия может произойти по многим причинам. Для меня это было просто, что я пытался получить доступ https://example.com/вместо https://www.example.com/.

Поэтому вы можете дважды проверить свои URL-адреса перед началом создания собственного диспетчера доверия (как я сделал).

Unkulunkulu
источник
0

В телефонах Gingerbread я всегда получаю эту ошибку: Trust Anchor not found for Android SSL Connectionдаже если я настроен на использование своего сертификата.

Вот код, который я использую (на языке Scala):

object Security {
    private def createCtxSsl(ctx: Context) = {
        val cer = {
            val is = ctx.getAssets.open("mycertificate.crt")
            try
                CertificateFactory.getInstance("X.509").generateCertificate(is)
            finally
                is.close()
        }
        val key = KeyStore.getInstance(KeyStore.getDefaultType)
        key.load(null, null)
        key.setCertificateEntry("ca", cer)

        val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm)
    tmf.init(key)

        val c = SSLContext.getInstance("TLS")
        c.init(null, tmf.getTrustManagers, null)
        c
    }

    def prepare(url: HttpURLConnection)(implicit ctx: Context) {
        url match {
            case https: HttpsURLConnection 
                val cSsl = ctxSsl match {
                    case None 
                        val res = createCtxSsl(ctx)
                        ctxSsl = Some(res)
                        res
                    case Some(c)  c
                }
                https.setSSLSocketFactory(cSsl.getSocketFactory)
            case _ 
        }
    }

    def noSecurity(url: HttpURLConnection) {
        url match {
            case https: HttpsURLConnection 
                https.setHostnameVerifier(new HostnameVerifier {
                    override def verify(hostname: String, session: SSLSession) = true
                })
            case _ 
        }
    }
}

и вот код подключения:

def connect(securize: HttpURLConnection  Unit) {
    val conn = url.openConnection().asInstanceOf[HttpURLConnection]
    securize(conn)
    conn.connect();
    ....
}

try {
    connect(Security.prepare)
} catch {
    case ex: SSLHandshakeException /*if ex.getMessage != null && ex.getMessage.contains("Trust anchor for certification path not found")*/ 
        connect(Security.noSecurity)
}

По сути, я настроен на доверие к своему пользовательскому сертификату. Если это не удается, я отключаю безопасность. Это не лучший вариант, но единственный выбор, который я знаю со старыми и глючными телефонами.

Этот пример кода может быть легко переведен на Java.

david.perez
источник
Решение для Android 2.3.x на случай, если это кому-то понадобится, stackoverflow.com/a/46465722/7125370
Newbie009
0

В моем случае это происходило после обновления до Android 8.0. Самоподписанный сертификат Android, которому доверяли, использовал алгоритм подписи SHA1withRSA. Переход на новый сертификат с использованием алгоритма подписи SHA256 с RSA устранил проблему.

ЦУС
источник
0

Я знаю, что вам не нужно доверять всем сертификатам, но в моем случае у меня были проблемы с некоторыми средами отладки, где у нас были самозаверяющие сертификаты, и мне требовалось грязное решение.

Все, что мне нужно было сделать, это изменить инициализацию sslContext

mySSLContext.init(null, trustAllCerts, null); 

где trustAllCertsбыл создан так:

private final TrustManager[] trustAllCerts= new TrustManager[] { new X509TrustManager() {
    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
        return new java.security.cert.X509Certificate[]{};
    }

    public void checkClientTrusted(X509Certificate[] chain,
                                   String authType) throws CertificateException {
    }

    public void checkServerTrusted(X509Certificate[] chain,
                                   String authType) throws CertificateException {
    }
} };

Надеюсь, что это пригодится.

Адриан С.
источник
Это я и хотел найти! Спасибо
Oxied
Я получаю ошибку Hostname '192.168.0.16' was not verified. Я тестирую свой webapi через мой отладчик (IIS Express) локально. Есть идеи как это исправить? Спасибо :)
Сэм
1
Это радикально небезопасно. Не используй.
Маркиз Лорн
0

У меня была похожая проблема, и я полностью исключил стратегию доверия всем источникам.

Я делюсь здесь своим решением, примененным к приложению, внедренному в Kotlin

Сначала я бы порекомендовал использовать следующий веб-сайт для получения информации о сертификате и его действительности.

Если он не отображается как «Принятые эмитенты» в доверенном хранилище Android по умолчанию , мы должны получить этот сертификат и включить его в приложение для создания настраиваемого хранилища доверенных сертификатов.

Идеальным решением в моем случае было создание диспетчера доверия высокого уровня, который сочетает в себе пользовательское хранилище доверия и Android-хранилище по умолчанию.

Здесь он представляет высокоуровневый код, используемый для настройки OkHttpClient, который он использовал с Retrofit.

override fun onBuildHttpClient(httpClientBuild: OkHttpClient.Builder) {

        val trustManagerWrapper = createX509TrustManagerWrapper(
            arrayOf(
                getCustomX509TrustManager(),
                getDefaultX509TrustManager()
            )
        )

        printX509TrustManagerAcceptedIssuers(trustManagerWrapper)

        val sslSocketFactory = createSocketFactory(trustManagerWrapper)
        httpClientBuild.sslSocketFactory(sslSocketFactory, trustManagerWrapper)

    }

Таким образом, я мог общаться с сервером с самозаверяющим сертификатом и с другими серверами с сертификатом, выданным доверенным органом сертификации.

Это все, я надеюсь, что это может кому-то помочь.

Серхио Санчес Санчес
источник
0

Я знаю, что это очень старая статья, но я наткнулся на эту статью, пытаясь решить свои проблемы с доверием. Я опубликовал, как я это исправил. Если вы предварительно установили Root CA, вам нужно добавить конфигурацию в манифест.

https://stackoverflow.com/a/60102517/114265

GR посланник
источник
только для API 24+
BekaBot
@BekaBot - это, вероятно, так, но в соответствии с документацией 23 и ниже доверяет сертификатам пользователей по умолчанию. По умолчанию защищенные соединения (использующие протоколы, такие как TLS и HTTPS) из всех приложений доверяют предустановленным системным ЦС и приложениям, ориентированным на Android 6.0. (Уровень API 23) и ниже также доверяют добавленному хранилищу CA по умолчанию
GR Envoy
-1
**Set proper alias name**
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509","BC");
            X509Certificate cert = (X509Certificate) certificateFactory.generateCertificate(derInputStream);
            String alias = cert.getSubjectX500Principal().getName();
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            trustStore.load(null);
trustStore.setCertificateEntry(alias, cert);
Даянанд Вагмаре
источник
-2

Я также столкнулся с той же проблемой. Я просто удаляю hhtps в http, например

final public static String ROOT_URL = "https://example.com"; в final public static String ROOT_URL = "http://example.com";

Наконец, я решил эту проблему.

Rasheduzzaman
источник
Конечно, это просто удаление защиты SSL из уравнения, что, вероятно, является плохой идеей для производственной среды.
Драконьи мысли
Это действительно не решение, удаляющее безопасность SSL.
omega1