Java: sun.security.provider.certpath.SunCertPathBuilderException: Es konnte kein gültiger Zertifizierungspfad zum angeforderten Ziel gefunden werden

248

Ich habe eine Klasse, die eine Datei von einem https- Server herunterlädt . Wenn ich es ausführe, werden viele Fehler zurückgegeben. Es scheint, dass ich ein Problem mit meinem Zertifikat habe. Ist es möglich, die Client-Server-Authentifizierung zu ignorieren? Wenn das so ist, wie?

package com.da;

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.CharBuffer;
import java.util.concurrent.Future;

import org.apache.http.HttpResponse;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.impl.nio.client.DefaultHttpAsyncClient;
import org.apache.http.nio.IOControl;
import org.apache.http.nio.client.HttpAsyncClient;
import org.apache.http.nio.client.methods.AsyncCharConsumer;
import org.apache.http.nio.client.methods.HttpAsyncGet;
import org.apache.http.nio.client.methods.HttpAsyncPost;

public class RSDDownloadFile {
    static FileOutputStream fos;

    public void DownloadFile(String URI, String Request) throws Exception
    {
        java.net.URI uri = URIUtils.createURI("https", "176.66.3.69:6443", -1, "download.aspx",
                "Lang=EN&AuthToken=package", null);
        System.out.println("URI Query: " + uri.toString());

        HttpAsyncClient httpclient = new DefaultHttpAsyncClient();
        httpclient.start();
        try {
            Future<Boolean> future = httpclient.execute(
                    new HttpAsyncGet(uri),
                    new ResponseCallback(), null);

            Boolean result = future.get();
            if (result != null && result.booleanValue()) {
                System.out.println("\nRequest successfully executed");
            } else {
                System.out.println("Request failed");
            }              
        } 
        catch(Exception e){
            System.out.println("[DownloadFile] Exception: " + e.getMessage());
        }
        finally {
            System.out.println("Shutting down");
            httpclient.shutdown();
        }
        System.out.println("Done");  

    }

    static class ResponseCallback extends AsyncCharConsumer<Boolean> {

        @Override
        protected void onResponseReceived(final HttpResponse response) {
             System.out.println("Response: " + response.getStatusLine());
             System.out.println("Header: " + response.toString());
             try {   
                 //if(response.getStatusLine().getStatusCode()==200)
                     fos = new FileOutputStream( "Response.html" );
             }catch(Exception e){
                 System.out.println("[onResponseReceived] Exception: " + e.getMessage());
             }
        }

        @Override
        protected void onCharReceived(final CharBuffer buf, final IOControl ioctrl) throws IOException {
            try
            {
                while (buf.hasRemaining()) 
                {
                    //System.out.print(buf.get());
                    fos.write(buf.get());
                }
            }catch(Exception e)
            {
                System.out.println("[onCharReceived] Exception: " + e.getMessage());
            }
        }

        @Override
        protected void onCleanup() {
            try
            {             
                if(fos!=null)
                    fos.close();
            }catch(Exception e){
                System.out.println("[onCleanup] Exception: " + e.getMessage());         
            }
             System.out.println("onCleanup()");
        }

        @Override
        protected Boolean buildResult() {
            return Boolean.TRUE;
        }

    }
}

Fehler:

