Skip to main content

Meshtastic Encryption

Explanation

Meshtastic provides AES256-CTR encryption for the payload of each packet when sending via LoRa, with a different key for each channel. The packet header is always sent unencrypted, which allows nodes to relay packets they can't decrypt as well. One can disable this by setting a different rebroadcast mode.

By default you have one primary channel which is encrypted with a simple known key ("AQ=="), so to use proper encryption you must change this key first, or create a new channel and share it with the ones you want to communicate with. However, if you don't have the default key, it means you will not be able to communicate with devices that don't have your key.

Direct messages to a specific node (e.g. text, traceroute or position requests) may use any channel you share with the recipient. Namely, the device will use the one where it most recently heard a NodeInfo packet from the recipient on. Client apps will not show messages directed to other nodes, but in principle they could be read by anyone who knows the used channel key. This means that if it uses the default key, you have to assume anyone could read your direct messages.

All periodic broadcasts (position, telemetry, etc.) the device sends out itself are sent over the primary channel and thus encrypted with that key.

The device will decrypt the payload before sending it to a client app via BLE, serial, Wi-Fi/Ethernet. For MQTT you can specify whether you want to send an encrypted or unencrypted payload.

Is it as secure as Wi-Fi WPA3, HTTPS TLS1.3 or Signal ?

No.

WPA3, TLS1.3, Signal and Meshtastic can all use AES256, yet AES is one of the many cogs required in a modern encryption system, see below the main features "missing" in Meshtastic.

Perfect-Forward-Secrecy

Perfect-Forward-Secrecy also known as PFS means previous communications and more generally anything passively captured cannot be decrypted even when the key is compromised.

This means Meshtastic is vulnerable to « Harvest now, Decrypt later » attacks, this attack itself is not enough to decrypt messages it relies on an other failure leaking the channel key such as:

  • Accidently sharing the channel key with the wrong person.
  • One of your nodes being stolen.
  • Any unknown bug revealing the channel key to an attacker.

Other protocols such as misconfigured TLS1.2 are far more impacted by Harvest now, Decrypt later attacks because their keys will be broken by near future Quantum-Computers yet they do not provide PFS.

Meshtastic's encryption is not threatened by Quantum-Computers* so realistic attack vectors are accidental miss-handling of channel keys and nodes being lost.

*on the Quantum-Resistance of AES256 see:

Recommendations for users using private channels:

  • Do not configure private channels on unattended nodes, nodes will relay meshtastic traffic even if they are not able to decrypt it. Your unattended routers should not have the private PSK configured as it is easy to gain physical access and extract the channel key.
  • Keep in mind, everything sent on a channel can be stored and decrypted later by anyone who gain access to the key even if you locally delete the messages.
  • Change your Channel Keys from time to time.

Integrity

Integrity means ensuring messages cannot be modified without the key.

Meshtastic does not check messages have not been tempered with, see #4030 for details.

Recommendations:

  • Keep in mind, by applying a known plaintext attack anyone could send messages on a channel even with the channel key is private and secure.
  • For developers of third party applications integrating meshtastic, include a cryptographic MAC over the message content and PSK, we are also considering an AEAD secured channel mode which would provide this natively.

Authentication

Authentication means nodes say who they are on the network, meshtastic does not implement this so it is trivial to impersonate anyone else if you have access to the channel key.

This is because node ids are based on hardware MAC address, theses are hardcoded by the manufacturer.

Some other networks like Yggdrasil, cjdns or libp2p use public / private key pairs and the Public Key becomes the Node Identity, this make all messages bigger and or require an interactive handshake process.

Recommendations:

  • Keep in mind, the sender field is indicative and anyone with access to the channel key can trivially lie.

Direct-Messages

Direct-Messages are implemented as channel messages which have a to protobuf field set.

This means anyone in the channel can read all your direct-messages.

Also the node needs to know the right channel to use, this is done by using the latest one a NodeInfo was received, due to the lack of Authentication this means anyone you share a channel with can send a spoofed NodeInfo and make you send direct-messages on an incorrect public channel.

Recommendations:

  • Keep in mind, due to NodeInfo spoof issue Direct-Messages are very significantly less secure than a private channel with a secure PSK.
  • Do not use Direct-Messages for anything private, instead ahead of time create a new private channel and share it with the person you want to message with.
    • Nodes will relay encrypted packets even if they can't decrypt it, so you only loose on some small DM optimizations.
    • Do not send the private channel key in direct messages or a public channel, because then anyone listening gain access.
    • Use a different private channel for each person you want to have private conversations with.

Comments

Cryptography is tricky, so we've tried to 'simply' apply standard crypto solutions to our implementation. However, the project developers are not cryptography experts.

Based on comments from reviewers (see below), here are some tips for usage of these radios, so that you may know the level of protection offered:

  • It is pretty likely that the AES256 security is implemented 'correctly' and an observer will not be able to decode your messages.
  • Warning: If an attacker is able to get one of the radios in their possession, they could either a) extract the channel key from that device or b) use that radio to listen to new communications.
  • Warning: If an attacker is able to get the "Channel QR code/URL" that you share with others - that attacker could then be able to read any messages sent on the channel (either tomorrow or in the past - if they kept a raw copy of those broadcast packets)

