Practical IoT Cryptography On The Espressif ESP8266

The Espressif ESP8266 chipset makes three-dollar ‘Internet of Things’ development boards an economic reality. According to the popular automatic firmware-building site nodeMCU-builds, in the last 60 days there have been 13,341 custom firmware builds for that platform. Of those, only 19% have SSL support, and 10% include the cryptography module.

We’re often critical of the lack of security in the IoT sector, and frequently cover botnets and other attacks, but will we hold our projects to the same standards we demand? Will we stop at identifying the problem, or can we be part of the solution?

This article will focus on applying AES encryption and hash authorization functions to the MQTT protocol using the popular ESP8266 chip running NodeMCU firmware. Our purpose is not to provide a copy/paste panacea, but to go through the process step by step, identifying challenges and solutions along the way. The result is a system that’s end-to-end encrypted and authenticated, preventing eavesdropping along the way, and spoofing of valid data, without relying on SSL.

We’re aware that there are also more powerful platforms that can easily support SSL (e.g. Raspberry Pi, Orange Pi, FriendlyARM), but let’s start with the cheapest hardware most of us have lying around, and a protocol suitable for many of our projects. AES is something you could implement on an AVR if you needed to.

Theory

MQTT is a lightweight messaging protocol that runs on top of TCP/IP and is frequently used for IoT projects. Client devices subscribe or publish to topics (e.g. sensors/temperature/kitchen), and these messages are relayed by an MQTT broker. More information on MQTT is available on their webpage or in our own getting-started series.

The MQTT protocol doesn’t have any built-in security features beyond username/password authentication, so it’s common to encrypt and authenticate across a network with SSL. However, SSL can be rather demanding for the ESP8266 and when enabled, you’re left with much less memory for your application. As a lightweight alternative, you can encrypt only the data payload being sent, and use a session ID and hash function for authentication.

A straightforward way to do this is using Lua and the NodeMCU Crypto module, which includes support for the AES algorithm in CBC mode as well as the HMAC hash function. Using AES encryption correctly requires three things to produce ciphertext: a message, a key, and an initialization vector (IV). Messages and keys are straightforward concepts, but the initialization vector is worth some discussion.

When you encode a message in AES with a static key, it will always produce the same output. For example, the message “usernamepassword” encrypted with key “1234567890ABCDEF” might produce a result like “E40D86C04D723AFF”. If you run the encryption again with the same key and message, you will get the same result. This opens you to several common types of attack, especially pattern analysis and replay attacks.

In a pattern analysis attack, you use the knowledge that a given piece of data will always produce the same ciphertext to guess what the purpose or content of different messages are without actually knowing the secret key. For example, if the message “E40D86C04D723AFF” is sent prior to all other communications, one might quickly guess it is a login. In short, if the login system is simplistic, sending that packet (a replay attack) might be enough to identify yourself as an authorized user, and chaos ensues.

IVs make pattern analysis more difficult. An IV is a piece of data sent along with the key that modifies the end ciphertext result. As the name suggests, it initializes the state of the encryption algorithm before the data enters. The IV needs to be different for each message sent so that repeated data encrypts into different ciphertext, and some ciphers (like AES-CBC) require it to be unpredictable – a practical way to accomplish this is just to randomize it each time. IVs do not have to be kept secret, but it’s typical to obfuscate them in some way.

While this protects against pattern analysis, it doesn’t help with replay attacks. For example, retransmitting a given set of encrypted data will still duplicate the result. To prevent that, we need to authenticate the sender. We will use a public, pseudorandomly generated session ID for each message. This session ID can be generated by the receiving device by posting to an MQTT topic.

Preventing these types of attacks is important in a couple of common use cases. Internet controlled stoves exist, and questionable utility aside, it would be nice if they didn’t use insecure commands. Secondly, if I’m datalogging from a hundred sensors, I don’t want anyone filling my database with garbage.

Practical Encryption

Implementing the above on the NodeMCU requires some effort. You will need firmware compiled to include the ‘crypto’ module in addition to any others you require for your application. SSL support is not required.

