Implement an extra layer of encryption, but it's untested.
This commit is contained in:
parent
0604062966
commit
723941bdf8
7 changed files with 45 additions and 6 deletions
|
@ -20,8 +20,14 @@ Run `bash ./build setup` from the command line at the root of this repository.
|
||||||
|
|
||||||
### IoT Device
|
### IoT Device
|
||||||
- Copy `settings.custom.cpp.example` to `settings.custom.cpp` and fill in the fields there
|
- Copy `settings.custom.cpp.example` to `settings.custom.cpp` and fill in the fields there
|
||||||
|
- This Bash one-liner can be used to generate a new encryption key in the right formats: `head -c16 /dev/urandom | od -tx1 | awk '{ gsub(/^0+\s+/, "", $0); toml=$0; gsub(/\s+/, "", toml); print("settings.toml format: " toml); arduino=toupper($0); gsub(/\s+/, ", 0x", arduino); print("settings.custom.cpp format: 0x" arduino); exit }'`
|
||||||
- Review `settings.h` to make sure it matches your setup
|
- Review `settings.h` to make sure it matches your setup
|
||||||
- Copy the folders in `iot/libraries` to your Arduino IDE libraries folder
|
- Copy the folders in `iot/libraries` to your Arduino IDE libraries folder
|
||||||
|
|
||||||
|
### Server
|
||||||
|
- The `bash ./build setup` should have already installed the necessary dependencies.
|
||||||
|
- Create `settings.toml` in the root of the repository if it doesn't exist already.
|
||||||
|
- Review `server/settings.default.toml` and adjust `settings.toml` to fill in the values for the required fields, not forgetting the encryption key generated when setting up the IoT device.
|
||||||
|
|
||||||
## Useful Links
|
## Useful Links
|
||||||
- Entropy extraction from the watchdog timer vs the internal clock: https://github.com/taoyuan/Entropy
|
- Entropy extraction from the watchdog timer vs the internal clock: https://github.com/taoyuan/Entropy
|
||||||
|
|
|
@ -8,19 +8,24 @@
|
||||||
// LoRaWAN NwkSKey, network session key
|
// LoRaWAN NwkSKey, network session key
|
||||||
// This is the default Semtech key, which is used by the early prototype TTN
|
// This is the default Semtech key, which is used by the early prototype TTN
|
||||||
// network.
|
// network.
|
||||||
static const PROGMEM u1_t NWKSKEY[16] = { .... };
|
const PROGMEM u1_t NWKSKEY[16] = { .... };
|
||||||
|
|
||||||
// LoRaWAN AppSKey, application session key
|
// LoRaWAN AppSKey, application session key
|
||||||
// This is the default Semtech key, which is used by the early prototype TTN
|
// This is the default Semtech key, which is used by the early prototype TTN
|
||||||
// network.
|
// network.
|
||||||
static const u1_t PROGMEM APPSKEY[16] = { ..... };
|
const u1_t PROGMEM APPSKEY[16] = { ..... };
|
||||||
|
|
||||||
// LoRaWAN end-device address (DevAddr)
|
// LoRaWAN end-device address (DevAddr)
|
||||||
static const u4_t DEVADDR = 0x....; // <-- Change this address for every node!
|
const u4_t DEVADDR = 0x....; // <-- Change this address for every node!
|
||||||
|
|
||||||
|
// The RFM95 pin mapping
|
||||||
const lmic_pinmap lmic_pins = {
|
const lmic_pinmap lmic_pins = {
|
||||||
.nss = PIN_SPI_CS_RFM95,
|
.nss = PIN_SPI_CS_RFM95,
|
||||||
.rxtx = LMIC_UNUSED_PIN,
|
.rxtx = LMIC_UNUSED_PIN,
|
||||||
.rst = 9,
|
.rst = 9,
|
||||||
.dio = {2, 6, 7},
|
.dio = {2, 6, 7},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The AES-ECB 128-bit key to encrypt the data with.
|
||||||
|
// See the README for a Bash oneliner that generates a new key in the right format.
|
||||||
|
uint8_t encrypt_key[16] = { ..... };
|
||||||
|
|
|
@ -7,8 +7,15 @@
|
||||||
* it settings.cpp, and edit that instead.
|
* it settings.cpp, and edit that instead.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// The network session key. From The Things Network console
|
||||||
extern const PROGMEM u1_t NWKSKEY[16];
|
extern const PROGMEM u1_t NWKSKEY[16];
|
||||||
|
// The application session key from The Things Network console
|
||||||
extern const u1_t PROGMEM APPSKEY[16];
|
extern const u1_t PROGMEM APPSKEY[16];
|
||||||
|
// The device address
|
||||||
extern const u4_t DEVADDR;
|
extern const u4_t DEVADDR;
|
||||||
|
|
||||||
|
// The pin mapping for the RFM95
|
||||||
extern const lmic_pinmap lmic_pins;
|
extern const lmic_pinmap lmic_pins;
|
||||||
|
|
||||||
|
// The key to encrypt the data with
|
||||||
|
extern uint8_t encrypt_key[16];
|
||||||
|
|
|
@ -8,6 +8,9 @@
|
||||||
// Global static variable that's used to detect when LMIC has finished doing it's thing
|
// Global static variable that's used to detect when LMIC has finished doing it's thing
|
||||||
bool is_sending_complete = false;
|
bool is_sending_complete = false;
|
||||||
|
|
||||||
|
// Defined as part of LMIC, but LMIC is compiled and linked in separately
|
||||||
|
extern "C" void lmic_aes_encrypt(unsigned char *Data, unsigned char *Key);
|
||||||
|
|
||||||
|
|
||||||
void transmit_counter_save() {
|
void transmit_counter_save() {
|
||||||
store_eeprom_uint32_save(0, LMIC.seqnoUp);
|
store_eeprom_uint32_save(0, LMIC.seqnoUp);
|
||||||
|
@ -82,6 +85,9 @@ void transmit_init() {
|
||||||
* @param length The length of the given message.
|
* @param length The length of the given message.
|
||||||
*/
|
*/
|
||||||
bool transmit_send(uint8_t* data, int length) {
|
bool transmit_send(uint8_t* data, int length) {
|
||||||
|
// Encrypt the data with the extra encryption key
|
||||||
|
lmic_aes_encrypt(data, encrypt_key);
|
||||||
|
|
||||||
// Check if there is not a current TX/RX job running
|
// Check if there is not a current TX/RX job running
|
||||||
if (LMIC.opmode & OP_TXRXPEND) {
|
if (LMIC.opmode & OP_TXRXPEND) {
|
||||||
// Serial.println(F("OP_TXRXPEND: Job running, can't send"));
|
// Serial.println(F("OP_TXRXPEND: Job running, can't send"));
|
||||||
|
|
|
@ -40,6 +40,10 @@ app_id = "CHANGE_THIS"
|
||||||
# there.
|
# there.
|
||||||
access_key = "CHANGE_THIS"
|
access_key = "CHANGE_THIS"
|
||||||
|
|
||||||
|
# The additional encryption key, in hex, generated when setting up the IoT device.
|
||||||
|
# This is used as an exrtra layer of encryption to ensure that The Things Network does not have access to the decrypted data.
|
||||||
|
encryption_key = "CHANGE_THIS"
|
||||||
|
|
||||||
# A list of devices to monitor.
|
# A list of devices to monitor.
|
||||||
# If a device isn't specified here, then we won't hear messages from it.
|
# If a device isn't specified here, then we won't hear messages from it.
|
||||||
# FUTURE: Automatically fetch a list of devices from the TTN API
|
# FUTURE: Automatically fetch a list of devices from the TTN API
|
||||||
|
|
|
@ -1,11 +1,17 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
import aes from 'aes-js';
|
||||||
|
|
||||||
const offset_id = 0;
|
const offset_id = 0;
|
||||||
const offset_lat = 32 / 8;
|
const offset_lat = 32 / 8;
|
||||||
const offset_lng = (32 / 8) + (32 / 8);
|
const offset_lng = (32 / 8) + (32 / 8);
|
||||||
|
|
||||||
function decode_payload(payload_base64) {
|
function decode_payload(payload_base64, key_hex) {
|
||||||
let payload_buffer = Buffer.from(payload_base64, "base64");
|
let payload_buffer_enc = Buffer.from(payload_base64, "base64");
|
||||||
|
let key_buffer = Buffer.from(key_hex, "hex");
|
||||||
|
|
||||||
|
let aes_ecb = new aes.ModeOfOperation.ecb(key_buffer);
|
||||||
|
let payload_buffer = aes_ecb.decrypt(payload_buffer_enc);
|
||||||
|
|
||||||
// console.debug(`Offsets: ${offset_id}, ${offset_lat}, ${offset_lng}`);
|
// console.debug(`Offsets: ${offset_id}, ${offset_lat}, ${offset_lng}`);
|
||||||
// console.debug(`Message hex: ${payload_buffer.toString("hex")}`)
|
// console.debug(`Message hex: ${payload_buffer.toString("hex")}`)
|
||||||
|
|
|
@ -16,7 +16,12 @@ class MessageHandler {
|
||||||
async handle(message) {
|
async handle(message) {
|
||||||
if(this.debug) console.log(message);
|
if(this.debug) console.log(message);
|
||||||
|
|
||||||
let decoded_payload = decode_payload(message.payload_raw);
|
if(this.settings.ttn.encryption_key == "CHANGE_THIS") {
|
||||||
|
this.log.error(`Error: No encryption key specified. Try filling in the required values in settings.toml. If they don't exist yet, try using server/settings.default.toml as a reference.`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let decoded_payload = decode_payload(message.payload_raw, this.settings.ttn.encryption_key);
|
||||||
if(this.debug) console.log(decoded_payload);
|
if(this.debug) console.log(decoded_payload);
|
||||||
|
|
||||||
let rssis = [];
|
let rssis = [];
|
||||||
|
|
Loading…
Reference in a new issue