URI Query: https://176.66.3.69:6443/download.aspx?Lang=EN&AuthToken=package
Aug 2, 2011 3:47:57 PM org.apache.http.impl.nio.client.NHttpClientProtocolHandler exception
SEVERE: I/O error: General SSLEngine problem
javax.net.ssl.SSLHandshakeException: General SSLEngine problem
    at com.sun.net.ssl.internal.ssl.Handshaker.checkThrown(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLEngineImpl.checkTaskThrown(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLEngineImpl.writeAppRecord(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLEngineImpl.wrap(Unknown Source)
    at javax.net.ssl.SSLEngine.wrap(Unknown Source)
    at org.apache.http.impl.nio.reactor.SSLIOSession.doHandshake(SSLIOSession.java:154)
    at org.apache.http.impl.nio.reactor.SSLIOSession.isAppInputReady(SSLIOSession.java:276)
    at org.apache.http.impl.nio.client.InternalClientEventDispatch.inputReady(InternalClientEventDispatch.java:79)
    at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:161)
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:335)
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:315)
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:275)
    at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104)
    at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:542)
    at java.lang.Thread.run(Unknown Source)
Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLEngineImpl.fatal(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.net.ssl.internal.ssl.Handshaker$DelegatedTask.run(Unknown Source)
    at org.apache.http.impl.nio.reactor.SSLIOSession.doHandshake(SSLIOSession.java:180)
    ... 9 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.validator.PKIXValidator.doBuild(Unknown Source)
    at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
    at sun.security.validator.Validator.validate(Unknown Source)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
    at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(Unknown Source)
    ... 16 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
    at java.security.cert.CertPathBuilder.build(Unknown Source)
    ... 21 more
onCleanup()

[DownloadFile] Exception: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
Shutting down
Done
neztreh
quelle
2
Einmal bekam ich diesen Fehler und kontaktierte unser Sicherheitsteam. Es stellte sich heraus, dass ich die von uns verwendete JAR patchen musste, da unser Team eine veraltete von der Firma bereitgestellte verwendete. Nur zu Ihrer Information für alle anderen, die sich in einer ähnlichen Situation befinden.
KayleeFrye_onDeck

Antworten:

215

Das Problem tritt auf, wenn Ihr Server über ein selbstsigniertes Zertifikat verfügt. Um dies zu umgehen, können Sie dieses Zertifikat zur Liste der vertrauenswürdigen Zertifikate Ihrer JVM hinzufügen.

In diesem Artikel beschreibt der Autor, wie Sie das Zertifikat von Ihrem Browser abrufen und zur cacerts-Datei Ihrer JVM hinzufügen. Sie können entweder die JAVA_HOME/jre/lib/security/cacertsDatei bearbeiten oder Ihre Anwendung mit -Djavax.net.ssl.trustStoreParametern ausführen . Überprüfen Sie, welches JDK / JRE Sie ebenfalls verwenden, da dies häufig zu Verwirrung führt.

Siehe auch: Wie werden SSL-Zertifikatservernamen aufgelöst? / Kann ich mithilfe von Keytool alternative Namen hinzufügen? Wenn Sie auf eine java.security.cert.CertificateException: No name matching localhost foundAusnahme stoßen.

Maxim Mazin
quelle
3
Das hat bei mir nicht funktioniert. Ich habe das Root- und das Kettenzertifikat installiert, aber Tomcat-7 meldet weiterhin eine validatorException, die durch "Fehler beim Suchen eines gültigen Zertifizierungspfads zum angeforderten Ziel" verursacht wurde.
Cheruvim
Das Problem tritt auch bei einem Zertifikat auf, das von einer anderen Person signiert wurde, die nicht vertrauenswürdig ist.
Marquis von Lorne
Toll! Es klappt! Vergiss nur nicht, dass du sowohl jre als auch jdk haben könntest und beide cacertsmüssen aktualisiert werden
Dima Fomin
In meinem Fall war die Stammzertifizierungsstelle vorhanden, die nächste jedoch nicht. Das Hinzufügen der nächsten Zertifizierungsstelle hat den Trick getan - danke.
Java-Addict301
1
In meinem Fall verwende ich Netbeans + Apache Tomcat (integriert), also füge ich .cer zum Trust Store "cacerts" unter Jdk / jre hinzu (C: \ Programme \ Java \ jdk1.8.0_152 \ jre \ lib \) Sicherheit) und Jre (C: \ Programme \ Java \ jre1.8.0_91 \ lib \ Sicherheit) funktioniert für mich
Jnn
149

Folgendes funktioniert für mich unter macOS zuverlässig. Stellen Sie sicher, dass Sie example.com und 443 durch den tatsächlichen Hostnamen und Port ersetzen, zu dem Sie eine Verbindung herstellen möchten, und geben Sie einen benutzerdefinierten Alias ​​an. Der erste Befehl lädt das bereitgestellte Zertifikat vom Remote-Server herunter und speichert es lokal im x509-Format. Der zweite Befehl lädt das gespeicherte Zertifikat in den SSL-Vertrauensspeicher von Java.

openssl x509 -in <(openssl s_client -connect example.com:443 -prexit 2>/dev/null) -out ~/example.crt
sudo keytool -importcert -file ~/example.crt -alias example -keystore $(/usr/libexec/java_home)/jre/lib/security/cacerts -storepass changeit
Gabe Martin-Dempesy
quelle
3
Funktioniert für mich warum? Sie müssen eine Erklärung abgeben.
Marquis von Lorne
openssl x509 -in <(openssl s_client -connect example.com:443 -prexit 2> / dev / null) -out ~ / example.crt - Was ist example.crt im Befehl? Ich habe ein .pem-Zertifikat, das ich geben muss das hier ??
Vishnu Ranganathan
3
.crt und .pem sind häufig verwendete Dateierweiterungen für dasselbe Dateiformat. Wenn Sie die Datei bereits haben, führen Sie einfach den zweiten Befehl aus und übergeben Sie ihn an das Argument -file.
Gabe Martin-Dempesy
1
Tolles Zeug. Das einzige ist: Ich musste aus irgendeinem Grund das neueste openssl 1.0.Xx verwenden, das alte 9.X.Xx funktionierte nicht.
Zbstof
1
Dies funktioniert nicht mit dem SNI-Endpunkt. Für diesen Fall müssen Sie hinzufügen: -servername example.com beim Abrufen des Zertifikats
Patrik Beck
46

Ich hatte das gleiche Problem mit einem gültigen signierten Platzhalterzertifikat von symantec.

Versuchen Sie zunächst, Ihre Java-Anwendung mit -Djavax.net.debug = SSL auszuführen, um zu sehen, was wirklich los ist.

Am Ende habe ich das Zwischenzertifikat importiert, wodurch die Zertifikatskette unterbrochen wurde.

