Java 使用MOSQUITO代理的mqtt中的SSL

Java 使用MOSQUITO代理的mqtt中的SSL,java,ssl-certificate,mqtt,mosquitto,Java,Ssl Certificate,Mqtt,Mosquitto,我使用MQTT MOSQUITO代理并使用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 MOSQUITO代理并使用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格式。您可以尝试使用或使用openssl将证书文件转换为PEM格式

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

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

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

在类似您的场景中,您将拥有以下文件:

  • server-key.pem
  • 客户端{#}-key.pem
  • server-cert.pem
  • 客户端{#}-cert.pem
  • server-ca.pem(包含所有客户端{#}-cert.pem)
  • 客户端{#}-ca.pem(包含server-cert.pem,基本上是它的副本)
其中
#
是客户ID或号码,如果您愿意的话

您可以使用以下方法生成所有密钥/证书集:

  • 生成2048位RSA私钥:
  • openssl genrsa-out-key.pem 2048

  • 从私钥生成CSR文件:
  • openssl-req-new-sha256-key-key.pem-out-csr.pem-days

  • 自签名CSR文件并生成证书:
  • opensslx509-req-in-csr.pem-signkey-key.pem-out-cert.pem

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


    cat-cert.pem[-cert.pem][…]>ca-cert.pem

    我的问题得到解决。它的问题是java库没有识别cacrt.crt文件begin字符串,一旦我删除了它正在工作的可信字符串。玩得开心。

    抓得好

    其java库似乎有识别客户端证书启动参数的限制:-

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

    希望下一个版本能对此进行修复。

    这是bouncy castle中的一个bug,报告如下:

    它已在2014年7月发布的v1.51中修复,因此您可能使用了bouncy castle的一个非常旧的版本(超过2年)

    下面是一些使用bouncy castle最新版本的示例代码:

    它已经是CRT格式,在线工具中没有CRT的输入格式类型。我不明白*.cer文件或我的java代码有什么问题。我使用的代码来自这里(),他在这里执行从client.cer到X509CertificateHolder的转换。但您建议查看证书生成级别。我很困惑。您是使用SSL进行客户端身份验证还是仅用于安全数据传输?这是有区别的。假设是前者,正如您在问题中提到的,并且深入到链接中,服务器中的
    cafile
    必须包含
    client.crt
    ,客户端中的
    cafile
    必须包含
    server.crt
    。到目前为止,它仅用于客户端身份验证。我将检查服务器中cafile的可用性,以便有一次client.crt。为什么这是经过验证的答案?错误甚至不是来自jdk,而是来自bouncy castle。