Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enable TLSv1.2 and TLS_RSA_WITH_AES_256_CBC_SHA256 Cipher Suite

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.

like image 559
Ashok Goli Avatar asked Oct 12 '15 19:10

Ashok Goli


3 Answers

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);
like image 59
pedrofb Avatar answered Nov 12 '22 19:11

pedrofb


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.

like image 21
Humberto Machado Avatar answered Nov 12 '22 18:11

Humberto Machado


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.

like image 3
Kumba Avatar answered Nov 12 '22 19:11

Kumba