Skip to main content

Tutorial: Use TLS in Java for MQTT

Ensure you have a CA certificate file created and configured on the FairCom server.Tutorial: Create certificates using OpenSSL

This tutorial shows how to implement TLS using the Paho Java library to secure an MQTT connection. This configuration loads the certificate from the file system at runtime.

  1. Create an MqttClient object with the following parameters:

    MqttClient tlsClient = new MqttClient( mqttURI, clientID, new MemoryPersistence() )
    1. The broker address.

    2. clientID

    3. MemoryPersistence()

  2. Create an SSLContext object.

    1. Generate a Certificate class object from the CA certificate file using the following code:

      Certificate caCertificate = CertificateFactory.getInstance( "X.509" ).generateCertificate( new FileInputStream( caCertFilename ) );
    2. With the generated Certificate, generate a KeyStore class object using the following code:

      Certificate caCertificate = CertificateFactory.getInstance( "X.509" ).generateCertificate( new FileInputStream( caCertFilename ) );
    3. Build a TrustManager from the KeyStore using the following code:

      TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm() ); trustManagerFactory.init( keyStore );
    4. Create an SSLContext class object from the TrustManager using the following code:

      SSLContext sslContext = SSLContext.getInstance( "TLS" ); sslContext.init( null, trustManagerFactory.getTrustManagers(), null );
  3. Instantiate a new MqttConnectOptions, and apply the SSLContext to it using the following code:

    MqttConnectOptions connOpts = new MqttConnectOptions(); connOpts.setSocketFactory( Objects.requireNonNull( sslContext ).getSocketFactory() );
  4. With the MqttClient, connect to the broker using the connection options using the following code:

    tlsClient.connect( connOpts );
  5. Create an MqttMessage class object, and set the QoS using the following code:

    MqttMessage message = new MqttMessage( messageBody.getBytes() ); message.setQos( 1 );
  6. Publish the message to the broker using the following code:

    tlsClient.publish( topic, message );
  7. Disconnect from the broker using the following code:

    tlsClient.disconnect();
Example 1. Complete main()

Note

  • The address used for the mqttURI variable must match the Common Name in the broker certificate — for example, if the broker certificate Common Name is set to hostname JohnDoePC, then the mqttURI variable should be set to ssl://JohnDoePC:8883 or the code will throw an exception:

    javax.net.ssl.SSLHandshakeException: No name matching localhost found
  • Configuring the Edge broker to use the CA certificate is not necessary.  However, if the Edge broker is configured to use the CA certificate, a client certificate and key must be added to the SSLContext.

public static void main( String[] args )
{
	String mqttURI = "ssl://localhost:8883";
	String clientID = "JavaMQTTS1";
	String caCertificate = "C:/Certificates/ca.crt";
	String topic = "test/JavaMqttTlsTest";
	String messageBody = "Java MQTTS test";

// Create a client using the URI, client ID, and a simple MemoryPersistence object.
try( MqttClient tlsClient = new MqttClient( mqttURI, clientID, new MemoryPersistence() ) )
	{
		// Get an SSLContext class object to secure the connection.
		SSLContext sslContext = getSslContextFromCertificate( caCertificate );

		// Apply the SSLContext to the connection options.
		MqttConnectOptions connOpts = new MqttConnectOptions();
		connOpts.setSocketFactory( Objects.requireNonNull( sslContext ).getSocketFactory() );

		// Connect to the broker with the secure connection options.
		tlsClient.connect( connOpts );

		// Prepare a message to send.
		MqttMessage message = new MqttMessage( messageBody.getBytes() );
		message.setQos( 1 );

		// Publish a simple message.
		tlsClient.publish( topic, message );
		System.out.println( "The message has been published." );

		// Disconnect from the broker.
		tlsClient.disconnect();
	}
	catch( MqttException mqttException )
	{
		printException( Thread.currentThread().getStackTrace()[1].getMethodName(), mqttException );
	}
}


Example 2. Complete getSslContextFromCertificate()
private static SSLContext getSslContextFromCertificate( String caCertFilename )
{
	try
	{
		Certificate caCertificate = CertificateFactory.getInstance( "X.509" ).generateCertificate( new FileInputStream( caCertFilename ) );

		KeyStore keyStore = KeyStore.getInstance( KeyStore.getDefaultType() );
		keyStore.load( null, null );
		keyStore.setCertificateEntry( String.valueOf( caCertificate.hashCode() ), caCertificate );

		TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm() );
		trustManagerFactory.init( keyStore );

		SSLContext sslContext = SSLContext.getInstance( "TLS" );
		sslContext.init( null, trustManagerFactory.getTrustManagers(), null );
		return sslContext;
	}
	catch( CertificateException | KeyStoreException | NoSuchAlgorithmException | KeyManagementException | IOException certificateException )
	{
		printException( Thread.currentThread().getStackTrace()[1].getMethodName(), certificateException );
	}
	return null;
}