Vertrauensanker für Android SSL-Verbindung nicht gefunden


184

Ich versuche, eine Verbindung zu einer IIS6-Box herzustellen, auf der ein Godaddy 256-Bit-SSL-Zertifikat ausgeführt wird, und es wird folgende Fehlermeldung angezeigt:

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

Ich habe versucht herauszufinden, was das verursachen könnte, aber jetzt Leerzeichen gezogen.

So verbinde ich mich:

HttpsURLConnection conn;              
conn = (HttpsURLConnection) (new URL(mURL)).openConnection();
conn.setConnectTimeout(20000);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.connect();
String tempString = toString(conn.getInputStream()); 

Antworten:


78

Die Lösung von @Chrispix ist gefährlich! Wenn Sie allen Zertifikaten vertrauen, kann jeder einen Mann im mittleren Angriff ausführen! Senden Sie einfach JEDES Zertifikat an den Kunden und er wird es akzeptieren!

Fügen Sie Ihre Zertifikate einem benutzerdefinierten Vertrauensmanager hinzu, wie in diesem Beitrag beschrieben: Vertrauen aller Zertifikate mithilfe von HttpClient über HTTPS

Obwohl es etwas komplexer ist, eine sichere Verbindung mit einem benutzerdefinierten Zertifikat herzustellen, bietet es Ihnen die gewünschte SSL-Verschlüsselungssicherheit, ohne dass die Gefahr besteht, dass sich ein Mann im mittleren Angriff befindet!


1
Dies ist in Ordnung für die Arbeit mit einem selbst generierten Zertifikat, aber für eines (wie das OP), das eine gültige Kette zurück zu den Stammzertifizierungsstellen hat, ist es nur eine Problemumgehung für einen schlecht konfigurierten Server - siehe meine Antwort.
Stevie

4
@Stevie Das Akzeptieren JEDES Zertifikats ist nur eine Option für einen Proof-of-Concept-Test, bei dem die SSL-Verbindung nicht der Teil ist, den Sie testen möchten. Andernfalls müssen Sie kein SSL verwenden, wenn Sie jedes Zertifikat akzeptieren, da die Verbindung nicht sicher ist!
Matthias B

1
Ah, es tut mir leid, ich denke, es gibt ein Missverständnis - ich stimme vollkommen zu, dass niemand jemals jedes Zertifikat akzeptieren sollte! :) Mein Kommentar bezog sich auf Ihren zweiten Absatz - den Vorschlag, einen benutzerdefinierten Vertrauensmanager zu verwenden -, der meiner Meinung nach eher ein letzter Ausweg als eine empfohlene Lösung sein sollte.
Stevie

2
Ich habe die 'Lösung' entfernt, die ich als Workaround eingefügt habe, um keine weiteren Probleme zu verursachen, da die Leute sie nicht als 'temporäre Workaround' betrachteten.
Chrispix

7
@Chrispix, Sie sollten die teilweise Korrektur nicht entfernt haben, es ist nur zu Testzwecken gut
Hugo Allexis Cardona

224

Im Gegensatz zur akzeptierten Antwort benötigen Sie keinen benutzerdefinierten Vertrauensmanager, sondern müssen Ihre Serverkonfiguration korrigieren!

Ich habe das gleiche Problem beim Herstellen einer Verbindung zu einem Apache-Server mit einem falsch installierten Dynadot / Alphassl-Zertifikat festgestellt. Ich verbinde mich mit HttpsUrlConnection (Java / Android), das geworfen hat -

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

Das eigentliche Problem ist eine Fehlkonfiguration des Servers. Testen Sie es mit http://www.digicert.com/help/ oder ähnlichem, und Sie erfahren sogar die Lösung:

"Das Zertifikat ist nicht von einer vertrauenswürdigen Behörde signiert (Überprüfung anhand des Mozilla-Stammspeichers). Wenn Sie das Zertifikat von einer vertrauenswürdigen Behörde gekauft haben, müssen Sie wahrscheinlich nur ein oder mehrere Zwischenzertifikate installieren . Wenden Sie sich an Ihren Zertifikatsanbieter, um diesbezüglich Unterstützung zu erhalten Serverplattform. "

Sie können das Zertifikat auch mit openssl überprüfen:

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

Sie werden wahrscheinlich sehen:

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

