TLS certificates

Hi. Im struggeling with connecting a device to my broker using TLS. My IoT device ask for certificate files when configure it for MQTTS. Its 3 options:

  1. Server Root CA
  2. Client Certificate
    3 Client Private Key

I just dont get it how to create this files. What will be the best way and the most easy way of this 3 options?

Like for the create server root certificate. I found a blog post and som documentation.
https://www.hivemq.com/docs/hivemq/4.7/user-guide/howtos.html

Is this for creating server certificate (Server Root CA)?
What is this tool keytool? How do I get it?
Any other tip on how to create the required certificates?

Hope anyone can help my on my basic questions. Im somehow new to MQTT.

Hi Hans,

Thanks for your interest in MQTT and HiveMQ. Could you please clarify whether you have your own HiveMQ broker set up or you are using HiveMQ Cloud broker account?

In case if it is HiveMQ cloud broker, you can retrieve the server CA file as described in here: Frequently Asked Questions.

In case if you are running your own HiveMQ MQTT Broker, you might find useful our blog article Setting up TLS for your cloud-based MQTT broker.

Keytool is a certificate management utility included with Java . It allows users to create a single store, called a keystore, that can hold multiple certificates within it. This file can then be assigned or installed to a server and used for SSL/TLS connections.

For generating all certificates described in the blog article that I have suggested above, we have prepared a helpful shell script. You can use it as a reference or save it to a file certly.sh and run it with bash:

#!/bin/bash

defaultPass="changeme"
hostname="hivemq"

#hostname input
read -p "please input the hostname of the broker:  (default [$hostname]): " hostnameInput
    hostname=${hostnameInput:-$hostname}   # set the default Password (if user skip this entry)
    echo "the hostname is:  $hostname"

#password input
read -p "please input the password you wish to use:  (default [$defaultPass]): " passInput
    defaultPass=${passInput:-$defaultPass}   # set the default Password (if user skip this entry)
    echo "the password is:  $defaultPass"

#default file names and passwords
brokerCertName="server"
brokerKeystoreName="broker-keystore"
brokerKeystorePass=$defaultPass
brokerTruststoreName="broker-truststore"
brokerTruststorePass=$defaultPass
clientCertName="client-cert"
clientKeyName="client-key"
clientKeyPass=$defaultPass
clientKeystoreName="client-keystore"
clientKeystorePass=$defaultPass
clientName="client"
clientTruststoreName="client-truststore"
clientTruststorePass=$defaultPass

#check the time
time1=$(date +%s)
#crate output directory
outDirName="certs_$time1"
mkdir $outDirName
#goto output directory
pushd $outDirName

#create new broker .jks keystore
keytool -genkey -keyalg RSA -alias "hivemq" -keystore $brokerKeystoreName.jks -storepass $brokerKeystorePass -validity 360 -keysize 2048 -dname "CN=$hostname"

#export broker's cert .pem from the keystore
keytool -exportcert -alias "hivemq" -keystore $brokerKeystoreName.jks -rfc -file $brokerCertName.pem -storepass $brokerKeystorePass

#convert broker .pem certificate to .crt
openssl x509 -outform der -in $brokerCertName.pem -out $brokerCertName.crt

#import broker cert. into new client truststore
printf "yes\n" |keytool -import -file $brokerCertName.crt -alias "client" -keystore $clientTruststoreName.jks -storepass $clientTruststorePass

#generate .pem based client certificate and convert to .crt
openssl req -x509 -newkey rsa:2048 -keyout $clientKeyName.pem -out $clientCertName.pem -days 360 -passout pass:$clientKeyPass -subj "/CN=$clientName"
openssl x509 -outform der -in $clientCertName.pem -out $clientCertName.crt

#import client-cert into the broker's truststore
printf "yes\n" |keytool -import -file $clientCertName.crt -alias "client" -keystore $brokerTruststoreName.jks -storepass $brokerTruststorePass