Ich habe das fehlende Zwischenzertifikat von symantec heruntergeladen (Sie können den Download-Link zum fehlenden Zertifikat im SSL-Handshake-Protokoll sehen: in meinem Fall http://svrintl-g3-aia.verisign.com/SVRIntlG3.cer ).

Und ich habe das Zertifikat in den Java-Keystore importiert. Nach dem Import des Zwischenzertifikats funktionierte mein Wildcard-SSL-Zertifikat endlich:

keytool -import -keystore ../jre/lib/security/cacerts -trustcacerts -alias "VeriSign Class 3 International Server CA - G3" -file /pathto/SVRIntlG3.cer
Stephan Oudmaijer
quelle
Dies war der Fall:
Kisna
2
Um Verwirrung zu vermeiden, führen Sie Java (oder jcurl) mit Debug-Parametern aus, um die entfernte "Zertifikatkette" in den Protokollen anzuzeigen, und überprüfen Sie dann den "CN" im Truststore explizit übergeben (anstelle der Standardeinstellung) wie folgt, falls nicht vorhanden, müssen Sie hinzufügen. ssllabs.com/ssltest/analyze.html zeigt an, ob serverseitige Zertifikate eine unvollständige Kette aufweisen, und enthält Zertifikate für Zwischenzertifizierungspfade, die hinzugefügt werden müssen. -Djavax.net.debug=ssl,handshake -Djavax.net.ssl.keyStoreType=PKCS12 -Djavax.net.ssl.keyStore=our-client-certs -Djavax.net.ssl.trustStoreType=jks -Djavax.net.ssl.trustStore=their-server-certs
Kisna
Und natürlich der offizielle Artikel zum Debuggen von SSL-Problemen: docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/… blogs.oracle.com/java-platform-group/entry/…
Kisna
Ich hatte das gleiche Problem, das ist sehr nützlich, aber in meinem Fall mussten Sie nur das Serverzertifikat zur cacerts-Datei der JDK-Version
hinzufügen
41
  1. Exportieren Sie das SSL-Zertifikat mit Firefox. Sie können es exportieren, indem Sie im Browser auf die URL klicken und dann die Option zum Exportieren des Zertifikats auswählen. Nehmen wir an, der Name der Zertifizierungsdatei lautet your.ssl.server.name.crt
  2. Geh zu deinem JRE_HOME/binoderJDK/JRE/bin
  3. Geben Sie den Befehl ein
  4. keytool -keystore ..\lib\security\cacerts -import -alias your.ssl.server.name -file .\relative-path-to-cert-file\your.ssl.server.name.crt
  5. Starten Sie Ihren Java-Prozess neu
Robin
quelle
13
Wenn Sie nach einem Kennwort gefragt werden, verwenden Sie das Standardkennwort für den Cacerts-Schlüsselspeicher changeit( stackoverflow.com/a/22782035/1304830 ). Stellen Sie außerdem sicher, dass Sie cmd als Administrator ausführen.
Fr4nz
22

@ Gabe Martin-Dempesys Antwort wird mir geholfen. Und ich habe ein kleines Skript dazu geschrieben. Die Bedienung ist sehr einfach.

Installieren Sie ein Zertifikat vom Host:

> sudo ./java-cert-importer.sh example.com

Entfernen Sie das bereits installierte Zertifikat.

> sudo ./java-cert-importer.sh example.com --delete

java-cert-importer.sh

#!/usr/bin/env bash

# Exit on error
set -e

# Ensure script is running as root
if [ "$EUID" -ne 0 ]
  then echo "WARN: Please run as root (sudo)"
  exit 1
fi

# Check required commands
command -v openssl >/dev/null 2>&1 || { echo "Required command 'openssl' not installed. Aborting." >&2; exit 1; }
command -v keytool >/dev/null 2>&1 || { echo "Required command 'keytool' not installed. Aborting." >&2; exit 1; }

# Get command line args
host=$1; port=${2:-443}; deleteCmd=${3:-${2}}

# Check host argument
if [ ! ${host} ]; then
cat << EOF
Please enter required parameter(s)

usage:  ./java-cert-importer.sh <host> [ <port> | default=443 ] [ -d | --delete ]

EOF
exit 1
fi;

if [ "$JAVA_HOME" ]; then
    javahome=${JAVA_HOME}
elif [[ "$OSTYPE" == "linux-gnu" ]]; then # Linux
    javahome=$(readlink -f $(which java) | sed "s:bin/java::")
elif [[ "$OSTYPE" == "darwin"* ]]; then # Mac OS X
    javahome="$(/usr/libexec/java_home)/jre"
fi

if [ ! "$javahome" ]; then
    echo "WARN: Java home cannot be found."
    exit 1
elif [ ! -d "$javahome" ]; then
    echo "WARN: Detected Java home does not exists: $javahome"
    exit 1
fi

echo "Detected Java Home: $javahome"

# Set cacerts file path
cacertspath=${javahome}/lib/security/cacerts
cacertsbackup="${cacertspath}.$$.backup"

if ( [ "$deleteCmd" == "-d" ] || [ "$deleteCmd" == "--delete" ] ); then
    sudo keytool -delete -alias ${host} -keystore ${cacertspath} -storepass changeit
    echo "Certificate is deleted for ${host}"
    exit 0
fi

# Get host info from user
#read -p "Enter server host (E.g. example.com) : " host
#read -p "Enter server port (Default 443) : " port

# create temp file
tmpfile="/tmp/${host}.$$.crt"

# Create java cacerts backup file
cp ${cacertspath} ${cacertsbackup}

echo "Java CaCerts Backup: ${cacertsbackup}"

# Get certificate from speficied host
openssl x509 -in <(openssl s_client -connect ${host}:${port} -prexit 2>/dev/null) -out ${tmpfile}

# Import certificate into java cacerts file
sudo keytool -importcert -file ${tmpfile} -alias ${host} -keystore ${cacertspath} -storepass changeit

# Remove temp certificate file
rm ${tmpfile}

# Check certificate alias name (same with host) that imported successfully
result=$(keytool -list -v -keystore ${cacertspath} -storepass changeit | grep "Alias name: ${host}")

# Show results to user
if [ "$result" ]; then
    echo "Success: Certificate is imported to java cacerts for ${host}";
else
    echo "Error: Something went wrong";
fi;
bhdrk
quelle
Funktioniert einwandfrei. Gut gemacht! . So funktioniert es: Starten Sie Ihren SSL-Dienst (falls er nicht ausgeführt wird) und führen Sie den Befehl wie erläutert aus (z ./java-cert-importer.sh example.com 1234. B. ). Das ist es.
Lepe
1
Funktioniert super. Ich habe den Fehler auf einem Jenkins-Server erhalten, der eine Verbindung zu einer externen API herstellt, die sein Zertifikat ändert und meine Builds fehlschlägt. Dies löst mein Problem
user9869932
Oracle hätte so etwas überhaupt erst bereitstellen sollen, oder niemals jeder hat seine eigene schreckliche SSL-Lösung entwickelt. Die Behandlung von SSL-Zertifikaten sollte Aufgabe eines Betriebssystems sein.
Wolfgang Fahl
17

Zitat aus Nicht mehr "Es kann kein gültiger Zertifizierungspfad zum angeforderten Ziel gefunden werden".

Wenn Sie versuchen, mit JSSE eine SSL-Verbindung zu einem Host herzustellen. Dies bedeutet normalerweise, dass der Server ein Testzertifikat (möglicherweise mithilfe von Keytool generiert) anstelle eines Zertifikats einer bekannten kommerziellen Zertifizierungsstelle wie Verisign oder GoDaddy verwendet. Webbrowser zeigen in diesem Fall Warndialoge an. Da JSSE jedoch nicht davon ausgehen kann, dass ein interaktiver Benutzer vorhanden ist, wird standardmäßig nur eine Ausnahme ausgelöst.

Die Zertifikatsüberprüfung ist ein sehr wichtiger Bestandteil der SSL-Sicherheit, aber ich schreibe diesen Eintrag nicht, um die Details zu erläutern. Wenn Sie interessiert sind, können Sie zunächst den Klappentext von Wikipedia lesen. Ich schreibe diesen Eintrag, um eine einfache Möglichkeit zu zeigen, mit diesem Host mit dem Testzertifikat zu sprechen, wenn Sie dies wirklich möchten.

Grundsätzlich möchten Sie das Serverzertifikat mit Ihren vertrauenswürdigen Zertifikaten zum KeyStore hinzufügen

Probieren Sie den dort angegebenen Code aus. Es könnte helfen.

Nishant
quelle
5
Der Teil über "Zertifikatvalidierung ist ein sehr wichtiger Teil der SSL-Sicherheit" ist nicht unbedingt wahr. SSL gibt Ihnen zwei Zusicherungen: (1) dass Ihre Kommunikation privat ist und (2) dass Sie mit einem Server sprechen, der der NSA bekannt ist. (:-) Manchmal kümmern Sie sich nur um die Privatsphäre der Konversation, und dann a Selbstsignierte Zertifizierung ist in Ordnung. Siehe social-biz.org/2011/10/16/the-anti-ssl-conspiracy
AgilePro
@AgilePro SSL bietet Ihnen vier Zusicherungen: Authentifizierung, Datenschutz, Integrität und die Möglichkeit der Autorisierung. Es ist nicht geben Sie eine Zusicherung , dass Sie auf einen Server der NSA bekannt zu sprechen sind. Sich nur um die Privatsphäre ohne Authentifizierung zu kümmern, ist ein Widerspruch.
Marquis von Lorne
@EJP Stimmen Sie zu, dass Sie bei Verwendung eines Client-Zertifikats eine Authentifizierung erhalten können und ich nehme die Möglichkeit einer Autorisierung an ... aber die meisten Verwendungen erfolgen nicht mit einem Client-Zertifikat. Wie würden Sie den Unterschied zwischen einem "selbstsignierten" Zertifikat und einem Zertifikat einer signierenden Behörde nennen? Gibt die Unterzeichnungsbehörde "Integrität"? Mein Witz über die NSA ist, dass nicht alle Unterzeichnungsbehörden die Unabhängigkeit von allem positiv garantieren können. Nicht wirklich paranoid, aber der Punkt ist, dass Ihr Zertifikat NUR so geheim ist, wie es die Unterzeichnungsbehörde machen kann. Selbstsigniert kann geheimer sein.
AgilePro
@AgilePro Die Verwendung eines Serverzertifikats authentifiziert den Server und ist erforderlich , um SSL sicher zu machen, wie in RFC 2246 angegeben. Zertifikate sind überhaupt nicht geheim. Daher macht der Rest Ihres Kommentars keinen Sinn.
Marquis von Lorne
6

Dies löste mein Problem,

Wir müssen das Zertifikat in das lokale Java importieren. Wenn nicht, könnten wir die folgende Ausnahme bekommen.

    javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX-Pfaderstellung fehlgeschlagen: sun.security.provider.certpath.SunCertPathBuilderException: Es konnte kein gültiger Zertifizierungspfad zum angeforderten Ziel gefunden werden
        at sun.security.ssl.Alerts.getSSLException (Alerts.java:192)
        at sun.security.ssl.SSLSocketImpl.fatal (SSLSocketImpl.java:1949)
        at sun.security.ssl.Handshaker.fatalSE (Handshaker.java:302)

SSLPOKE ist ein Tool, mit dem Sie die https-Konnektivität von Ihrem lokalen Computer aus testen können.

Befehl zum Testen der Konnektivität:

"%JAVA_HOME%/bin/java" SSLPoke <hostname> 443
    sun.security.validator.ValidatorException: PKIX-Pfaderstellung fehlgeschlagen: 
    sun.security.provider.certpath.SunCertPathBuilderException: Es konnte kein gültiger Zertifizierungspfad zum angeforderten Ziel gefunden werden
        at sun.security.validator.PKIXValidator.doBuild (PKIXValidator.java:387)
        at sun.security.validator.PKIXValidator.engineValidate (PKIXValidator.java:292)
        at sun.security.validator.Validator.validate (Validator.java:260)
        at sun.security.ssl.X509TrustManagerImpl.validate (X509TrustManagerImpl.java:324)
        at sun.security.ssl.X509TrustManagerImpl.checkTrusted (X509TrustManagerImpl.java:229)
        at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted (X509TrustManagerImpl.java:124)
        at sun.security.ssl.ClientHandshaker.serverCertificate (ClientHandshaker.java:1496)
        at sun.security.ssl.ClientHandshaker.processMessage (ClientHandshaker.java:216)
        at sun.security.ssl.Handshaker.processLoop (Handshaker.java:1026)
        at sun.security.ssl.Handshaker.process_record (Handshaker.java:961)
        at sun.security.ssl.SSLSocketImpl.readRecord (SSLSocketImpl.java:1062)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake (SSLSocketImpl.java:1375)
        at sun.security.ssl.SSLSocketImpl.writeRecord (SSLSocketImpl.java:747)
        at sun.security.ssl.AppOutputStream.write (AppOutputStream.java:123)
        at sun.security.ssl.AppOutputStream.write (AppOutputStream.java:138)
        bei SSLPoke.main (SSLPoke.java:31)
    Auslöser: sun.security.provider.certpath.SunCertPathBuilderException: Es konnte kein gültiger Zertifizierungspfad zu gefunden werden 
    angefordertes Ziel
        at sun.security.provider.certpath.SunCertPathBuilder.build (SunCertPathBuilder.java:141)
        at sun.security.provider.certpath.SunCertPathBuilder.engineBuild (SunCertPathBuilder.java:126)
        unter java.security.cert.CertPathBuilder.build (CertPathBuilder.java:280)
        at sun.security.validator.PKIXValidator.doBuild (PKIXValidator.java:382)
        ... 15 mehr
keytool -import -alias <anyname> -keystore "%JAVA_HOME%/jre/lib/security/cacerts" -file <cert path>

Dies würde zuerst zur Eingabe von "Keystore-Passwort eingeben:" changeitals Standardkennwort führen. und schließlich eine Eingabeaufforderung "diesem Zertifikat vertrauen? [nein]:", geben Sie "ja" an, um das Zertifikat zum Keystore hinzuzufügen.

Verfeinerung:

C:\tools>"%JAVA_HOME%/bin/java" SSLPoke <hostname> 443
Successfully connected    
Naveen
quelle
5

Ich konnte es nur mit Code zum Laufen bringen, dh ich musste kein Keytool verwenden:

import com.netflix.config.DynamicBooleanProperty;
import com.netflix.config.DynamicIntProperty;
import com.netflix.config.DynamicPropertyFactory;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.apache.http.nio.conn.NoopIOSessionStrategy;
import org.apache.http.nio.conn.SchemeIOSessionStrategy;
import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public class Test
{
    private static final DynamicIntProperty MAX_TOTAL_CONNECTIONS = DynamicPropertyFactory.getInstance().getIntProperty("X.total.connections", 40);
    private static final DynamicIntProperty ROUTE_CONNECTIONS = DynamicPropertyFactory.getInstance().getIntProperty("X.total.connections", 40);
    private static final DynamicIntProperty CONNECT_TIMEOUT = DynamicPropertyFactory.getInstance().getIntProperty("X.connect.timeout", 60000);
    private static final DynamicIntProperty SOCKET_TIMEOUT = DynamicPropertyFactory.getInstance().getIntProperty("X.socket.timeout", -1);
    private static final DynamicIntProperty CONNECTION_REQUEST_TIMEOUT = DynamicPropertyFactory.getInstance().getIntProperty("X.connectionrequest.timeout", 60000);
    private static final DynamicBooleanProperty STALE_CONNECTION_CHECK = DynamicPropertyFactory.getInstance().getBooleanProperty("X.checkconnection", true);

    public static void main(String[] args) throws Exception
    {

        SSLContext sslcontext = SSLContexts.custom()
                .useTLS()
                .loadTrustMaterial(null, new TrustStrategy()
                {
                    @Override
                    public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException
                    {
                        return true;
                    }
                })
                .build();
        SSLIOSessionStrategy sslSessionStrategy = new SSLIOSessionStrategy(sslcontext, new AllowAll());

        Registry<SchemeIOSessionStrategy> sessionStrategyRegistry = RegistryBuilder.<SchemeIOSessionStrategy>create()
                .register("http", NoopIOSessionStrategy.INSTANCE)
                .register("https", sslSessionStrategy)
                .build();

        DefaultConnectingIOReactor ioReactor = new DefaultConnectingIOReactor(IOReactorConfig.DEFAULT);
        PoolingNHttpClientConnectionManager connectionManager = new PoolingNHttpClientConnectionManager(ioReactor, sessionStrategyRegistry);
        connectionManager.setMaxTotal(MAX_TOTAL_CONNECTIONS.get());
        connectionManager.setDefaultMaxPerRoute(ROUTE_CONNECTIONS.get());

        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(SOCKET_TIMEOUT.get())
                .setConnectTimeout(CONNECT_TIMEOUT.get())
                .setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT.get())
                .setStaleConnectionCheckEnabled(STALE_CONNECTION_CHECK.get())
                .build();

        CloseableHttpAsyncClient httpClient = HttpAsyncClients.custom()
                .setSSLStrategy(sslSessionStrategy)
                .setConnectionManager(connectionManager)
                .setDefaultRequestConfig(requestConfig)
                .build();

        httpClient.start();

        // use httpClient...
    }

    private static class AllowAll implements X509HostnameVerifier
    {
        @Override
        public void verify(String s, SSLSocket sslSocket) throws IOException
        {}

        @Override
        public void verify(String s, X509Certificate x509Certificate) throws SSLException {}

        @Override
        public void verify(String s, String[] strings, String[] strings2) throws SSLException
        {}

        @Override
        public boolean verify(String s, SSLSession sslSession)
        {
            return true;
        }
    }
}
Jonas Bergström
quelle
1
Übrigens benutze ich httpasyncclient: 4.0.1
Jonas Bergström
Ich brauchte etwas Ähnliches, @ JonasBergström, deine Lösung mit SSLContext hat mir sehr geholfen.
EnterSB
8
Beachten Sie, dass diese Lösung unsicher ist.
Marquis von Lorne
Danke Jonas, deine Lösung hat das Problem gelöst. Aber ich fand, dass es sehr lange dauert (3 - 5s), um die erste Verbindung herzustellen, danach benötigt jede Verbindung nur noch 300-400 ms.
Twcai
5

