Reputation: 8830
Ran into another problem using SSL and Tomcat: I've configured a keystore which contains a key and a certificate (the server certificate I wish to present to the clients connecting to the site). I've done the same for the truststore (I'm going to need client authentication).
The problem I have now is that when I connect to my Tomcat instance via HTTPS, the certificate presented to me (the server certificate) is not my actual server certificate, but rather the key in the JKS keystore. Using -Djavax.net.debug=ssl reveals that it's presenting the correct CA for client authentication, but not the correct server certificate.
adding as trusted cert: Subject: CN=A Issuer: CN=A Algorithm: RSA; Serial number: - Valid from Tue Nov 10 14:48:31 CET 2009 until Mon Feb 08 14:48:31 CET 2010 adding as trusted cert: Subject: X Issuer: X Algorithm: RSA; Serial number: - Valid from Wed Jan 19 01:00:00 CET 2005 until Mon Jan 19 00:59:59 CET 2015
I've replaced the real values with place holders. A = the domain name of the server (but in this case, for some reason this is the key and not the certificate). X = a VeriSign CA (this should be correct). I have an existing certificate I would like to use to present to the clients, which I imported into a JKS keystore using keytool.
The Tomcat connector configuration:
<Connector port="444" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="conf/ssl/keystore.jks"
keystorePass="xx"
keyAlias="testkey"
truststoreFile="conf/ssl/truststore.jks"
truststorePass="xx" />
Any idea why my Tomcat instance is not presenting the correct certificate?
Upvotes: 18
Views: 40753
Reputation: 11
Here are the commands to generate a proper certificate entry for a keystore. Background knowledge: since Tomcat version 7, Tomcat supports PKCS12 as a keystore format, and java keystores can readily import such files. More background knowledge: key entries in keystores require the entire certificate chain to be present, or else SSL errors will happen.
So here's what to do:
concatenate your intermediate (signing root) cert and your root CA cert together:
cat intermediate.pem root.pem > chain.pem
concatenate your signed certificate with the chain:
cat cert.pem chain.pem > fullchain.pem
Now, create a pkcs12 file with the full chain, and the roots clearly identified. Make sure to copy the private key you generated with your CSR (named privkey.pem in my example) is in the same dir as the other files you generated when you execute this command::
openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out keystore.p12 -name server -CAfile chain.pem -caname root
Okay, cool; this file should work fine. You could just copy this to conf/ssl and modify your server.xml to use keystore.p12 instead of keystore.jks. Or, you could import it into your keystore file by cding to conf/ssl and running this command (maybe make a backup first):
keytool -importkeystore -destkeystore keystore.jks -deststoretype JKS -srckeystore keystore.p12 -srcstoretype PKCS12 -alias server
Upvotes: 0
Reputation: 1724
Expanding on @Bozho comment,
This was really critical. "The key and the purchased certificate are to be under the same alias".
The SSL certificate bought from the CA (Verisign, Digicert etc.) should be imported with the same alias as the private key generated before creating the csr. After importing the purchased certificate into the keystore using java keytool, you will see "Certificate reply added to keystore".
To check the trust chain, use the terminal command openssl s_client -connect yourdomain.com:443 -showcerts. It starts at your cert and leads to up to a trusted root CA.
Upvotes: 2
Reputation: 8830
The problem is (apparently - I can not really confirm this) that it's impossible to properly import a previously generated certificate (and matching key) into a JKS keystore and have it presented properly by Tomcat.
The situation in which my problem occurred is as follows:
The solution I found to work is:
Convert the existing certificate and its private key to the DER format. For example (using OpenSSL):
For the private key;
openssl pkcs8 -topk8 -nocrypt -in my_private_key.key -inform PEM -out my_private_key.der -outform DER
For the actual signed certificate;
openssl x509 -in my_certificate.crt -inform PEM -out my_certificate.der -outform DER
Import both DER files into a keystore (JKS file) using a custom Java class.
java ImportKey my_private_key.der my_certificate.der
I did not figure this out myself (all credit goes to the original inventor(s)).The source for this Java class, and some more details can be found here and here. I modified this class slightly so that there is a 3rd (or 4th) parameter that specifies the output location of the resulting JKS file.
The end result is a JKS keystore which can then be used in the Tomcat Connector configuration as the keystore. The above tool will generate the JKS file with default passwords for the key and JKS file itself, these can be changed later using keytool -storepasswd
and keytool -keypasswd
. Hope this helps for people facing the same issue.
Upvotes: 15
Reputation: 596996
Your configuration should work correctly.
Tomcat's how-to explains the steps to take in order to have a proper JKS.
Make sure you have imported the Certificate to the jks, with the appropriate alias (testKey)
Upvotes: 3