4

I'm trying to do a TLS connection using any of the AES GCM variants and from what I understand in the docs this should be possible but I get this error:

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)
    at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1989)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1096)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1342)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1369)

The problem is that the server I try to connect to only accepts these cyphers:

TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_256_GCM_SHA384
TLS_RSA_WITH_AES_128_GCM_SHA256

I cannot post here the server I try to connect to but I tried to replicate the issue on a github repo. I failed to find a server which only accepts these cypher suites that is why my repo fails with another error.

git clone https://github.com/andreicristianpetcu/gcm_with_bc_onjdk17
cd gcm_with_bc_onjdk17
JAVA_HOME="/usr/lib/jvm/java-7-openjdk-amd64/jre" mvn clean install

Basically this it the code from GitHub

    package com.github.gcm_with_bc_onjdk17;

    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.conn.ssl.NoopHostnameVerifier;
    import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.ssl.SSLContexts;

    import javax.crypto.Cipher;
    import javax.crypto.NoSuchPaddingException;
    import javax.net.ssl.SSLContext;
    import java.io.IOException;
    import java.security.KeyManagementException;
    import java.security.NoSuchAlgorithmException;
    import java.security.NoSuchProviderException;
    import java.security.Security;

    public class GcmWithBouncyCasteleOnJDK17 {

        public SSLConnectionSocketFactory getSslConnectionSocketFactory() throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, KeyManagementException, IOException {
            Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
            System.out.println(cipher);

            SSLContext sslContext = SSLContexts.custom()
                    .build();

            SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);

            CloseableHttpClient httpClient = HttpClients.custom()
                    .setSSLSocketFactory(sslConnectionSocketFactory)
                    .build();

            HttpGet out = new HttpGet("https://cloudflare.com/");
            CloseableHttpResponse execute = httpClient.execute(out);
            return sslConnectionSocketFactory;
        }

    }

Thank you

ddreian
  • 1,766
  • 5
  • 21
  • 29
  • 1
    what is the error message ? – Eugène Adell Apr 05 '18 at 12:46
  • Thank you Eugène for looking into this. I added the error message as part of the question for posterity reasons. Fortunately a work colleague figured out the solution. Can you shed some light into why I got down voted to a -1? Did I break any stack overflow rules? Thank you again for looking into my issue. – ddreian Apr 06 '18 at 18:59
  • I don't know and nobody knows who and why. When there is a comment we can think the person commenting is the one who voted. SO isn't perfect, you cannot imagine how many people ask, get their answer, and don't even mark it as correct. I'll upvote you for the good job done. – Eugène Adell Apr 06 '18 at 20:40

1 Answers1

8

A work colleague figured out the issue :) here is the fix:

Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
Security.removeProvider(BouncyCastleJsseProvider.PROVIDER_NAME);
Security.insertProviderAt(new BouncyCastleProvider(), 0);
Security.insertProviderAt(new BouncyCastleJsseProvider(), 1);

It seems that JDK7 supports TLS 1.2 but not the AES GCM ciphers. Since the cryptography providers are a list somehow the JDK provider was picked up since it supports TLS 1.2 even if it did not support the needed ciphers. Just putting Bouncy Castle a bit higher in the list fixed the issue.

I have no clue why my question was down voted :( I have no clue what rules I broke so it got down voted, I even provided source code.

Anyway.... super glad I found the fix even if it was outside of Stack Overflow. Leaving it here for posterity.

ddreian
  • 1,766
  • 5
  • 21
  • 29
  • 2
    you could mark your answer as correct, see [Can I answer my own question](https://stackoverflow.com/help/self-answer) – Eugène Adell Apr 06 '18 at 20:41
  • 1
    Small correction, you should use 1 and 2 as the indexes in your insertProviderAt() calls. According to [the docs](https://docs.oracle.com/javase/7/docs/api/java/security/Security.html#insertProviderAt(java.security.Provider,%20int)), the list is 1-based. If you use 0, it adds it at the end. – Bdoserror Sep 09 '20 at 22:02