SSL/TLS

GnatMQ and SSL/TLS support : make it up and running !

After the last blog post on the new GnatMQ release with SSL/TLS support, it’s now time to show how to use this new feature.

Asymmetric encryption and SSL/TLS : a brief introduction

Speaking about SSL/TLS security means to speak a lot about asymmetric encryption (even if symmetric encryption is used as well) and X.509 certificates. Regarding asymmetric encryption we know that it’s based on public and private keys compared to symmetric encryption that uses only one shared key. Simplifying how asymmetric encryption works we can say that the message sender needs the public key of the receiver in order to use it for encrypting data. The receiver is the only one to have its private key so that it’s the only one that is able to decrypt a message that was encrypted with its own related public key. It means that public key can be distributed publically but private key must be kept secret. Asymmetric encryption can be used not only to encrypt data but for signing it too. In this case, the sender processes an hash on the message to send using its private key; the receiver can use the corresponding sender public key to verify the signature (the hash) and in this way it can be sure that the message was received from the right sender.

Of course, it’s only a simple and brief introduction on how asymmetric encryption works and I can suggest you to deep into it finding a lot of content online.

How is asymmetric encryption related to SSL/TLS protocol ?

SSL/TLS is a protocol on top of TCP/IP that is used for server authentication (to know that we are speaking with the server we want really to speak), client authentication (check on server side that the client can connect to the server itself) and content encryption (we can guarantee confidentiality on transmitted data). SSL/TLS is based on asymmetric encryption in the following way :

  • the server has a private key for encrypting messages during the first connection phase named SSL/TLS handshake;
  • the server has a related public key distributed publically to all clients want to connect to it;

I said that the server private key is used only during SSL/TLS handshake and not for encrypting all messages exchanged during connection. It’s true because during this phase, client and server exchange some information to generate a symmetric key that they will use during communication to encrypt all exchanged data. Why this step from asymmetric to symmetric encryption ?

Asymmetric encryption is more complex than symmetric and it needs more CPU and memory footprint for executing even if it’s more secure than symmetric. This one is less complex and doesn’t need huge resources for processing. This is the reason why for generating a symmetric key, the client and server use asymmetric encryption with more load during the handshake but they use the generated symmetric key for encrypting all traffic to be much faster during communication.

Now, the big question is : how the client can be sure it’s talking with the server it’d like to talk ? Here the X.509 certificates standard and the Certification Authority concepts come in and of course the second possible usage of asymmetric encryption : the signature.

The server public key must be signed by a trusted third party authority so that the client can trust this public key and check that it’s talking with the right server. A Certification Authority (CA) is a trusted third party that distributes X.509 certificates : you can think about a certificate as a server public key with a signature from CA (with more other information). It means that we can buy a server certificate from a CA directly or we can ask the CA to sign our already generated public key. Of course the CA uses its own private key to process the hash/signature for that public key to obtain a valid X.509 certificate.

How the client is able to check the server certificate validity ? Of course, the client needs the CA certificate (its public key) and can use it to verify the signature on the received certificate from the server.

Now you could ask … who signs the CA certificate ? In this case the CA is considered as a “root” so no other trusted third party over it; for this reason the CA certificate is self signed and it means that it’s signed by the CA itself … you need to trust it ! However you need to know that there are CA certificates not self signed but signed by other CAs; in this way there is the possibility to have CAs who can distribute X.509 certificates to companies but you can’t consider them as “root” because their certificates are signed by other “root” CAs.

After this higher level introduction to SSL/TLS (you need to deep into it for understanding it better), it’s time to “play” with certificates and prepare our GnatMQ broker with the new security feature.

Self-signed CA certificate creation

First of all we need a CA certificate to generate and sign the server certificate. We could buy the server certificate from a trusted third party Certificate Authority such as GoDaddy, Symantec (Verisign), Comodo or GlobalSign but only for testing, we can first generate a self-signed CA certificate and then using it to sign our server certificate. With our CA certificate we are able to impersonate a trusted Certification Authority so that we can sign any other certificate we’d like to use for our servers.

