Trust Anchor не найден для подключения SSL для Android

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

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()); 

Ответ 1

Решение @Chrispix опасно! Доверяя всем сертификатам, кто-то может сделать человека в средней атаке! Просто отправьте ANY сертификат клиенту, и он примет его!

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

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

Ответ 2

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

Я столкнулся с той же проблемой при подключении к серверу 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`

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

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-utils-android:

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

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

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

Ответ 4

Обновление на основе последней документации для 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. CA, выдавший сертификат сервера, был неизвестен
  2. Сертификат сервера не был подписан ЦС, но был подписан сам
  3. В конфигурации сервера отсутствует промежуточный центр сертификации

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

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

Ответ 5

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

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

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

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

шаги:

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

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

Откройте Android Studio. Нажмите верхнее меню "Сборка"> "Создать подписанный АПК". В следующем окне нажмите кнопку " Создать новый...". В новом окне введите данные во все поля. Помните, что два поля Password, которые я рекомендую, должны иметь один и тот же пароль; не используйте другой пароль; а также помните путь сохранения в верхней части поля основного хранилища ключей:. После ввода всего поля нажмите кнопку "ОК".

Подписать файл Apk

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

  1. Build> Clean Project, дождитесь завершения очистки
  2. Сборка> Создание подписанного APK
  3. Нажмите " Choose existing...
  4. Выберите файл.keystore, который мы только что создали, в разделе Create.keystore
  5. Введите тот же пароль, который вы создали при создании в разделе Создать.keystore. Используйте тот же пароль для полей Key store password Key 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. Запустить name of the apk file adb install name of the apk file
  5. Если по какой-либо причине приведенная выше команда возвращает adb command not found. Введите полный путь как C:\Users\shah\AppData\Local\Android\sdk\platform-tools\adb.exe name of the apk file install name of the apk file

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

Салам!

Ответ 6

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

В общем случае, если сертификат находится в хранилище ключей и его "VALID", эта ошибка будет отключена.

Ответ 7

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

Ответ 8

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

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

в windows я выполняется скопируйте файл Inter.crt + Root.crt newCertificate.crt

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

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

Ответ 9

В телефонах 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.

Ответ 10

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

Ответ 11

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

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

Ответ 12

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

Все, что мне нужно было сделать, это изменить инициализацию 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 {
    }
} };

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

Ответ 13

**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);