Java, JavaEE

getting javax.net.ssl.SSLHandshakeException after upgrading to Java 16

TL;DR on Java 16, TLSv1.0 is disabled by default, use TLSv1.2 instead

Symptom 1 – MySQL

After upgrading to Java 16, got a following exception with mysql:mysql-connector-java:8.0.23:

Caused by: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
	at java.base/sun.security.ssl.HandshakeContext.(HandshakeContext.java:172)
	at java.base/sun.security.ssl.ClientHandshakeContext.(ClientHandshakeContext.java:98)
	at java.base/sun.security.ssl.TransportContext.kickstart(TransportContext.java:238)
	at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:434)
	at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:412)
	at com.mysql.cj.protocol.ExportControlled.performTlsHandshake(ExportControlled.java:336)
	at com.mysql.cj.protocol.StandardSocketFactory.performTlsHandshake(StandardSocketFactory.java:188)
	at com.mysql.cj.protocol.a.NativeSocketConnection.performTlsHandshake(NativeSocketConnection.java:99)
	at com.mysql.cj.protocol.a.NativeProtocol.negotiateSSLConnection(NativeProtocol.java:325)

This exception suggests that the application is requested to connect using an unsupported TLS version by the host.

The version MySQL instance on Amazon RDS is MySQL 5.6.44 which supports only TLS1.0
MySQL on Amazon RDS > Using SSL with a MySQL DB instance

MySQL 5.6 reached it’s end of life on Feb 5 and it’s encouraged to migrate to v8.0.
I’ve
As upgrading directly from v5.6 to v8.0 is not supported, upgrading to v8.0 through v5.7 resolved the issue.

Symptom 2 – JavaMail

JavaMail is also throwing the exception:

Caused by: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
	at java.base/sun.security.ssl.HandshakeContext.(HandshakeContext.java:172)
	at java.base/sun.security.ssl.ClientHandshakeContext.(ClientHandshakeContext.java:98)
	at java.base/sun.security.ssl.TransportContext.kickstart(TransportContext.java:238)
	at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:434)
	at java.base/sun.security.ssl.SSLSocketImpl.ensureNegotiated(SSLSocketImpl.java:903)
	at java.base/sun.security.ssl.SSLSocketImpl$AppInputStream.read(SSLSocketImpl.java:994)
	at com.sun.mail.util.TraceInputStream.read(TraceInputStream.java:110)

The latest version of JavaMail – com.sun.mail:javax.mail:1.6.2 doesn’t throw the exception, but org.eclipse.jetty.aggregate:jetty-all:9.4.38.v20210224 is depending on an older version of JavaMail – org.eclipse.jetty.orbit:javax.mail.glassfish:1.4.1.v201005082020 slipped into the class path and caused the issue. The issue was resolved by explicitly excluding org.eclipse.jetty.orbit:javax.mail.glassfish.

Root cause

From Java 16 onward, TLSv1 and v1.1 are disabled by default in $JAVA_HOME/conf/security/java.security

# Note: This property is currently used by the JDK Reference implementation.
# It is not guaranteed to be examined and used by other implementations.
#
# Example:
#   jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048, \
#       rsa_pkcs1_sha1, secp224r1
jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \
    DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL

TLSv1.0, and 1.1 are deprecated by IETF, and they will be disabled on Java 8,11, and 15 as well.

You can workaround the issue by removing the "TLSv1" entry from $JAVA_HOME/conf/security/java.security#jdk.tls.disabledAlgorithms, but it’s largely discouraged.