Meshcore-sensor-net: Difference between revisions
| Line 43: | Line 43: | ||
Encryption of the payload is done using the key: | Encryption of the payload is done using the key: | ||
* Payload is padded with 0 to multiple of 16 | * Payload is padded with 0 to multiple of 16 | ||
* Encrypted using AES ECB mode, initialised with the key | * Encrypted using AES-128 ECB (!) mode, initialised with the key | ||
The 2-byte MAC is calculated over the *encrypted* payload, using the key: | The 2-byte MAC is calculated over the *encrypted* payload, using the key: | ||
Revision as of 23:21, 2 March 2026
| Project meshcore-sensor-net | |
|---|---|
| File:Yunopicture.png | |
| Status | In progress |
| Contact | bertrik |
| Last Update | 2026-03-02 |
Introduction
This project is an investigation for using meshcore as a transport layer for citizen science data.
Meshcore is basically a network of radio repeaters for lora messages with a specific radio setting. The idea is to use a citizen science sensor with a LoRa radio to uplink citizen science data through this repeater network, get the data repeated, then pick it up using a special kind of node is connected to the internet (e.g. MQTT) that forwards the data to a collection server for further processing.
The LoRa setting used for meshcore almost universally in the Netherlands now is the EU/UK setting:
- 869.618 / SF8 / BW62.5 / CR8
- explicit header, CRC enabled
- sync word 0x12
Description of the on-the-air message:
- General description: https://gist.github.com/recrof/ca7ccff28c43d1b6bf7e55ce5159100b
- Dissection code: https://github.com/folkertvanheusden/meshcore-store/blob/master/utils/dissect.py
- Meshcore source: https://github.com/meshcore-dev/MeshCore/tree/main/src
Meshcore repeaters a relatively "dumb", they just forward anything that resembles a packet (they can't inspect the encrypted part).
The idea is basically:
Sensor first starts up, sends a kind of discovery packet in "flood" mode. This kind of packet is flooded over the entire network. At some point the discovery packets reaches a special internet-connected gateway that forwards it to the backend software. The backend software processes the data payload and sends back an acknowledgement packet back over the (best) path that it received the message on. When this reaches the sensor node, the sensor node knows the most efficient way to reach the gateway node and uses a "direct" packet. Every now and then it expects a kind of acknowledgement packet back from the server, to know that messages are still coming through. This is actually a bit similar to how LoRaWAN works.
Investigation
Meshcore security
The 16-byte channel key is derived from the channel name, as follows:
key = hashlib.sha256(name.encode('utf-8')).digest()[0:16]
where 'name' is the channel name, including the '#'
The 1-byte channel hash is derived from the channel key, as follows:
hash = hashlib.sha256(key).digest()[0]
where 'key' is the byte array containing the key
Encryption of the payload is done using the key:
- Payload is padded with 0 to multiple of 16
- Encrypted using AES-128 ECB (!) mode, initialised with the key
The 2-byte MAC is calculated over the *encrypted* payload, using the key:
mac = sha256-hmac(payload)[0:2]
Design
The plan is to use payload type "PAYLOAD_TYPE_GRP_DATA". Initially flood mode, normally direct mode.
Meshcore packet structure from sensor:
- Header: 1 byte = payload type PAYLOAD_TYPE_GRP_DATA + (flood or direct)
- Path: length + path bytes (0 in case of flood)
- Channel hash: 1 byte
- MAC: 2 bytes, according to PAYLOAD_TYPE_GRP_DATA format
- Encrypted payload: citizen science payload structure, encrypted with key derived from "channel name" (e.g. '#meshcore-sensor-net')
Citizen science payload structure:
- 4 bytes deviceid
- 4 bytes counter
- x bytes citizen science data
- 4 bytes MAC
Security:
- The PAYLOAD_TYPE_GRP_DATA payload follows the meshcore structure: 2-byte MAC + encrypted payload
- The citizen science data is not secret, it is encrypted with a key derived from the channel name ('#meshcore-sensor-net'), but we do add a cryptographic checksum to recognize authentic messages belonging to a specific application and device
- The checksum is calculated using the blake2s algorithm, calculated as follows:
- Blake2s hash with key (32-bytes)
- Fields included in hash: deviceid, counter, citizen science data
- We retain 4 bytes of the hash
- The hash key itself also calculated as follows:
- Blake2s hash with key, where key = application secret
- Fields included in hash: application name, deviceid
- The application name is part of the program image, the deviceid is derived from a unique hardware id, the application secret is entered only during key generation (never stored on device). The resulting key is written to non-volatile storage of the sensor.