HiveMQ Platform How-Tos

Configure server-side TLS with HiveMQ and Keytool (self-signed)

The next sections give you step-by-step instructions on how to configure server-side SSL/TLS with HiveMQ.
In this scenario, the client only validates the correct server certificate.

Generate a server-side certificate for HiveMQ

  • Execute the following command and enter all prompted information for the certificate:

    keytool -genkey -keyalg RSA -alias hivemq -keystore hivemq.jks -storepass changeme -validity 360 -keysize 2048
    We highly recommend that you update the changeme default to a strong password.
    The first question asks about your first and last name. This is the common name of your certificate. Please enter the URL under which you will connect with your MQTT clients. For example, broker.yourdomain.com (for production) or localhost (for development).
  • Select yes to confirm your entries.

  • Define a password for the newly generated key.

    We highly recommend not to use the same password for the key and the key store.
  • Place the hivemq.jks in the HiveMQ directory and add a TLS listener to the config.xml file.

    <listeners>
    ...
        <tls-tcp-listener>
            <port>8883</port>
            <bind-address>0.0.0.0</bind-address>
            <tls>
                <keystore>
                    <path>hivemq.jks</path>
                    <password>your-keystore-password</password>
                    <private-key-password>your-key-password</private-key-password>
                </keystore>
                <client-authentication-mode>NONE</client-authentication-mode>
            </tls>
        </tls-tcp-listener>
    ...
    </listeners>
    The your-keystore-password and your-key-password passwords depend on the passwords from the previous steps.

Generate a PEM client certificate (mosquitto_pub/_sub)

When you connect with mosquitto_pub/_sub command-line utilities, a PEM file of the certificate is required to allow the mosquitto clients to validate the self-signed certificate. You need to have access to the server key store generated in the above steps.

  • To export a PEM file from the server key store, enter:

    keytool -exportcert -keystore hivemq.jks -alias hivemq -keypass your-key-password -storepass your-keystore-password -rfc -file hivemq-server-cert.pem
    Be sure to replace your-keystore-password and your-key-password in the command with your chosen passwords.
  • To use the PEM with mosquitto_pub, enter:

    mosquitto_pub -t "test/topic" -m "TLS works with client PEM" -p 8883 --cafile hivemq-server-cert.pem

Generate a client JKS trust store (Paho Java)

When you connect with a Java MQTT client, a JKS client key store is required to validate the self-signed certificate. You need to have access to the server key store generated in the above steps.

  • Export the server certificate from the server key store

    keytool -export -keystore hivemq.jks -alias hivemq -storepass your-keystore-password -file hivemq-server.crt
    Be sure to replace your-keystore-password in the command with your chosen password.
  • To generate a client trust store, enter:

    keytool -import -file hivemq-server.crt -alias HiveMQ -keystore mqtt-client-trust-store.jks -storepass changeme
    We highly recommend the use of a strong password instead of changeme.
    • Confirm the certificate with yes, before the trust store is successfully created.

  • Connect with Eclipse Paho

    The following simple example only shows how to test if TLS is working.
    For production usage, a more sophisticated implementation is necessary.
    Connect to HiveMQ with SSL using Eclipse Paho
    private static Logger log = LoggerFactory.getLogger(PublisherSSL.class);
    
    public static void main(String... args) {
        try {
            String clientId = "sslTestClient";
            MqttClient client = new MqttClient("ssl://localhost:8883", clientId, new MemoryPersistence());
    
            MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
    
            try {
                mqttConnectOptions.setSocketFactory(getTruststoreFactory());
            } catch (Exception e) {
                log.error("Error while setting up TLS", e);
            }
    
            client.connect(mqttConnectOptions);
            client.publish("test/topic", "TLS works with client JKS!".getBytes(), 0, false);
            client.disconnect();
    
        } catch (MqttException e) {
            log.error("MQTT Exception:",e);
        }
    }
    
    public static SocketFactory getTruststoreFactory() throws Exception {
    
        KeyStore trustStore = KeyStore.getInstance("JKS");
        InputStream in = new FileInputStream("mqtt-client-trust-store.jks");
        trustStore.load(in, "your-client-keystore-password".toCharArray());
    
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustStore);
    
        SSLContext sslCtx = SSLContext.getInstance("TLSv1.2");
        sslCtx.init(null, tmf.getTrustManagers(), null);
        return sslCtx.getSocketFactory();
    }
    Remember to replace the passwords in the snippet with your chosen passwords.

