Trust anchor for certification path not found.

  • Antworten:19
Ralf Kruppa
  • Forum-Beiträge: 26

22.01.2018, 08:27:23 via Website

Hallo,
ich ahbe eine App die Rezepte vom meinem Server holt.
Diese shat auch wunderbar funktioniert bis ich mir jetzt ein neues Handy gekauft habe.

Im Request bei der https abfrage bekomme ich folgende Meldung:

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

Ich nutze HTTPS mit Bentzer Zertifikat.
In der APP sieht es folgendermaßen aus :

 public class ImageDownloader extends AsyncTask<String, Void, String> {
    private Api exampleApi;
    @Override
    protected  String doInBackground(String... urls) {
        String result = "";

        try {
            AuthenticationParameters authParams = new AuthenticationParameters();
            authParams.setClientCertificate(getClientCertFile());
            authParams.setClientCertificatePassword(clientCertificatePassword);
            authParams.setCaCertificate(readCaCert());

            exampleApi = new Api(authParams);
            Log.d("Kruppa_Log",exampleUrl);
            result = exampleApi.doGet(exampleUrl);
            int responseCode = exampleApi.getLastResponseCode();

        } catch (Exception ex) {
            Log.e(TAG, "failed to create timeApi", ex);
            //updateOutput(ex.toString());
        }

        Log.d("Kruppa_Log",result);
        return result;
    }

}

Hat jemand eine Idee do das Problem liegen könnte ?

Ich habe eien Samsung S5 gehabt und habe jetzt eine Samsung A5 2017.

Gruß Ralf

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.288

23.01.2018, 08:37:00 via App

Hmm ich glaube du kannst neuerdings ein einzelnes Zertifikat garnicht mehr als Vertrauenswürdig einstufen, außer du installierst es auf dem Gerät.
Alternativ mal alle Zertifikate zulassen, dann geht es auch.
Wenn du die App allerdings veröffentlichen willst, würde ich über ein offiziell signiertes Zertifikat nachdenken.

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
Ralf Kruppa
  • Forum-Beiträge: 26

23.01.2018, 10:42:01 via Website

Nein es soll nicht veröffentlicht werden.
Wie bekomme ich es denn hin das allen Zertifikaten vertraut wird ?

Antworten
Ralf Kruppa
  • Forum-Beiträge: 26

23.01.2018, 10:46:32 via Website

Ich denke die Einstellung muß im TrustManager gemacht werden ?

