I've been given 3 files: MY.cer, MY.key, B.pem (root,intermediate certs). Using openssl I get a successful connection:
openssl s_client -connect abc.com:10101 -cert MY.cer -key MY.key, -CAfile B.pem
Using openssl, we bundled MY.cer and MY.key (pkcs12) and using keytool imported the pair into keystore.jks then imported B.pem into truststore.jks. Our Java SSLConnector object (which we use everywhere here) barfs:
main, READ: TLSv1 Alert, length = 2
main, RECV TLSv1 ALERT: fatal, bad_certificate
%% Invalidated: [Session-1, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA]
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
main, called close()
main, called closeInternal(true)
javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
at sun.security.ssl.Alerts.getSSLException(Unknown Source)
at sun.security.ssl.Alerts.getSSLException(Unknown Source)
at sun.security.ssl.SSLSocketImpl.recvAlert(Unknown Source)
at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(Unknown Source)
at com.dam.system.SSLConnector.sendPost(SSLConnector.java:132)
SSLConnector uses HttpsUrlConnection and with this new customer's server, we're seeing this error for the first time.
We've examined the openssl debug, javax.ssl debug, googled extensively, tried portecle and InstallCert.java (which both show the bad_certificate) with no resolution.
What reasons might the server have for deeming our cert(s) bad from JSSE, but not bad from openssl?
The problem is entirely in the way the keystores were created.
List instead of Chain: The client, its root and intermiedate CA certificates (from the B.pem file) were imported into the keystore.jks separately (showed up as a list) instead of APPENDED to each other in a CHAIN. We used kse v5.1.1 to remove the CA certs then edit the chain and append them back.
Missing server certificates. The truststore.jks had the client certs instead of the server's. Used openssl to obtain the server's certs and keytool to create a new truststore.jks.
Everything works flawlessly now without change any Java code.