#create client P12 keystore
openssl pkcs12 -export -in $clientCertName.pem -inkey $clientKeyName.pem -certfile $clientCertName.pem -out $clientKeystoreName.p12 -passin pass:$clientKeyPass -passout pass:$clientKeystorePass;

#convert client P12 keystore to JKS keystore
keytool -importkeystore -srckeystore $clientKeystoreName.p12 -srcstoretype pkcs12 -destkeystore $clientKeystoreName.jks  -deststoretype JKS -storepass $clientKeystorePass -srcstorepass $clientKeystorePass 2>/dev/null;

#restore original directory
popd

echo "$outDirName"

If at any point you require further help please do not hesitate and ask. Feel free to share your code and the text of error messages, if any error arises.

Kind regards,
Dasha from HiveMQ Team

Hi. Im using HiveMQ Cloud broker account. Pay as you go…
I still cant make it. Its cryptic to me. So I was able to download a OpenSSL command tool. I inserted the suggested command: s_client -connect “My broker URL” :8883 -showcerts < /dev/null 2> /dev/null | sed -n ‘/BEGIN/,/END/p’ > server.pem

I get error back. reporting unknown option <

Any more tip?

Hi Hans,

seems that you are directly in the OpenSSL console mode, which do not know the option “<”.
Please try directly from shell.

Like

user@pc ~ % openssl s_client -connect ...

And not

user@pc ~ % openssl
OpenSSL> s_client -connect ...

Hope that helps.

Kind regards,
Dominic

shell is that windows command? I cant make it there either… The original post suggested this:

But no furter explanations. This is cryptic to a newbe like me… How is this working. I understand I have to replace the URL with my own broker URL, but what about all the other arguments in that string:
-showcerts < /dev/null 2> /dev/null | sed -n ‘/BEGIN/,/END/p’ > server.pem
What to do here?

Will this generate a file?

I tried to run this : s_client -connect 4ad85b7fade04d07911be2ac1da2f5e4.s2.eu.hivemq.cloud:8883
then i get this back:

Please help me understand furter on how to generate the server sertificate I can use in my IoT device.

BR
Hans

Hi Hans,

currently, you opened the OpenSSL command line tool, via command openssl. However, that’s not required.
Just open your terminal (shell, bash, zsh) and use the full command with your URL.

$ openssl s_client -connect brokerurl.s2.eu.hivemq.cloud:8883 -showcerts < /dev/null 2> /dev/null | sed -n ‘/BEGIN/,/END/p’ > server.pem

The other arguments in this command are:
-showcerts → shows the full certificate chain
< /dev/null 2> /dev/null → closes the command and redirects stderr
sed -n ‘/BEGIN/,/END/p’ → finds the begin and end of each certificate
> server.pem. → redirects the output to the file server.pem

Kind regards,
Dominic

Ok thnks for your help Dominic. Now i may be asking very basic question. I understand shell command as the same as windows comand prompt window?

The system does not recognice the path:

Do I need to navigate to folder of openssl application?

Or do I totally misunderstand this?

BR
Hans

Hi Hans,

if you are using Windows you have to use the WSL (Windows Subsystem for Linux) to be able to use the whole command.
In the Windows Terminal you can use openssl s_client -connect brokerurl.s2.eu.hivemq.cloud:8883 -showcerts and you will see 3 certficates. Each certificate starts with the —BEGIN CERTIFICATE— line and end with the —END CERTIFICATE— line.
Use the mouse and select each certificate one-by-one and copy paste them into a single file and name it server.pem and save it.
Finally, the server.pem file should look like:

Kind regards,
Dominic

1 Like

Hi there,

I made the server.pem file as you suggest above, and using MQTT.fx - I selected the file as the “CA certifcate file”.
MQTT.fx connected and all is good.

But, I don’t need to use this file to connect.
Instead, I can select the option “CA signed server certificate” - and it still connects fine.

