web-dev-qa-db-fra.com

javax.net.ssl.SSLHandshakeException: Java.security.cert.CertPathValidatorException: ancre de confiance pour le chemin de certification introuvable

J'utilise Retrofit pour accéder à mon API REST. Cependant, lorsque je mets mon API derrière SSL et que je l’accède par http://myhost/myapi, j’obtiens cette erreur:

Dois-je faire quelque chose de plus maintenant que mon API est derrière SSL? 

Voici comment je me connecte:

private final String API = "https://myhost/myapi";

private final RestAdapter REST_ADAPTER = new RestAdapter.Builder()
        .setServer(API)
        .setLogLevel(RestAdapter.LogLevel.FULL)
        .build();

01-10 09:49:55.621    2076-2100/com.myapp.mobile D/Retrofit﹕ 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:401)
            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.getResponseCode(HttpURLConnectionImpl.Java:497)
            at libcore.net.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.Java:134)
            at retrofit.client.UrlConnectionClient.readResponse(UrlConnectionClient.Java:90)
            at retrofit.client.UrlConnectionClient.execute(UrlConnectionClient.Java:48)
            at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.Java:287)
            at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.Java:222)
            at $Proxy12.signin(Native Method)
            at com.myapp.loginactivity$3.doInBackground(LoginActivity.Java:143)
            at com.myapp.loginactivity$3.doInBackground(LoginActivity.Java:136)
            at Android.os.AsyncTask$2.call(AsyncTask.Java:287)
            at Java.util.concurrent.FutureTask.run(FutureTask.Java:234)
            at Android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.Java:230)
            at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.Java:1080)
            at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:573)
            at Java.lang.Thread.run(Thread.Java:841)
     Caused by: Java.security.cert.CertificateException: Java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
            at org.Apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkTrusted(TrustManagerImpl.Java:282)
            at org.Apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.Java:202)
            at org.Apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.Java:595)
            at org.Apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method)
            at org.Apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.Java:398)
            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.getResponseCode(HttpURLConnectionImpl.Java:497)
            at libcore.net.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.Java:134)
            at retrofit.client.UrlConnectionClient.readResponse(UrlConnectionClient.Java:90)
            at retrofit.client.UrlConnectionClient.execute(UrlConnectionClient.Java:48)
            at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.Java:287)
            at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.Java:222)
            at $Proxy12.signin(Native Method)
            at com.myapp.LoginActivity$3.doInBackground(LoginActivity.Java:143)
            at com.myapp.LoginActivity$3.doInBackground(LoginActivity.Java:136)
            at Android.os.AsyncTask$2.call(AsyncTask.Java:287)
            at Java.util.concurrent.FutureTask.run(FutureTask.Java:234)
            at Android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.Java:230)
            at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.Java:1080)
            at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:573)
            at Java.lang.Thread.run(Thread.Java:841)
17
birdy

La raison en est que la machine virtuelle/Dalvik n’a pas confiance en les certificats de l’autorité de certification du système ni dans les magasins de certificats d’utilisateur.

Pour résoudre ce problème avec Retrofit, si vous utilisez okhttp, il est très similaire avec un autre client.
Vous devez faire:

UNE). Créez un magasin de certificats contenant la clé publique de l'autorité de certification. Pour ce faire, vous devez lancer le script suivant pour * nix. Vous devez installer openssl sur votre ordinateur et télécharger à partir de https://www.bouncycastle.org/ jar bcprov-jdk16-1.46.jar. Ne téléchargez pas cette version D’autre, la version 1.5x n’est pas compatible avec Android 4.0.4.

#!/bin/bash

if [ -z $1 ]; then
  echo "Usage: cert2Android<CA cert PEM file>"
  exit 1
fi

CACERT=$1
BCJAR=bcprov-jdk16-1.46.jar

TRUSTSTORE=mytruststore.bks
ALIAS=`openssl x509 -inform PEM -subject_hash -noout -in $CACERT`

if [ -f $TRUSTSTORE ]; then
    rm $TRUSTSTORE || exit 1
fi

echo "Adding certificate to $TRUSTSTORE..."
keytool -import -v -trustcacerts -alias $ALIAS \
      -file $CACERT \
      -keystore $TRUSTSTORE -storetype BKS \
      -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider \
      -providerpath $BCJAR \
      -storepass secret

echo "" 
echo "Added '$CACERT' with alias '$ALIAS' to $TRUSTSTORE..."

B) Copiez le fichier truststore mytruststore.bks dans res/raw de votre projet truststore location

C) Réglage de SSLContext de la connexion:

.............
okHttpClient = new OkHttpClient();
try {
    KeyStore ksTrust = KeyStore.getInstance("BKS");
    InputStream instream = context.getResources().openRawResource(R.raw.mytruststore);
    ksTrust.load(instream, "secret".toCharArray());

    // TrustManager decides which certificate authorities to use.
    TrustManagerFactory tmf = TrustManagerFactory
        .getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmf.init(ksTrust);
    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, tmf.getTrustManagers(), null);

    okHttpClient.setSslSocketFactory(sslContext.getSocketFactory());
} catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException | KeyManagementException e) {
    e.printStackTrace();
}
.................
12
Fernando.

Salut même problème j'ai résolu vous pouvez essayer ceci 

Java.security.cert.CertPathValidatorException: ancre de confiance pour le chemin de certification introuvable. NETWORK

 // SET SSL
