We are using java client(openJDK 1.8.0) to call an api that needs mutual authentication. For this we are using java standard JKS file as a keystore and truststore (same file for containing both trustcerts and identity certs/privatekey). Sample java we are using to test is as below ::
KeyStore clientKeyStore = KeyStore.getInstance("JKS");
clientKeyStore.load(new FileInputStream("./client.keystore"),
password.toCharArray());
// create a client connection manager to use in creating httpclients
PoolingHttpClientConnectionManager mgr = new PoolingHttpClientConnectionManager();
SSLContext sslContext = SSLContextBuilder.create()
.loadKeyMaterial(clientKeyStore, password.toCharArray())
.loadTrustMaterial(clientKeyStore, null).build();
// create the client based on the manager, and use it to make the call
CloseableHttpClient httpClient = HttpClientBuilder.create()
.setConnectionManager(mgr)
.setSslcontext(sslContext)
.setSSLHostnameVerifier(new NoopHostnameVerifier())
.build();
HttpPost httppost = new HttpPost("https://someUrl");
String params = "";
StringEntity param = new StringEntity(params);
httppost.setEntity(param);
System.out.println("Sending request...............");
HttpResponse response = httpClient.execute(httppost);
During SSL handshake as a last step of "serverhello", server is requesting client's identity by issuing "certificaterequest" - please find below request ::
*** CertificateRequest
Cert Types: RSA, ECDSA, DSS
Supported Signature Algorithms: SHA512withRSA, Unknown (hash:0x6, signature:0x2), SHA512withECDSA, SHA384withRSA, Unknown (hash:0x5, signature:0x2), SHA384withECDSA, SHA256withRSA, SHA256withDSA, SHA256withECDSA, SHA224withRSA, SHA224withDSA, SHA224withECDSA, SHA1withRSA, SHA1withDSA, SHA1withECDSA
Cert Authorities:
<CN=Intermediate CA, OU=ourCA.com, O=ourCA Inc, C=US>
Right after this, we are seeing below lines indicating java's keyManager is not able to find anything signed with the same signer.
*** ServerHelloDone
[read] MD5 and SHA1 hashes: len = 4
0000: 0E 00 00 00 ....
Warning: no suitable certificate found - continuing without client authentication
*** Certificate chain
<Empty>
***
We have validated that the certificate is present in the keystore and its a valid certificate( by opening it in windows box, it wont open if its invalid cert). So our keystore has an chain : myIdentity >> signed by Intermediate CA >>signed by Root CA
A few things we have tried(without any luck) is :
- Tried overriding keystoremanager to return a hardcoded alias ie alias of the certificate in keystore.jks
- Tried splitting identity certs and CA certs in two separate files ie separate keystore.jks and truststore.jks
Its worth sharing that the same connectivity works well if we are using cURL. In case of cURL, we have to pass client certificate explicitly as an argument ( cURL has no concept of keystore) and we are using linux default keystore (/etc/pki/tls/certs/ca-bundle.crt)
curl -vvv GET https://api.someone.com/some/path -E /home/certificates/client.test.pem --key /home/certificates/client.test.key
I am not sure what other details can add value but I'll be happy to share all the possible details needed ( except my private key :-P )