Sigh. It always happens, I always figure it out and I always forget to document it, destined to re-learn it all next time around.
One of our applications connects, using SSL, to an HTTP server. It POSTs a single parameter, SMS-Request, in form-data format and the parameter contains an XML document. We have a client SSL certificate signed by their CA, which is not signed by a trusted root CA like Verisign. They have a server SSL certificate signed, I think, by the same CA.
Our certificates are about to expire, so we need a new one. Also, they're changing their certification scheme to bring all the CA certificates, and thus client and server certificates signed by them, under the authority of a global CA certificate. Thus, our client certificate chain looks a bit like this:
-
Global Root CA
-
UK Root CA
-
UK Platform CA Certificate
- Our Client Certificate
- Somone Else's Client Certificate
Now, they used to offer a service whereby they just created the certificate for us, wrapped it up in a .jks file and we'd switch over to that. Now they're doing things a bit more like the 'proper' way, so we have to send them a CSR and so on. Here's what I've done:
- Created a new keypair using OpenSSL.
- Created a CSR conforming to their requirements and containing my public key.
- Sent said CSR off to them for signing.
- Received signed certificate, in PEM format.
- Concatenated my private key with the signed certificate.
- Used
keytool -import to import my new certificate and the various CA certificates in the chain.
That, however, hasn't worked. In the old keystore, our client certificate was listed by keytool -list as:
Entry type: keyEntry
Certificate chain length: 1
In our new keystore, it's listed as:
Entry type: trustedCertEntry
Which is the same as all the CA certificates. I read in the keytool documentation that if the imported file is in PKCS7 format, with a full certificate chain, it would establish the chain of trust up to a trusted root CA certificate, so I tried to use OpenSSL to convert my PEM format certificate to PKCS7, failed and resorted to using the Internet Explorer Certificate Export Wizard to do it, then used OpenSSL to convert the DER-encoded PKCS7 chain to a PEM-encoded file. I imported that under the same alias as the previous client certificate, so it should have overwritten it, but it's still listed as the same.
Now when we use this keystore to POST requests (we're using Commons HTTP Client) we're treated to:
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
Please, can someone hit me with the clue bat before our certificate expires next Friday? It should be so simple, but I need a fresh head.