SSL in mqtt using mosquitto broker

2.4k Views Asked by At

I am using MQTT mosquitto broker and using SSL certificate for authentication. I am facing issue like below, please check once.

java.io.IOException: unrecognised object: TRUSTED CERTIFICATE
at org.bouncycastle.openssl.PEMParser.readObject(Unknown Source)
at com.iot.mqtt.client.SslUtil.getSocketFactory(SslUtil.java:50)
at com.iot.mqtt.client.Publisher.start(Publisher.java:40)
at com.iot.mqtt.client.Publisher.main(Publisher.java:81)
MqttException (0) - javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at org.eclipse.paho.client.mqttv3.internal.ExceptionHelper.createMqttException(ExceptionHelper.java:34)
at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:553)
at java.lang.Thread.run(Thread.java:745)
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at org.eclipse.paho.client.mqttv3.internal.SSLNetworkModule.start(SSLNetworkModule.java:84)
at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:538)

The code i am using is below,

 private static final String caFile = "D:\\Srini_10568\\IOT\\Mosquitto\\ca.crt";
 private static final String caCrtFile = "D:\\Srini_10568\\IOT\\Mosquitto\\cacrt.crt";
 private static final String clientKeyFile = "D:\\Srini_10568\\IOT\\Mosquitto\\client.key";
public static final String BROKER_URL = "ssl://123.12.123.12:1883";
MqttConnectOptions options = new MqttConnectOptions();
        options.setCleanSession(false);
        options.setSocketFactory(SslUtil.
                getSocketFactory(caFile,caCrtFile, clientKeyFile, null));

SslUtil.getSocketFactory method has below code

reader = new PEMParser(new FileReader(crtFile));
        X509CertificateHolder certHolder = (X509CertificateHolder) reader.readObject();
        reader.close();

        X509Certificate cert = certificateConverter.getCertificate(certHolder);
5

There are 5 best solutions below

1
On BEST ANSWER

Good Catch!!!

Its seems java library is having limitation to recognize client certificate starting parameter :-

"-----BEGIN TRUSTED CERTIFICATE-----"

Hope next version will get the fix for this.

1
On

Probably your *.crt files have DER format. You can try to convert your certificate files to PEM format with online tool or use openssl.

openssl x509 -inform der -in certificate.cer -out certificate.pem
3
On

If you are using SSL for client authentication, the CA file used in the server must contain all client certificates.

On the client side, the CA file contains the server's certificate.

In a scenario like yours you would have the following files:

  • server-key.pem
  • client{#}-key.pem
  • server-cert.pem
  • client{#}-cert.pem
  • server-ca.pem (contains all client{#}-cert.pem)
  • client{#}-ca.pem (contains server-cert.pem, basically a copy of it)

Where # is the client ID or number, if you will.

You can generate all the key/cert sets using:

  1. Generating a 2048-bit RSA private key:

openssl genrsa -out <KEY-NAME>-key.pem 2048

  1. Generating a CSR file from the private key:

openssl req -new -sha256 -key <KEY-NAME>-key.pem -out <CSR-NAME>-csr.pem -days <NUMBER-OF-DAYS>

  1. Self-signing the CSR file and generating certificate:

openssl x509 -req -in <CSR-NAME>-csr.pem -signkey <KEY-NAME>-key.pem -out <CERTIFICATE-NAME>-cert.pem

Every time you generate a new client certificate you must dump its content in the server's CA so that the server can recognize it as a trusted device.

cat <CERTIFICATE-NAME>-cert.pem [<CERTIFICATE-NAME>-cert.pem] [...] > ca-cert.pem

0
On

My issue is resolved. its issue with java library which is not identifying the cacrt.crt file begin string, once i removed the TRUSTED string it is working. Have fun.

0
On

This is a bug in bouncy castle reported here : http://www.bouncycastle.org/jira/browse/BJA-475

It has been fixed in v1.51 released in july 2014, so you were probably using a really old version (more than 2 years) of bouncy castle.

Here is some sample code working with the most recent version of bouncy castle : https://gist.github.com/rohanag12/07ab7eb22556244e9698