What is the difference? why use the server.pem file at all? Does it provide any kind of security?

I’m completely confused by all this certificate stuff!

Thanks
Darren

Hi Dominic,
I did as you instructed. I created a .pem file from the three certificates generated by openssl. However the device could not take a document above 4kb. This was 6kb. I got this feedback from vendor:

Your format may be a certificate issued by an intermediate authority, I am not sure if the certificate issued by the Root CA authority is the same

1. It may be the reason of openssl parameters, you can try to modify the parameters
2. The test only keeps a set of content from “BEGIN CERTIFICATE” to “END CERTIFICATE” to see if it can be connected
3. Generally speaking, each “certificate” should be less than 4KB; this is also the reason why “Invalid File” appears when burning the software and importing server.pem (6KB).

Any comment to this? Do I need all 3 certificates in the file?

Hi @DarrenL ,

Some systems do not trust the specific CA used by HiveMQ cloud, which is why using the ca.pem file is then necessary.
There’s not difference in security whether or not the ca is trusted by the system or you specifically trust it via adding the ca.pem file.

Best,
Florian

1 Like

Hi @hapetter,

You can download the root certificate here.
It should be sufficient to use it. It has 2kb size.

Regards,
Florian

1 Like

Hi Florian,

Thanks for your reply.

I can connect to HiveMQ cloud using MQTTnet library for Visual Studio.
I didn’t need to refer to any certificates to do this.
So, is simply connecting to HiveMQ without any certificates involved a secure (and encrypted?) connection on it’s own, or do I still need to use other certificates?

In my software MQTT connection window, there are the following inputs:

  • Broker address
  • Broker port
  • Client ID
  • Username
  • Password
  • UseTLS (tick box)
  • MQTT Version (3.1, 3.1.1 & 5.0)

Do I also need to include a “browse for certificate (pem?) file” - just in case?

Thank you

Hi Darren,

When you are connecting without any certificates but using a TLS connection, then your default SSL options are used, connection is secure.

You can include a “browse for CA file” in case if you need to accommodate your app for the above mentioned case:

Some systems do not trust the specific CA used by HiveMQ cloud, which is why using the ca.pem file is then necessary.

Kind regards,
Dasha from HiveMQ Team

Hi @Daria_H ,

Thanks for your message.

Can I conclude then, that if I also include a “Browse for CA file” option, & the client can connect to the TLS broker - then this is all the security I need to offer?

Is the data in this TLS connection encrypted and absolutely secure against hackers?
If so, then I think my work may be done in this respect.

Thanks again.

Regards,
Darren

Hi @hapetter ,

Please try to create the server.pem file in the following way and use it for mqtt-cli connection:

openssl s_client -connect 18b93f452b8445ba86ac0ec6d2228eb9.s2.eu.hivemq.cloud:8883 -showcerts </dev/null 2>/dev/null | sed -n '/BEGIN/,/END/p' > server.pem

Where:

  • The openssl s_client -showcerts command retrieve the certificate from the server;
  • The sed ... command will extract from the output of the previous command everything between BEGIN and END, inclusive;
  • The > server.pem will output the result to the server.pem file.

Use the server.pem with mqtt-cli:

#SUBSCRIBE
mqtt sub -t test -h 18b93f452b8445ba86ac0ec6d2228eb9.s2.eu.hivemq.cloud -p 8883 -u HiveUser1 -pw HiveUser1  --cafile server.pem


#PUBLISH
mqtt pub -t test -m dasha -h 18b93f452b8445ba86ac0ec6d2228eb9.s2.eu.hivemq.cloud -p 8883 -u HiveUser1 -pw HiveUser1 --cafile server.pem

Note that there is no -s (--secure) flag used here.

Note2: If you copy-paste my commands from here, sometimes the single quotes might get replaced by different quotes by the operating system. So, after you paste, please check that all the quotes are correct.

Kind regards,
Dasha