-
-
Save jimrok/d25cb45b840f5a4ad700 to your computer and use it in GitHub Desktop.
| package test_mqtt; | |
| import java.io.BufferedInputStream; | |
| import java.io.FileInputStream; | |
| import java.io.FileReader; | |
| import java.security.KeyPair; | |
| import java.security.KeyStore; | |
| import java.security.Security; | |
| import java.security.cert.CertificateFactory; | |
| import java.security.cert.X509Certificate; | |
| import javax.net.ssl.KeyManagerFactory; | |
| import javax.net.ssl.SSLContext; | |
| import javax.net.ssl.SSLSocketFactory; | |
| import javax.net.ssl.TrustManagerFactory; | |
| import org.bouncycastle.jce.provider.BouncyCastleProvider; | |
| import org.bouncycastle.openssl.PEMDecryptorProvider; | |
| import org.bouncycastle.openssl.PEMEncryptedKeyPair; | |
| import org.bouncycastle.openssl.PEMKeyPair; | |
| import org.bouncycastle.openssl.PEMParser; | |
| import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; | |
| import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder; | |
| import org.eclipse.paho.client.mqttv3.MqttClient; | |
| import org.eclipse.paho.client.mqttv3.MqttConnectOptions; | |
| import org.eclipse.paho.client.mqttv3.MqttException; | |
| public class TestMQTT { | |
| public static void main(String[] args) { | |
| String serverUrl = "ssl://serverip:1883"; | |
| String caFilePath = "/your_ssl/cacert.pem"; | |
| String clientCrtFilePath = "/your_ssl/client.pem"; | |
| String clientKeyFilePath = "/your_ssl/client.key"; | |
| String mqttUserName = "guest"; | |
| String mqttPassword = "123123"; | |
| MqttClient client; | |
| try { | |
| client = new MqttClient(serverUrl, "2"); | |
| MqttConnectOptions options = new MqttConnectOptions(); | |
| options.setUserName(mqttUserName); | |
| options.setPassword(mqttPassword.toCharArray()); | |
| options.setConnectionTimeout(60); | |
| options.setKeepAliveInterval(60); | |
| options.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1); | |
| SSLSocketFactory socketFactory = getSocketFactory(caFilePath, | |
| clientCrtFilePath, clientKeyFilePath, ""); | |
| options.setSocketFactory(socketFactory); | |
| System.out.println("starting connect the server..."); | |
| client.connect(options); | |
| System.out.println("connected!"); | |
| Thread.sleep(1000); | |
| client.subscribe( | |
| "/u/56ca327d17531d08e76bddd4a215e37f5fd6082f7442151c4d3f1d100a0ffd4e", | |
| 0); | |
| client.disconnect(); | |
| System.out.println("disconnected!"); | |
| } catch (MqttException e) { | |
| e.printStackTrace(); | |
| } catch (Exception e) { | |
| e.printStackTrace(); | |
| } | |
| } | |
| private static SSLSocketFactory getSocketFactory(final String caCrtFile, | |
| final String crtFile, final String keyFile, final String password) | |
| throws Exception { | |
| Security.addProvider(new BouncyCastleProvider()); | |
| // load CA certificate | |
| X509Certificate caCert = null; | |
| FileInputStream fis = new FileInputStream(caCrtFile); | |
| BufferedInputStream bis = new BufferedInputStream(fis); | |
| CertificateFactory cf = CertificateFactory.getInstance("X.509"); | |
| while (bis.available() > 0) { | |
| caCert = (X509Certificate) cf.generateCertificate(bis); | |
| // System.out.println(caCert.toString()); | |
| } | |
| // load client certificate | |
| bis = new BufferedInputStream(new FileInputStream(crtFile)); | |
| X509Certificate cert = null; | |
| while (bis.available() > 0) { | |
| cert = (X509Certificate) cf.generateCertificate(bis); | |
| // System.out.println(caCert.toString()); | |
| } | |
| // load client private key | |
| PEMParser pemParser = new PEMParser(new FileReader(keyFile)); | |
| Object object = pemParser.readObject(); | |
| PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder() | |
| .build(password.toCharArray()); | |
| JcaPEMKeyConverter converter = new JcaPEMKeyConverter() | |
| .setProvider("BC"); | |
| KeyPair key; | |
| if (object instanceof PEMEncryptedKeyPair) { | |
| System.out.println("Encrypted key - we will use provided password"); | |
| key = converter.getKeyPair(((PEMEncryptedKeyPair) object) | |
| .decryptKeyPair(decProv)); | |
| } else { | |
| System.out.println("Unencrypted key - no password needed"); | |
| key = converter.getKeyPair((PEMKeyPair) object); | |
| } | |
| pemParser.close(); | |
| // CA certificate is used to authenticate server | |
| KeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType()); | |
| caKs.load(null, null); | |
| caKs.setCertificateEntry("ca-certificate", caCert); | |
| TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509"); | |
| tmf.init(caKs); | |
| // client key and certificates are sent to server so it can authenticate | |
| // us | |
| KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); | |
| ks.load(null, null); | |
| ks.setCertificateEntry("certificate", cert); | |
| ks.setKeyEntry("private-key", key.getPrivate(), password.toCharArray(), | |
| new java.security.cert.Certificate[] { cert }); | |
| KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory | |
| .getDefaultAlgorithm()); | |
| kmf.init(ks, password.toCharArray()); | |
| // finally, create SSL socket factory | |
| SSLContext context = SSLContext.getInstance("TLSv1.2"); | |
| context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); | |
| return context.getSocketFactory(); | |
| } | |
| } |
java.io.FileNotFoundException: /your_ssl/cacert.pem (No such file or directory)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.(FileInputStream.java:138)
at java.io.FileInputStream.(FileInputStream.java:93)
at gropu1.SSL_MQTT.getSocketFactory(SSL_MQTT.java:77)
at gropu1.SSL_MQTT.main(SSL_MQTT.java:50)
.... I am getting this earror plz help me.............
Hi All
Using Maven dependencies
org.eclipse.paho org.eclipse.paho.client.mqttv3 1.2.2 org.bouncycastle bcpkix-jdk15on 1.64using JDK 12, SSLSocketFactory getSocketFactory(...) in TestMQTT.java class I am able to publish and subscribe using MQTT 3.x
However if include
org.eclipse.paho
org.eclipse.paho.mqttv5.client
1.2.5
I am getting an error of Unsupported protocol version. when I try to publish and subscribe using MQTT 5.x. Please exception below.
org.eclipse.paho.mqttv5.common.MqttException: Unsupported protocol version.
at org.eclipse.paho.mqttv5.client.internal.ExceptionHelper.createMqttException(ExceptionHelper.java:32)
at org.eclipse.paho.mqttv5.client.internal.ClientState.notifyReceivedAck(ClientState.java:1074)
at org.eclipse.paho.mqttv5.client.internal.CommsReceiver.run(CommsReceiver.java:153)
at java.base/java.lang.Thread.run(Thread.java:835)
Can you please advise what I need to get MQTT 5.x. works with SSL certificate.
Thank you for your help
@mluis , et. al. - Does this connect to AWS IOT core using X.509 cert authentication to port 8883?
I have only a slight difference in sample project below because it seems that bouncycastle is being deprecated, but since private key and cert is properly parsed into a data structure and successful connection to mosquitto.org:8883 proves it works.
https://github.com/srlohr/PublicPahoClient.git
if you get:
Received fatal alert: protocol_version
change the line to
SSLContext context = SSLContext.getInstance("TLSv1.3");
hi, i faced two issue Issue 1: Got exception in parsing private key excpetion java.lang.ClassCastException: org.bouncycastle.asn1.pkcs.PrivateKeyInfo cannot be cast to org.bouncycastle.openssl.PEMKeyPair.. then i modified code to parse private key
if (object instanceof PrivateKeyInfo) { final JcaPEMKeyConverter jcaPEMKeyConverter = new JcaPEMKeyConverter(); Log.d(TAG,"Unencrypted key - no password needed"); //key = converter.getKeyPair((PEMKeyPair) object); PrivateKeyInfo privateKeyInfo = (PrivateKeyInfo) object; key = jcaPEMKeyConverter.getPrivateKey(privateKeyInfo); with the above code change exception solved. issue 2: i am getting error when i connect to mosquito mqtt broker in linux. mosquito error-1562115998: OpenSSL Error: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown 1562115998: OpenSSL Error: error:140940E5:SSL routines:ssl3_read_bytes:ssl handshake failure AndroidGetting Exception: MqttException (0) - javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
Using bouncy castle - bcprov-jdk15on:1.62,bcpkix-jdk15on:1.62 Help to fix this
KeyPair key;
if (object instanceof PEMEncryptedKeyPair pemEncryptedKeyPair) {
...
} else if (object instanceof PrivateKeyInfo pKey) {
var privateKey = converter.getPrivateKey(pKey);
key = new KeyPair(null, privateKey);
} else {
...
}I had a similar problem and i fixed with the code above
Dear all,
If I have only cert.pem, privkey.pem. How can I connect to MQTT Broker.
I can conenct to MQTT Broker by using Python and React, but can not conenct to MQTT Broker by using Java/Kotlin.
Please help me. Thanks a lots
In my case I have only client certificate (crt) and client key (key) files, how can I connect to Azure Event Grid MQTT. With the above code I get error as follows:
javax.net.ssl.SSLException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
I checked in other MQTT client like MQTTBox and MQTTX the connection is successful by using only client certificate and client key.
@mluis , et. al. - Does this connect to AWS IOT core using X.509 cert authentication to port 8883?
I have only a slight difference in sample project below because it seems that bouncycastle is being deprecated, but since private key and cert is properly parsed into a data structure and successful connection to mosquitto.org:8883 proves it works.
yes it worked at the time for aws iot
Hi All
I am getting the following error show below when running with JDK 12. Any idea, thank you for your help.
20:52:36.312 [main] INFO au.gov.nsw.rms.its.sdcs.mb.vernemq.TestMQTTSSL - starting connect the server... 20:52:36.454 [main] ERROR au.gov.nsw.rms.its.sdcs.mb.vernemq.TestMQTTSSL - Exception encounter with error MqttException org.eclipse.paho.client.mqttv3.MqttException: MqttException at org.eclipse.paho.client.mqttv3.internal.ExceptionHelper.createMqttException(ExceptionHelper.java:38) at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:738) at java.base/java.lang.Thread.run(Thread.java:835) Caused by: javax.net.ssl.SSLHandshakeException: No subject alternative names present at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131) at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:320) at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:263) at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:258) at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:641) at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:460) at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:360) at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392) at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:443) at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:421) at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:177)
//禁止服务端检查
options.setHttpsHostnameVerificationEnabled(false);
Works like a charm for AWS IoT. I'm using OpenJDK 21, with paho mqtt v5. Only some small modifications to adapt to v5 API is needed.
Hi All
I am getting the following error show below when running with JDK 12.
Any idea, thank you for your help.
20:52:36.312 [main] INFO au.gov.nsw.rms.its.sdcs.mb.vernemq.TestMQTTSSL - starting connect the server...
20:52:36.454 [main] ERROR au.gov.nsw.rms.its.sdcs.mb.vernemq.TestMQTTSSL - Exception encounter with error MqttException
org.eclipse.paho.client.mqttv3.MqttException: MqttException
at org.eclipse.paho.client.mqttv3.internal.ExceptionHelper.createMqttException(ExceptionHelper.java:38)
at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:738)
at java.base/java.lang.Thread.run(Thread.java:835)
Caused by: javax.net.ssl.SSLHandshakeException: No subject alternative names present
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:320)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:263)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:258)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:641)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:460)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:360)
at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392)
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:443)
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:421)
at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:177)