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:
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.SSLv2Hello
- but it doesn't change the picture. 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)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
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.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 pictureThere'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.
Go to your GoDaddy product page. Select SSL Certificates and select Manage for the certificate you want to rekey. Select Rekey your certificate.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With