First, let’s assume you’re connected to an MQTT broker with something like the following. You can implement this as a separate function from the cryptography to keep things clean. The client subscribes to a sessionID channel, which publishes suitably long, pseudorandom session IDs. You could encrypt them, but it’s not necessary.

m = mqtt.Client("clientid", 120)

m:connect("myserver.com", 1883, 0,
function(client)
print("connected")
client:subscribe("mytopic/sessionID", 0,
function(client) print("subscribe success") end
)
end,
function(client, reason)
print("failed reason: " .. reason)
end
)

m:on("message", function(client, topic, sessionID) end)

Moving on, the node ID is a convenient way to help identify data sources. You can use any string you wish though: nodeid = node.chipid().

Then, we set up a static initialization vector and a key. This is only used to obfuscate the randomized initialization vector sent with each message, NOT used for any data. We also choose a separate key for the data. These keys are 16-bit hex, just replace them with yours.

Finally we’ll need a passphrase for a hash function we’ll be using later. A string of reasonable length is fine.

staticiv = "abcdef2345678901"
ivkey = "2345678901abcdef"
datakey = "0123456789abcdef"
passphrase = "mypassphrase"

We’ll also assume you have some source of data. For this example it will be a value read from the ADC. data = adc.read(0)

Now, we generate a pseudorandom initialization vector. A 16-digit hex number is too large for the pseudorandom number function, so we generate it in two halves (16^8 minus 1) and concatenate them.

half1 = node.random(4294967295)
half2 = node.random(4294967295)
I = string.format("%8x", half1)
V = string.format("%8x", half2)
iv = I .. V

We can now run the actual encryption. Here we are encrypting the current initialization vector, the node ID, and one piece of sensor data.

encrypted_iv = crypto.encrypt("AES-CBC", ivkey, iv, staticiv)
encrypted_nodeid = crypto.encrypt("AES-CBC", datakey, nodeid,iv)
encrypted_data = crypto.encrypt("AES-CBC", datakey, data,iv)

Now we apply the hash function for authentication. First we combine the nodeid, iv, data, and session ID into a single message, then compute a HMAC SHA1 hash using the passphrase we defined earlier. We convert it to hex to make it a bit more human-readable for any debugging.

fullmessage = nodeid .. iv .. data .. sessionID
hmac = crypto.toHex(crypto.hmac("sha1", fullmessage, passphrase))

Now that both encryption and authentication checks are in place, we can place all this information in some structure and send it. Here, we’ll use comma separated values as it’s convenient:

payload = table.concat({encrypted_iv, eid, data1, hmac}, ",")
m:publish("yourMQTTtopic", payload, 2, 1, function(client) p = "Sent" print(p) end)

When we run the above code on an actual NodeMCU, we would get output something like this:

1d54dd1af0f75a91a00d4dcd8f4ad28d,
d1a0b14d187c5adfc948dfd77c2b2ee5,
564633a4a053153bcbd6ed25370346d5,
c66697df7e7d467112757c841bfb6bce051d6289

All together, the encryption program is as follows (MQTT sections excluded for clarity):

nodeid = node.chipid()
staticiv = "abcdef2345678901"
ivkey = "2345678901abcdef"
datakey = "0123456789abcdef"
passphrase = "mypassphrase"

data = adc.read(0)
half1 = node.random(4294967295)
half2 = node.random(4294967295)
I = string.format("%8x", half1)
V = string.format("%8x", half2)
iv = I .. V

encrypted_iv = crypto.encrypt("AES-CBC", ivkey, iv, staticiv)
encrypted_nodeid = crypto.encrypt("AES-CBC", datakey, nodeid,iv)
encrypted_data = crypto.encrypt("AES-CBC", datakey, data,iv)
fullmessage = nodeid .. iv .. data .. sessionID
hmac = crypto.toHex(crypto.hmac("sha1",fullmessage,passphrase))
payload = table.concat({encrypted_iv, encrypted_nodeid, encrypted_data, hmac}, ",")

