使用 mosquitto 代理的 mqtt 中的 SSL

SSL in mqtt using mosquitto broker

我正在使用 MQTT mosquitto 代理并使用 SSL 证书进行身份验证。 我遇到如下问题,请检查一次。

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)

我使用的代码如下,

 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 方法有以下代码

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

        X509Certificate cert = certificateConverter.getCertificate(certHolder);

可能您的 *.crt 文件是 DER 格式。您可以尝试使用 online tool 或使用 openssl.

将您的证书文件转换为 PEM 格式
openssl x509 -inform der -in certificate.cer -out certificate.pem

如果您使用 SSL 进行客户端身份验证,则服务器中使用的 CA 文件必须包含所有客户端证书。

在客户端,CA 文件包含服务器的证书。

在像您这样的场景中,您将拥有以下文件:

  • 服务器-key.pem
  • 客户端{#}-key.pem
  • 服务器-cert.pem
  • 客户端{#}-cert.pem
  • server-ca.pem(包含所有client{#}-cert.pem)
  • client{#}-ca.pem(包含server-cert.pem,基本上是它的一个副本)

其中 # 是客户 ID 或号码,如果您愿意的话。

您可以使用以下方法生成所有 key/cert 集:

  1. 生成 2048 位 RSA 私钥:

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

  1. 正在从私钥生成 CSR 文件:

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

  1. 自签名 CSR 文件并生成证书:

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

每次生成新的客户端证书时,都必须将其内容转储到服务器的 CA 中,以便服务器可以将其识别为受信任的设备。

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

我的问题已解决。它与 java 库有关的问题未识别 cacrt.crt 文件开始字符串,一旦我删除了它正在工作的 TRUSTED 字符串。玩得开心。

抓得好!!!

它似乎 java 库在识别客户端证书起始参数方面存在限制:-

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

希望下个版本能解决这个问题。

这是此处报告的充气城堡错误:http://www.bouncycastle.org/jira/browse/BJA-475

它已在 2014 年 7 月发布的 v1.51 中修复,因此您可能使用的是非常旧的版本(超过 2 年)的充气城堡。

下面是一些使用最新版本的充气城堡的示例代码: https://gist.github.com/rohanag12/07ab7eb22556244e9698