Fehlermeldung
javax.net.ssl.SSLHandshakeException: (handshake_failure) Received fatal alert: handshake_failure
Auch ausgegeben als
- javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
- Received fatal alert: handshake_failure
JDK 21 und neuer zeigen den Namen des Alerts in Klammern: „(handshake_failure) Received fatal alert: handshake_failure“; JDK 8 und 11 geben nur „Received fatal alert: handshake_failure“ aus.
Java (JSSE) — TLS alert 40 received from the server
Was der Fehler bedeutet
Der Server hat den TLS-Handshake mit dem Alert 40 (handshake_failure) abgebrochen. Entweder fand er im ClientHello der JVM nichts Akzeptables (keine gemeinsame Cipher Suite, keine gemeinsame Gruppe oder kein gemeinsamer Signaturalgorithmus), oder er verlangt ein Client-Zertifikat, das die JVM nicht vorgelegt hat. Java meldet nur, dass der Alert eingetroffen ist; der Grund steht im Log des Servers oder wird mit javax.net.debug sichtbar.
Warum der Fehler auftritt
Der Server bietet nur Suites an, die das JDK deaktiviert hat
häufigAktuelle JDK-Updates (in unseren Tests 21.0.12 und 25.0.4) führen TLS_RSA_* (RSA-Schlüsselaustausch), 3DES, RC4 und anonyme Suites in jdk.tls.disabledAlgorithms auf. Verbindungen zu Legacy-Servern, die auf diese Suites beschränkt sind, scheitern mit jeder aktuellen JVM.
Mutual TLS ohne Client-Zertifikat
häufigDer Server hat ein Zertifikat angefordert, und die JVM hatte keins (kein javax.net.ssl.keyStore oder keins, das von einer CA ausgestellt wurde, die der Server akzeptiert).
SNI fehlt oder ist unbekannt
gelegentlichEine Verbindung über die IP-Adresse oder mit jsse.enableSNIExtension=false lässt CDNs und mandantenfähige Server den Handshake abbrechen.
Eine sehr alte JVM trifft auf einen modernen Server
gelegentlichJava 7 oder frühen Updates von Java 8 fehlen die ECDHE-/GCM-Suites, und TLS 1.2 ist dort nicht standardmäßig aktiviert – beides verlangen gehärtete Server.
So behebst du den Fehler
- 1.
Handshake ansehen
javax.net.debug=ssl:handshake gibt das ClientHello (angebotene Suites) und den Alert aus; -XshowSettings:security:tls listet die im JDK aktivierten Protokolle und Suites auf.
bash # Show what the JVM offers and how the handshake ends java -Djavax.net.debug=ssl:handshake -jar app.jar 2>&1 | grep -E 'ClientHello|cipher_suites|Alert|fatal' # Settings in effect (protocols, suites) for this JDK java -XshowSettings:security:tls -version - 2.
Eigener Server: aktuelle Suites aktivieren
TLS 1.3 und TLS 1.2 mit ECDHE und AES-GCM oder ChaCha20 funktionieren mit jedem gepflegten JDK.
text # Server side: offer ECDHE + AEAD suites that current JDKs support ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; - 3.
Mutual TLS: Client-Keystore konfigurieren
javax.net.ssl.keyStore (oder ein SSLContext, der aus einer KeyManagerFactory gebaut wird) liefert das Client-Zertifikat.
bash # Mutual TLS: give the JVM the client certificate and key java -Djavax.net.ssl.keyStore=client.p12 -Djavax.net.ssl.keyStorePassword=changeit \ -Djavax.net.ssl.keyStoreType=PKCS12 -jar app.jar - 4.
Letzter Ausweg: disabledAlgorithms für einen einzelnen Legacy-Client anpassen
Eine Override-Datei, die du mit -Djava.security.properties übergibst, kann TLS_RSA_* für eine einzelne JVM aus jdk.tls.disabledAlgorithms entfernen; kopiere den vollständigen Standardwert und entferne nur das, was nötig ist. Diesen Suites fehlt Forward Secrecy, halte die Ausnahme also eng begrenzt und befristet.
bash # Last resort for one legacy server: take this JDK's own value and drop only TLS_RSA_* v=$(sed -n '/^jdk.tls.disabledAlgorithms=/,/[^\\]$/p' "$JAVA_HOME/conf/security/java.security" | sed 's/\\$//' | tr -d '\n') printf '%s\n' "$v" | sed -E 's/, TLS_RSA_\*//' > legacy-rsa.security java -Djava.security.properties=legacy-rsa.security -jar legacy-client.jar
Verwandte Fehler
No appropriate protocol (protocol is disabled or cipher suites are inappropriat…Java (JSSE)javax.net.ssl.SSLHandshakeException: (protocol_version) Received fatal alert: p…Java (JSSE)SSL routines:ssl3_read_bytes:ssl/tls alert handshake failureOpenSSL (client side)SSL routines:tls_post_process_client_hello:no shared cipherOpenSSL (server side: nginx, Apache, Postfix, openssl s_server)