SSLHandShakeException No Appropriate Protocol

JavaSslBufferedreader

Java Problem Overview


I recently added SSL to my website and it can be accessed over https. Now when my java application tries to make requests to my website and read from it with a buffered reader it produces this stack trace

Im not using a self signed certificate the cert is from Namecheap who uses COMODO SSL as the CA to sign my certificate. im using java 8

javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
at sun.security.ssl.Handshaker.activate(Handshaker.java:503)
at sun.security.ssl.SSLSocketImpl.kickstartHandshake(SSLSocketImpl.java:1482)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1351)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)

My code is very basic and simply tries to read the page on my site using a buffered reader

 private void populateDataList() {
    try {
        URL url = new URL("https://myURL.com/Data/Data.txt");
        URLConnection con = url.openConnection();
        con.setRequestProperty("Connection", "close");
        con.setDoInput(true);
        con.setUseCaches(false);

        BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
        String line;
        int i = 0;
        while((line = in.readLine()) != null) {
            this.url.add(i, line);
            i++;
        }
    }   catch (Exception e) {
        e.printStackTrace();
    }

}

Ive tried adding my SSL certificate to the JVM's Keystore and Ive also even tried to accept every certificate (which defeats the purpose of SSL I know) with this code

 private void trustCertificate() {
    TrustManager[] trustAllCerts = new TrustManager[] {
            new X509TrustManager() {
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }
                public void checkClientTrusted(
                        java.security.cert.X509Certificate[] certs, String authType) {
                }
                public void checkServerTrusted(
                        java.security.cert.X509Certificate[] certs, String authType) {
                }
            }
    };
    try {
        SSLContext sc = SSLContext.getInstance("TLS");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    } catch (GeneralSecurityException e) {
    }
    try {
        URL url = new URL("https://myURL.com/index.php");
        URLConnection con = url.openConnection();
        BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
        String line;
        while((line = br.readLine()) != null) {
            System.out.println(line);
        }

    } catch (Exception e) {

    }
}

Im stumped and any help would be much appreciated!

Java Solutions


Solution 1 - Java

In $JRE/lib/security/java.security:

jdk.tls.disabledAlgorithms=SSLv3, TLSv1, RC4, DES, MD5withRSA, DH keySize < 1024, \
EC keySize < 224, 3DES_EDE_CBC, anon, NULL

This line is enabled, after I commented out this line, everything is working fine. Apparently after/in jre1.8.0_181 this line is enabled.

My Java version is "1.8.0_201.

Solution 2 - Java

I also run into this with the Java8 update 1.8.0.229 on Ubuntu 18.04.

I changed the following part:

# Example:
#   jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
#jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \
#    DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
#    include jdk.disabled.namedCurves

jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, \
    DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
    include jdk.disabled.namedCurves

I removed TLSv1 and TLSv1.1 from the list of jdk.tls.disabledAlgorithms inside the file
> /etc/java-8-openjdk/security/java.security

After checking this:

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 28
Server version: 5.7.33-0ubuntu0.18.04.1 (Ubuntu)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> SHOW GLOBAL VARIABLES LIKE 'tls_version';
+---------------+-----------------------+
| Variable_name | Value                 |
+---------------+-----------------------+
| tls_version   | TLSv1,TLSv1.1,TLSv1.2 |
+---------------+-----------------------+
1 row in set (0.00 sec)

mysql> exit

Solution 3 - Java

protocol is disabled or cipher suites are inappropriate

The key to the problem lies in that statement. What it basically means is either:

  1. The TLS implementation used by the client does not support the cipher suites used by the server's certificate.

  2. The TLS configuration on the server has disabled cipher suites supported by the client.

  3. The TLS configurations on the client disable cipher suites offered by the server.

  4. TLS version incompatibility between the client and server.

This leads to handshake failure in TLS, and the connection fails. Check one or all of the three scenarios above.

Solution 4 - Java

You can add the expected TLS protocol to your connection string like this:

jdbc:mysql://localhost:3306/database_name?enabledTLSProtocols=TLSv1.2

That fixed the problem for me.


Edit 04-02-2022:

As Yair's comment says:

> Since Connector/J 8.0.28 enabledTLSProtocols has been renamed to tlsVersions.

Solution 5 - Java