public class CustomTrustManager implements X509TrustManager {

private final X509TrustManager originalX509TrustManager;
private final KeyStore trustStore;

/**
 * @param trustStore A KeyStore containing the server certificate that should be trusted
 * @throws NoSuchAlgorithmException
 * @throws KeyStoreException
 */
public CustomTrustManager(KeyStore trustStore) throws NoSuchAlgorithmException, KeyStoreException {
    this.trustStore = trustStore;

    TrustManagerFactory originalTrustManagerFactory = TrustManagerFactory.getInstance("X509");
    originalTrustManagerFactory.init((KeyStore) null);

    TrustManager[] originalTrustManagers = originalTrustManagerFactory.getTrustManagers();
    originalX509TrustManager = (X509TrustManager) originalTrustManagers[0];
}

/**
 * No-op. Never invoked by client, only used in server-side implementations
 * @return
 */
public X509Certificate[] getAcceptedIssuers() {
    return new X509Certificate[0];
}

/**
 * No-op. Never invoked by client, only used in server-side implementations
 * @return
 */
public void checkClientTrusted(X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {
}


/**
 * Given the partial or complete certificate chain provided by the peer,
 * build a certificate path to a trusted root and return if it can be validated and is trusted
 * for client SSL authentication based on the authentication type. The authentication type is
 * determined by the actual certificate used. For instance, if RSAPublicKey is used, the authType should be "RSA".
 * Checking is case-sensitive.
 * Defers to the default trust manager first, checks the cert supplied in the ctor if that fails.
 * @param chain the server's certificate chain
 * @param authType the authentication type based on the client certificate
 * @throws java.security.cert.CertificateException
 */
public void checkServerTrusted(X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {
    try {
        originalX509TrustManager.checkServerTrusted(chain, authType);
    } catch(CertificateException originalException) {
        try {
            X509Certificate[] reorderedChain = reorderCertificateChain(chain);
            CertPathValidator validator = CertPathValidator.getInstance("PKIX");
            CertificateFactory factory = CertificateFactory.getInstance("X509");
            CertPath certPath = factory.generateCertPath(Arrays.asList(reorderedChain));
            PKIXParameters params = new PKIXParameters(trustStore);
            params.setRevocationEnabled(false);
            validator.validate(certPath, params);
        } catch(Exception ex) {
            throw originalException;
        }
    }

}

/**
 * Puts the certificate chain in the proper order, to deal with out-of-order
 * certificate chains as are sometimes produced by Apache's mod_ssl
 * @param chain the certificate chain, possibly with bad ordering
 * @return the re-ordered certificate chain
 */
private X509Certificate[] reorderCertificateChain(X509Certificate[] chain) {

    X509Certificate[] reorderedChain = new X509Certificate[chain.length];
    List<X509Certificate> certificates = Arrays.asList(chain);

    int position = chain.length - 1;
    X509Certificate rootCert = findRootCert(certificates);
    reorderedChain[position] = rootCert;

    X509Certificate cert = rootCert;
    while((cert = findSignedCert(cert, certificates)) != null && position > 0) {
        reorderedChain[--position] = cert;
    }

    return reorderedChain;
}

/**
 * A helper method for certificate re-ordering.
 * Finds the root certificate in a possibly out-of-order certificate chain.
 * @param certificates the certificate change, possibly out-of-order
 * @return the root certificate, if any, that was found in the list of certificates
 */
private X509Certificate findRootCert(List<X509Certificate> certificates) {
    X509Certificate rootCert = null;

    for(X509Certificate cert : certificates) {
        X509Certificate signer = findSigner(cert, certificates);
        if(signer == null || signer.equals(cert)) { // no signer present, or self-signed
            rootCert = cert;
            break;
        }
    }

    return rootCert;
}

/**
 * A helper method for certificate re-ordering.
 * Finds the first certificate in the list of certificates that is signed by the sigingCert.
 */
private X509Certificate findSignedCert(X509Certificate signingCert, List<X509Certificate> certificates) {
    X509Certificate signed = null;

    for(X509Certificate cert : certificates) {
        Principal signingCertSubjectDN = signingCert.getSubjectDN();
        Principal certIssuerDN = cert.getIssuerDN();
        if(certIssuerDN.equals(signingCertSubjectDN) && !cert.equals(signingCert)) {
            signed = cert;
            break;
        }
    }

    return signed;
}

/**
 * A helper method for certificate re-ordering.
 * Finds the certificate in the list of certificates that signed the signedCert.
 */
private X509Certificate findSigner(X509Certificate signedCert, List<X509Certificate> certificates) {
    X509Certificate signer = null;

    for(X509Certificate cert : certificates) {
        Principal certSubjectDN = cert.getSubjectDN();
        Principal issuerDN = signedCert.getIssuerDN();
        if(certSubjectDN.equals(issuerDN)) {
            signer = cert;
            break;
        }
    }

    return signer;
}

}

Aber wie ?

Gruß Ralf

Antworten
Ralf Kruppa
  • Forum-Beiträge: 26

23.01.2018, 12:42:07 via Website

Hallo,

ich habe jetzt folgendes aus dem Link genommen:

private void trustEveryone() { 
try { 
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier(){ 
                public boolean verify(String hostname, SSLSession session) { 
                        return true; 
                }}); 
        SSLContext context = SSLContext.getInstance("TLS"); 
        context.init(null, new X509TrustManager[]{new X509TrustManager(){ 
                public void checkClientTrusted(X509Certificate[] chain, 
                                String authType) throws CertificateException {} 
                public void checkServerTrusted(X509Certificate[] chain, 
                                String authType) throws CertificateException {} 
                public X509Certificate[] getAcceptedIssuers() { 
                        return new X509Certificate[0]; 
                }}}, new SecureRandom()); 
        HttpsURLConnection.setDefaultSSLSocketFactory( 
                        context.getSocketFactory()); 
} catch (Exception e) { // should never happen 
        e.printStackTrace(); 
} 

}

und rufe dieses dann folgendermaßen mit auf :

    public String doGet(String url)  throws Exception {
    String result = null;

    HttpURLConnection urlConnection = null;
    try {
        URL requestedUrl = new URL(url);
        urlConnection = (HttpURLConnection) requestedUrl.openConnection();
        if(urlConnection instanceof HttpsURLConnection) {
            ((HttpsURLConnection)urlConnection).setSSLSocketFactory(sslContext.getSocketFactory());
        }
        urlConnection.setRequestMethod("GET");
        urlConnection.setConnectTimeout(1500);
        urlConnection.setReadTimeout(1500);
        trustEveryone();
        lastResponseCode = urlConnection.getResponseCode();
        result = IOUtil.readFully(urlConnection.getInputStream());

    } catch(Exception ex) {
        result = ex.toString();
    } finally {
        if(urlConnection != null) {
            urlConnection.disconnect();
        }
    }
    return result;
}

}

Es ändert sich aber leider an dem Verhalten nicht. Es geht nach wie vor nicht mehr.

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.288

23.01.2018, 13:06:38 via App

