Once you've graduated from a proof of concept and have begun deploying your edge application into the real world, there may come a need to secure the data your device is sending.
Thankfully Notecard was designed with security in mind, across all of our supported radio access technologies! Notecards ship with a factory-installed ECC P-384 certificate, provisioned at manufacture, which can be used to secure your data before it leaves the Notecard. Combined with "off-the-internet" communication between Notecard Cellular and Notehub cloud service, there are multiple mechanisms designed to keep data secure during transport. Likewise, the data sent and received with a Notecard WiFi is always transferred over TLS.
While Notecard LoRa does not support the encryption shown in this tutorial, the transport is encrypted using standard LoRa transport encryption.
A further layer of security can be applied between your host device and cloud application by introducing end-to-end encryption of your Notefiles. Using Notecard's cryptographic functions, an AES-256 symmetric algorithm can be used to both encrypt outbound Notes added from your host device and decrypt inbound Notes encrypted by your cloud application.
In this article we'll explore the mechanisms you can use to secure your application, from using TLS transports, end-to-end encrypting your Notefiles, and retrieving/decrypting Notes after they've been routed through Notehub.
Quick Wins - Enabling TLS Within Notefiles
When creating Notefiles to store your data, the use of .dbs
, .qos
, and .qis
extensions instructs Notecard to use encrypted TLS sessions. You may choose to omit the use of TLS sessions if your data is not sensitive and you would prefer to conserve bandwidth.
For example, to create a new Notefile using TLS:
{
"req": "note.add",
"file": "sensors.qos",
"body": { "temp": 72.22 },
"sync": true
}
Notice, all that was required to secure the communication transport was to set the file type to .qos
!
Improving Further - Using End-to-End Encryption for the Contents of a Notefile
The next item on the agenda is encrypting the payload of our Notefiles; we'll need to perform a couple of important steps to make this happen:
- Generate a Private / Public Key pair to use both on Notecard and in our cloud application
- Set the value of an environment variable in Notehub to our Public Key
- Sync our Notecard to pull down the Public Key
- Instruct Notecard to use the Public Key each time we add to a Notefile, to encrypt the contents
- Establish a Notehub route to move our encrypted Notefiles to our web server
- Use our Private Key and the Ephemeral Public Key (Generated by Notehub) to decrypt our data
We're going to build this as a pseudo-workflow, giving you the foundations of building the end-to-end workflow for yourselves. This guide won't cover all the details, such as the firmware running on your host microcontroller or securing your web service, but it will give you a foundation to begin securing your data.
To follow along, you'll need to have a working Notecard / Notecarrier and Notehub account and are familiar with the basics of using them. If you haven't already, you can sign up for a free account here. It will also help to clone the repository from GitHub.
Step 1 - Generate a Private / Public Key Pair
To generate a private / public key pair, we'll use the openssl
CLI tool. Alternatively you can also run the generate.sh
script included in the repo.
openssl ec -in privateKey.pem -text -noout
openssl ec -pubin -in publicKey.pem -text -noout
You should end up with two keys that look similar to the following:
-----BEGIN PUBLIC KEY-----
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAElJIclWQieGY/FUvSMT2fOrE2hTlRsey3
ImIwzpUXwaFLVXxjh7gY8xoaYRNSSkiTNP/LmdDZsGwCEr6DhxsDi3fA+VuWp7KC
gBy7Fq+EZmv723hdbGaq5dNtPHErtx0i
-----END PUBLIC KEY-----
Don't misplace the
privateKey.pem
—you'll need it to decrypt the data later! For real world applications, you should take the appropriate precautions to secure this file.
Step 2 - Setting Notehub Environment Variables
Now, within Notehub, create a new project and head to Settings
(1) and then Environment
(2). You'll want to create a new variable (3) labeled encrypt_key
. Set this to the contents of your Public Key
, ensuring to prepend the algorithm used to generate the key, in this case secp384r1-aes256cbc:
before the key itself, as shown below.
Step 3 - Syncing Notecard
Next you'll need to pull the environment variable, encrypt_key
from Notehub to your Notecard. This is required for the next step, where you'll instruct Notecard to use this during the note.add
command to encrypt the data.
{"req": "hub.sync"}
Step 4 - Update note.add API
Now we'll update the note.add
API to use the key
field to instruct Notecard to use the encrypt_key
environment variable to encrypt the data.
{
"req": "note.add",
"file": "sensors.qos",
"key": "encrypt_key",
"body":
{
"temp": 72.22,
"humidity": 21.3,
"pressure": 1.002,
"sound_level": 68.9,
"heart_rate": 65
},
"sync": true
}
Step 5 - Establishing a Notehub Route
Let's verify that our data has made it up to Notehub, head to Events (1) and expand the event (2) from your Notecard. You can see the payload consists of a number of interesting fields:
alg
- the algorithm used to encrypt the datadata
- your encrypted dataenv
- the environment variable specifying the public key that the Notecard used to encrypt datakey
- an ephemeral public key created on the Notecard to encrypt the data
Now let's look at getting your data out of Notehub, to a server and decrypted to use!
Step 6 - Create a Web Server to Handle and Decrypt Incoming Requests
To process incoming encrypted messages, we need to do two things; first set up a route within Notehub, then set up and expose a web server to handle the processing and decryption of the events.
Head to Routes (1) and create a new Route (2).
We want to create a generic HTTP route, and for this tutorial we'll locally host the web server and expose it over a reverse proxy tool, ngrok
. This development mechanism allows us to test the decryption handling. Please take care to notice, this part of the tutorial is designed to demonstrate the decryption process and is not suitable for production. To build a production solution, you should take the appropriate precautions to limit exposing your data to the wider internet.
We'll pause here as we'll need to generate a URL to forward our data onto, which we can do by pointing an ngrok tunnel at a local web server. To handle and decrypt requests, we'll use a simple Python Flask web server and our private key from earlier. Clone the following repo, https://github.com/Bucknalla/note-encryption, and install the dependencies with pip install -r requirements.txt
. You'll also need to install Ngrok from https://download.ngrok.com. Follow their setup instructions and authenticate the CLI tool.
This repo also includes a Golang version of the web server, if you'd prefer to use that instead. See the README for instructions.
Start the web server with the command python python/main.py
and then generate a tunnel with ngrok http 5000
; we'll use the generated URL (1) in Notehub.
Once you've added the URL to Notehub, scroll down to see an option for Transform Data
, and select 'Body Only'
; this will make it easier for us to see the just payload we're interested in. Finally press Create Route
and we're ready to start testing the Route / Events.
Returning to the earlier step where we requested that Notecard send a TLS encrypted Notefile, we can re-run the request. With ngrok running, you can visit http://localhost:4040/inspect/http to see the events that arrive.
Conclusion
This tutorial has hopefully helped provide you with the fundamentals for creating a secure end-to-end encrypted workflow for getting data from your Notecard in the field, to your web server in the cloud. To understand more about sending encrypted data from the cloud to your Notecard, check out the guide in the docs.
While there's more to explore here such as best practices for securing your host microcontroller's firmware and introducing signed OTAs, this is an important step to move beyond prototyping and into real world deployments.