title: TLS handshake failure with JDK 7 - RECV TLSv1 ALERT: fatal, handshake_failure
body: <p>I am trying to write a Java client that makes HTTP RESTful calls to a remote server that only accepts TLSv1.2 and only accepts three 
  ciphers:
  TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 
  TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 
  TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 </p>
  
  <p>My Java client is version 1.7.0_60 and I can't upgrade for various corporate reasons. I applied the unlimited strength ciphers to my client JDK to be able to use the higher strength ciphers in my client but I get an SSL handshake failure.</p>
  
  <p>I ran my program with -Djavax.net.debug=all debug logging turned on I see the following. I notice that the strong ciphers are being reported as "ignored" and the list of ciphers the client presents to the server during the SSL handshake in fact does not include any of the these "ignored" ciphers; in fact my client doesn't present any of the stronger ciphers. The unfortunate part is that one of the ciphers being ignored is one that is supported by the server (TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384). </p>
  
  <pre><code>--snip---
  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 unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 
  Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 
  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 unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256 
  *** ClientHello, TLSv1.2
  RandomCookie:  GMT: 1493933783 bytes = { 75, 107, 53, 9, 115, 14, 55, 1, 156, 111, 130, 173, 243, 225, 154, 195, 184, 92, 141, 170, 24, 113, 191, 194, 4, 244, 192, 218 }
  Session ID:  {}
  Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, 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_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, 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, 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 signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA224withECDSA, SHA224withRSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA, MD5withRSA
  Extension server_name, server_name: [host_name: *************]
  ***
  [write] MD5 and SHA1 hashes:  len = 223
  0000: 01 00 00 DB 03 03 59 0C   9F D7 4B 6B 35 09 73 0E  ......Y...Kk5.s.
  0010: 37 01 9C 6F 82 AD F3 E1   9A C3 B8 5C 8D AA 18 71  7..o.......\...q
  0020: BF C2 04 F4 C0 DA 00 00   38 C0 0A C0 14 00 35 C0  ........8.....5.
  0030: 05 C0 0F 00 39 00 38 C0   09 C0 13 00 2F C0 04 C0  ....9.8...../...
  0040: 0E 00 33 00 32 C0 08 C0   12 00 0A C0 03 C0 0D 00  ..3.2...........
  0050: 16 00 13 C0 07 C0 11 00   05 C0 02 C0 0C 00 04 00  ................
  0060: FF 01 00 00 7A 00 0A 00   34 00 32 00 17 00 01 00  ....z...4.2.....
  0070: 03 00 13 00 15 00 06 00   07 00 09 00 0A 00 18 00  ................
  0080: 0B 00 0C 00 19 00 0D 00   0E 00 0F 00 10 00 11 00  ................
  0090: 02 00 12 00 04 00 05 00   14 00 08 00 16 00 0B 00  ................
  00A0: 02 01 00 00 0D 00 1A 00   18 06 03 06 01 05 03 05  ................
  00B0: 01 04 03 04 01 03 03 03   01 02 03 02 01 02 02 01  ................
  00C0: 01 00 00 00 1A 00 18 00   xx xx xx xx xx xx xx xx  ..........xxxxxx
  00D0: xx xx xx xx xx xx xx xx   xx xx xx xx xx xx xx     xxxxxxxxxxxx
  main, WRITE: TLSv1.2 Handshake, length = 223
  [Raw write]: length = 228
  0000: 16 03 03 00 DF 01 00 00   DB 03 03 59 0C 9F D7 4B  ...........Y...K
  0010: 6B 35 09 73 0E 37 01 9C   6F 82 AD F3 E1 9A C3 B8  k5.s.7..o.......
  0020: 5C 8D AA 18 71 BF C2 04   F4 C0 DA 00 00 38 C0 0A  \...q........8..
  0030: C0 14 00 35 C0 05 C0 0F   00 39 00 38 C0 09 C0 13  ...5.....9.8....
  0040: 00 2F C0 04 C0 0E 00 33   00 32 C0 08 C0 12 00 0A  ./.....3.2......
  0050: C0 03 C0 0D 00 16 00 13   C0 07 C0 11 00 05 C0 02  ................
  0060: C0 0C 00 04 00 FF 01 00   00 7A 00 0A 00 34 00 32  .........z...4.2
  0070: 00 17 00 01 00 03 00 13   00 15 00 06 00 07 00 09  ................
  0080: 00 0A 00 18 00 0B 00 0C   00 19 00 0D 00 0E 00 0F  ................
  0090: 00 10 00 11 00 02 00 12   00 04 00 05 00 14 00 08  ................
  00A0: 00 16 00 0B 00 02 01 00   00 0D 00 1A 00 18 06 03  ................
  00B0: 06 01 05 03 05 01 04 03   04 01 03 03 03 01 02 03  ................
  00C0: 02 01 02 02 01 01 00 00   00 1A 00 18 00 00 15 70  ...............x
  00D0: xx xx xx xx xx xx xx xx   xx xx xx xx xx xx xx xx  xxxxxxxxxxxxxxxx
  00E0: xx xx xx xx                                        xxxxx
  [Raw read]: length = 5
  0000: 15 03 03 00 02                                     .....
  [Raw read]: length = 2
  0000: 02 28                                              .(
  main, READ: TLSv1.2 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
  --snip---
  </code></pre>
  
  <p>As per <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/security/SunProviders.html" rel="noreferrer">http://docs.oracle.com/javase/7/docs/technotes/guides/security/SunProviders.html</a> the Java 7 docs do state that the cipher TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 is supported by Java 7 with unlimited strength ciphers but is only available with TLS1.2. I do see in my ClientHello message that my client is requesting to connect to the server using TLSv1.2 but in the end I am getting a handshake failure: RECV TLSv1 ALERT </p>
  
  <p>I was able to get it working by creating my own SSLSocketFactory and specifying I want it to explicitly use TLS1.2 and the above cipher. </p>
  
  <p>Added this method to explicitly set TLSv1.2 and the cipher I want: </p>
  
  <pre><code>public static HttpClient getHttpClient() throws Exception { 
      SSLContext sslContext = SSLContexts.custom().build(); 
      SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, 
              new String[]{"TLSv1.2"}, new String[]{"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"}, null); 
      return HttpClients.custom() 
              .setSSLSocketFactory(sslConnectionSocketFactory) 
              .build(); 
  } 
  </code></pre>
  
  <p>And modified the Spring Framework RestTemplate constructor to use this like so: </p>
  
  <pre><code>final RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory(getHttpClient())); 
  </code></pre>
  
  <p>I am not sure this is the right thing to do (or the best way to do it). I prefer not to explicitly set my cipher list but would like if my Java client automatically picks up the list of all ciphers by default and presents that to the server during the SSL handshake.</p>
  
  <p>I am aware that while Java 7 supports TLSv1.2 it is off by default and one recommendation is to turn it on globally for the JVM using: -Dhttps.protocols=TLSv1.2,TLSv1.1,etc… and can also specify the ciphers globally by using -Dhttps.cipherSuites=xxxxx. Also my older version of Java 1.7.0_60 does support the newer -Djdk.tls.client.protocols arg.</p>
  
  <p>Any other recommendations?</p>
  
  <p>Note: This was run on Mac OSx Sierra</p>