Ruf mal trustEveryone auf, bevor du überhaupt eine HttpUrlConnection anlegst. Ab besten sogar beim start der Apl, da die Einstellung ja bis AppClosed gilt

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
Ralf Kruppa
  • Forum-Beiträge: 26

23.01.2018, 13:30:04 via Website

HI jetzt habe ich es mal gleich am Anfang in die onCreate gepackt.

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    trustEveryone();

Leider geht dieses auch nicht.

Antworten
Ralf Kruppa
  • Forum-Beiträge: 26

23.01.2018, 13:51:06 via Website

Hier ist nochmal der Auszug aus dem LogCat/Debug

01-23 13:46:49.259 17443-8493/eu.selfosu.a30851kr.cookingkruppa D/Kruppa_Log: https://xxxxxxxxxx.eu/index.php?TinyWebDB=SELECT.....e

01-23 13:46:49.260 17443-8493/eu.selfosu.a30851kr.cookingkruppa I/System.out: (HTTPLog)-Static: isSBSettingEnabled false
01-23 13:46:49.260 17443-8493/eu.selfosu.a30851kr.cookingkruppa I/System.out: (HTTPLog)-Static: isSBSettingEnabled false
01-23 13:46:49.263 4040-4517/? D/EnterpriseController: netId is 0
01-23 13:46:49.263 4040-4517/? D/Netd: getNetworkForDns: using netid 516 for uid 10227
01-23 13:46:49.263 4040-4517/? D/DnsProxyListener: DNSDBG::dns addrinfo af 2
01-23 13:46:49.284 4379-4379/? D/WifiTrafficPoller: notifyOnDataActivity() - mBusMaxLock.acquire()
01-23 13:46:49.290 4379-4624/? D/wifi: onLinkStatsResults: radio_stat.on_time = 4701224
01-23 13:46:49.290 4379-4624/? D/wifi: onLinkStatsResults: radio_stat.tx_time = 21978
01-23 13:46:49.290 4379-4624/? D/wifi: onLinkStatsResults: radio_stat.rx_time = 98086
01-23 13:46:49.290 4379-4624/? D/wifi: android_net_wifi_getLinkLayerStats: radio_stat.on_time = 4701224
01-23 13:46:49.290 4379-4624/? D/wifi: android_net_wifi_getLinkLayerStats: radio_stat.tx_time = 21978
01-23 13:46:49.290 4379-4624/? D/wifi: android_net_wifi_getLinkLayerStats: radio_stat.rx_time = 98086
01-23 13:46:49.293 4379-4624/? D/WifiStateMachine: Current network is: "PubSpoDSL" , ID is: 0
01-23 13:46:49.293 4379-4624/? D/WifiStateMachine: Current network is still qualified due to heavy traffic, txSuccessRate=1.75 rxSuccessRate=0.0
01-23 13:46:49.293 4379-4624/? D/WifiStateMachine: Heavy traffic on current network (txSuccessRate=1.75 rxSuccessRate=0.0), bail out...
01-23 13:46:49.654 17443-8493/eu.selfosu.a30851kr.cookingkruppa D/Kruppa_Log: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

Fehler gibt es nicht und die APP stürzt auch nicht ab.

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.288

23.01.2018, 13:57:42 via App

Wenn du dir das ganze ersparen willst, dann nimm eine Http(s) Lib wie OkHttp oder ION. Damit geht das ganz sicher.

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
Ralf Kruppa
  • Forum-Beiträge: 26

23.01.2018, 17:20:05 via Website

Hallo , ich bin jetzt dabei es mit okhttp zu versuchen aber ich bekomme s gar nicht erst implementiet.

ich habe eine neues Projekt angelegt. Die Datei okhttp-3.9.1.jar runtergeladen von http://square.github.io/okhttp/

build.gradle(Project:) folgendes hinzugefügt:

 dependencies {
    compile 'com.squareup.okhttp3:okhttp:3.9.1'

    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
}

Wenn ich dann über try das ganze aktualiesiere bekomme ich ein Fehler das er compile nicht kennt.

An welcher telle meine Projectes muss ich die jar Datei ablegen.
Ich habe dieses unter app\src\main\java\com\squareup\okhttp3\ abgelegt.

Was mache ich jetzt schon wieder falsch ?

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.288

23.01.2018, 17:26:57 via App

Mit Gradle brauchst du keine Jar Dateien einbinden.
Du kannst das direkt über jcenter/Maven einbinden. Muss auf deren Homepage stehen.

— geändert am 23.01.2018, 17:27:09

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
Ralf Kruppa
  • Forum-Beiträge: 26

23.01.2018, 17:31:47 via Website

Habe es gefunden es muß der eintagr in der build.gradle (Module:app) gemacht werden . Mal sehen ob ich jetzt weiter komme.

Antworten
Ralf Kruppa
  • Forum-Beiträge: 26

24.01.2018, 18:33:19 via Website