Die Ursache für diesen Fehler auf meiner Apache 2.4-Instanz (unter Verwendung eines Comodo-Platzhalterzertifikats) war ein unvollständiger Pfad zum von SHA-1 signierten Stammzertifikat. Das ausgestellte Zertifikat enthielt mehrere Ketten, und der Kette, die zu einem SHA-1-Stammzertifikat führte, fehlte ein Zwischenzertifikat . Moderne Browser wissen, wie man damit umgeht, aber Java 7 geht standardmäßig nicht damit um (obwohl es einige verschlungene Möglichkeiten gibt, dies im Code zu erreichen). Das Ergebnis sind Fehlermeldungen, die mit selbstsignierten Zertifikaten identisch sind:

Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:196)
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:268)
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:380)
    ... 22 more

In diesem Fall wird aufgrund des fehlenden Zwischenzertifikats die Meldung "Kein gültiger Zertifizierungspfad zum angeforderten Ziel gefunden" angezeigt. Sie können überprüfen, welches Zertifikat fehlt, indem Sie den SSL Labs- Test für den Server durchführen. Wenn Sie das entsprechende Zertifikat gefunden haben, laden Sie es herunter und fügen Sie es (sofern der Server unter Ihrer Kontrolle steht) dem Zertifikatspaket hinzu. Alternativ können Sie das fehlende Zertifikat lokal importieren. Die Behebung dieses Problems auf dem Server ist eine allgemeinere Lösung des Problems.

