Prerequisites
Create the following directory tree and empty, two index.txt and serial files containing integer values.
Place files in their corresponding directories and modify them to match your organisation’s information.
Your keystores and truststores will be output to a directory named keystores
one level above your working directory.
mkdir -p certs crl intermediate intermediate/certs intermediate/csr intermediate/newcerts intermediate/private private newcerts ../keystores; touch index.txt intermediate/index.txt; echo 1001 | tee serial intermediate/serial;
In each openssl.cnf modify dir to match their respective absolute paths (pwd
will show your current working directory).
Root CA
First we want to create a private key and root CA
openssl genrsa -aes256 -out private/ca.key.pem 4096; chmod 400 private/ca.key.pem; openssl req -config ca-openssl.cnf \ -key private/ca.key.pem \ -new -x509 -days 7300 -sha256 -extensions v3_ca \ -out certs/ca.cert.pem; chmod 444 certs/ca.cert.pem;
Intermediate CA
We need to generate an intermediate CA
openssl genrsa -aes256 \ -out intermediate/private/intermediate.key.pem 4096; chmod 400 intermediate/private/intermediate.key.pem;
Since we want to sign our fresh key with the root CA, we need a CSR…
openssl req -config intermediate/int-openssl.cnf -new -sha256 \ -key intermediate/private/intermediate.key.pem \ -out intermediate/csr/intermediate.csr.pem;
…which we can now sign.
openssl ca -config ca-openssl.cnf -extensions v3_intermediate_ca \ -days 3650 -notext -md sha256 \ -in intermediate/csr/intermediate.csr.pem \ -out intermediate/certs/intermediate.cert.pem; chmod 444 intermediate/certs/intermediate.cert.pem;
You can verify that CA index contains the certificate by inspecting index.txt
and the certificate chain with the following command
openssl verify -CAfile certs/ca.cert.pem \ intermediate/certs/intermediate.cert.pem;
Should both be OK, it is time to create the certificate chain
cat intermediate/certs/intermediate.cert.pem \ certs/ca.cert.pem > intermediate/certs/ca-chain.cert.pem; chmod 444 intermediate/certs/ca-chain.cert.pem;
Sever Certificate
Next we will be creating a certificate and key for our server, sign it and generate the keystore to be used by HiveMQ. In the following examples, you will need to replace broker.hivemq.local
with the FQDN of the individual nodes you are creating these for.
Generate the server’s private key
openssl genrsa -aes256 \ -out intermediate/private/broker.hivemq.local.key.pem 2048; chmod 400 intermediate/private/broker.hivemq.local.key.pem;
Create a signing request
openssl req -config intermediate/int-openssl.cnf \ -key intermediate/private/broker.hivemq.local.key.pem \ -new -sha256 -out intermediate/csr/broker.hivemq.local.csr.pem;
Sign the server’s key and generate its certificate
openssl ca -config intermediate/int-openssl.cnf \ -extensions server_cert -days 375 -notext -md sha256 \ -in intermediate/csr/broker.hivemq.local.csr.pem \ -out intermediate/certs/broker.hivemq.local.cert.pem; chmod 444 intermediate/certs/broker.hivemq.local.cert.pem;
We now have all necessary parts to produce a keystore…
Concatenate the certificate chain:
cat certs/ca.cert.pem intermediate/certs/intermediate.cert.pem intermediate/certs/broker.hivemq.local.cert.pem > ../keystores/broker.hivemq.local.chain.pem;
Import the certificate chain and the private key in to a PKCS12 container
openssl pkcs12 -export -in ../keystores/broker.hivemq.local.chain.pem -inkey intermediate/private/broker.hivemq.local.key.pem > ../keystores/broker.hivemq.local.p12;
Import the contents of the PKCS12 container in to an JKS container.
keytool -importkeystore -trustcacerts -srckeystore ../keystores/broker.hivemq.local.p12 -destkeystore ../keystores/broker.hivemq.local-keystore.jks -srcstoretype pkcs12 -destalias broker.hivemq.local -alias 1;
Remove the concatenated certificate chain and the PKCS12 container
rm -f ../keystores/broker.hivemq.local.p12 ../keystores/broker.hivemq.local.chain.pem;
… and truststore
keytool -import -trustcacerts -alias 'Root CA' -file certs/ca.cert.pem -keystore ../keystores/broker.hivemq.local-truststore.jks;
Client certificates
Now we can start creating certificates which our clients can present to the server while establishing a connection. You may replace client1
with any desired name.
As before, our starting point is to generate a key…
openssl genrsa -aes256 \ -out intermediate/private/client1.key.pem 2048; chmod 400 intermediate/private/client1.key.pem;
…create a signing request for it
openssl req -config intermediate/int-openssl.cnf \ -key intermediate/private/client1.key.pem \ -new -sha256 -out intermediate/csr/client1.csr.pem;
… and sign it/generate a certificate
openssl ca -config intermediate/int-openssl.cnf \ -extensions usr_cert -days 375 -notext -md sha256 \ -in intermediate/csr/client1.csr.pem \ -out intermediate/certs/client1.cert.pem;
Now it is time to generate the client’s keystore…
Concatenate the certificate chain:
cat certs/ca.cert.pem intermediate/certs/intermediate.cert.pem intermediate/certs/client1.cert.pem > ../keystores/client1.chain.pem;
If you want to create a certificate chain to be used in PEM format directly the order of the certificates needs to be changed:cat intermediate/certs/client1.cert.pem intermediate/certs/intermediate.cert.pem
certs/ca.cert.pem> ../keystores/new-client1.chain.pem;
Import the certificate chain and the private key in to a PKCS12 container
openssl pkcs12 -export -in ../keystores/client1.chain.pem -inkey intermediate/private/client1.key.pem > ../keystores/client1.p12;
Import the contents of the PKCS12 container in to an JKS container.
keytool -importkeystore -trustcacerts -srckeystore ../keystores/client1.p12 -destkeystore ../keystores/client1-keystore.jks -srcstoretype pkcs12 -destalias client1 -alias 1;
Remove the concatenated certificate chain and the PKCS12 container
rm -f ../keystores/client1.p12 ../keystores/client1.chain.pem;
…and truststore
keytool -import -trustcacerts -alias 'Root CA' -file certs/ca.cert.pem -keystore ../keystores/client1-truststore.jks;