Configure TLS with HiveMQ and Portecle (self-signed)

  • Download and unzip the current version of Portecle.

  • To start Portecle, double-click the provided portecle.jar file or enter java -jar portecle.jar in the console:

    Portecle after start

    Portecle after start

  • To create the server key store, select File → New Keystore from the menu and select JKS as key store type in the popup window:

    Choose Java key store

    Choose Java key store

  • To create a new key pair, select Tools → Generate Key Pair and define the Key Algorithm and Key Size:

    Common Key Algorithm and Size

    Common Key Algorithm and Size

    • Enter the Signature Algorithm ( SHA512withRSA is recommended) and the Certificate Details:

      Certificate Signature Algorithm and Details

      Certificate Signature Algorithm and Details

    • Choose a Key Pair Entry Alias:

      An alias for the key pair

      An alias for the key pair

    • Set a password for the Key Pair Entry:

      A password to protect the private key

      A password to protect the private key

      Successful Generation of Key Pair

      Successful Generation of Key Pair

    • To save the key store, define File → Save Keystore As…​:

      Save the key store

      Save the key store

  • To export the certificate for the client, right-click the certificate key pair and select Export.

    • Select Head Certificate as Export Type and choose an export format ( PEM is recommended):

      Export Details

      Export Details

  • Select Choose directory to save the certificate.

    Export Successful

    Export Successful

  • Next, create the client key store

    • Select File → New Keystore from the menu and JKS as key store type.

    • Import the just saved certificate via Tools → Import Trusted Certificate.

    • Select the previous exported certificate:

      Import server head certificate

      Import server head certificate

    • Confirm the message that the trust path could not be established.
      This is because the certificate is self-signed and no certificate chain can verify it:

      Warning because of the self-signed certificate

      Warning because of the self-signed certificate

    • Confirm the showed certificate details:

      Certificate Details

      Certificate Details

    • To trust the certificate, click Yes.

      Trust the created self-signed certificate for the server

      Accept to trust our created self-signed certificate for the server

    • Enter an alias:

      Alias for the server certificate in the client key store

      Alias for the server certificate in the client key store

      Successful import of the server certificate in the client key store

      Successful import of the server certificate in the client key store

    • Save the key store as client.jks with File → Save Keystore As…​.

  • Place the server.jks in the HiveMQ directory and add a TLS listener to config.xml.

    <listeners>
    ...
        <tls-tcp-listener>
            <port>8883</port>
            <bind-address>0.0.0.0</bind-address>
            <tls>
                <keystore>
                    <path>server.jks</path>
                    <password>your-keystore-password</password>
                    <private-key-password>your-key-password</private-key-password>
                </keystore>
                <client-authentication-mode>NONE</client-authentication-mode>
            </tls>
        </tls-tcp-listener>
    ...
    </listeners>
  • Use client.jks to connect with a client.

Configure TLS with client certificates (self-signed) for HiveMQ using Keytool

Configure with PEM files (for mosquitto_pub/_sub and other clients)

  1. Follow the procedures to Generate a server-side certificate for HiveMQ and Generate a PEM client certificate.

  2. Make sure the server-side TLS works with mosquitto_pub/_sub and HiveMQ.

  3. Generate client certificates.

    This step needs to be done for each client that connects to HiveMQ. Also this is not the only way on how to create certificates. There are different options depending on your use case and capabilities.
    1. To generate a client certificate for PEM-based clients such as mosquitto_sub/_pub, execute the following command for each client:

      openssl req -x509 -newkey rsa:2048 -keyout mqtt-client-key-2.pem -out mqtt-client-cert-2.pem -days 360

      Enter all prompted information for the certificate.
      You end up with two PEM files: mqtt-client-key-2.pem and mqtt-client-cert-2.pem.

  4. Create a trust store for HiveMQ.

    When the client connects with a certificate, HiveMQ needs a trust store in order to validate the self-signed certificates. You need to have access to all certificate PEM files generated in the previous step.

    1. To export the client certificate from the PEM certification file, enter:

      openssl x509 -outform der -in mqtt-client-cert-2.pem -out mqtt-client-cert-2.crt
    2. To generate one common server trust store, execute the following command for each client certificate:

      keytool -import -file mqtt-client-cert-2.crt -alias client2 -keystore hivemq-trust-store.jks -storepass changeme
      We highly recommend the use of a strong password instead of changeme.

      Confirm the certificate with yes, before the trust store is successfully created.

  5. Change the config.xml in the HiveMQ home directory

    <listeners>
    ...
        <tls-tcp-listener>
            ...
            <tls>
                <keystore> ... </keystore>
                <client-authentication-mode>REQUIRED</client-authentication-mode>
                <truststore>
                        <path>hivemq-trust-store.jks</path>
                        <password>your-hivemq-trust-store-password</password>
                </truststore>
            </tls>
        </tls-tcp-listener>
    ...
    </listeners>
    • Connect with mosquitto_pub/_sub to HiveMQ

      In the code example, we use the previously generated client trust store (hivemq-server-cert.pem) and the just generated PEM files to set up a full TLS client authentication to HiveMQ.

      mosquitto_pub -t "test" -m "test" -p 8883 --cert mqtt-client-cert-2.pem --key mqtt-client-key-2.pem --cafile hivemq-server-cert.pem