vallismortis
quelle
ssllabs.com/ssltest ist ein Retter, muss es nur mit einer funktionierenden Zertifikatsvalidierung vergleichen.
Kisna
5

Führen Sie die folgenden Schritte nur für Windows aus:

  1. Gehen Sie in Chrome zu den Einstellungen.
  2. Klicken Sie unter Einstellungen auf Erweiterte Einstellungen anzeigen.
  3. Klicken Sie unter HTTPS / SSL auf Zertifikate verwalten.
  4. Exportieren Sie Ihr Zertifikat.
  5. Geben Sie bei Windows-Suchen (Drücken der Windows-Taste auf der Tastatur) Java ein.
  6. Wählen Sie die Option (Java konfigurieren), um die Java-Systemsteuerung zu öffnen
  7. Wählen Sie in der Java-Systemsteuerung die Registerkarte Sicherheit
  8. Wählen Sie Zertifikate verwalten
  9. Klicken Sie auf Importieren
  10. Auf der Registerkarte (Benutzer) ausgewählt und Zertifikatstyp als (Vertrauenswürdige Zertifikate)
  11. Klicken Sie auf die Schaltfläche Importieren, navigieren Sie zum heruntergeladenen Zertifikat und importieren Sie es.
Praveen
quelle
4

Für diejenigen, die Debian und vorverpacktes Java mögen:

