-
-
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(); | |
} | |
} |
I believe I was missing the bouncy castle plugin at all. After importing it to the right directory it was fixed. The JVM didn't had the plugin.
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
@jenifram I believe this is a jdk issue use openjdk instead of oracle jdk.
@sanre6 - I changed the openJDK in the Android Project structure window and still same issue facing again and my android tablet version is Android 7.1.2
downloaded jdk from here
i use maven dependency
<!-- mqtt client-->
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>1.2.2</version>
</dependency>
<!-- ssl support -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.64</version>
</dependency>
and it work
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)
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);
@mluis I have the same exact problem were you able to fix it ?