web-dev-qa-db-fra.com

Impossible de trouver le chemin de certification valide vers la cible demandée - erreur même après l'importation du certificat

J'ai un client Java qui tente d'accéder à un serveur avec un certificat auto-signé.

Lorsque j'essaie de publier sur le serveur, j'obtiens le message d'erreur suivant:

impossible de trouver un chemin de certification valide vers la cible demandée

Après avoir fait des recherches sur la question, j'ai ensuite fait ce qui suit.

  1. Enregistré le nom de domaine de mes serveurs en tant que fichier root.cer.
  2. Dans le JRE de mon serveur Glassfish, j'ai exécuté ceci:
    keytool -import -alias example -keystore cacerts -file root.cer
  3. Pour vérifier que le certificat a bien été ajouté à mon compte, je l'ai fait:
    keytool -list -v -keystore cacerts
    .__ Je peux voir que le cert est présent.
  4. J'ai ensuite redémarré Glassfish et retiré le «post».

Je reçois toujours la même erreur.

J'ai l'impression que c'est parce que mon Glassfish ne lit pas le fichier cacert que j'ai modifié, mais peut-être un autre.

L'un de vous a-t-il eu ce problème et peut me pousser dans la bonne direction?

158
TheCoder

Malheureusement - cela pourrait être beaucoup de choses - et de nombreux serveurs d'applications et autres "wrappers" Java sont enclins à jouer avec les propriétés et leurs "propres" prises sur les trousseaux de clés et autres. Donc, il se peut que vous cherchiez quelque chose de totalement différent. 

À court de treillis - je voudrais essayer:

Java -Djavax.net.debug=all -Djavax.net.ssl.trustStore=trustStore ...

pour voir si cela aide. Au lieu de "tout", vous pouvez également le définir sur "ssl", gestionnaire de clés et gestionnaire de confiance - ce qui peut vous aider dans votre cas. Le paramétrer sur 'help' listera quelque chose comme ci-dessous sur la plupart des plateformes.

Peu importe - assurez-vous de bien comprendre la différence entre le magasin de clés (dans lequel vous avez la clé privée et le certificat avec lequel vous prouvez votre propre identité) et le magasin de confiance (qui détermine votre confiance) - et le fait que votre propre identité a une «chaîne» de confiance à la racine - qui est distincte de toute chaîne en une racine dont vous avez besoin pour déterminer «en qui» vous avez confiance.

all            turn on all debugging
ssl            turn on ssl debugging

The   following can be used with ssl:
    record       enable per-record tracing
    handshake    print each handshake message
    keygen       print key generation data
    session      print session activity
    defaultctx   print default SSL initialization
    sslctx       print SSLContext tracing
    sessioncache print session cache tracing
    keymanager   print key manager tracing
    trustmanager print trust manager tracing
    pluggability print pluggability tracing

    handshake debugging can be widened with:
    data         hex dump of each handshake message
    verbose      verbose handshake message printing

    record debugging can be widened with:
    plaintext    hex dump of record plaintext
    packet       print raw SSL/TLS packets

Source: # See http://download.Oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html#Debug

123

Voici la solution, suivez le lien ci-dessous, étape par étape:

http://www.mkyong.com/webservices/jax-ws/suncertpathbuilderexception-unable-to-find-valid-certification-path-to-requested-target/

Java FILE: qui manque au blog

/*
 * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */



import Java.io.*;
import Java.net.URL;

import Java.security.*;
import Java.security.cert.*;

import javax.net.ssl.*;

public class InstallCert {