Remember that the certificates story starts from generating a public and private key for asymmetric cryptography. A server public key is signed with a CA private key to obtain a so called “certificate”. In this way the server public key can be distributed publically in a certificate fashion. In the case of a self-signed CA certificate, the CA private key is used to sign the same CA public key to obtain the self-signed CA certificate itself.

To execute all available operations on X.509 certificates (create, sign, convert and so on) there are two main available tools : OpenSSL or Makecert.
During this article we’ll use Makecert that we receive with our Visual Studio 2015 installation (it’s available with previous versions as well).
Of course, the certificate generation operation will generate both private key and public key; the last one will be signed to become a standard X.509 certificate to distribute publically.
Let’s start with the “Developer Command Prompt for VS2015” and check that the Makecert usage is the following :
makecert [options] outputCertificateFile
with a lot of “options” we can specify and the output certificate file.
Let’s execute following command :
makecert -n "CN=MyCARoot" -r -a sha512 -len 4096 -cy authority -sv MyCARoot.pvk MyCARoot.cer
01_gnatmq_ssl
where options have following meaning :
  • -n : specifies the so called Common Name and it’s the subject certificate name that conform to the X.500 standard
  • -r : ask for creation of a self-signed certificate
  • -a : specifies what algorithm must be used to sign (in this case self-signed) the certificate
  • -len : specifies the generated private key length, in bits
  • -cy : specifies the certificate type. Valid values are “end” for end-entity and “authority” for Certification Authority
  • -sv : specifies the name of the generated subject’s private key file

It’s important to notify the the -n parameter can receive more other options like Country Name (C), Organization Name (O), Locality Name (L) and so on; in this case a more complex value could be : “CN=MyCARoot,C=Italy,O=MyCACompany,L=Naples”.

There are a lot of other options you can specify like the expiration date and so on. For more information, you can see the official documentation for Makecert tool.

After executing this command you are prompted to insert the “passphrase” (a password) to protect the private key.

02_gnatmq_ssl
The first time you need to create the password for the private key and the second time you are prompted to insert the previous one to access the private key and (self)signing the certificate.
03_gnatmq_ssl
Now we have the MyCARoot.cer file and the MyCARoot.pvk file. The former is the self-signed CA certificate in the DER (binary) format and the latter is the private key used to signed the generated public key to obtain the above certificate and that will be used to sign any other server certificate.

Create the server certificate

Next step is to create the server certificate and sign it with the above CA certificate (using the related private key of course).
makecert -n "CN=DESKTOP-862CII2" -iv MyCARoot.pvk -ic MyCARoot.cer -pe -a sha512 -len 4096 -sky exchange -sv GnatMQ.pvk GnatMQ.cer
where options have following meaning :
  • -n : specifies the Common Name of the server. It must match the domain name or the PC name (like for this example)
  • -iv : specifies the issuer’s .pvk private key file (so the CA private key file)
  • -ic : specifies the issuer’s certificate file (so the self-signed CA certificate)
  • -pe : marks the generated private key as exportable (we’ll see what it means)
  • -a : specifies what algorithm must be used to sign the certificate
  • -len : specifies the generated private key length, in bits
  • -sky : specifies the subject’s key type.The “exchange” value means the key is used for key encryption and key exchange (what happes during SSL/TLS handshake)
  • -sv : specifies the name of the generated subject’s private key file

04_gnatmq_ssl

As for the CA certificate generation you are prompted to insert the passphrase to protect the private server key. In this case, you are prompted to insert the passphrase for the CA private key too (the Issuer) because it is necessary to access the CA private key for signing the server public key and generate the certificate.

05_gnatmq_ssl