The current implementation provides optional confidentiality to members of a configured network:

  • Encryption is implemented in devices/nodes with network-wide encryption keys.
  • Encryption is optional and is turned off when devices are in 'Ham mode'.
  • There is no encryption supported in the clients (iOS, Android) to facilitate distribution as mass market software.
  • Pairing from client-to-device is by:
    • direct USB cable
    • BT pairing
  • Devices are 'promiscuous' and will pair with any near-by client. Network confidentiality requires physical protection of all nodes.

Always keep in mind xkcd's note on encryption.

  • If you are a cryptography expert, please review these notes and our questions below. Can you help us by reviewing our notes below and offering advice? We will happily give as much or as little credit as you wish ;-).
  • Consider our existing solution 'alpha' and probably fairly secure against a not particularly aggressive adversary (but we can't yet make a more confident statement).

Notes for reviewers

If you are reviewing our implementation, this is a brief statement of our method.

  • We do all crypto at the SubPacket (payload) level only, so that all Meshtastic nodes will route for others - even those channels which are encrypted with a different key.
  • Mostly based on reading Wikipedia and using the modes the ESP32 provides support for in hardware.
  • We use AES256-CTR as a stream cypher (with zero padding on the last BLOCK) because it is well supported with hardware acceleration.
  • Our AES key is 128 or 256 bits, shared as part of the 'Channel' specification.
  • The node number concatenated with the packet number is used as the NONCE. This nonce will be stored in flash in the device and should essentially never repeat. If the user makes a new 'Channel' (i.e. picking a new random 256 bit key), the packet number will start at zero.
  • The packet number is sent in cleartext with each packet. The node number can be derived from the "from" field of each packet. (Cleartext is acceptable because it merely provides IV for each encryption run)
  • Each 16 byte BLOCK for a packet has an incrementing COUNTER. COUNTER starts at zero for the first block of each packet.
  • The IV for each block is constructed by concatenating the NONCE as the upper 96 bits of the IV and the COUNTER as the bottom 32 bits. Since our packets are small counter portion will really never be higher than 32 (five bits).

Comments from reviewer #1

This reviewer is a cryptography professional, but would like to remain anonymous. We thank them for their comments ;-):

I'm assuming that meshtastic is being used to hike in places where someone capable is trying to break it - like you were going to walk around DefCon using these. I spent about an hour reviewing the encryption, and have the following notes:

  • The write-up isn't quite as clear as the code.
  • The code is using AES-CTR mode correctly to ensure confidentiality.
  • The comment for initNonce really covers the necessary information.
  • I think the bigger encryption question is "what does the encryption need to do"? As it stands, an attacker who has yet to capture any of the devices cannot reasonably capture text or location data. An attacker who captures any device in the channel/mesh can read everything going to that device, everything stored on that device, and any other communication within the channel that they captured in encrypted form. If that capability basically matches your expectations, it is suitable for whatever adventures this was intended for, then, based on information publicly available or widely disclosed, the encryption is good. If those properties are distressing (like, device history is deliberately limited and you don't want a device captured today to endanger the information sent over the channel yesterday) we could talk about ways to achieve that (most likely synchronizing time and replacing the key with its own SHA256 every X hours, and ensuring the old key is not retained unnecessarily).
  • Two other things to keep in mind are that AES-CTR does not itself provide authenticity (e.g. an attacker can flip bits in replaying data and scramble the resulting plaintext), and that the current scheme gives some hints about transmission in the size. So, if you worry about an adversary deliberately messing-up messages or knowing the length of a text message, it looks like those might be possible.

I'm guessing that the network behaves somewhat like a store-and-forward network - or, at least, that the goal is to avoid establishing a two-way connection to transmit data. I'm afraid I haven't worked with mesh networks much, but remember studying them briefly in school about ten years ago.

Comments from @Jorropo

  • The IV initialization only use 31 random bits per reboot, it then increment messages sequentially. This is not high, it makes duplicate unlikely but probable given the complete scale of the network. Thankfully IV include lower 32 bits of the MAC address which should be unique per node, so each node is it's own birthday paradox, we aren't looking for network wide birthday paradox which would be easy to hack. See #4031. Could be fixed.
  • The lack of integrity wasn't properly considered, the remote administration module implements priviliged RPC calls over AES-CTR without any MAC or AEAD. Could be fixed.
  • The AES-CTR implementation looks like it protects Confidentiality assuming IVs are not duplicated.
  • The lack of Forward Secrecy is a bit worrying for a chat messenger when new users lack the paranoid and annoying key management practice that would be required for safe operation.
  • IMO the clients should have a big red box the first time you open a Direct-Message indicating theses are not private and not E2E. This was not clear to me without reading the code.
  • This project is completely fine for chatting with strangers, using the default key and understanding everything is public, I would not trust it with anything private without some other layer or significant reworks. For example I would consider SSH or Signal over Meshtastic safe. Yet Meshtastic does not choose to have worse crypto for bad reasons, they make the network significantly more usable over the unreliable slow LoRa backhaul it is using.