|Hi All
I am having a problem getting my Java MQTT 5.x Client with ssl certificate gets an error Unsupported protocol version when connecting to VerneMQ
I am getting an error of
Unsupported protocol version. (132)
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)
Please see source code MQTTV5WithSSL.java list below
Note using JDK 12, SSLSocketFactory getSocketFactory(…) in my TestMQTTV3SSL.java class, I am able to publish and subscribe using to secure VerneM Broker. Using mosquitto_pub and mosquitto_sub client also work.
The VerneMQ’s console.log from /log directory does not tell log any client connection.
Can you please me know how I can configure VerneMQ, so I get client connection failure log
Can you please have a look at my maven pom dependencies and MQTTV5WithSSL.java
let me know what I missing.
Thank you for your help
Below are my Maven dependencies
org.eclipse.paho
org.eclipse.paho.client.mqttv3
1.2.2
org.eclipse.paho
org.eclipse.paho.mqttv5.client
1.2.5
TestMQTTV5SSL.java class code
public class TestMQTTV5WithSSL {
public static void main(String[] args) {
String publishTopic = "sp/moc/bc/sdd/rt-veh/veh/1.0.1";
String subscribeTopic = "sp/moc/#";
String testResourcePath = "/opt/scats/mqtt_cert/";
String serverUrl = "ssl://eveitsdsfew05.tmb.rta.nsw.gov.au:8885";
String caFilePath = testResourcePath + "ca.crt";
String clientCrtFilePath = testResourcePath + "client.crt";
String clientKeyFilePath = testResourcePath + "client.key";
//System.setProperty("javax.net.ssl.trustStore", caFilePath);
//System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
System.setProperty("com.sun.jndi.ldap.object.disableEndpointIdentification", "true");
//-Dcom.sun.jndi.ldap.object.disableEndpointIdentification=true
MqttClient client;
try {
client = new MqttClient(serverUrl, "2");
MqttConnectionOptions options = new MqttConnectionOptions();
//options.setUserName(mqttUserName);
//options.setPassword(mqttPassword.toCharArray());
options.setConnectionTimeout(60);
options.setKeepAliveInterval(60);
SSLSocketFactory socketFactory = getSocketFactory(caFilePath,
clientCrtFilePath, clientKeyFilePath, "scatsadmin");
options.setSocketFactory(socketFactory);
System.out.println("Get Options properties " + options.getDebug());
System.out.println("starting connect the server...");
client.connect(options);
System.out.println("connected!");
Thread.sleep(1000);
client.subscribe(subscribeTopic, 1);
client.disconnect();
System.out.println("disconnected!");
} catch (MqttException me) {
System.out.println("MQTT exception reason " + me.getReasonCode());
System.out.println("MQTT exception msg " + me.getMessage());
System.out.println("MQTT exception loc " + me.getLocalizedMessage());
System.out.println("MQTT exception cause " + me.getCause());
System.out.println("MQTT exception excep " + me);
me.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 = new SCATSX509Cert(bis);
//Object cert = cf.generateCertificate(bis);
//caCert = (X509Certificate)cert;
caCert = (X509Certificate) cf.generateCertificate(bis);
// System.out.println(caCert.toString());
}
System.out.println("caCert.hashCode() = " + caCert.hashCode());
Collection<List<?>> caCertSANList = caCert.getSubjectAlternativeNames();
if( caCertSANList != null ) {
System.out.println("caCertSANList size = " + caCertSANList.size());
} else {
System.out.println("caCertSANList = " + caCertSANList);
}
// load client certificate
bis = new BufferedInputStream(new FileInputStream(crtFile));
X509Certificate crtCert = null;
while (bis.available() > 0) {
crtCert = (X509Certificate) cf.generateCertificate(bis);
// System.out.println(caCert.toString());
}
System.out.println("crtCert.hashCode() = " + crtCert.hashCode());
Collection<List<?>> crtCertSANList = crtCert.getSubjectAlternativeNames();
if( crtCertSANList != null ) {
System.out.println("crtCertSANList size = " + crtCertSANList.size());
} else {
System.out.println("crtCertSANList = " + crtCertSANList);
}
// 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 if (object instanceof PrivateKeyInfo) {
System.out.println("Unencrypted PrivateKeyInfo key - no password needed");
PrivateKeyInfo privateKeyInfo = (PrivateKeyInfo) object;
key = converter.getKeyPair((PEMKeyPair)privateKeyInfo.parsePrivateKey());
}
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", crtCert);
ks.setKeyEntry("private-key", key.getPrivate(), password.toCharArray(),
new java.security.cert.Certificate[] { crtCert });
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory
.getDefaultAlgorithm());
kmf.init(ks, password.toCharArray());
// finally, create SSL socket factory
SSLContext context = SSLContext.getInstance("SSL");
//SSLContext context = SSLContext.getInstance("TLSv1.2");
context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
return context.getSocketFactory();
}
}