Decryption

Now, your MQTT broker doesn’t know or care that the data is encrypted, it just passes it on. So, your other MQTT clients subscribed to the topic will need to know how to decrypt the data. On NodeMCU this is rather easy. Just split the received data into strings via the commas, and do something like the below. Note this end will have generated the session ID so already knows it.

staticiv = "abcdef2345678901"
ivkey = "2345678901abcdef"
datakey = "0123456789abcdef"
passphrase = "mypassphrase"

iv = crypto.decrypt("AES-CBC", ivkey, encrypted_iv, staticiv)
nodeid = crypto.decrypt("AES-CBC", datakey, encrypted_nodeid,iv)
data = crypto.decrypt("AES-CBC",datakey, encrypted_data,iv)
fullmessage = nodeid .. iv .. data .. sessionID
hmac = crypto.toHex(crypto.hmac("sha1",fullmessage,passphrase))

Then compare the received and computed HMAC, and regardless of the result, invalidate that session ID by generating a new one.

Once More, In Python

For a little variety, consider how we would handle decryption in Python, if we had an MQTT client on the same virtual machine as the broker that was analysing the data or storing it in a database. Lets assume you’ve received the data as a string “payload”, from something like the excellent Paho MQTT Client for Python.

In this case it’s convenient to hex encode the encrypted data on the NodeMCU before transmitting. So on the NodeMCU we convert all encrypted data to hex, for example: encrypted_iv = crypto.toHex(crypto.encrypt("AES-CBC", ivkey, iv, staticiv))

Publishing a randomized sessionID is not discussed below, but is easy enough using os.urandom() and the Paho MQTT Client. The decryption is handled as follows:

from Crypto.Cipher import AES
import binascii
from Crypto.Hash import SHA, HMAC

# define all keys
ivkey = '2345678901abcdef'
datakey = '0123456789abcdef'
staticiv = 'abcdef2345678901'
passphrase = 'mypassphrase'

# Convert the received string to a list
data = payload.split(",")

# extract list items
encrypted_iv = binascii.unhexlify(data[0])
encrypted_nodeid = binascii.unhexlify(data[1])
encrypted_data = binascii.unhexlify(data[2])
received_hash = binascii.unhexlify(data[3])

# decrypt the initialization vector
iv_decryption_suite = AES.new(ivkey,AES.MODE_CBC, staticiv)
iv = iv_decryption_suite.decrypt(encrypted_iv)

# decrypt the data using the initialization vector
id_decryption_suite = AES.new(datakey,AES.MODE_CBC, iv)
nodeid = id_decryption_suite.decrypt(encrypted_nodeid)
data_decryption_suite = AES.new(datakey,AES.MODE_CBC, iv)
sensordata = data_decryption_suite.decrypt(encrypted_data)

# compute hash function to compare to received_hash
fullmessage = s.join([nodeid,iv,sensordata,sessionID])
hmac = HMAC.new(passphrase,fullmessage,SHA)
computed_hash = hmac.hexdigest()

# see docs.python.org/2/library/hmac.html for how to compare hashes securely

The End, The Beginning

Now we have a system that sends encrypted, authenticated messages through an MQTT server to either another ESP8266 client or a larger system running Python. There are still important loose ends for you to tie up if you implement this yourself. The keys are all stored in the ESP8266s’ flash memory, so you will want to control access to these devices to prevent reverse engineering. The keys are also stored in the code on the computer receiving the data, here running Python. Further, you probably want each client to have a different key and passphrase. That’s a lot of secret material to keep safe and potentially update when necessary. Solving the key distribution problem is left as an exercise for the motivated reader.

And on a closing note, one of the dreadful things about writing an article involving cryptography is the possibility of being wrong on the Internet. This is a fairly straightforward application of the tested-and-true AES-CBC mode with HMAC, so it should be pretty solid. Nonetheless, if you find any interesting shortcomings in the above, please let us know in the comments.