sudo mkdir /usr/share/ca-certificates/test/  # don't mess with other certs
sudo cp ~/tmp/test.loc.crt /usr/share/ca-certificates/test/
sudo dpkg-reconfigure --force ca-certificates  # check your cert in curses GUI!
sudo update-ca-certificates --fresh --verbose

Vergessen Sie nicht zu prüfen /etc/default/cacertsauf:

# enable/disable updates of the keystore /etc/ssl/certs/java/cacerts
cacerts_updates=yes

So entfernen Sie cert:

sudo rm /usr/share/ca-certificates/test/test.loc.crt
sudo rm /etc/ssl/certs/java/cacerts
sudo update-ca-certificates --fresh --verbose
Gavenkoa
quelle
2

Dies kann auch durch die Verwendung von GoDaddy-Zertifikaten mit Java 7 verursacht werden, die mit SHA2 signiert sind.

Chrome und alle anderen Browser beginnen, mit SHA1 signierte SSL-Zertifikate zu verwerfen, da diese nicht so sicher sind.

Weitere Informationen zu diesem Problem finden Sie hier sowie Informationen zur Behebung auf Ihrem Server, falls dies jetzt erforderlich ist.

Brad Parks
quelle
2

Ich hatte das gleiche Problem mit dem Zertifikatfehler und lag an SNI, und der von mir verwendete http-Client hatte SNI nicht implementiert. Also hat ein Versionsupdate den Job gemacht

   <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.3.6</version>
    </dependency>