In order to use the server certificate inside the broker we need to export it in the PFX format (predecessor of current PKCS#12). The PKCS#12 evolved from the personal information exchange (PFX) standard and is used to exchange public and private objects in a single file. It means that the single PFX file contains both the public and private key of the server. In this way, it has all needed data to support an SSL/TLS connection for deploying its certificate and encrypt data using the private key. This is the reason way we used the “pe” option in the Makecert command to mark the private key as exportable into the PFX file.

To do this we can use the pvk2pfx tool in the following way :

pvk2pfx -pvk GnatMQ.pvk -spc GnatMQ.cer -pfx GnatMQ.pfx -po <password>

where options have following meaning :

  • -pvk : specifies the name of a .pvk file (broker private key)
  • -spc : specifies the name and extension of the Software Publisher Certificate (SPC) file that contains the certificate (broker certificate)
  • -pfx : specifies the name of the output .pfx file
  • -po : password for the .pfx file

06_gnatmq_ssl

Setup GnatMQ security

Now we are able to use the server certificate to create a GnatMQ instance with SSL/TLS support. You can get the latest version as Nuget package and reference it inside your project. You can use the MqttBroker class instance inside a simple console application or a worker role on Azure; it’s up to you how to use it. For a simple example, the console application is the right choice.

First of all you need to add the generated GnatMQ.pfx file as resource inside your project to make it available in your source code.

07_gnatmq_ssl

The source code is so simple …

class Program
{
    static void Main(string[] args)
    {
        X509Certificate2 serverCert = new X509Certificate2(Resource1.GnatMQ, "<pwd>");

        // create and start broker
        MqttBroker broker = new MqttBroker(serverCert, MqttSslProtocols.TLSv1_0);
        broker.Start();

        Console.ReadLine();

        broker.Stop();
    }
}

In order to use the PFX file you can instantiate the X509Certificate2 class providing it the raw bytes and the password (you specified during PFX file creation). The MqttBroker class has a simple constructor for SSL/TLS support with only two parameters :

  • the server certificate;
  • the SSL/TLS protocol version;

In this way the broker is up and running and can accept only SSL/TLS connections !

Another way to instantiate the class is to use the constructor with other parameters like the RemoteCertificateValidationCallback and LocalCertificateSelectionCallback that you can use to customize the certificate validation and selection process.

Remember that any client you use to connect the broker it needs the self-signed CA certificate and your connection will be protected and encrypted after the server authentication.

Last one thing to know is that the SSL/TLS feature is supported by GnatMQ only for the .Net Framework platform and not for the WinRT (Windows 8.1 and Windows 10) due to the sandboxed execution environment that doesn’t accept incoming SSL/TLS connection (only as client).

M2Mqtt 3.5 : .Net MQTT client con un miglior supporto SSL/TLS, altri miglioramenti e licenza Apache 2.0 !

Questa volta la libreria M2Mqtt ha subito alcune modifiche “importanti” sia in termini di nuove funzionalità che di bug fixing. Devo ammettere che i miglioramenti sono dovuti soprattutto alle persone che la utilizzano in maniera assidua e mi segnalano nuove funzionalità da aggiungere o bug da risolvere. Oltre ad alcuni problemi segnalati su CodePlex, questa volta anche Clemens Vasters, PM su Microsoft Azure, mi ha sottoposto alcuni miglioramenti da applicare nell’ambito dell’autenticazione SSL/TLS. Infatti, come già twittato molte settimane fa, Clemens ha usato la mia libreria per eseguire i test sul progetto Reykjavik (Device Gateway) presentato a Build 2014 ed io non posso che esserne onorato.

Autenticazione SSL/TLS

In questo caso, il miglioramento è strettamente legato alla versione per .Net Framework, poiché è l’unica versione a supportare quanto è stato aggiunto. In particolare, la classe MqttClient mette disposizione altri costruttori ai quali è possibile fornire le seguenti callback :

  • RemoteCertificateValidationCallback : permette all’utente di effettuare ulteriori controlli sulla validazione del certificato ricevuto dal server oltre a quelli già eseguiti dal sistema. Utile nel caso di debugging e di utilizzo di certificati self-signed, in modo da accettare a prescindere la connessione con il server;
  • LocalCertificateSelectionCallback : permette all’utente di selezionare in maniera opportuna il certificato client da trasferire al server in caso di mutua autenticazione durante l’handshake SSL. Il certificato può essere selezionato da un pool di certificati locali oppure creato “a volo” direttamente nella callback;

Per maggiori informazioni, è possibile fare riferimento alla documentazione MSDN ufficiale.

Nel caso del costruttore più complesso (con entrambe le callback), un esempio di applicazione può essere il seguente :

MqttClient client = new MqttClient("<server_name>", 8883, true, ValidateServerCertificate, SelectClientCertificate);
...
...

bool ValidateServerCertificate(object sender,
 X509Certificate certificate,
 X509Chain chain,
 SslPolicyErrors sslpolicyerrors)
{
 bool valid;
 // check sslpolicyerrors and execute your certificate validation
 ...
 ...
 return valid;
}

X509Certificate SelectClientCertificate(
 Object sender,
 string targetHost,
 X509CertificateCollection localCertificates,
 X509Certificate remoteCertificate,
 string[] acceptableIssuers)
{
 X509Certificate cert;

 // choose client certificate from local store or creating new one
 ...
 ...
 return cert;
}

Per cercare di semplificare la creazione dell’oggetto client, i costruttori che ricevono in ingresso un IPAddress sono stati “marcati” con l’attributo Obsolete. Infatti, tutti gli altri costruttori permettono di specificare in ingresso un indirizzo IP o un host name in formato stringa; sarò carico del costruttore verificare di che tipo si tratta e nel caso di host name effettuare una conversione ad indirizzo IP attraverso DNS.

Per quanto riguarda il tracing, alcune persone hanno segnalato che nella versione Nuget questa funzionalità non visualizzava il contenuto di ciascuno messaggio scambiato ma il tipo del messaggio; ciò era dovuto al fatto che la libreria Nuget è compilata in modalità Release ma i messaggi di trace erano attivi in Debug. La versione attuale fornisce il tracing sia in debug che release in quanto è legata al simbolo TRACE (e non più al simbolo DEBUG) che è definito in entrambe le configurazioni. Ovviamente, il tracing è sempre legato alla definizione di un TraceListener da parte dell’utilizzatore.

Bug fixing

I principali bug risolti sono stati segnalati sul sito CodePlex da alcuni utenti e di seguito riporto i riferimenti :

Conclusioni

La libreria è in continua evoluzione grazie alla community e molto presto includerà il supporto per MQTT 3.1.1 che tra poche settimane sarà standard OASIS. L’ulteriore passo è la licenza passata da L-GPL ad Apache 2.0 !

Come sempre potete trovare la versione aggiornata su CodePlex, Nuget e Microsoft Code Gallery. Infine, è stato ovviamente aggiornato anche il broker GnatMQ alla versione 0.9.1.0 ed il progetto M2Mqtt4CE.

MQTT su SSL/TLS con la libreria M2Mqtt ed il broker Mosquitto

Dopo aver rilasciato la nuova versione della mia libreria M2Mqtt con il supporto per l’SSL/TLS con autenticazione lato server, è giunto il momento di mostrarvi un esempio di utilizzo.

Scegliamo ed installiamo il broker : Mosquitto

In primo luogo dobbiamo scegliere un broker MQTT tra quelli disponibili ma purtroppo nessuno è sviluppato utilizzando il .Net Framework. Scartando soluzioni più complesse, soprattutto per quanto riguarda l’installazione e la configurazione, come IBM Websphere, possiamo prendere in considerazione dei broker come RabbitMQ, HiveMQ oppure Mosquitto. In questo caso, la mia scelta è caduta proprio su Mosquitto che possiamo scaricare dal sito ufficiale per vari sistemi operativi basati su Linux, così come è presente un comodissimo installer per l’ambiente Windows. In realtà, per Windows esistono due modalità di installazione : la prima utilizza un installer in cui il broker è compilato in maniera nativa mentre nel secondo caso ci si basa su Cygwin che fornisce un ambiente Linux-like per Windows. E’ ovvio che la prima modalità è la più semplice ed immediata. Al termine dell’installazione, oltre ad essere installato il broker vero e proprio (mosquitto.exe), saranno forniti anche due applicazioni console che rappresentano un publisher (mosquitto_pub.exe) ed un subscriber (mosquitto_sub), molto utili per testare il funzionamento del broker stesso. L’utilizzo di Mosquitto è molto ben documentato sul sito ufficiale ma ciò che noi interessa sapere è soprattutto la parte di configurazione legata all’SSL/TLS. Per modificare le impostazioni di default del broker, quest’ultimo può essere lanciato specificando un file di configurazione (un file di esempio mosquitto.conf è presente nella cartella di installazione). Prima di affrontare tale argomento, è necessario generare i certificati della CA (Certification Authority) e del server/broker che andremo ad utilizzare nel corso dell’esempio.

Generazione dei certificati : CA e broker

In questo post, non voglio affrontare l’argomento complesso relativo al protocollo SSL/TLS ma ne voglio almeno sottolineare gli aspetti principali più strettamente legati all’esempio che andremo a realizzare. Il server che ospita il broker necessita di un certificato X.509 che deve essere opportunamente firmato da una CA (Certification Authority). Nel nostro caso, per evitare di “acquistare” un certificato e farlo firmare da una vera CA, andremo a generare un certificato “self-signed” root per la CA attraverso il quale poi firmeremo quello del server. La generazione e firma dei certificati può essere effettuata in due modi : attraverso il pacchetto OpenSSL, il cui installer per Windows può essere scaricato qui, oppure attraverso il tool Makecert che ritroviamo nell’ambito dell’installazione del nostro “caro” Visual Studio. Utilizzando per lavoro OpenSSL, ho preferito puntare su quest’ultimo, anche perché è molto più completo. L’installer da scaricare è quello relativo alla versione 1.0.1e (Win32 o Win64 dipende dal vostro sistema operativo) che necessita del Visual C++ 2008 Redistributables package. Al termine dell’installazione (tipicamente nella cartella C:\OpenSSL-WinXX con XX=32 oppure 64), può accadere (come si è verificato a me) che lanciando il comando openssl dal prompt dei comandi (all’interno della cartella bin di installazione), vi venga mostrato il seguente warning :

WARNING : can’t open config file: /usr/local/ssl/openssl.cfg

Unable to load config info from /usr/local/ssl/openssl.cfg

La soluzione immediata prevede di aggiungere una variabile di ambiente in cui definire il path nel quale si trova tale file di configurazione :

set OPENSS_CONF=C:\OpenSSL-Win64\bin\openssl.cfg

Lo so, avete ragione, non è normale che un’installazione non termini nel migliore dei modi…e sono perfettamente d’accordo !! Ma superato questo scoglio, OpenSSL è sicuramente il migliore ! Tutte le operazioni che seguono, vanno eseguite dal prompt dei comandi all’interno della cartella C:\OpenSSL-Win64\bin\PEM, nella quale OpenSSL gestisce il suo store di certificati.

In primo luogo, generiamo il certificato della CA con il seguente comando :

openssl req -new -x509 -days 3650 -keyout m2mqtt_ca.key -out m2mqtt_ca.crt

attraverso il quale otterremo una chiave privata per la CA (m2mqtt_ca.key ed il certificato “self-signed” m2mqtt_ca.crt). Verrà richiesta una “pass phrase” per crittografare anche la chiave privata ed in successione tutte le informazioni relative al certificato (Country Name, State, …) tra le quale ho preferito impostare come CN (Common Name) il nome del mio PC (questa impostazione è più strettamente necessaria al momento della generazione del certificato server).01_cert_ca

A questo punto possiamo passare alla generazione di una chiave privata per il server e la relativa richiesta di certificato che dovrà essere firmata dalla CA. Per quanto riguarda la generazione della chiave privata, possiamo eseguire :

openssl genrsa -des3 -out m2mqtt_srv.key 1024

attraverso il quale otterremo la chiave privata m2mqtt_srv.key del server crittografata mediante una “pass phrase”.

02_key_srv

Fatto ciò, passiamo alla generazione della richiesta di certificato da parte del server che dovrà essere firmato dalla CA.

openssl req -out m2mqtt_srv.csr -key m2mqtt_srv.key -new

In questo modo generiamo la richiesta m2mqtt_srv.csr (attenzione ! non è ancora il certificato firmato) all’interno della quale ci sono tutte le informazioni del server (richieste dall’esecuzione del comando) tra le quali il CN va impostato uguale al nome del server stesso che fornirà il certificato all’atto delle richieste da parte dei client. Nel mio caso, poiché il broker sarà eseguito sul mio PC, il Common Name è uguale al nome del mio PC “ppatierno-PC”.

03_csr_srv

L’ultimo passo consiste nel firmare la richiesta del server attraverso la CA ed ottenere il certificato definitivo del broker.

openssl x509 -req -in m2mqtt_srv.csr -CA m2mqtt_ca.crt -CAkey m2mqtt_ca.key -CAcreateserial -out m2mqtt_srv.crt -days 3650

Abbiamo così completato tutti i passaggi necessari alla generazione dei certificati.

04_cert_srv

In realtà, preferisco anticipare un passo. I certificati appena generati sono in formato PEM ma il .Net Framework, attraverso la classe SslStream (utilizzata nella M2Mqtt library), utilizza i certificati in formato DER. Il certificato che dobbiamo convertire è ovviamente quello della CA che va installato sul client, il quale invece riceverà quello del server da verificare durante l’handshake SSL. La conversione può essere eseguita sempre attraverso OpenSSL nel modo seguente :

openssl x509 -outform der -in m2mqtt_ca.crt -out m2mqtt_ca.der

Abbiamo finalmente tutto ciò che ci serve per poter configurare il broker !

Configurazione ed avvio del broker

Per la configurazione del broker, consiglio di fare una copia del file di esempio mosquitto.conf che andremo a modificare. Nel mio caso, ho creato il file mosquitto_m2mqtt.conf nel quale i parametri da modificare sono i seguenti all’interno della sezione “Default Listener” e “Certificate based SSL/TLS support” :

  • bind_address : va impostato al nome del server (nel mio caso bind_address ppatierno-PC);
  • port : la porta del protocollo MQTT per SSL/TLS è la 8883 (port 8883);
  • cafile : definisce il path del certificato della CA (cafile C:\OpenSSL-Win64\bin\PEM\m2mqtt_ca.crt);
  • certfile : path al certificato del server (certfile C:\OpenSSL-Win64\bin\PEM\m2mqtt_srv.crt);
  • keyfile : path della chiave privata del server (keyfile C:\OpenSSL-Win64\bin\PEM\m2mqtt_srv.key);
  • tls_version : versione del protocollo TLS (tls_version tlsv1);

Una volta terminate le impostazioni, il broker Mosquitto può essere lanciato dal prompt dei comandi (eseguito come amministratore) nel modo seguente :

mosquitto –c mosquitto_m2mqtt.conf –v

Attraverso il parametro –c specifichiamo il file di configurazione da usare mentre –v attiva la modalità “verbose” per visualizzare i messaggi di debug. Verrà richiesta la “pass phrase” della chiave privata del server necessaria durante l’handshake SSL/TLS nell’ambito dell’utilizzo dell’algoritmo di cifratura asimmetrica RSA.

05_broker_start

Nel mio caso, è stato fatto il binding all’indirizzo IPv6 del mio PC in corrispondenza del quale il broker si mette in ascolto sulla porta 8883. Abbiamo così il broker in esecuzione pronto per ricevere messaggi e distribuire i messaggi tra i vari client MQTT.

Avvio di un subscriber e test del broker

Poiché nel corso dell’esempio, il client che utilizzerà la M2Mqtt library farà da publisher dei messaggi, utilizziamo il tool mosquitto_sub per la parte di subscriber in modo da poter anche testare immediatamente se il broker funziona correttamente. Sempre da un prompt dei comandi (eseguito come amministratore) all’interno della cartella di installazione di Mosquitto, lanciamo il client nel modo seguente :

mosquitto_sub -h ppatierno-PC -p 8883 -q 1 -t sensor/temp –cafile C:\OpenSSL-Win64\bin\PEM\m2mqtt_ca.crt –tls-version tlsv1 -d

Abbiamo specificato l’host e la porta al quale connettersi, il path del file certificato della CA per verificare il certificato server ricevuto durante l’handshake SSL/TLS, la versione TLS, il topic al quale sottoscriversi con il corrispondente livello di QoS ed infine la flag che attiva il debug per visualizzare i messaggi scambiati con il broker.

06_sub_connect

Lo scambio dei messaggi per la connessione (CONNECT, CONNACK) ed il ping per mantenere viva la connessione tra client e broker (PINREQ, PINGRESP) è visibile anche nella console in cui stiamo eseguendo il broker stesso.

07_sub_broker_connect

Installazione certificato della CA

Le classi del .Net Framework che permettono di gestire le connessioni SSL/TLS, come la classe SslStream, fanno uso della SSPI (Security Support Provider Interface) di Windows per la gestione dei certificati. Ciò vuol dire che, prima di utilizzare il certificato della CA all’interno della nostra applicazione client, è necessario installarlo nel nostro sistema operativo. Uno dei modi più semplici per accedere al wizard di import dei certificati è attraverso le “Opzioni Internet” per importare il certificato tra le “Autorità di certificazione radice attendibili”.

08_import_der

Ricordiamoci che è necessario importare il certificato nel formato DER.

Nel caso in cui il client sia sviluppato con il .Net Micro Framework, se fosse eseguito nell’emulatore, tale operazione sarebbe ancora necessaria, in quanto l’emulatore utilizza la medesima interfaccia verso il sistema operativo. Ovviamente, solo nel caso in cui l’applicazione sia eseguita su una board reale, il certificato della CA andrebbe semplicemente copiato su un supporto (es. Flash, scheda SD, …) per poi essere letto a runtime dall’applicazione stessa. Nel nostro caso, eseguiremo l’applicazione su un PC con il .Net Framework (il risultato sarebbe lo stesso eseguendo la medesima applicazione con il .Net Micro Framework sull’emulatore).

Realizziamo il client e … pubblichiamo i messaggi criptati !

L’applicazione client, che utilizza la M2Mqtt library, non fa altro che connettersi al broker e pubblicare un dato finto di temperatura sul topic “sensor/temp” (al quale abbiamo sottoscritto un altro client al paragrafo precedente). Il certificato della CA è stato incluso in un file di risorse (Resources.resx) ed, una volta letto come stream di byte, viene fornito al costruttore della classe X509Certificate, in modo da ricavare un certificato X.509 valido per l’MqttClient.

class Program
{
	static void Main(string[] args)
	{
		MqttClient client = new MqttClient("ppatierno-PC",
			MqttClient.MQTT_BROKER_DEFAULT_SSL_PORT,
			true,
			new X509Certificate(Resources.m2mqtt_ca));

		client.Connect(Guid.NewGuid().ToString());

		for (int i = 0; i < 1000; i++)
			client.Publish("sensor/temp", Encoding.UTF8.GetBytes("27"), MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE);

		Thread.Sleep(Timeout.Infinite);
	}
}

Nelle finestre console del broker si evince la pubblicazione e lo scambio dei messaggi MQTT relativo al QoS 1 (Exactly Once).

09_pub_broker

Nella finestra console del subscriber è possibile osservare il messaggio ricevuto dal publisher.

10_pub_sub

Conclusioni

Il protocollo MQTT non fornisce in maniera intrinseca funzionalità di sicurezza, per cui è necessario affidarsi a ciò che offre lo strato di trasporto su cui viaggiano i messaggi MQTT, ossia il TCP/IP. In questo caso, uno dei protocolli maggiormente utilizzati è SSL/TLS che mette a disposizione anche l’autenticazione del server oltre alla criptazione dei dati. E’ ovvio che tale strato, riduce le performance dell’intero sistema e la velocità con la quale i messaggi sono scambiati. Un’ulteriore possibilità potrebbe essere quella di applicare la criptazione direttamente sui dati contenuti nel messaggio MQTT ma ciò prevede l’utilizzo di un algoritmo di criptazione simmetrico stabilito a priori e per il quale i client hanno tutti conoscenza della chiave. Questa modalità, però, eliminerebbe l’autenticazione del server che andrebbe realizzata a livello applicativo in altro modo. In molti casi, comunque, l’adozione di una tecnica rispetto ad un’altra, dipende molto dalle potenzialità del nostro sistema che nel caso di sistemi embedded potrebbe non supportare l’SSL/TLS per una questione di costo di elaborazione ed occupazione di memoria delle librerie di criptazione.