Zum Inhalt springen
ecdsa.com
Java (JSSE, SunX509 trust manager)Java

Fehlermeldung

PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Auch ausgegeben als

  • javax.net.ssl.SSLHandshakeException: (certificate_unknown) PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
  • javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
  • unable to find valid certification path to requested target

JDK 21 und 25 stellen den TLS-Alert voran: „javax.net.ssl.SSLHandshakeException: (certificate_unknown) PKIX path building failed: …“. Logs älterer JDKs zeigen „javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: …“. Frameworks und Build-Tools (Spring, Maven, Gradle, IDEs) verpacken den Fehler in eigene Meldungen, behalten den PKIX-Text aber in der verursachenden Exception.

Java (JSSE, SunX509 trust manager) — javax.net.ssl.SSLHandshakeException caused by sun.security.validator.ValidatorException

Was der Fehler bedeutet

Beim PKIX-Pfadaufbau konnte Java vom Zertifikat des Servers keine Kette zu einem Vertrauensanker im Trust Store bilden, den die JVM verwendet. „Requested target“ ist das Zertifikat des Servers. Java vertraut nur seiner eigenen Datei cacerts (oder dem mit javax.net.ssl.trustStore angegebenen Store), nicht dem des Betriebssystems – deshalb scheitert hier ein Zertifikat von einer Firmen-CA, von einem Proxy mit TLS-Inspektion oder von einem Server ohne sein Zwischenzertifikat.

Warum der Fehler auftritt

So behebst du den Fehler

  1. 1.

    Kette und verwendeten Trust Store ansehen

    openssl s_client zeigt, was der Server sendet. Mit javax.net.debug=ssl:handshake:verbose gibt Java den Pfad des geladenen Trust Stores und jedes empfangene Zertifikat aus.

    bash
    openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts </dev/null 2>/dev/null \
      | grep -E '^ *[0-9]+ s:|^ *i:'
    # Or from Java itself: prints the chain and the trust store in use
    java -Djavax.net.debug=ssl:handshake:verbose -jar app.jar 2>&1 | grep -E 'trustStore is|Subject:|Issuer:'
  2. 2.

    Anwendungseigenen Trust Store mit deinem Root-Zertifikat verwenden

    Kopiere die Datei cacerts des JDK (damit öffentliche CAs weiter funktionieren), importiere das Root-Zertifikat der Firma oder des Proxys mit keytool und verweise die Anwendung mit javax.net.ssl.trustStore und trustStorePassword darauf (oder über JAVA_TOOL_OPTIONS bei Tools, die du nicht selbst startest).

    bash
    # A copy of the JDK's cacerts plus your root: public sites keep working
    cp "$JAVA_HOME/lib/security/cacerts" app-truststore.p12
    keytool -importcert -noprompt -alias corp-root -file corp-root-ca.pem \
      -keystore app-truststore.p12 -storepass changeit
    java -Djavax.net.ssl.trustStore=app-truststore.p12 -Djavax.net.ssl.trustStorePassword=changeit -jar app.jar
  3. 3.

    Root-Zertifikat in die Datei cacerts des JDK importieren

    keytool -cacerts schreibt in den Standard-Store des JDK, unter dem keytool läuft (Passwort standardmäßig „changeit“). Jede Anwendung auf diesem JDK vertraut dann dem Root-Zertifikat; die Änderung geht verloren, wenn das JDK ersetzt wird.

    bash
    # Add the root to this JDK's default trust store (applies to every app on this JDK;
    # repeat after each JDK upgrade)
    sudo keytool -importcert -noprompt -cacerts -alias corp-root -file corp-root-ca.pem -storepass changeit
  4. 4.

    Container: CA vom Image importieren lassen

    Ist USE_SYSTEM_CA_CERTS gesetzt, fügt der Entrypoint der Images von Eclipse Temurin beim Start die unter /certificates eingehängten Zertifikatsdateien *.crt zur Datei cacerts der JVM hinzu (das geschieht nur mit dem Standard-Entrypoint des Images). Andere Images brauchen den keytool-Schritt im Dockerfile.

    bash
    # Eclipse Temurin images: mount your CA(s) as *.crt and let the entrypoint add them to cacerts
    docker run -e USE_SYSTEM_CA_CERTS=1 \
      -v "$PWD/certs:/certificates/" eclipse-temurin:25.0.4.1_1-jdk-noble java -jar /app/app.jar
  5. 5.

    Einem einzelnen Client einen eigenen Trust Store geben

    Baue einen SSLContext aus einer TrustManagerFactory, die mit deinem Trust Store initialisiert ist, und übergib ihn an HttpClient (oder OkHttp, Apache HttpClient, Netty). Installiere nie einen Trust Manager, der jedes Zertifikat akzeptiert.

    java
    // One client with its own trust store (verification stays on)
    KeyStore ts = KeyStore.getInstance("PKCS12");
    try (InputStream in = Files.newInputStream(Path.of("app-truststore.p12"))) { ts.load(in, "changeit".toCharArray()); }
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmf.init(ts);
    SSLContext ssl = SSLContext.getInstance("TLS");
    ssl.init(null, tmf.getTrustManagers(), null);
    HttpClient client = HttpClient.newBuilder().sslContext(ssl).build();

Verwandte Fehler

Gesamte Signaturfehler-Datenbank durchsuchen