Radu Toader
quelle
2

UPDATE: Dass ein Neustart geholfen hat, war zufällig (ich habe es gehofft, hurra!). Die eigentliche Ursache des Problems war folgende: Wenn Gradle angewiesen wird, einen bestimmten Schlüsselspeicher zu verwenden, muss dieser Schlüsselspeicher auch alle offiziellen Stammzertifikate enthalten. Andernfalls kann es nicht über reguläre Repositorys auf Bibliotheken zugreifen. Was ich tun musste war folgendes:

Importieren Sie das selbstsignierte Zertifikat:

keytool -import -trustcacerts -alias myselfsignedcert -file /Users/me/Desktop/selfsignedcert.crt -keystore ./privateKeystore.jks

Fügen Sie die offiziellen Stammzertifikate hinzu:

keytool -importkeystore -srckeystore <java-home>/lib/security/cacerts -destkeystore ./privateKeystore.jks

Vielleicht ist auch der Gradle-Dämon in die Quere gekommen. Könnte es wert sein, alle laufenden Dämonen zu töten, die gefunden wurden, ./gradlew --statuswenn die Dinge düster aussehen.

ORIGINAL POSTING:

Niemand wird das glauben, ich weiß. Wenn alles andere fehlschlägt, probieren Sie es trotzdem aus: Nach einem Neustart meines Mac war das Problem behoben. Grrr.

Hintergrund: ./gradlew jar gab mir immer wieder die Meldung "Ich konnte keinen gültigen Zertifizierungspfad zum angeforderten Ziel finden".

Ich habe ein selbstsigniertes Zertifikat, das vom Browser gespeichert und in privateKeystore.jks importiert wurde. Dann wies Gradle an, mit privateKeystore.jks zu arbeiten:

org.gradle.jvmargs=-Djavax.net.debug=SSL -Djavax.net.ssl.trustStore="/Users/me/IntelliJ/myproject/privateKeystore.jks"  -Djavax.net.ssl.trustStorePassword=changeit

Wie bereits erwähnt, funktionierte dies erst nach einem Neustart.

StaticNoiseLog
quelle
2

Die AVG-Version 18.1.3044 (unter Windows 10) stört meine lokale Spring-Anwendung.

Lösung: Geben Sie in den AVG-Bereich "Web und E-Mail" ein und deaktivieren Sie den "E-Mail-Schutz". AVG blockiert das Zertifikat, wenn die Site nicht sicher ist.

Insoft
quelle
2

Stellen Sie sicher, dass https://176.66.3.69:6443/ über ein gültiges Zertifikat verfügt. Sie können es zuerst über den Browser überprüfen, https nicht sicherwenn es im Browser funktioniert, funktioniert es in Java.

das funktioniert bei mir

