I am writing this post in hope that it will help others by saving hours of research in trying to generate and use SSL certificates.
These steps outline the complete activity needed for generating SSL certificates for a web server in Java. For clarity, I have also included the steps that are done by the Certificate Authority. As such, you can follow these steps exactly and experience the role each of them plays.
Activity 1: Creating the Root CA
Step 1: Create a Private Key for the Root CA
openssl genrsa -out ca.key 4096
Step 2: Create the Self-Signed Certificate of the Root CA
openssl req -sha256 -new -x509 -days 1826 -key ca.key -out ca.crt
Root CA Certificates are always self signed. These certificates are valid for a long period, like 20-25 years.
Notice the -sha256 option, it forces the certificate to use the now mandatory SHA-2 instead of the unsecure SHA-1 algorithm which is blocked by browsers
Activity 2: Creating the Intermediate Certificate
Step 1: Create a Private Key for the Intermediate CA
openssl genrsa -out ia.key 4096
Step 2: Generate a Certificate Signing Request (CSR) for the Intermediate CA Certificate
openssl req -new -key ia.key -out ia.csr
Unlike the Root CA Certificate, this one cannot be self signed. It will be signed by the Root CA. The CSR created during this step is used by the Root CA to generate this certificate.
Step 3: Create an extension file for the Intermediate CA Certificate
echo "basicConstraints=CA:TRUE" > ia.ext
This step is needed to give the Intermediate CA the authority to generate certificates for others. If this step is omitted along with the -extfile option in the next step, the browser will display a warning saying that the Intermediate CA is not authorized to generate certificates.
This rule does not apply to the Root CA certificates. It is needed to differentiate between End Entity and Intermediate CA certificates. Without this security in place, all end entity certificates (like for your server) would have been able to generate certificates for others while inheriting the trust from the Root CA.
Step 4: Create the Intermediate CA Certificate signed by the Root CA
openssl x509 -req -sha256 -days 730 -in ia.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out ia.crt -extfile ia.ext
Notice the -extfile option which passes the extensions file from the previous step.
Activity 3: Creating the Server Certificate for your Web Server
Step 1: Create a Private Key for the Server
openssl genrsa -out test.maxotek.net.key 4096
Step 2: Generate a Certificate Signing Request (CSR) for the Server Certificate
openssl req -new -key test.maxotek.net.key -out test.maxotek.net.csr
In this case, the Intermediate CA will generate the certificate for our server. So, a CSR needs to be generated and sent to the Intermediate CA.
Step 3: Create the Server Certificate signed by the Intermediate CA
openssl x509 -req -sha256 -days 730 -in test.maxotek.net.csr -CA ia.crt -CAkey ia.key -set_serial 02 -out test.maxotek.net.crt
We don’t need the -extfile option or the extensions file in this case. This is because this Server certificate is an End Entity certificate and it should not have the authority to generate certificates.
Activity 4: Using the certificates with JAVA
If you did not use keytool to create the private key and CSR (like in our case), there is a bit of a trick to using these certificates with JAVA. Keytool does not allow you to import the private key directly. This is for security reasons because the private key should never leave the server. You don’t need to provide your private key to the CA for it to generate a certificate for you.
Step 1: Chain Root and Intermediate Certificates
cat ia.crt ca.crt > bundledca.crt
This is very important because the client will only have the Root CA’s certificate in it’s certificate store. All intermediate certificates must be passed by the server to the client.
Step 2: Convert the certificate and private key to the Intermediate PKCS12 format
As keytool lacks (more like intentionally omitted) the ability to import the private key directly, we are going to use the PKCS12 intermediate format. This PKCS12 file will have the private key of our server along with the public keys of our server, the Intermediate CA and the Root CA chained together.
openssl pkcs12 -export -in test.maxotek.net.crt -inkey test.maxotek.net.key -out test.maxotek.net.p12 -name testmaxotek -CAfile bundledca.crt -caname gidia -chain
Step 3: Convert the PKCS12 file to Java Keystore
Finally we convert the PKCS12 file to JAVA’s Keystore format which can then be used by a web server like Tomcat, JBoss.
keytool -importkeystore -deststorepass changeit -destkeypass changeit -destkeystore test.maxotek.net.keystore -srckeystore test.maxotek.net.p12 -srcstoretype PKCS12 -srcstorepass changeit -alias testmaxotek
The important thing here is to match the alias with the one used in the previous step.
Convert Keystore to PKCS12
keytool -importkeystore -srckeystore test-142.keystore -destkeystore test-142.p12 -deststoretype PKCS12
Export the certificate
openssl pkcs12 -in test-142.p12 -nokeys -out test-142.pem
Export the private key
openssl pkcs12 -in test-142.p12 -nodes -nocerts -out test-142.key