Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SSL: 400 no required certificate was sent

Tags:

java

ssl

oracle

The code and inputs

I'm trying to establish SSL connection and I'm getting 400 No required SSL certificate was sent response from the server. I'm doing this in a standard way like it's described for example here; I run Java 8.

The sample of my code would be:

    OkHttpClient client     = new OkHttpClient();
    KeyStore keyStoreClient = getClientKeyStore();
    KeyStore keyStoreServer = getServerKeyStore();
    String algorithm        = ALGO_DEFAULT;//this is defined as "PKIX"

    KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(algorithm);
    keyManagerFactory.init(keyStoreClient, PASSWORD_SERVER.toCharArray());

    SSLContext sslContext = SSLContext.getInstance("TLS");

    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(algorithm);
    trustManagerFactory.init(keyStoreServer);

    sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());

    client.setSslSocketFactory(sslContext.getSocketFactory());
    client.setConnectTimeout(32, TimeUnit.SECONDS); // connect timeout
    client.setReadTimeout(32, TimeUnit.SECONDS);    // socket timeout

    return client;

And here is the code that I use to send GET-request:

public String get(String url) throws IOException
{
    String callUrl  = URL_LIVE.concat(url);
    Request request = new Request.Builder()
            .url(callUrl)
            .build();
    Response response = this.client.newCall(request).execute();
    return response.body().string();
}

I enabled:

System.setProperty("javax.net.debug", "ssl");

So to see debug messages - but there's no errors/warnings/alerts there, the only thing is in the very end:

main, called close()
main, called closeInternal(true)
main, SEND TLSv1.2 ALERT:  warning, description = close_notify
main, WRITE: TLSv1.2 Alert, length = 26
main, called closeSocket(true)

Which is the only thing I can treat as "abnormal" stuff (but I doubt it is).

I tried:

  • Different protocols disabling/enabling. For instance, forcing TLSv1 / TLSv1.1 for the socket with no success. To try that I wrapped my ssl factory into another factory which disables/enables certain protocols.
  • Disabling SSLv2Hello - but it doesn't change the picture.
  • Install Oracle policies because before there were notices about some skipped algorithms and this installation "solved" that but the overall result is still same.
  • Setting System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true"); - lame, but also didn't change a thing apart from message in the log Allow unsafe renegotiation: true (was "false" obviously)
  • Using KeyManagerFactory.getDefaultAlgorithm() as algorithm for KeyManagerFactory.getInstance() call. That raises exception Get Key failed: Given final block not properly padded and as far as I got the idea, it's because of wrong algorithm used (read this). My default algorithm is: SunX509
  • Adding the certificate directly to my machine with keytool -importcert -file /path/to/certificate -keystore keystore.jks -alias "Alias" and then using this in my program via System.setProperty("javax.net.ssl.trustStore","/path/to/keystore.jks"); with setting password: System.setProperty("javax.net.ssl.trustStorePassword","mypassword"); (I set password in keytool after which confirmed trusted certificate with yes); see this and this posts. No errors were raised with this - but issue persisted.
  • Adding the certificate to the global keystore (the one located in JAVA_PATH/jre/lib/security/cacerts) with: keytool -import -trustcacerts -keystore cacerts -storepass changeit -noprompt -alias Alias -file /path/to/certificate (see this); looks like import operation was successful but it didn't change the picture

There's also notice in debug: ssl: KeyMgr: choosing key: 1 (verified: OK) - not sure if it's relevant as I'm not SSL expert.

Unfortunately I can not see the server-side logs so I can't observe the full picture.

Question

What can be the reason for this 400 error and how can I progress further (debug/try something else) ? Any tips would be much appreciated.

like image 659
Alma Do Avatar asked Mar 29 '16 12:03

Alma Do


People also ask

How do I fix my GoDaddy SSL certificate?

Go to your GoDaddy product page. Select SSL Certificates and select Manage for the certificate you want to rekey. Select Rekey your certificate.


1 Answers

Your server is asking for a client-side certificate. You need to install a certificate (signed by a trusted authority) on your client machine, and let your program know about it.

Typically, your server has a certificate (with the key purpose set to "TLS server authentication") signed by either your organization's IT security or some globally trusted CA. You should get a certificate for "TLS client authentication" from the same source.

If you capture the TLS handshake in Wireshark, you'll see the ServerHello message followed by a "Client Certificate Request", to which you reply with a "Client Certificate" message with length 0. Your server chooses to reject this.

like image 126
Freezer Avatar answered Sep 30 '22 13:09

Freezer