Configure with Java Key stores (Eclipse Paho Java clients)

  1. Follow the procedures to Generate a server-side certificate for HiveMQ and Generate a PEM client certificate.

  2. Make sure the server-side TLS works with Eclipse Paho and HiveMQ.

  3. To generate a client certificate for each Eclipse Paho Java client, execute the following command for each client and enter all prompted information for the certificate:

    keytool -genkey -keyalg RSA -alias mqtt-paho-client-1 -keystore mqtt-paho-client-1.jks -storepass changeme -validity 360 -keysize 4096
    We highly recommend the use of a strong password instead of changeme.
    This step needs to be done for each client that connects to HiveMQ. Also, this is not the only way to create certificates. There are different options depending on your use case and capabilities.
  4. Generate one common server trust store for HiveMQ.

    When the client connects with a certificate, HiveMQ needs a trust store to validate the self-signed certificates. You need to have access to all client key stores generated in the previous step.

  5. To export the client certificate from each of the client key stores, enter:

    keytool -export -keystore mqtt-paho-client-1.jks -alias mqtt-paho-client-1 -storepass your-client-keystore-password -file mqtt-paho-client-1.crt
    Remember to replace your-client-keystore-password in the command with your chosen key store password.
  6. To generate a server trust store, execute the following command for each client certificate:

    keytool -import -file mqtt-paho-client-1.crt -alias client1 -keystore hivemq-trust-store.jks -storepass changeme
    We highly recommend the use of a strong password instead of changeme.
    1. Confirm the certificate with yes, before the trust store is successfully created.

  7. Change the config.xml in the HiveMQ home directory:

    <listeners>
    ...
        <tls-tcp-listener>
            ...
            <tls>
                <keystore> ... </keystore>
                <client-authentication-mode>REQUIRED</client-authentication-mode>
                <truststore>
                        <path>hivemq-trust-store.jks</path>
                        <password>your-hivemq-trust-store-password</password>
                </truststore>
            </tls>
        </tls-tcp-listener>
    ...
    </listeners>
    • Connect with Paho

      In the code example, we use the previously generated client trust store and the just generated client key store to set up a full TLS client authentication with Eclipse Paho for Java

      This simple example only tests whether TLS is working. For production usage, a more sophisticated implementation is necessary.
      Connect to HiveMQ with SSL using Eclipse Paho
      private static Logger log = LoggerFactory.getLogger(PublisherClientCertSSL.class);
      
      public static void main(String... args) {
          try {
              String clientId = "sslTestWithCert";
              MqttClient client = new MqttClient("ssl://localhost:8883", clientId, new MemoryPersistence());
      
              MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
      
              try {
                  mqttConnectOptions.setSocketFactory(getTruststoreFactory());
              } catch (Exception e) {
                  log.error("Error while setting up TLS", e);
              }
      
              client.connect(mqttConnectOptions);
              client.publish("test", "test".getBytes(), 1, true);
              client.disconnect();
      
          } catch (MqttException e) {
              log.error("MQTT Exception:",e);
          }
      }
      
      public static SocketFactory getTruststoreFactory() throws Exception {
      
          //Create key store
      
          KeyStore keyStore = KeyStore.getInstance("JKS");
          InputStream inKey = new FileInputStream("mqtt-paho-client-1.jks");
          keyStore.load(inKey, "your-client-key-store-password".toCharArray());
      
          KeyManagerFactory kmf = KeyManagerFactory
                  .getInstance(KeyManagerFactory.getDefaultAlgorithm());
          kmf.init(keyStore,"your-client-key-password".toCharArray());
      
          //Create trust store
      
          KeyStore trustStore = KeyStore.getInstance("JKS");
          InputStream in = new FileInputStream("mqtt-client-trust-store.jks");
          trustStore.load(in, "your-client-trust-store-password".toCharArray());
      
          TrustManagerFactory tmf = TrustManagerFactory
                  .getInstance(TrustManagerFactory.getDefaultAlgorithm());
          tmf.init(trustStore);
      
          // Build SSL context
      
          SSLContext sslCtx = SSLContext.getInstance("TLSv1.2");
          sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers() , null);
          return sslCtx.getSocketFactory();
      
      }
      Remember to replace the passwords in the snippet with your chosen passwords.