44 thoughts on “Practical IoT Cryptography On The Espressif ESP8266

  1. NodeMCU?

    Wait, what? You are talking crypto and build your “firmware” via some random service out there with no way to check what is really going into the sausage?

    Are you serious?

    1. Well, you are left with disassembler (written by yourself, of course)… as with just right ANY build platform.

      Can you trust C compiler from Microsoft (remember the hype about automatical [and unwanted] inclusion of telemetry into DLLs during compilation in Visual C about a year ago?)?

      Can you trust GCC which from time to time spawns some kind of bug (used to happen because of aggresive optimalization which in some versions happened to optimize-out even instructions which were neccessary for the code)?

      Can you trust MPLAB X which injects slow-down code into programs when using student/free version? They claim that the paid version makes at least 20% faster code. Well, that’s because of those slow-down instructions (like store W to some place in RAM and then immediately read it back and toss away), not some wizardry.

      Can you ever trust anything you didn’t completely dig through? Nope. There always may be some malicious code left intentionally by the maker of the toolchain. And if that’s not the case, can you be sure that the code itself produced by the toolchain doesn’t include some kind of error? Nope, until it shows somehow. And when it comes to, can you trust the chip itself? Do you know exactly what is in the internal ROM of ESP8266 (well, maybe, not sure here)? Do you know what is in the internal ROM of STM32 (probably not)? Do you always know everything? Nope.

      It’s not about using some automatic service or your own deployment system, it’s about where your paranoia stops. Or where you stop to care. There can almost always be something hidden you can miss that can hit you back.

      1. True for blob-ware, but gcc is opensource.. no mater how many bugged bytes it spits out, it’s open, and messy bytes are not comparable to intentional malware bytes

      2. It’s not MPLAB X, it’s XCn compilers themselves, which are AFAIK based on GCC that deoptimise the code in free version. Solution: either edit ASM files generated by XCn and then recompile from ASM or use pirated version of XCn, which is illegal and can be considered dishonest. On the other hand intentionally messing up a valid code to sell “better” version of the compiler is dishonest and immoral, so why not screw them? If you are willing to break the law, that is…

        1. What I dont get is why no-one has taken the source code to the XC compiler (which Microchip are required to publish since its based on GCC which is GPL) and recompiled it to get the full-pay “pro” version with all the optimizations for free. Perfectly legal under the terms of the GPL

          As for the libraries, someone just needs to create an open source clone of those libraries and tell Atmel to get stuffed.

    1. For the AVR Arduini (UNO and so on): https://github.com/DavyLandman/AESLib will get the AES part handled.

      Which Arduino?

      A couple years ago, I tried getting some hash functions from https://github.com/cantora/avr-crypto-lib working (can’t remember which) and ran out of RAM on an ATmega168. Don’t know if that’s still the case or for all hash algos. Anyone? Hashing on AVRs?

      The ESP8266 has plenty of RAM. Getting a hash / HMAC running in the ESP-Arduino environment should be a simple matter of porting some (very portable) code.

      If you control the network, encryption should be enough. If it’s out on the Internet, you’ll want authentication, and the hash functions.

      1. I’m sorry I should be more clear – I’m speaking of the ESP8266 programmed with the Arduino IDE. I know there are several libraries out there, but for a guy that doesn’t natively understand the complexities around how to construct a safe implementation of all the required pieces (IVs, etc), this sort of guide would be really handy.

        1. I’m working on this. AES on ESP8266 using the Arduino IDE has some quirks and it’s not as straightforward as with Lua.

          It still ‘works’ in the sense that I can encrypt things (after making a small change to the library), but it’s going to take me some time to actually implement it in a sensible way, and then a while longer to understand it well enough to explain it.

          Overall I haven’t had a good experience using the Arduino IDE on the ESP8266. It’s involved a lot of library debugging. Occasionally it has saved me time but overall not. Anyway, if I’m successful I’m likely to write it up for people that prefer the platform more.

  2. Why? your esp8266 is using encrypted wifi and it’s communication is to MQTT on your local network. I can see this for silly things like a cloud MQTT broker, but inside your protected network that already has a level of encryption on it? no reason for it.

    1. I use ESP8266+MQTT all over my internal home network and it’s completely unsecured and I haven’t had any problems thus far, but that doesn’t mean that it’s a good idea. Further, if I want to take my hobby projects to a larger audience I think it’s irresponsible not to at least attempt to secure the project in some basic manner. I think this sort of guide is really helpful for a hobbyist hacker like myself.

      1. Same here: ESP8266 Broker node-red
        I use SSL to secure the connection.
        I had code running doing AES encryption of the payload, both on the ESP8266 and on the node-red side. But it was a pain to maintain and I had a number of problems (IV Vektor not working, random number on ESP8266), so I dropped it once I got SLL running.
        This article and the ESP32 give this another push. I need to wait for more experienced programmers to do the hard work and do some documentation. My knowledge stops very early, so I’m usually frankensteining bits and pieces together until it works more or less.

      2. Yes this is exactly why I use techniques like this — my hobby projects often become unexpectedly commercially viable. After it happened a few times I started getting in the habit of adding encryption from the start. Once it’s a habit it’s not much extra work, but while developing it I often wished there were more code examples out there so thought I would share.

        I realize the article covers both encryption and authentication, which is more security than a lot of projects need, but I reasoned it was better to spend the time to discuss both. If you want to just use WPA, that’s fine — but different tools are appropriate for different jobs and all that.

        I’ve certainly encountered situations where WPA wasn’t enough, and figured I wasn’t alone in that. There are many countries where you can’t trust your competitors, staff, ISP, and hosting provider if you’re generating data of any value.

    2. WPA does not protect against an attacker who has your shared key. If you’re running it on a network where the key is given out (like a coffee shop or a hackerspace), then those packets can be decrypted by anyone.

        1. > should have its own WiFi network
          > If only for availability reasons.

          Why? A 2.4GHz jammer would easily take out any availability ;-)

          Separation of networks is a fine idea, but the bigger issue is that vendors ship insecure devices and update cycles are measured in years (or never). This is especially problematic for public projects where there might be years between the tender and delivery.

  3. In NodeMCU you can connect to broker via secure port 8883 using TLS 1.2 ( https://nodemcu.readthedocs.io/en/dev/en/modules/mqtt/#mqttclientconnect ) and check broker cert with TLS module ( https://nodemcu.readthedocs.io/en/dev/en/modules/tls/#tlscertverify ) but last time I checked this feature wasn’t working – when using tls.cert.verify(true) and custom build with my cert in firmware it won’t connect ( client handshake failed! Reason:[-0x2700] )

    1. Yes, I had the same problem. My best guess is that the broker and client didn’t have an algorithm in common. I couldn’t find enough documentation to get it working.

      More seriously though I kept on running out of memory. That’s what led me to this solution, which turned out to be more practical, and figured I’d better document it :)

      1. Update: Years later, I still have problems with the NodeMCU TLS 1.2 implementation running out of memory connecting securely to an MQTT broker.

        It did eventually work reliably, but involved so much code optimization that the above method was actually easier, and implementing elliptical curve ciphers on the ESP32 is easier still… and probably much more secure.

        You can generate one-time throwaway public keys server-side as sessionIDs, encrypt on the ESP32, then decrypt server side with the private key.

  4. I use ESPs as IOT “endpoints” that communicate via dedicated IOT only local wifi networks to Pi based servers/concentrators which deal with encryption for external communication. These dedicated wifi networks are secured using WPA2 with (importantly) long random passwords. The passwords don’t have to be easy to remember, just securely stored, for example on paper in a safe or on a secure memory device. This leaves authenticated/encrypted MQTT to the Pi servers which is straightforward. I am looking for hardware based encryption in the future, maybe with the ESP32 combined with encryption hardware for the Pi. There was a Kickstarter project for a Pi encryption add-on but it was too expensive. Does anyone know of a reasonably priced crypto board for the Pi?

    1. This looks like a smart plan to me. Years ago when I started my “LAN of things” projects here and it was obvious an IoT was simply dumb, at least to me, for a host of reasons, I just put things on my wifi or wired LAN without much thought – raspies, ESPs now, you name it.
      I’ve started out building a pi-3 based WAP but it’s special in that it won’t pass through things from the LoT stuff at all – just aggregate them and serve up a set of webpages itself, and that’s all my LAN – and if there’s a crack – the internet – would ever see. In my current “it just grew” setup, each thing has a web page, and doing cgi’s in C for esp isn’t my idea of fun, nor is surfing to one to get sensor data, and then another to control something. Sometimes I DO want a human input, but many times it could be automated if the things could talk to one another, or architecturally better, a central thing where changing the rules is easier.

      1. The nice thing with this approach is that I can use simple and fast UDP based message protocols, such as CoAP, from the ESP endpoints, which speeds up response and saves power compared to TCP/IP based protocols. Then I can use node.js, Node-Red and secure MQTT on a Pi local server to host an app server or a web server that integrates all the local ESP devices. I have used Blynk on the Pi but am moving to something more flexible and open. Not sure exactly what yet.

  5. I don’t see any mechanism for expiring compromised keys. If you transmit your key via the secured channel I would think you would lose perfect forward secrecy. Like dominoes, an attacker with a compromised key can compromise any key that follows just by capturing packets. This is why I would choose TLS instead. (Forgive me if I misstated something because I’m rather green at this.)

    The lack of SSL certificate verification for the ESP8266 with MicroPython moved me to abandon it for my product. ESP32 costs a dollar more and can verify SSL if you flash it with the Pycom firmware.

    1. I should say, if you have a compromised key then decide to update the clients by transmitting a new key via the same compromised channel I would think you would lose perfect forward security and dominoes to follow.

      1. Yes this is a weakness. For the use cases I had in mind, each device could have it’s own key so a single compromised key is equivalent to a broken device. I could centrally revoke access to that device, and ship a new one out.

        In my part of the world (Asia), the price differential between the ESP8266 and the ESP32 is significant, it’s a very cost-driven market, and delivering a new device per key compromised is cost-effective. Given the constraints it was an acceptable solution.

        If the cost of the ESP32 drops further or a new platform solves these problems better I’ll switch to that, and we’ll hopefully get a new article!

        1. Odd that it’s so much more expensive. Here I can order (from Asia) ESP32s for $1 more. Yes that’s about 50% more but still the price of a nice cup of coffee. As a percentage of my overall parts cost it’s about 3%, worth the change for me.

          Anyway, your thought process seems sound. There are other concerns about leaving some non encrypted portions of your data channel exposed as mentioned elsewhere in the comments, but for at least this one problem you seem to have it solved.

          How about providing a web interface for changing the key? Then a new key could be sent over an alternate channel.

          I actually intend to do both; TLS for everything and individual AES encryption on data. If TLS is compromised the SSL vendor has that problem taken care of. And if AES gets compromised it’s only one device and the user can be contacted to change the key over the phone via the web interface.

          I don’t want to be held responsible for the next IoT botnet so I’m a bit paranoid.

  6. While I did it in C, I added AES to all my 8266 projects quite a while ago. And the inbuilt hardware random number generator is getting reasonably good press from serious people who are looking into how random it really is (and it is fast!).

    So it is quite easy (and it runs quite fast) to get secure messages to/from your receiving app, and to put a random seed into every session so that differential attacks etc aren’t going to work..

    Trying the same on a ardunio is problematic – it is simply too slow to encrypt packets fast enough (I did try!).

    On the compromised key issue above, what I did was to allow the primary key to only be changed by USB. ie so that if it was compromised (which wouldn’t be easy given it is a hardware generated long random key) the attacker couldn’t then change it unless he had physical access to the devices. To do THAT change by USB requires another key, which is never used over wifi….
    Of course, if they have physical access for any reasonable amount of time someone could get around that, but virtually nothing is going to stop that..

  7. This can go wrong in many ways. For starters CBC mode is known to be broken, which has known padding oracle issues. This issue is dependent on whether or not the HMAC is checked first and if the code gives off an obvious padding oracle. Secondly if the HMAC isn’t compared in a constant time fashion, then an attacker can feed in a hash value which would partially match up to the compared hash and leak out information on a correct comparison. Through this an attacker could eventually gain a correct HMAC value and send their modified message. Additionally CBC is known to be vulnerable to bitflipping attacks, where an attacker can change a value of the decrypted message. A proper implementation of this is dependent on the order of the decryption, and message integrity verification. I’d suggest to anybody doing this to stick using SSL, but if you really are insistent on rolling this out make use of something better such as GCM mode AES. BTW I am not a cryptographer, and just some guy who did half of these (http://cryptopals.com/) .

    1. The best laid plans of mice and men… are subject to management price targets and hardware constraints. If I’ve got a Raspberry Pi for each sensor (and sometimes I do) then I agree completely! SSL is the best solution and it’s not worth mucking around with the techniques covered here except as an academic exercise.

      I like the idea of further discussing the order in which the server deals with the data, e.g. decryption and authentication. I’ve been thinking about that a lot lately. If the hash is built using some amount of the original data (as a way to check integrity), then logically at least some decryption must take place before authentication. I’m not convinced this is the best way, and I’m still concerned about DDoS, but I think that will be a story for another day.

      1. Hey Sean, always, always, always use Encrypt-then-Authenticate!! There are attacks called “chosen ciphertext attacks” (CCA) that can be used to break the security of Authenticate-then-Encrypt or Encrypt-and-Authenticate. Encrypt-then-Authenticate prevents the whole class of CCA because the encrypted bits are authenticated. To do this, create the ciphertext from the plaintext, then sign (or HMAC) the ciphertext. On the receiving end, verify the HMAC before trying to decrypt the data. Think of it like a tamper seal on an envelope. If the tamper seal is broken, don’t open the envelope. It would be dangerous to open the envelope then check a tamper seal within because the contents could have been tampered with. It doesn’t help so much if you already have anthrax to find out the tamper seal has been broken.

  8. I’m currently using the 2.1.0 NONOS SDK w/ MBEDTLS to do TLS1.2 PKI Client Auth with Amazon AWS IOT. I’m working on AWS IOT Greengrass discovery (got it worked out, just need to “finalize” it). The connection is server/client certificate based, and I’m using a 2k RSA private key. Much easier than described above. I’ve looked into the NodeMCU Source Code, and have made modifications to support the server/client PKI auth to Amazon AWS. However, NodeMCU is big compared to the NONOS SDK size. NodeMCU wants 600kb, while my NONOS setup uses 350k. I wanted to target under 512k due to ESP8285s being only 1MB in size. I wanted to split the ROM in half so I can do OTA updates (which is working for me via rBoot examples & CRC checks work well using OTA too).

  9. There is hardware to do encryption/validation for less than a dollar. Specifically ATECC108A or ATSHA204.
    I’d rather use these which store the credentials in unreadable places. You can then integrate better HMAC and encryption protocols (AES on chip). The’re on the crypto shield from Ada if you have the $$ for that.

    1. mxb I have some ATECC508 and no idea how to use them. Bought them for Mongoose OS which supports them out of the box on the ESP8266 and then I switched gears to a language I am more familiar with (Python) which does not by default support these.

      In the context of this article which is getting security going on Lua could you share how to get these working in that language, and/or Python? I see Atmel put out some C libraries which is good for users of that language but…

  10. Hi !
    Great article thanks a lot..
    Just a silly question.. I don’t see how the sessionID part work..
    Think of say a temperature sensor that would post temperature on a topic every minute.. there is a priori not only one receiving device! You could subscribe multiple devices to the topic…. which one generates the session id?

    Thx

Leave a Reply to SjaakCancel reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.