Background

Our app, which is written in Java and run in Oracle Application Server, is communicating with other external system for information exchange. Recently, one of external systems has upgraded their infrastructure (moved to new hardware and new version of server). They have provided us new public certificate so that our app can establish connection to new endpoint without issue.

Problem

Since we deployed new certificate, our app’s request has been denied by their web server with following error message:

unknown_ca

I googled but didn’t find any useful information so I decided to troubleshoot step by step.

I firstly added following paramters into the jvm arguments to enable ssl logging capability:

-Djavax.net.debug=ssl

By thoroughly checking each line in the SSL log, I found following information:

  1. Java loads all public certificate from trust store (correct)
  2. Java loads all certificate from key store (correct)
  3. Java sends a Hello to their server (correct)
  4. Their server resonds and Java checks our key store to find matching certificate (correct)
  5. Java iterate each certificate pair in key store and sends the first one back to their server (wrong!!!)

This is why their server rejected our server with unknown_ca message because our app sent whatever at the first position in keystore back to their server.

Solution

I did a study on the SSL handshake process and found that the client certificate exchange is optional and it can be disabled. As a result, we sent an email to the administrator and asked him to disable it. After it is disabled, we are able to see that the conneciton is established successfully and has been working since then.

But I am still unsure why Java sent the first certificate (we don’t store the private key so there is no certificate to send back in keystore).