SSL: 400 no required certificate was sent

此生再无相见时 提交于 2021-02-07 07:19:17

问题


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.


回答1:


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.



来源:https://stackoverflow.com/questions/36284543/ssl-400-no-required-certificate-was-sent

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!