Here’s a little demo that you can paste into Spark Build that shows how to use the AES-128-CBC encryption already available in the Spark Core firmware.
Put that on a Core and watch what it says on Serial.
Once every 10 seconds it will create a random encryption key and will print a message plain, then encrypted, then decrypted.
The open source AES implementation is from tropicssl in the core-communication-lib if you’re curious, and typical usage internal to the communication library is through wrap, which calls encrypt.
Things to know about AES-128-CBC in general
The key should remain the same throughout one session, e.g., downloading one file with TCPClient in your firmware. The key must remain secret. Next time you download a file, generate a new key. You can trust that sending through our API as an argument to a Spark.function is a secret transmission line for such a key.
The IV (initialization vector) however, should change with every call to either encrypt or decrypt, e.g., each buffered chunk of the downloaded file. It’s OK if the IV is publicly transmitted on the wire; it just needs to change for every single crypto operation.
Take a look at the encrypt method in the communication library—we use the first 16 bytes of each encrypted message as the IV for the next message. We keep two separate IVs—one for Core-to-Cloud communication, another for Cloud-to-Core communication. Both sides need to agree on the scheme for predictably changing the IV.
Suggestion for encrypted download with secure handshake
The Core could thus download an encrypted file from your server like this:
- Your server calls a Spark.function where the string argument is 64 hex characters. The first 32 (parsed to 16 bytes) represent the key, the next 32 (parsed to 16 bytes) represent the starting IV. The server should generate these with a cryptographically secure PRNG. Examples: node, ruby, python
- The Spark.function parses the hex string into binary bytes, saves the key and IV, and sets a flag meaning “on the next loop, start downloading”, and then returns.
- On the next loop, seeing the flag is set, the Core sets up a TCPClient to open a socket to your server. I recommend the server write directly on the socket, like telnet, rather than HTTP. You don’t need hypertext links, CSS, images, javascript, metadata, or browser compatibility. Just write the file to the socket.
- You should add a simple little authentication layer on the socket, like the Core has to write the first half of the IV hex string it received to the socket before the server will say OK, sure, I know who you are, here’s a file.
- The Core should read a chunk of the file into a buffer, decrypt it, save it to flash, and then let loop finish. The next time loop is called, the TCPClient should read more. Rinse, repeat. Do this rather than trying to read the whole file in one call of loop, because if it takes longer than about 15 seconds, you’ll drop the network connection.
Happy encipherment!