Amr Ibrahim
quelle
Und was soll ich tun, wenn sich der Browser auch beschwert?
Der Pate
versuchen Sie, das Zertifikat zu installieren
Amr Ibrahim
2

Es gibt viele Möglichkeiten, dies zu lösen ...

Eine Möglichkeit besteht darin, die TrustStore-Zertifikate in einer Keystore-Datei festzulegen, sie in den Pfad der Anwendung einzufügen und diese Systemeigenschaften in der Hauptmethode festzulegen:

public static void main(String[] args) {
  System.setProperty("javax.net.ssl.trustStore", "trust-store.jks");
  System.setProperty("javax.net.ssl.trustStorePassword", "TrustStore");
  ...
}

Eine andere Möglichkeit besteht darin, den Schlüsselspeicher als Ressourcendatei in die Projekt-JAR-Datei zu platzieren und zu laden:

public static SSLContext createSSLContext(String resourcePath, String pass) throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException, UnrecoverableKeyException, KeyManagementException {
  // initialise the keystore
  final char[] password = pass.toCharArray();
  KeyStore ks = KeyStore.getInstance("JKS");
  ks.load(ThisClass.class.getResourceAsStream(resourcePath
  ), password);

  // Setup the key manager factory.
  KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
  kmf.init(ks, password);

  // Setup the trust manager factory.
  TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
  tmf.init(ks);

  SSLContext sslc = SSLContext.getInstance("TLS");
  sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
  return sslc;
}

public static void main(String[] args) {
  SSLContext.setDefault(
    createSSLContext("/trust-store.jks", "TrustStore"));
  ...
}

In Windows können Sie diese Lösung auch ausprobieren: https://stackoverflow.com/a/59056537/980442


Ich habe die Keystore-Datei auf folgende Weise aus einer CA- .crtDatei der Zertifizierungsstelle erstellt :

keytool -import -alias ca -keystore trust-store.jks -storepass TrustStore -trustcacerts -file ca.crt

Zu Ihrer Information: https://docs.oracle.com/javadb/10.8.3.0/adminguide/cadminsslclient.html

Daniel De León
quelle
1

Sie haben zwei Möglichkeiten: Importieren Sie das selbstsignierte Zertifikat für jeden JVM, auf dem die Software ausgeführt wird, in den Java-Keystore oder versuchen Sie es mit der nicht validierenden SSL-Factory:

jdbc:postgresql://myserver.com:5432/mydatabasename?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory
Pradip Das
quelle
1

Hatte das Problem wie dieses Bild.

Geben Sie hier die Bildbeschreibung ein

Versuchte ein paar Lösungen. Aber festgestellt, dass selbst wenn es dasselbe Projekt ist, wenn es am Arbeitsplatz eines anderen ist, es völlig in Ordnung ist. Keine zusätzlichen Einstellungen erforderlich. Wir haben also vermutet, dass es sich um ein Umweltproblem handelt. Wir haben versucht, die JDK-Version IDE zu ändern, aber es hat nicht funktioniert. Die Untersuchung dauerte ungefähr 4 Stunden, bis wir die am besten bewertete Antwort versuchten. Ich habe den in dieser Antwort erwähnten Fehler nicht gefunden, aber über meinen Browser über die HTTP-URL (Sperre) festgestellt, dass eine Zertifizierung von Charles vorliegt. Dann wurde mir klar, dass meine Charles die ganze Zeit an waren. Solange ich das ausgeschaltet habe, funktioniert alles einwandfrei.

Also habe ich meine Erfahrung hinterlassen, die für Ihren Fall hilfreich sein könnte.

Lalaphoon
quelle
0

In meinem Fall verwende ich MacOs High Sierra mit Java 1.6. Die Cacert-Datei befindet sich an einem anderen Ort als oben in der Antwort von Gabe Martin-Dempesy angegeben. Die Cacert-Datei war auch bereits mit einem anderen Speicherort verknüpft (/ Library / Internet Plug-Ins / JavaAppletPlugin.plugin / Contents / Home / lib / security / cacerts).

Mit FireFox habe ich das Zertifikat von der betreffenden Website in eine lokale Datei mit dem Namen "exportedCertFile.crt" exportiert. Von dort aus habe ich Keytool verwendet, um das Zertifikat in die Cacert-Datei zu verschieben. Dies hat das Problem behoben.

bash-3.2# cd /Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/lib/security/
bash-3.2# keytool -importcert -file ~/exportedCertFile.crt -alias example -keystore cacerts -storepass changeit
Alan Curtis
quelle
0

Laden Sie zuerst das SSL-Zertifikat herunter und gehen Sie dann zu Ihrem Java-Bin-Pfad. Führen Sie den folgenden Befehl in der Konsole aus.

C:\java\JDK1.8.0_66-X64\bin>keytool -printcert -file C:\Users\lova\openapi.cer -keystore openapistore
Lova Chittumuri
quelle
-1

In meinem Fall hatten sowohl der Keystore als auch der Truststore dasselbe Zertifikat, sodass das Entfernen des Truststores hilfreich war. Manchmal kann die Zertifikatskette ein Problem sein, wenn Sie mehrere Kopien von Zertifikaten haben.

Smart Coder
quelle