Tutorial: Use TLS in Java for MQTT
Ensure you have a CA certificate file created and configured on the FairCom server.
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.
Create an
MqttClient
object with the following parameters:MqttClient tlsClient = new MqttClient( mqttURI, clientID, new MemoryPersistence() )
The broker address.
clientID
MemoryPersistence()
Create an
SSLContext
object.Generate a
Certificate
class object from the CA certificate file using the following code:Certificate caCertificate = CertificateFactory.getInstance( "X.509" ).generateCertificate( new FileInputStream( caCertFilename ) );
With the generated
Certificate
, generate aKeyStore
class object using the following code:Certificate caCertificate = CertificateFactory.getInstance( "X.509" ).generateCertificate( new FileInputStream( caCertFilename ) );
Build a
TrustManager
from theKeyStore
using the following code:TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm() ); trustManagerFactory.init( keyStore );
Create an
SSLContext
class object from theTrustManager
using the following code:SSLContext sslContext = SSLContext.getInstance( "TLS" ); sslContext.init( null, trustManagerFactory.getTrustManagers(), null );
Instantiate a new
MqttConnectOptions
, and apply theSSLContext
to it using the following code:MqttConnectOptions connOpts = new MqttConnectOptions(); connOpts.setSocketFactory( Objects.requireNonNull( sslContext ).getSocketFactory() );
With the
MqttClient
, connect to the broker using the connection options using the following code:tlsClient.connect( connOpts );
Create an
MqttMessage
class object, and set the QoS using the following code:MqttMessage message = new MqttMessage( messageBody.getBytes() ); message.setQos( 1 );
Publish the message to the broker using the following code:
tlsClient.publish( topic, message );
Disconnect from the broker using the following code:
tlsClient.disconnect();
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 hostnameJohnDoePC
, then themqttURI
variable should be set tossl://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 ); } }
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; }