Hallo,
so jetzt habe ich es mit OkHttp3 in der APP zum laufen bekommen allerdings nur mit anderen Seiten und nicht mit meiner Seite.

Ich habe den apache noch mal neu gemacht und auch die entsprechenden einstellungen so das man https in geringster abstufung hat.

   <VirtualHost 192.168.0.31:443>
DocumentRoot /var/www

    <Directory /var/www/>
            Options Indexes FollowSymLinks MultiViews
            AllowOverride All
            Order allow,deny
            allow from all
</Directory>

SSLEngine on
SSLCertificateFile /etc/ssl/kruppa/apache.crt
SSLCertificateKeyFile /etc/ssl/kruppa/apache.key

ErrorLog ${APACHE_LOG_DIR}/app-error.log
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/app-access.log combined

Anschließend noch der Befehl
sudo a2enmod headers

Um die Sicherheitswarnung zu vermeiden.

Aber es geht nicht.

Antworten
Ralf Kruppa
  • Forum-Beiträge: 26

25.01.2018, 06:53:52 via Website

Hi, habe es mir angesehen, aber wie bekomme ich es bei mirimplementiert:

 public class feedBack extends AsyncTask<String, Void, String> {

    @Override
    protected String doInBackground(String... strings) {
        try {
            OkHttpClient client = new OkHttpClient();
            RequestBody PostData = new FormBody.Builder()
                    .add("yyyyy", "abc")
                    .build();
            Request request = new Request.Builder()
                    .url("https://xxxxxxxxxxxx/index.php")
                    .post(PostData)
                    .build();
            Response response = client.newCall(request).execute();
            String result = response.body().string();
            Log.d("Kruppa", result);
            return result;
        } catch (IOException e) {
            Log.d("Kruppa", "Error");
            return null;
        }

    }
    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        if (s != null) {
            Log.d("Kruppa", s);
        } else {
            Log.d("Kruppa","null");
        }
    }
}

An welcher stelle mußste ich denn welche Funktion einfügen ?

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.288

25.01.2018, 08:44:50 via App

Die getUnsafeHttpClient kopieren und dann statt new HttpClient() aufrufen

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
Ralf Kruppa
  • Forum-Beiträge: 26

25.01.2018, 09:11:48 via Website

Hallo,

das klappt nicht. Egal an welche stelle ich die Funktion einbaue es gibt immer fehler bzw. es wird nicht erkannt.

package eu.selfosu.a30851kr.testhttpok;

import android.icu.text.LocaleDisplayNames;
import android.os.AsyncTask;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class MainActivity extends AppCompatActivity {

private TextView result;
private Button getBtn;
private OkHttpClient client;

@RequiresApi(api = Build.VERSION_CODES.CUPCAKE)
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    result = (TextView) findViewById(R.id.result);
    getBtn = (Button) findViewById(R.id.getBtn);

    getBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            new feedBack().execute();
        }
    });

}


public class feedBack extends AsyncTask<String, Void, String> {

    @Override
    protected String doInBackground(String... strings) {
        try {
            //OkHttpClient client = new OkHttpClient();
            OkHttpClient client = new getUnsafeOkHttpClient();

            RequestBody PostData = new FormBody.Builder()
                    .add("yyy", "abc")
                    .build();
            Request request = new Request.Builder()
                    .url("https://xxxxxxxxx.eu")
                    .post(PostData)
                    .build();
            Response response = client.newCall(request).execute();
            String result = response.body().string();
            Log.d("Kruppa_log", result);
            return result;
        } catch (IOException e) {
            Log.d("Kruppa_log", "Error");
            return null;
        }

    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        if (s != null) {
            Log.d("Kruppa_log", s);
        } else {
            Log.d("Kruppa_Log", "null");
        }
    }


}

private static OkHttpClient 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;
            }
        });

        OkHttpClient okHttpClient = builder.build();
        return okHttpClient;
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

}

:'(

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.288

25.01.2018, 09:54:32 via App

Langsam hab ich das Gefühl dass du die Java Grundlagen nicht verstanden hast. Dies ist aber Grundvoraussetzung für die Android Programmierung.
Tipp: Eine (statische) Methode ruft man nicht mit new ... auf. Das sollte ein Compilefehler geben.

LG Pascal //It's not a bug, it's a feature. :) ;)

swa00

Antworten
Ralf Kruppa
  • Forum-Beiträge: 26

25.01.2018, 10:50:38 via Website

Hallo,

das ich bezüglich Java anfänger bin ist tatsache und auch das ich bezüglich der Grundlagen nicht sattelfest bin ist auch richtig.

Ich bin trotzdem froh das ich bis jetzt alles zum laufen bekommen habe, dank der Unterstützung hier im Forum.

Und auch jetzt hat es geklappt.

Danke für die Unterstützung.

Antworten