DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
Tame the Chaos: Make Multi-Cloud Management Secure and Cost Effective
Live Webinar

Trending

  • Container Security: Top 5 Best Practices for DevOps Engineers
  • The Benefits of Implementing Blue/Green Deployment in Your CI/CD Pipeline
  • Kafka: The Basics
  • Java Consumer and Producer Messages Between Kafka Server [Video Tutorials]
  1. DZone
  2. Coding
  3. Java
  4. Troubleshooting javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

Troubleshooting javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

Learn how to troubleshoot this infamous Java exception to see where the problem lies and find a solution.

Jakub Holý user avatar by
Jakub Holý
·
Oct. 09, 18 · Tutorial
Like (6)
Save
Tweet
Share
242.61K Views

Join the DZone community and get the full member experience.

Join For Free

The infamous Java exception javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure is hardly understandable to a mere mortal. What it wants to say is, most likely, something like this:

Sorry, none of the cryptographic protocols/versions and cipher suites is accepted both by the JVM and the server.

For instance, the server requires a higher version of TLS than the (old) JVM supports or it requires stronger cipher suites than the JVM knows. You will now learn how to find out what is the case.

We will first find out what both the server and the JVM support and compare it to see where they disagree. Feel free to just skim through the outputs and return to them later after they were explained.

What Does the Server Support?

We will use nmap for that ( brew install nmap on OSX):

map --script ssl-enum-ciphers -p 443 my-server.example.com
Starting Nmap 7.70 ( https://nmap.org ) at 2018-10-05 00:54 CEST
Nmap scan report for my-server.example.com (127.0.0.1)
Host is up (0.031s latency).

PORT STATE SERVICE
443/tcp open https
| ssl-enum-ciphers:
| TLSv1.2:
| ciphers:
| TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
| TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A
| TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
| TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
| compressors:
| NULL
| cipher preference: server
|_ least strength: A

Here we see that the server only supports TLS version 1.2 ( ssl-enum-ciphers: TLSv1.2:) and the listed ciphers, such as TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA.

What Does the JVM Have on Offer?

Now we will find out what the JVM supports (I did that through Clojure but you could have just as well used Java directly; notice the javax.net.debug property):

sh $ env -i java -Djavax.net.debug=ssl:handshake:verbose java -jar clojure-1.8.0.jar
Clojure 1.8.0
user=> (.connect (.openConnection (java.net.URL. "https://my-server.example.com/ping")))
;; ...
done seeding SecureRandom
Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256
Ignoring unavailable cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
Ignoring unavailable cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
Ignoring unavailable cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
main, setSoTimeout(0) called
%% No cached client session
*** ClientHello, TLSv1
RandomCookie: GMT: 1521850374 bytes = { 121, 217, 101, 186, 111, 183, 47, 46, 159, 230, 139, 103, 7, 181, 250, 172, 113, 121, 4, 55, 122, 148, 111, 82, 87, 170, 70, 10 }
Session ID: {}
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_SHA, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS_ECDH_RSA_WITH_RC4_128_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_RC4_128_MD5, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods: { 0 }
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
Extension server_name, server_name: [host_name: my-server.example.com]
***
main, WRITE: TLSv1 Handshake, length = 175
main, READ: TLSv1 Alert, length = 2
main, RECV TLSv1 ALERT: fatal, handshake_failure
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
SSLHandshakeException Received fatal alert: handshake_failure sun.security.ssl.Alerts.getSSLException (Alerts.java:192)

Here we see that the JVM uses TLS version 1 (see *** ClientHello, TLSv1) and supports the listed Cipher Suites, including TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA.

What's Wrong?

Here we see that the server and JVM share exactly one cipher suite, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA. But they fail to agree on the TLS version, since the server requires v1.2 while the JVM only offers v1.

The Solution

You can either configure the server to support a cipher suite and protocol version that the JVM has or teach JVM to use what the server wants. In my cases that was resolved by running java with -Dhttps.protocols=TLSv1.2 (alternatively, you could add all of SSLv3,TLSv1,TLSv1.1,TLSv1.2) as recommended by π at StackOverflow.

Sources

The troubleshooting technique comes from the article "SSLHandshakeException: Received fatal alert: handshake_failure due to no overlap in cipher suite" by Atlassian. The observation that the server and JVM disagreed on the TLS version comes from my good colleague Neil.

Java (programming language) Java virtual machine

Published at DZone with permission of Jakub Holý, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Trending

  • Container Security: Top 5 Best Practices for DevOps Engineers
  • The Benefits of Implementing Blue/Green Deployment in Your CI/CD Pipeline
  • Kafka: The Basics
  • Java Consumer and Producer Messages Between Kafka Server [Video Tutorials]

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com

Let's be friends: