Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Current »

SSL client certificates offer one of todays most secure avenues for establishing safe and trustworthy connections across untrusted networks. In this guide we will demonstrate key elements required to make use of client certificates with HiveMQ's mqtt client library.

Prerequisites

It is assumed, that you have followed our guide on creating self signed client certificates and have the following files containing your key/certificate pairs:

broker.hivemq.local-keystore.jks, broker.hivemq.local-truststore.jks - used by the broker

client1-keystore.jks, client1-truststore.jks - used by the client

Further, HiveMQ will need to have a TLS listener configured in its listeners section of config.xml.

Your passwords must match the ones chosen during certificate creation.

<tls-tcp-listener>
    <port>8883</port>
    <bind-address>0.0.0.0</bind-address>
    <tls>
	<keystore>
	    <path>/path/to/keystores/broker.hivemq.local-keystore.jks</path>
	    <password>secret</password>
	    <private-key-password>secret</private-key-password>
	</keystore>
	<truststore>
	    <path>/path/to/keystores/client1-truststore.jks</path>
	    <password>secret</password>
	</truststore>
	<client-authentication-mode>REQUIRED</client-authentication-mode>
    </tls>
</tls-tcp-listener>

Create a key store

To make our code more readable we will store the paths to both our keystore and truststore in String variables to be used throughout.

final String pathToJKS = "/path/to/keystores/client1-keystore.jks";
final String pathToJKSTrustStore = "/path/to/keystores/client1-truststore.jks";

From here we will:

  • define our keyStore

  • from it, load the certificate

  • instanciate a KeyManagerFactory

final KeyStore keyStore = KeyStore.getInstance("JKS");
final InputStream inKey = new FileInputStream(pathToJKS);
keyStore.load(inKey, "secret".toCharArray());
final Certificate certificate = keyStore.getCertificate("mqtt-client");

final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, "secret".toCharArray());

Create our trust store

Next we will setup a truststore. The truststore holds credentials of other machines that we intend to trust.

final KeyStore trustStore = KeyStore.getInstance("JKS");
final InputStream in = new FileInputStream(pathToJKSTrustStore);
trustStore.load(in, "secret".toCharArray());
final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);

Create an SSL context

By building our SSL context, we define and enumerate a list of TLS options, protocol versions and ciphers we accept.

final SSLContext sslCtx = SSLContext.getInstance("TLSv1.2");
        sslCtx.init(null, tmf.getTrustManagers(), null);

Initialise a client

At this point we have all the pieces required for a client to start communicating with HiveMQ using its individual certificate.

final Mqtt5AsyncClient client = Mqtt5Client.builder()
                .serverHost("localhost")
                .sslConfig()
                .protocols(Arrays.asList("TLSv1.2"))
                .keyManagerFactory(kmf)
                .trustManagerFactory(tmf)
                .applySslConfig()
                .serverPort(8883)
                .buildAsync();


We can verify our connection has been established by instructing the client to do so and seeing a corresponding entry in HiveMQ’s event.log

client.connect().get();


event.log:

2020-04-03 11:01:33,701 - Client ID: hmq_vJdLo_4_0a462bee1ad8693e9fd676f62f0f8af9, IP: 127.0.0.1, Clean Start: true, Session Expiry: 0 connected.

This is guide only presents a minimal code example and not ready for use in production environments

  • No labels