public static OkClient setSSLFactoryForClient(OkHttpClient client) {
    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 null;
                    }
                }
        };

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


        client.setSslSocketFactory(sslSocketFactory);
        client.setHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });

    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    return new OkClient(client);
}
2
sushant gosavi

Il y a 4 façons que je connaisse:

  • importer le certificat dans votre application et l'utiliser pour la connexion
  • désactiver la vérification de certificat
  • ajoutez votre certificat aux certificats de système de confiance dans Android
  • acheter un certificat vérifié qui est accepté par Android

Je suppose que vous ne voulez pas payer pour cela, alors je pense que la solution la plus élégante est la première, ce qui peut être accompli de cette façon:

http://blog.crazybob.org/2010/02/Android-trusting-ssl-certificates.html

2
kupsef

Le SSL n'est pas correctement configuré. Ces erreurs trustAnchor signifient généralement que le Trust Store est introuvable. Vérifiez votre configuration et assurez-vous que vous pointez bien sur le magasin de clés de confiance et qu'il est en place.

Assurez-vous que la propriété système -Djavax.net.ssl.trustStore est définie, puis vérifiez que le chemin d'accès mène réellement au magasin de données de confiance.

Vous pouvez également activer le débogage SSL en définissant cette propriété système -Djavax.net.debug=all. Dans la sortie de débogage, vous remarquerez qu'il indique qu'il ne peut pas trouver le magasin de clés de confiance.

1
Kevin Bowersox

Cela peut se produire pour plusieurs raisons, notamment:

  1. L'autorité de certification ayant émis le certificat de serveur était inconnue.
  2. Le certificat de serveur n'a pas été signé par une autorité de certification, mais a été auto-signé
  3. Il manque une autorité de certification intermédiaire à la configuration du serveur.

veuillez consulter ce lien pour trouver une solution: https://developer.Android.com/training/articles/security-ssl.html#CommonProblems

0
Defuera

J'utilise cette classe et n'ai aucun problème.

public class WCFs
{
    //  https://192.168.30.8/myservice.svc?wsdl
private static final String NAMESPACE = "http://tempuri.org/";
private static final String URL = "192.168.30.8";
private static final String SERVICE = "/myservice.svc?wsdl";
private static String SOAP_ACTION = "http://tempuri.org/iWCFserviceMe/";


public static Thread myMethod(Runnable rp)
{
    String METHOD_NAME = "myMethod";

    SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);

    request.addProperty("Message", "Https WCF Running...");
    return _call(rp,METHOD_NAME, request);
}

protected static HandlerThread _call(final RunProcess rp,final String METHOD_NAME, SoapObject soapReq)
{
    final SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
    int TimeOut = 5*1000;

    envelope.dotNet = true;
    envelope.bodyOut = soapReq;
    envelope.setOutputSoapObject(soapReq);

    final HttpsTransportSE httpTransport_net = new HttpsTransportSE(URL, 443, SERVICE, TimeOut);

    try
    {
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() // use this section if crt file is handmake
        {
            @Override
            public boolean verify(String hostname, SSLSession session)
            {
                return true;
            }
        });

        KeyStore k = getFromRaw(R.raw.key, "PKCS12", "password");
        ((HttpsServiceConnectionSE) httpTransport_net.getServiceConnection()).setSSLSocketFactory(getSSLSocketFactory(k, "SSL"));


    }
    catch(Exception e){}

    HandlerThread thread = new HandlerThread("wcfTd"+ Generator.getRandomNumber())
    {
        @Override
        public void run()
        {
            Handler h = new Handler(Looper.getMainLooper());
            Object response = null;

            for(int i=0; i<4; i++)
            {
                response = send(envelope, httpTransport_net , METHOD_NAME, null);

                try
                {if(Thread.currentThread().isInterrupted()) return;}catch(Exception e){}

                if(response != null)
                    break;

                ThreadHelper.threadSleep(250);
            }

            if(response != null)
            {
                if(rp != null)
                {
                    rp.setArguments(response.toString());
                    h.post(rp);
                }
            }
            else
            {
                if(Thread.currentThread().isInterrupted())
                    return;

                if(rp != null)
                {
                    rp.setExceptionState(true);
                    h.post(rp);
                }
            }

            ThreadHelper.stopThread(this);
        }
    };

    thread.start();

    return thread;
}


private static Object send(SoapSerializationEnvelope envelope, HttpTransportSE androidHttpTransport, String METHOD_NAME, List<HeaderProperty> headerList)
{
    try
    {
        if(headerList != null)
            androidHttpTransport.call(SOAP_ACTION + METHOD_NAME, envelope, headerList);
        else
            androidHttpTransport.call(SOAP_ACTION + METHOD_NAME, envelope);

        Object res = envelope.getResponse();

        if(res instanceof SoapPrimitive)
            return (SoapPrimitive) envelope.getResponse();
        else if(res instanceof SoapObject)
            return ((SoapObject) envelope.getResponse());
    }
    catch(Exception e)
    {}

    return null;
}

public static KeyStore getFromRaw(@RawRes int id, String algorithm, String filePassword)
{
    try
    {
        InputStream inputStream = ResourceMaster.openRaw(id);
        KeyStore keystore = KeyStore.getInstance(algorithm);
        keystore.load(inputStream, filePassword.toCharArray());
        inputStream.close();

        return keystore;
    }
    catch(Exception e)
    {}

    return null;
}

public static SSLSocketFactory getSSLSocketFactory(KeyStore trustKey, String SSLAlgorithm)
{
    try
    {
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustKey);

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

        return context.getSocketFactory();
    }
    catch(Exception e){}

    return null;
}

}

0
Ali Bagheri