I'm trying to implement MQTT in my program using M2MQTT v4.3.0.0 (github), but when I try to connect using signed certificates my code cannot establish a connection. I'm on a Windows 10 system, and using C# with .NET 4.8. The version of Mosquitto I have installed is 2.0.10.
To make the server certificate I followed this tutorial: http://www.steves-internet-guide.com/mosquitto-tls/#server
To make the client certificate I followed this tutorial:
http://www.steves-internet-guide.com/creating-and-using-client-certificates-with-mqtt-and-mosquitto/
I also made a host name in my etc/hosts file for 127.0.0.1 that points to localhost.conrad.com.
The configuration for my Mosquitto Broker is:
bind_address localhost.conrad.com
port 8883
allow_anonymous true
cafile C:/mosquitto/certs/ca.crt
keyfile C:/mosquitto/certs/server.key
certfile C:/mosquitto/certs/server.crt
require_certificate true
tls_version tlsv1.2
log_dest file C:/mosquitto/log/mosquitto.log
log_type error
log_type warning
log_type notice
log_type information
I successfully tested that this configuration works using Mosquitto's command line publish tool with
mosquitto_pub --cafile C:\mosquitto\certs\ca.crt --cert C:\mosquitto\certs\client.crt --key C:\mosquitto\certs\client.key -d -h localhost.conrad.com -p 8883 -t herp/derp/test -m "hi"
I received this message after using the command.
Client (null) sending CONNECT
Client (null) received CONNACK (0)
Client (null) sending PUBLISH (d0, q0, r0, m1, 'herp/derp/test', ... (2 bytes))
Client (null) sending DISCONNECT
My Mosquitto log confirms a successful connection:
1621547553: New connection from 127.0.0.1:57874 on port 8883.
1621547553: New client connected from 127.0.0.1:57874 as auto-6A8387C3-E091-0EC6-CED7-0A78BAA63099 (p2, c1, k60).
1621547553: Client auto-6A8387C3-E091-0EC6-CED7-0A78BAA63099 disconnected.
However when I try to connect using M2MQTT I run into a problem when trying to connect using signed certificates. My code is as follows:
int securePort = 8883;
MqttClient client = null;
string subTopic1 = "herp/derp/test";
string subTopic2 = "herp/derp/test2";
X509Certificate caCert = new X509Certificate("C:/mosquitto/certs/ca.crt");
X509Certificate clientCert = new X509Certificate("C:/mosquitto/certs/client.crt");
string clientID = "TestClientID";
public MQTTTest()
{
try
{
client = new MqttClient("localhost.conrad.com", securePort, true, caCert, clientCert, MqttSslProtocols.TLSv1_2, RemoteCertificateValidationCallback);
client.MqttMsgPublishReceived += client_MqttMsgPublishReceived;
client.MqttMsgPublished += client_MqttMsgPublished;
client.MqttMsgSubscribed += client_MqttMsgSubscribed;
client.ConnectionClosed += client_ConnectionClosed;
client.Connect(clientID, "", "", true, 1000);
client.Subscribe(new string[] { subTopic1, subTopic2 }, new byte[] { MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE, MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE });
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
I get the following exception when trying at client.Connect.
Exception message: "A call to SSPI failed, see inner exception."
Inner exception: "The message received was unexpected or badly formatted"
My Mosquitto logs show:
1621547793: New connection from 127.0.0.1:57896 on port 8883.
1621547793: OpenSSL Error[0]: error:1417C0C7:SSL routines:tls_process_client_certificate:peer did not return a certificate
1621547793: Client <unknown> disconnected: protocol error.
I can establish insecure connections just fine. As it is written my code also connects when I set require_certificate to false in my Mosquitto config file; however I am worried that if require_certificate is set to false that I won't have the security I want. Any help would be greatly appreciated.
Thanks to Brits' comment I was able to figure it out (link to answer). I made a pfx certificate and used that instead of using a crt.
Instead of...
X509Certificate caCert = new X509Certificate("C:/mosquitto/certs/ca.crt");
X509Certificate clientCert = new X509Certificate("C:/mosquitto/certs/client.crt");
I used...
X509Certificate2 caCert = new X509Certificate2("C:/mosquitto/certs/ca.pfx", "password");
X509Certificate2 clientCert = new X509Certificate2("C:/mosquitto/certs/client.pfx", "password");