How to Encrypt MQTT Payloads with Python – Example Code

mqtt-payload-encryption--smallEncrypting the MQTT payload rather than the link has the advantage that the data is encrypted end to end and not just between the broker and the client.



It also means that the intermediate brokers don’t need to support SSL and that you don’t need to obtain and install certificates.

It is therefore much easier to set up and use.

As a demonstration I’ve modified the simple pub-sub script to use payload encryption.

Here is a screen shot of the script with annotations:

python-mqtt-payload-encrypt

Notes:

Note 1 -I’ve used the cryptography package to do the encryption. See this article for an example usage and the cryptography web page here.

Note 2– First we create an encryption key  – cipher_key = Fernet.generate_key(). This key is used to encrypt and decrypt and we would need to use this same key on the receiving client. In our example the sender and receiver are the same client.

Note 3-The message to be encrypted must be in bytes.

Note 4: We need to create a UTF-8 encoded string to pass as the message payload to the MQTT publish method.

Note 5– The received message is already in bytes and so we pass it straight to the decrypt function.

Note 6: We then convert the decrypted byte message to a UTF-8 string as normal.

Running the Script

When we run the script this is what we see.

mqtt-payload-encrption-script-output

By enabling client logging as follows:

def on_log(client, userdata, level, buf):
    print("log: ",buf)
client.on_log=on_log

You can look at the message size.

You will notice that the outgoing message size is much larger when it has been encrypted.

In the example the 2 byte “on” message becomes 100 bytes when encrypted.

encrrypt-message-size

Using Separate Clients

If you have two separate clients a publisher and subscriber then you will need to generate the key manually, and paste it into the code on both the subscribing client and publishing client.

Open a python command prompt which you can do from the IDE.

run-python-shell

Enter the following commands shown n the screen shot to generate a key.

create-cipher-key

Now in both the subscribe and publish scripts replace the:

cipher_key = Fernet.generate_key()

with the key you created as shown below.

cipher-key

Python Scripts

You can download the actual script here.

Useful Resources:

Useful Tutorials and Resources:

Save

Save

Facebooktwittergoogle_plusredditpinterestlinkedinmail

4 comments

  1. Hi Mr.Steve
    i’ve written a simple code for payload encryption, i’v done it with AES-128 CBC mode ,it works fine ,
    the senario is very simple : the publisher send a JSON payload format that include the encryption key , IV (Initialisation Vector) and the encrypted data, the subscriber extract the key and IV then decrypt the data received, but i want to do a sort of hybrid encryption ,to encrypt the key with Asymetric algorithm, i know the famous RSA, but after reading somre articles, RSA is not suitable for constrained ressources, have you any idea wich algorithm can i use or somthing else that ensure the key trasmition ?
    thank you

    1. Hi
      Sorry but I chose the simpler solution of using a fixed pre-shared key. I took the view that anything more complicated and it would be easier to use SSL and certificates

  2. Hi Steve,
    Firstly
    I am publishing from my laptop via a raspberry pi broker to a client raspberry pi how do i use the same key in relation to this page on your site http://www.steves-internet-guide.com/encrypting-the-mqtt-payload-python-example/

    Secondly
    would you be able to give me and guidance on how to modify my setup so that i can publish to the broker from outside my LAN? i assume i will have to do NAT of some type but am not 100% on how to get the translation from my public ipv4 address to the address of the broker to work

    Thanks in advance,
    Eoin

Leave a Reply

Your email address will not be published. Required fields are marked *