und früher in der Ausgabe:

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`

Die Zertifikatskette enthält nur 1 Element (Ihr Zertifikat):

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

... sollte aber die Signaturbehörden in einer Kette auf eine zurückführen, der Android vertraut (Verisign, GlobalSign usw.):

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

Anweisungen (und die Zwischenzertifikate) zum Konfigurieren Ihres Servers werden normalerweise von der Behörde bereitgestellt, die Ihr Zertifikat ausgestellt hat, z. B.: Http://www.alphassl.com/support/install-root-certificate.html

Nach der Installation der von meinem Zertifikatsaussteller bereitgestellten Zwischenzertifikate habe ich jetzt keine Fehler beim Herstellen einer Verbindung mit HttpsUrlConnection.


3
Wenn das OP Zugriff auf die SSL-Konfiguration des Servers hat, zu der es eine Verbindung herstellt, ist dies möglicherweise eine Lösung. Wenn er jedoch nicht derjenige ist, der den Dienst hostet, mit dem er eine Verbindung herstellt, muss er das Problem auf seiner Seite beheben, dh einen benutzerdefinierten Vertrauensmanager implementieren.
Matthias B

9
Ihre Lösung funktioniert, keine Frage, aber stimmen Sie nicht zu, dass es sich eher um eine Problemumgehung als um eine Lösung für die Grundursache handelt? Wenn ich von 3 Clients (Android, iOS, Windows Mobile) aus eine Verbindung zu einem Server herstellen muss, muss ich die Problemumgehung auf alle 3 anwenden, während ich den Server einmal reparieren kann und alle "nur funktionieren".
Stevie

2
Danke Stevie, ich hatte meinen Server 3 Monate lang falsch konfiguriert und erst jetzt habe ich das erkannt! Jetzt funktioniert meine Android App 100%
jpros

2
@Stevie Ich rufe viele verschiedene APIs auf, die dieselbe Domain verwenden, aber nur eine davon schlägt fehl (javax.net.ssl.SSLHandshakeException) ... eine Idee, warum so etwas passieren würde? Übrigens ist das SSL-Zertifikat nicht vertrauenswürdig. Daher dachte ich, dass alle Anrufe mit derselben Ausnahme fehlschlagen sollten.
Ein fairer Spieler

1
@dvaey setzen Sie sich mit demjenigen in Verbindung, dem der Server gehört, und teilen Sie ihm mit, dass seine Konfiguration fehlerhaft ist und sein https nicht richtig funktioniert. Geben Sie ihm diesen Link, um dies zu beweisen. digicert.com/help ... Ich kann mir vorstellen, dass sie dankbar und schnell dafür sind Entschlossenheit. Andernfalls müssen Sie einen der Workaround-Schritte in den anderen Antworten ausführen, dann aber entweder keine Sicherheit akzeptieren (Zertifikate ignorieren) oder Ihre Apps erneut bereitstellen, wenn das Zertifikat abläuft und Ihr benutzerdefinierter Trust Store nicht mehr mit dem neuen übereinstimmt cert.
Stevie

17

Sie können einem bestimmten Zertifikat zur Laufzeit vertrauen.
Laden Sie es einfach vom Server herunter, fügen Sie Assets ein und laden Sie es mit ssl-utils-android wie folgt :

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

Im obigen Beispiel habe ich verwendet OkHttpClient, SSLContextkann aber mit jedem Client in Java verwendet werden.

Wenn Sie Fragen haben, können Sie diese gerne stellen. Ich bin der Autor dieser kleinen Bibliothek.


was ist mit .pfx?
Choletski

2
Ist das nicht unsicher, da jeder Benutzer auf den Assets-Ordner für eine App zugreifen kann, sobald er die apk hat?
Patrice Andala

@PatriceAndala, Stammzertifizierungsstellen sind öffentlich verfügbar, daher ist es in
Ordnung

16

Update basierend auf der neuesten Android-Dokumentation (März 2017):

Wenn Sie diese Art von Fehler erhalten:

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)

Das Problem könnte eines der folgenden sein:

  1. Die Zertifizierungsstelle, die das Serverzertifikat ausgestellt hat, war unbekannt
  2. Das Serverzertifikat wurde nicht von einer Zertifizierungsstelle signiert, sondern selbst signiert
  3. In der Serverkonfiguration fehlt eine Zwischenzertifizierungsstelle

Die Lösung besteht darin, zu lehren HttpsURLConnection, einem bestimmten Satz von Zertifizierungsstellen zu vertrauen. Wie? Bitte überprüfen Sie https://developer.android.com/training/articles/security-ssl.html#CommonProblems

Andere, die AsyncHTTPClientaus der com.loopj.android:android-async-httpBibliothek verwenden, überprüfen bitte Setup AsyncHttpClient, um HTTPS zu verwenden .


5
Was ist, wenn man einen okhttp-Client verwendet?
TheLearner

Für okhttp überprüfen Sie bitte die Antwort von @ mklimek.
user1506104

14

Wenn Sie eine Nachrüstung verwenden, müssen Sie Ihren OkHttpClient anpassen.

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

Der vollständige Code ist wie folgt.

    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
Ich versuche, Code zu verwenden, erhalte jedoch erneut den folgenden Fehler. "Javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Vertrauensanker für Zertifizierungspfad nicht gefunden."
Vishwa Pratap

Das ist radikal unsicher. Verwende nicht.
Marquis von Lorne

Vielen Dank! Die Methode getUnsafeOkHttpClient()in Kotlin wurde neu geschrieben: stackoverflow.com/a/60507560/2914140 .
CoolMind

11

Antwort auf sehr alten Beitrag. Aber vielleicht hilft es einem Neuling und wenn keiner der oben genannten Punkte klappt.

Erklärung: Ich weiß, niemand will Erklärung Mist; eher die Lösung. In einem Liner versuchen Sie jedoch, von Ihrem lokalen Computer aus auf einen Dienst von einem Remotecomputer aus zuzugreifen, der Ihrem Computer nicht vertraut. Sie müssen das Vertrauen vom Remote-Server gewinnen.

Lösung: Bei der folgenden Lösung wird davon ausgegangen, dass die folgenden Bedingungen erfüllt sind

  1. Der Versuch, von Ihrem lokalen Computer aus auf eine Remote-API zuzugreifen.
  2. Sie bauen für Android App
  3. Ihr Remote-Server wird von einem Proxy gefiltert (Sie verwenden Proxy in Ihrer Browsereinstellung, um auf den Remote-API-Dienst zuzugreifen, normalerweise einen Staging- oder Entwicklungsserver).
  4. Sie testen auf einem realen Gerät

Schritte:

Sie benötigen eine .keystore-Erweiterungsdatei, um Ihre App anzumelden. Wenn Sie nicht wissen, wie Sie eine .keystore-Datei erstellen; Folgen Sie dann dem folgenden Abschnitt Erstellen einer .keystore-Datei oder fahren Sie auf andere Weise mit dem nächsten Abschnitt fort. Sign Apk File

Erstellen Sie eine .keystore-Datei

Öffnen Sie Android Studio. Klicken Sie auf das Hauptmenü Erstellen> Signierte APK generieren. Klicken Sie im nächsten Fenster auf die Schaltfläche Neu erstellen ... Bitte geben Sie im neuen Fenster Daten in alle Felder ein. Denken Sie daran, dass das von mir empfohlene Feld mit zwei Passwörtern dasselbe Passwort haben sollte. Verwenden Sie kein anderes Passwort. und merken Sie sich auch den Speicherpfad am obersten Feld Schlüsselspeicherpfad : . Nachdem Sie alle Felder eingegeben haben, klicken Sie auf OK.

Sign Apk-Datei

Jetzt müssen Sie eine signierte App mit der gerade erstellten .keystore-Datei erstellen. Folge diesen Schritten

  1. Erstellen> Projekt reinigen, warten Sie, bis die Reinigung abgeschlossen ist
  2. Erstellen> Signierte APK generieren
  3. Klicken Choose existing... Schaltfläche
  4. Wählen Sie die gerade erstellte .keystore-Datei in der .keystore-Datei erstellen aus Abschnitt
  5. Geben Sie dasselbe Kennwort ein, das Sie beim Erstellen im Abschnitt " .keystore-Datei erstellen" erstellt haben . Verwenden Sie dasselbe Passwort für Key store passwordund Key passwordFelder. Geben Sie auch den Alias ​​ein
  6. Klicken Sie auf die Schaltfläche Weiter
  7. Im nächsten Bildschirm; was auf der Grundlage Ihrer Einstellungen unterschiedlich sein können build.gradleDateien, müssen Sie wählen Build Typesund Flavors.
  8. Für die Build TypesAuswahl releaseaus der Dropdown-Liste
  9. Für Flavorsjedoch wird es hängt von Ihren Einstellungen in build.gradleDatei. Wählen Sie stagingaus diesem Feld. Ich habe die folgenden Einstellungen in verwendet build.gradle, Sie können die gleichen wie meine verwenden, aber stellen Sie sicher, dass Sie die applicationIdin Ihren Paketnamen ändern

    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. Klicken Sie auf die beiden unteren Signature VersionsKontrollkästchen und dann auf die FinishSchaltfläche.

Fast dort:

Die ganze harte Arbeit ist erledigt, jetzt die Bewegung der Wahrheit. Um auf den durch einen Proxy gesicherten Staging-Server zugreifen zu können, müssen Sie einige Einstellungen in Ihren realen Test-Android-Geräten vornehmen.

Proxy-Einstellung im Android-Gerät:

  1. Klicken Sie auf die Einstellung im Android-Handy und dann auf Wi-Fi
  2. Drücken Sie lange auf das angeschlossene WLAN und wählen Sie Modify network
  3. Klicken Advanced optionsSie auf, wenn Sie das Proxy HostnameFeld nicht sehen können
  4. In der Proxy Hostnamedie Host - IP eingeben oder benennen Sie anschließen möchten. Ein typischer Staging-Server wird als benanntstg.api.mygoodcompany.com
  5. Geben Sie für den Port beispielsweise die vierstellige Portnummer ein 9502
  6. Drücken Sie die SaveTaste

Eine letzte Station:

Denken Sie daran, dass wir die signierte apk-Datei im Abschnitt APK-Datei signieren generiert haben . Jetzt ist die Zeit gekommen, diese APK-Datei zu installieren.

  1. Öffne ein Terminal und wechsle in den signierten apk-Dateiordner
  2. Verbinden Sie Ihr Android-Gerät mit Ihrem Computer
  3. Entfernen Sie alle zuvor installierten apk-Dateien vom Android-Gerät
  4. Lauf adb install name of the apk file
  5. Wenn aus irgendeinem Grund der obige Befehl mit zurückkehrt adb command not found. Geben Sie den vollständigen Pfad als einC:\Users\shah\AppData\Local\Android\sdk\platform-tools\adb.exe install name of the apk file

Ich hoffe das Problem könnte gelöst werden. Wenn nicht, hinterlasse mir bitte einen Kommentar.

Salam!


4

Die Fehlermeldung, die ich erhielt, war ähnlich, aber der Grund war, dass das selbstsignierte Zertifikat abgelaufen war. Beim Versuch des openssl-Clients wurde der Grund angegeben, der beim Überprüfen des Zertifikatdialogs von Firefox übersehen wurde.

Wenn sich das Zertifikat im Schlüsselspeicher befindet und "GÜLTIG" ist, wird dieser Fehler im Allgemeinen ausgelöst.


1
Wenn das Zertifikat abgelaufen ist, ist es gemäß einer Reihe von Standards nicht gültig. Es ist in Ordnung, eine benutzerdefinierte TrustManagerund einen anderen Kriteriensatz zu verwenden. Aber sofort müssen Sie damit arbeiten.
JWW

4

Ich hatte das gleiche Problem beim Herstellen einer Verbindung vom Android-Client zum Kurento-Server. Kurento-Server verwenden JKS-Zertifikate, daher musste ich PEM in dieses konvertieren. Als Eingabe für die Konvertierung habe ich die Datei cert.pem verwendet, die zu solchen Fehlern geführt hat. Wenn Sie jedoch fullchain.pem anstelle von cert.pem verwenden, ist alles in Ordnung.


3

Verwenden Sie https://www.ssllabs.com/ssltest/ , um eine Domain zu testen.

Die Lösung von Shihab Uddin in Kotlin.

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)
        }
}

2

Ich hatte das gleiche Problem, als ich feststellte, dass in der von mir bereitgestellten .crt-Datei des Zertifikats ein Zwischenzertifikat fehlte. Also habe ich alle .crt-Dateien von meinem Serveradministrator abgefragt und sie dann in umgekehrter Reihenfolge zusammengefasst.

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

In Windows habe ich die Kopie Inter.crt + Root.crt newCertificate.crt ausgeführt

(Hier habe ich myCrt.crt ignoriert)

Dann habe ich die Datei newCertificate.crt über den Inputstream in den Code eingefügt. Arbeit erledigt.


Wir hatten auch das gleiche Problem. Zwischenzertifikat fehlte
Nidhin Chandran

1

Der Trust-Ankerfehler kann aus vielen Gründen auftreten. Für mich war es einfach so, dass ich versuchte, darauf zuzugreifen, https://example.com/anstatthttps://www.example.com/ .

Vielleicht möchten Sie Ihre URLs noch einmal überprüfen, bevor Sie mit dem Erstellen Ihres eigenen Trust Managers beginnen (wie ich).


0

Bei Lebkuchenhandys wird immer folgende Fehlermeldung angezeigt: Trust Anchor not found for Android SSL Connection Auch wenn ich , dass ich mich auf mein Zertifikat verlasse.

Hier ist der Code, den ich verwende (in Scala-Sprache):

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 _ 
        }
    }
}

und hier ist der Verbindungscode:

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)
}

Grundsätzlich richte ich so ein, dass ich meinem benutzerdefinierten Zertifikat vertraue. Wenn dies fehlschlägt, deaktiviere ich die Sicherheit. Dies ist nicht die beste Option, aber die einzige Wahl, die ich mit alten und fehlerhaften Telefonen kenne.

Dieser Beispielcode kann leicht in Java übersetzt werden.


Lösung für Android 2.3.x für den Fall, dass jemand es benötigt, stackoverflow.com/a/46465722/7125370
Newbie009

0

In meinem Fall geschah dies nach dem Update auf Android 8.0. Das selbstsignierte Zertifikat, dem Android als vertrauenswürdig eingestuft wurde, verwendete den Signaturalgorithmus SHA1withRSA. Das Umschalten auf ein neues Zertifikat mithilfe des Signaturalgorithmus SHA256withRSA hat das Problem behoben.


0

Ich weiß, dass Sie nicht allen Zertifikaten vertrauen müssen, aber in meinem Fall hatte ich Probleme mit einigen Debugging-Umgebungen, in denen wir selbstsignierte Zertifikate hatten und ich eine schmutzige Lösung brauchte.

Alles was ich tun musste, war die Initialisierung des zu ändern sslContext

mySSLContext.init(null, trustAllCerts, null); 

wo trustAllCertswurde so erstellt:

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 {
    }
} };

Hoffe, dass dies nützlich sein wird.


Das wollte ich finden! Danke
oxied

Ich bekomme einen Fehler Hostname '192.168.0.16' was not verified. Ich teste mein Webapi lokal über meinen Debugger (IIS Express). Irgendeine Idee, wie man das behebt? Danke :)
Sam

1
Das ist radikal unsicher. Verwende nicht.
Marquis von Lorne

0

Ich hatte ein ähnliches Problem und habe die Strategie, allen Quellen zu vertrauen, völlig ausgeschlossen.

Ich teile hier meine Lösung für eine in Kotlin implementierte Anwendung

Ich würde zunächst empfehlen, die folgende Website zu verwenden zu verwenden, um Informationen über das Zertifikat und seine Gültigkeit zu erhalten

Wenn es im Standard-Trust Store von Android nicht als "Akzeptierte Emittenten" angezeigt wird , müssen wir dieses Zertifikat abrufen und in die Anwendung integrieren, um einen benutzerdefinierten Trust Store zu erstellen

Die ideale Lösung in meinem Fall war die Erstellung eines allgemeinen Vertrauensmanagers , der den benutzerdefinierten und den Standard-Vertrauensspeicher für Android kombiniert

Hier legt er den Code auf hoher Ebene offen, der zum Konfigurieren des OkHttpClient verwendet wird, den er mit Retrofit verwendet hat.

override fun onBuildHttpClient(httpClientBuild: OkHttpClient.Builder) {

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

        printX509TrustManagerAcceptedIssuers(trustManagerWrapper)

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

    }

Auf diese Weise konnte ich mit dem Server mit einem selbstsignierten Zertifikat und mit anderen Servern mit einem Zertifikat kommunizieren, das von einer vertrauenswürdigen Zertifizierungsstelle ausgestellt wurde

Das ist es, ich hoffe es kann jemandem helfen.


0

Ich weiß, dass dies ein sehr alter Artikel ist, aber ich bin auf diesen Artikel gestoßen, als ich versucht habe, meine Vertrauensankerprobleme zu lösen. Ich habe gepostet, wie ich es behoben habe. Wenn Sie Ihre Stammzertifizierungsstelle vorinstalliert haben, müssen Sie dem Manifest eine Konfiguration hinzufügen.

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


nur für API 24+
BekaBot

@BekaBot - Dies ist wahrscheinlich der Fall, aber gemäß der Dokumentation 23 und darunter vertrauen Benutzerzertifikate standardmäßig. Standardmäßig vertrauen sichere Verbindungen (unter Verwendung von Protokollen wie TLS und HTTPS) aller Apps den vorinstallierten Systemzertifizierungsstellen und Apps, die auf Android 6.0 abzielen (API-Stufe 23) und niedriger vertrauen standardmäßig auch dem vom Benutzer hinzugefügten CA-Speicher
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

Ich habe auch das gleiche Problem konfrontiert. Ich entferne nur hhtps zu http, wie z

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

Schließlich habe ich dieses Problem gelöst.


Dies entfernt sicherlich nur die SSL-Sicherheit aus der Gleichung, was für eine Produktionsumgebung wahrscheinlich eine schlechte Idee ist.
Dragon Thoughts

Dies ist wirklich keine Lösung, da die SSL-Sicherheit entfernt wird.
Omega1
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.