    public static void main(String[] args) throws Exception {
    String Host;
    int port;
    char[] passphrase;
    if ((args.length == 1) || (args.length == 2)) {
        String[] c = args[0].split(":");
        Host = c[0];
        port = (c.length == 1) ? 443 : Integer.parseInt(c[1]);
        String p = (args.length == 1) ? "changeit" : args[1];
        passphrase = p.toCharArray();
    } else {
        System.out.println("Usage: Java InstallCert <Host>[:port] [passphrase]");
        return;
    }

    File file = new File("jssecacerts");
    if (file.isFile() == false) {
        char SEP = File.separatorChar;
        File dir = new File(System.getProperty("Java.home") + SEP
            + "lib" + SEP + "security");
        file = new File(dir, "jssecacerts");
        if (file.isFile() == false) {
        file = new File(dir, "cacerts");
        }
    }
    System.out.println("Loading KeyStore " + file + "...");
    InputStream in = new FileInputStream(file);
    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
    ks.load(in, passphrase);
    in.close();

    SSLContext context = SSLContext.getInstance("TLS");
    TrustManagerFactory tmf =
        TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmf.init(ks);
    X509TrustManager defaultTrustManager = (X509TrustManager)tmf.getTrustManagers()[0];
    SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
    context.init(null, new TrustManager[] {tm}, null);
    SSLSocketFactory factory = context.getSocketFactory();

    System.out.println("Opening connection to " + Host + ":" + port + "...");
    SSLSocket socket = (SSLSocket)factory.createSocket(Host, port);
    socket.setSoTimeout(10000);
    try {
        System.out.println("Starting SSL handshake...");
        socket.startHandshake();
        socket.close();
        System.out.println();
        System.out.println("No errors, certificate is already trusted");
    } catch (SSLException e) {
        System.out.println();
        e.printStackTrace(System.out);
    }

    X509Certificate[] chain = tm.chain;
    if (chain == null) {
        System.out.println("Could not obtain server certificate chain");
        return;
    }

    BufferedReader reader =
        new BufferedReader(new InputStreamReader(System.in));

    System.out.println();
    System.out.println("Server sent " + chain.length + " certificate(s):");
    System.out.println();
    MessageDigest sha1 = MessageDigest.getInstance("SHA1");
    MessageDigest md5 = MessageDigest.getInstance("MD5");
    for (int i = 0; i < chain.length; i++) {
        X509Certificate cert = chain[i];
        System.out.println
            (" " + (i + 1) + " Subject " + cert.getSubjectDN());
        System.out.println("   Issuer  " + cert.getIssuerDN());
        sha1.update(cert.getEncoded());
        System.out.println("   sha1    " + toHexString(sha1.digest()));
        md5.update(cert.getEncoded());
        System.out.println("   md5     " + toHexString(md5.digest()));
        System.out.println();
    }

    System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]");
    String line = reader.readLine().trim();
    int k;
    try {
        k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1;
    } catch (NumberFormatException e) {
        System.out.println("KeyStore not changed");
        return;
    }

    X509Certificate cert = chain[k];
    String alias = Host + "-" + (k + 1);
    ks.setCertificateEntry(alias, cert);

    OutputStream out = new FileOutputStream("jssecacerts");
    ks.store(out, passphrase);
    out.close();

    System.out.println();
    System.out.println(cert);
    System.out.println();
    System.out.println
        ("Added certificate to keystore 'jssecacerts' using alias '"
        + alias + "'");
    }

    private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();

    private static String toHexString(byte[] bytes) {
    StringBuilder sb = new StringBuilder(bytes.length * 3);
    for (int b : bytes) {
        b &= 0xff;
        sb.append(HEXDIGITS[b >> 4]);
        sb.append(HEXDIGITS[b & 15]);
        sb.append(' ');
    }
    return sb.toString();
    }

    private static class SavingTrustManager implements X509TrustManager {

    private final X509TrustManager tm;
    private X509Certificate[] chain;

    SavingTrustManager(X509TrustManager tm) {
        this.tm = tm;
    }

    public X509Certificate[] getAcceptedIssuers() {
        throw new UnsupportedOperationException();
    }

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

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

}
17
user6258309

Vous devez configurer les propriétés système JSSE, en particulier pointer sur le magasin de certificats client. 

Via la ligne de commande:

Java -Djavax.net.ssl.trustStore=truststores/client.ts com.progress.Client

ou via code Java:

import Java.util.Properties;
    ...
    Properties systemProps = System.getProperties();
    systemProps.put("javax.net.ssl.keyStorePassword","passwordForKeystore");
    systemProps.put("javax.net.ssl.keyStore","pathToKeystore.ks");
    systemProps.put("javax.net.ssl.trustStore", "pathToTruststore.ts");
    systemProps.put("javax.net.ssl.trustStorePassword","passwordForTrustStore");
    System.setProperties(systemProps);
    ...

Pour plus d'informations, reportez-vous aux détails sur Site RedHat .

12
Vic

(republier de mon autre réponse )
Utilisez l'utilitaire cli keytool de la distribution de logiciels Java pour importer (et trust!) Les certificats nécessaires

Échantillon: 

  1. De cli, changez dir en jre\bin

  2. Vérifier le magasin de clés (fichier situé dans le répertoire jre\bin)
    keytool -list -keystore ..\lib\security\cacerts
    Le mot de passe est changeit 

  3. Téléchargez et enregistrez tous les certificats en chaîne à partir du serveur requis.

  4. Ajouter des certificats (avant de supprimer l'attribut "lecture seule" du fichier "..\lib\security\cacerts"), exécutez: Keytool -alias REPLACE_TO_ANY_UNIQ_NAME -import -keystore ..\lib\security\cacerts "r:\root.crt"

accidentellement, j'ai trouvé un conseil aussi simple. D'autres solutions nécessitent l'utilisation de InstallCert.Java et JDK

source: http://www.Java-samples.com/showtutorial.php?tutorialid=210

J'ai eu le même problème avec sbt.
Il a essayé d'extraire des dépendances de repo1.maven.org sur ssl
mais a déclaré qu'il était "incapable de trouver un chemin de certification valide vers l'URL cible demandée".
J'ai donc suivi ce post .__ et je n’ai toujours pas réussi à vérifier une connexion.
J'ai donc lu à ce sujet et découvert que le certificat racine ne suffisait pas, comme suggéré par le message, donc - 
la chose qui a fonctionné pour moi importait les certificats de l'autorité de certification intermédiaire dans le magasin de clés.
En fait, j'ai ajouté tous les certificats de la chaîne et cela a fonctionné à merveille.

3
Danny Mor

Solution lors de la migration de JDK 8 à JDK 10

JDK 10

root@c339504909345:/opt/jdk-minimal/jre/lib/security #  keytool -cacerts -list
Enter keystore password:
Keystore type: JKS
Keystore provider: Sun

Your keystore contains 80 entries

JDK 8

root@c39596768075:/usr/lib/jvm/Java-8-openjdk-AMD64/jre/lib/security/cacerts #  keytool -cacerts -list
Enter keystore password:
Keystore type: JKS
Keystore provider: Sun

Your keystore contains 151 entries

Étapes à suivre

  • J'ai supprimé le cert JDK 10 et l'ai remplacé par le JDK 8
  • Puisque je construis des images Docker, je pourrais rapidement le faire en utilisant des versions à plusieurs étages
    • Je construis un JRE minimal en utilisant jlink comme /opt/jdk/bin/jlink \ --module-path /opt/jdk/jmods...

Alors, voici les différents chemins et la séquence des commandes ...

# Java 8
COPY --from=marcellodesales-springboot-builder-jdk8 /usr/lib/jvm/Java-8-openjdk-AMD64/jre/lib/security/cacerts /etc/ssl/certs/Java/cacerts

# Java 10
RUN rm -f /opt/jdk-minimal/jre/lib/security/cacerts
RUN ln -s /etc/ssl/certs/Java/cacerts /opt/jdk-minimal/jre/lib/security/cacerts
2
Marcello de Sales

Je travaille actuellement sur un tutoriel pour les services Web REST à l'adresse www.udemy.com (services Web Java REST). L'exemple du tutoriel indique que pour avoir SSL, nous devons avoir un dossier appelé "trust_store" dans mon projet "client" Eclipse qui doit contenir un fichier "magasin de clés" (nous avons eu un projet "client" pour appeler le service. et "service" contenant le service Web REST - 2 projets dans le même espace de travail Eclipse, l’un du client, l’autre le service). Pour simplifier les choses, ils ont dit de copier "keystore.jks" depuis le serveur d'applications glassfish (glassfish\domains\domain1\config\keystore.jsk) que nous utilisons et de les placer dans ce dossier "trust_store" qu'ils m'ont fait créer le projet client. Cela semble logique: les certificats auto-signés dans le magasin de clés du serveur correspondent aux certificats dans le magasin de confiance client. Maintenant, faisant cela, je recevais l’erreur que le message original mentionne. J'ai googlé ceci et lu que l'erreur est due au fichier "keystore.jks" sur le client ne contenant pas de certificat approuvé/signé, que le certificat qu'il trouve est auto-signé.

Pour que tout soit clair, permettez-moi de dire que, si je comprends bien, le fichier "keystore.jsk" contient des certificats auto-signés et le fichier "cacerts.jks" contient des certificats CA (signés par l'autorité de certification). "Keystore.jks" est le "magasin de clés" et le "cacerts.jks" est le "magasin de confiance". Comme "Bruno", a commenté un commentaire, "keystore.jks" est local et "cacerts.jks" pour les clients distants.

Alors, je me suis dit, hé, Glassfish a aussi le fichier "cacerts.jks", qui est le fichier trust_store de glassfish. cacerts.jsk est censé contenir des certificats d'autorité de certification. Et, apparemment, j'ai besoin que mon dossier trust_store contienne un fichier de stockage de clés contenant au moins un certificat d'autorité de certification. J'ai donc essayé de placer le fichier "cacerts.jks" dans le dossier "trust_store" que j'avais créé sur mon projet client et de modifier les propriétés VM pour qu'elles pointent sur "cacerts.jks" au lieu de "keystore.jks ". Cela s'est débarrassé de l'erreur. Je suppose que tout ce dont il avait besoin était d’un certificat de CA pour fonctionner. 

Cela peut ne pas être idéal pour la production, ou même pour le développement, au-delà du simple travail. Par exemple, vous pourriez probablement utiliser la commande "keytool" pour ajouter des certificats CA au fichier "keystore.jks" du client. Mais de toute façon, j'espère que cela réduira au moins les scénarios possibles qui pourraient se produire ici pour causer l'erreur. 

AUSSI: mon approche semblait être utile pour le client (certificat de serveur ajouté au client trust_store), il semble que les commentaires ci-dessus pour résoudre le message d'origine soient utiles pour le serveur (certificat de client ajouté au serveur trust_store). À votre santé.

Configuration du projet Eclipse:

  • MyClientProject 
  • src 
  • tester 
  • Bibliothèque système JRE 
  • ... 
  • trust_store
    --- cacerts.jks --- magasin de clés.jks

Extrait de fichier MyClientProject.Java:

static {
  // Setup the trustStore location and password
  System.setProperty("javax.net.ssl.trustStore","trust_store/cacerts.jks");
  // comment out below line
  System.setProperty("javax.net.ssl.trustStore","trust_store/keystore.jks");
  System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
  //System.setProperty("javax.net.debug", "all");

  // for localhost testing only
  javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(new javax.net.ssl.HostnameVerifier() {
        public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) {
          return hostname.equals("localhost");
        }

  });
}
1
Steve T

Mon problème était qu'un Cloud Access Security Broker, NetSkope, avait été installé sur mon ordinateur portable de travail via une mise à jour logicielle. Cela modifiait la chaîne de certificats et je ne pouvais toujours pas me connecter au serveur via mon client Java après avoir importé la totalité de la chaîne dans mon magasin de clés cacerts. J'ai désactivé NetSkope et j'ai réussi à me connecter.

0
gary69

Vérifiez si le fichier $Java_HOME/lib/security/cacerts existe! Dans mon cas, il ne s’agissait pas d’un fichier, mais d’un lien vers /etc/ssl/certs/Java/cacerts.

Solution: Copiez le vrai fichier cacerts (vous pouvez le faire depuis un autre JDK) vers le répertoire /etc/ssl/certs/Java/ et le problème sera résolu :)

0
0x7E1