HiveMQ

TLS Connection using HiveMQ Client

We are new to TLS implementation for HiveMQ Client…

We had configured the HiveMQ using self-signed certs…

Config.xml

<hivemq>
    <listeners>
        <tls-tcp-listener>
            <port>1883</port>
            <bind-address>0.0.0.0</bind-address>
            <tls>
                <keystore>
                    <path>tls/hivemq.jks</path>
                    <protocols>
                        <protocol>TLSv1.2</protocol>
                    </protocols>
                    <password>test1234</password>
                    <private-key-password>test1234</private-key-password>
                </keystore>
                <client-authentication-mode>REQUIRED</client-authentication-mode>
                <truststore>
                    <path>tls/hivemq-trust-store.jks</path>
                    <password>test1234</password>
                </truststore>
            </tls>
        </tls-tcp-listener>
        <tls-websocket-listener>
            <port>8000</port>
            <bind-address>0.0.0.0</bind-address>
            <name>my-secure-websocket-listener</name>
            <path>mqtt</path>
            <subprotocols>
                <subprotocol>mqttv3.1</subprotocol>
                <subprotocol>mqtt</subprotocol>
            </subprotocols>
            <allow-extensions>true</allow-extensions>
            <tls>
                <protocols>
                    <protocol>TLSv1.2</protocol>
                </protocols>
                <keystore>
                    <path>tls/hivemq.jks</path>
                    <password>test1234</password>
                    <private-key-password>test1234</private-key-password>
                </keystore>
                <client-authentication-mode>REQUIRED</client-authentication-mode>
                <truststore>
                    <path>tls/hivemq-trust-store.jks</path>
                    <password>test1234</password>
                </truststore>
            </tls>
        </tls-websocket-listener>
    </listeners>
</hivemq>

Commands:

openssl pkcs12 -export -in ca.crt -inkey ca.key -name hivemq > server.p12
keytool -importkeystore -srckeystore server.p12 -destkeystore hivemq.jks -srcstoretype pkcs12 -alias hivemq
openssl req -x509 -newkey rsa:2048 -keyout hivemq-client-key.pem -out hivemq-public-cert.pem -days 360
openssl x509 -outform der -in hivemq-public-cert.pem -out hivemq-client-cert.crt
keytool -import -file hivemq-client-cert.crt -alias client -keystore hivemq-trust-store.jks -storepass your-test1234

Using MQTT Explorer, with manual keys input the connection gets established… But using HiveMQ Java Library it fails with exception
com.hivemq.client.mqtt.exceptions.ConnectionFailedException: javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown

Below is the code snippet:

try {
            KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
            FileInputStream fis = new FileInputStream("/usr/local/ncr_scot/hivemq-ce-2021.2/tls/hivemq.jks");
            ks.load(fis, "test1234".toCharArray());
            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            kmf.init(ks, "test1234".toCharArray());
            TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");

            KeyStore ts = KeyStore.getInstance(KeyStore.getDefaultType());
            FileInputStream tis = new FileInputStream("/usr/local/ncr_scot/hivemq-ce-2021.2/tls/hivemq-trust-store.jks");
            ts.load(tis, "test1234".toCharArray());
            tmf.init(ks);


            // Build MQTT v5 client. Also include lastWillMessage
            mqttClient = MqttClient.builder()
                    .useMqttVersion5()
                    .serverHost("localhost")
                    .serverPort(1883)
                    //.sslWithDefaultConfig()
                    .sslConfig()
                        .keyManagerFactory(kmf)
                        .trustManagerFactory(tmf)
                        .applySslConfig()
                    .buildAsync();
            mqttClient.connect().whenComplete((mqtt5ConnAck, throwable) ->
            {
                if (throwable != null) {
                    System.out.println(throwable.toString());
                } else {
                    System.out.println("Connected to broker");
                }
            });
        } catch (Exception e){
            e.printStackTrace();
        }