In my case I am runnig Centos 8 and had the same issue with Imap/Java. Had to update the system-wide cryptographic policy level.

  1. update-crypto-policies --set LEGACY
  2. reboot machine.

Thats it.

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/considerations_in_adopting_rhel_8/security_considerations-in-adopting-rhel-8#tls-v10-v11_security

Solution 6 - Java

We started experiencing this problem after upgrading to jre1.8.0_291. I commented out "jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA,
DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL,
include jdk.disabled.namedCurves" in java.security located in C:\Program Files\Java\jre1.8.0_291\lib\security which resolved the problem.

Solution 7 - Java

> javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)

For posterity, I recently bumped up against this using IBM's JDK8 implementation which specifically disables TLS1.1 and 1.2 by default (sic). If you want to see what TLS versions are supported by the JVM, run something like the following code:

SSLContext context = SSLContext.getInstance("TLS");
context.init(null, null, null);
String[] supportedProtocols = context.getDefaultSSLParameters().getProtocols();
System.out.println(Arrays.toString(supportedProtocols));

The code spits out [TLSv1] by default under AIX JDK8. Not good. Under Redhat and Solaris it spits out [TLSv1, TLSv1.1, TLSv1.2].

I could not find any values in the java.security file to fix this issue but there might be some for your architecture. In the IBM specific case, we have to add:

-Dcom.ibm.jsse2.overrideDefaultTLS=true

Solution 8 - Java

I have encountered

javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)

error when accessing TLS 1.3 enabled endpoint from a Java 11 application. That is a usual case in GCP, for example.

The problem has gone away without any changes in my code just by upgrading from Java 11 to Java 14.

The Java 11 doesn't deprecate earlier TLS protocol versions by default. Instead of configuring it, simple upgrade of the runtime to Java 14 has helped.

Solution 9 - Java

In my case I had to upgrade the mysql client library to the latest version and it started working again:

    <dependency>
       <groupId>mysql</groupId>
       <artifactId>mysql-connector-java</artifactId>
       <version>8.0.24</version>
    </dependency>

Solution 10 - Java

Apparently, if you have TLS 1.0 disabled the emails won't be sent out. TLS Versions 1.1 and 1.2 do not work. Peter's suggestion did the trick for me.

Solution 11 - Java

I was face with the same situation on a tomcat7 server, 5.7.34-0ubuntu0.18.04.1, openjdk version "1.8.0_292"

I tried many approaches like disabling SSL in the server.xml file, changing the connection strings etc etc

but in the end all i did was to edit the file java.security with sudo nano /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/security/java.security

comment out and remove TLSv1 and TLSv1.1

# Comment the line below
#jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \
#    DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
#    include jdk.disabled.namedCurves

# your new line should read as beloew
jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, \
DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
include jdk.disabled.namedCurves

Solution 12 - Java

For ME in this case :

javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)

I found that this is JDK/JRE (Java\jdk1.8.0_291\jre\lib\security) config related, and in order to solve it you need to Disable the TLS anon and NULL cipher suites.

You can found how to do this in the oficial documentation here: https://www.java.com/en/configure_crypto.html

Also before doing this, consider the implications of using LEGACY algorithms.

Solution 13 - Java

upgraded from 1 to 2 + modifying the $JRE/lib/security/java.security file did the trick. before after mysql driver

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionChrisianBartramView Question on Stackoverflow
Solution 1 - Javawwjih123View Answer on Stackoverflow
Solution 2 - JavaRodneyView Answer on Stackoverflow
Solution 3 - JavaautomatonView Answer on Stackoverflow
Solution 4 - JavaGerard de VisserView Answer on Stackoverflow
Solution 5 - JavaPeterView Answer on Stackoverflow
Solution 6 - Javasari paisleyView Answer on Stackoverflow
Solution 7 - JavaGrayView Answer on Stackoverflow
Solution 8 - JavaSergey ShcherbakovView Answer on Stackoverflow
Solution 9 - JavaadlererView Answer on Stackoverflow
Solution 10 - JavaCesc CanetView Answer on Stackoverflow
Solution 11 - JavaFrancis GuchieView Answer on Stackoverflow
Solution 12 - JavaYotta_DevView Answer on Stackoverflow
Solution 13 - JavaDonMehdiView Answer on Stackoverflow