24
Server: 
TLS Version: v1.2
Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA256 

Client:
JRE 1.7

I am receiving the below error when I try to connect to the Server from Client through SSL directly:

Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
        at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
        at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)

The below code enables TLSv1.2

  Set<String> enabledTLSSet = new HashSet<String>(Arrays.asList(sslsocket.getEnabledProtocols()));
  enabledTLSSet.add("TLSv1.2");      
  sslsocket.setEnabledProtocols(enabledTLSSet.toArray(new String[enabledTLSSet.size()]));

The below code enables TLS_RSA_WITH_AES_256_CBC_SHA256 Cipher Suite:

Set<String> enabledCipherSuitesSet = new HashSet<String>(Arrays.asList(sslsocket.getEnabledCipherSuites()));
      enabledCipherSuitesSet.add("TLS_RSA_WITH_AES_256_CBC_SHA256");
      sslsocket.setEnabledCipherSuites(enabledCipherSuitesSet.toArray(new String[enabledCipherSuitesSet.size()]));

After doing both of the above from Java code, I'm able to connect to the server successfully through SSL.

Is it possible to enable/force TLSv1.2 and TLS_RSA_WITH_AES_256_CBC_SHA256 in Java 7 without changing any Java Code through properties, parameters or Debug props?

I tried all of the below properties in all forms and combinations (enabling and disabling) and failed.

-Dhttps.protocols=TLSv1.2
-Dhttps.cipherSuites=TLS_RSA_WITH_AES_256_CBC_SHA256
-Ddeployment.security.TLSv1.2=true

I'm executing the program similar to the below:

java -jar -Dhttps.protocols=TLSv1.2 -Dhttps.cipherSuites=TLS_RSA_WITH_AES_256_CBC_SHA256 Ddeployment.security.TLSv1.2=true -Djavax.net.debug=ssl:handshake SSLPoker.jar <SERVER> 443

SSLPoker contains the below code:

package com.ashok.ssl;

import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.*;

/**
 * Establish a SSL connection to a host and port, writes a byte and prints the response - Ashok Goli. See
 * http://confluence.atlassian.com/display/JIRA/Connecting+to+SSL+services
 */
public class SSLPoke {

  /**
   * The main method.
   * Usage: $java -jar SSLPoker.jar <host> <port>
   *
   * @param args the arguments
   */
  public static void main(String[] args) {
    if (args.length != 2) {
      System.out.println("Usage: " + SSLPoke.class.getName() + " <host> <port>");
      System.exit(1);
    }
    try {
      SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
      SSLSocket sslsocket =
          (SSLSocket) sslsocketfactory.createSocket(args[0], Integer.parseInt(args[1]));

      InputStream in = sslsocket.getInputStream();
      OutputStream out = sslsocket.getOutputStream();

      // Write a test byte to get a reaction :)
      out.write(1);

      while (in.available() > 0) {
        System.out.print(in.read());
      }
      System.out.println("Successfully connected");

    } catch (Exception exception) {
      exception.printStackTrace();
    }
  }
}

Any pointers how to achieve this with no Java code changes would be much appreciated.

jww
  • 97,681
  • 90
  • 411
  • 885
Ashok Goli
  • 5,043
  • 8
  • 38
  • 68
  • 1
    You can't add TLS cipher suites without adding a whole security provider, such as Bouncy Castle, which indeed may support that one. – user207421 Oct 12 '15 at 21:14
  • What are the settings that I need to play around with to achieve this? – Ashok Goli Oct 12 '15 at 21:16
  • I did add TLS and successfully connected to the Server with the code above. Just looking for a way to do that via configuration. – Ashok Goli Oct 12 '15 at 21:20
  • Ashok + @EJP: you don't need Bouncy, and anyway there is no JCA/provider interface for individual SSL/TLS suites, only the whole protocol. Java7 JSSE supports that suite out of the box. In fact it is already enabled by default so you don't need to enable it, and TLSv1.2 is already enabled by default for *server* side so you don't need to enable it. But all suites that use a 256-bit data cipher will only be *used* if the **unlimited strength jurisdiction policy files** (2 jars in JRE/lib/security) are installed; are they? – dave_thompson_085 Oct 12 '15 at 22:44
  • 4
    For your client, the `https.*` properties only apply to connections made by `HttpsURLConnection`, i.e., connections from `URLConnection` with a URL whose scheme is `https:`. "Just-SSL/TLS" connections with `SSLSocketFactory` do not use them. For those you must call the `.setEnabled*` methods on the socket after creating it and before doing any input, output, or (explicit) `.startHandshake()`. – dave_thompson_085 Oct 12 '15 at 22:49
  • Youare absolutely right. And I did just what you said above. The snippets in the question show that. Is there a way to do it without changing Code? – Ashok Goli Oct 13 '15 at 06:34
  • Related, see [Which Cipher Suites to enable for SSL Socket?](https://stackoverflow.com/q/1037590/608639) – jww Feb 28 '18 at 23:15

3 Answers3

19

It is only possible if you use a simple HTTPS connection (not SSL Sockets) using the properties

-Dhttps.protocols=TLSv1.2 
-Dhttps.cipherSuites=TLS_RSA_WITH_AES_256_CBC_SHA256

See the post at http://fsanglier.blogspot.com.es/

Java 7 introduced support for TLS v1.2 (refer to http://docs.oracle.com/javase/7/docs/technotes/guides/security/enhancements-7.html) BUT does not enable it by default. In other words, your client app must explicitly specify "TLS v1.2" at SSLContext creation, or otherwise will just not be able to use it.

If you need to use directly secure socket protocol, create a "TLSv1.2" SSLContext at application startup and use the SSLContext.setDefault(ctx) call to register that new context as the default one.

SSLContext context = SSLContext.getInstance("TLSv1.2");
SSLContext.setDefault(context);
Crashalot
  • 33,605
  • 61
  • 269
  • 439
pedrofb
  • 37,271
  • 5
  • 94
  • 142
  • Wow... This is indeed required. I noticed they were ignored, but did not expect the server to already require TLS 1.2 – Kukeltje Nov 01 '16 at 17:20
8

The JREs disable all 256-bit crypto by default. To enable you can download Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files here: http://www.oracle.com/technetwork/java/javase/downloads/index.html

Replace the local_policy.jar and US_export_policy.jar jars files into your lib/security in jre directory.

3

It looks like current JRE's ship both the limited and unlimited policy files under the JRE's install folder in lib/security, each in separate sub folders. By default, in lib/security/java.security, the limited policy is used by default. But if you uncomment the crypto.policy=unlimited line, that will allow Java to use the unlimited policy files and enable the 256-bit ciphers/algorithms.

Kumba
  • 2,390
  • 3
  • 33
  • 60
  • 1
    This was true for (Oracle) 8u151/2 (Sep. 2017) only. 8u161/2 (Dec. 2017) up and all 9,10,11 have policy=unlimited out of the box. – dave_thompson_085 Oct 25 '18 at 23:24
  • 2
    Untrue for Java 7 (jdk1.7.0_80). `crypto.policy` does not exist in `lib/security/java.security` file. – alex Mar 23 '20 at 02:27