-
Notifications
You must be signed in to change notification settings - Fork 453
Cryptography overhaul for V2 #1450
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
- Transmit only 4-byte counter [boot_id(2)][sequence(2)] - Derive full 12-byte nonce internally: SHA256(key || counter)[0:12] - Combined with tag reduction: V2 overhead now 12 bytes (was 24) - Saves ~16.5ms airtime per packet at SF8/BW62.5/CR8 - Security maintained: nonce unpredictable without shared secret
Everybody loves numbers (SF8, BW62.5, CR8) (edit: corrected the math, initially I did not count the timestamp)Real Message ExamplesNote: Plaintext = message length + 4 bytes (timestamp prefix in TXT_MSG)
Overhead CalculationV1 (AES-ECB + HMAC):
V2 (ChaCha20-Poly1305):
When Each Wins
The crossover point: V2 wins when Security Comparison
Summary
|
|
Store now - decrypt later (post-quantum stuff) notes: To be safe:
|
|
Note on Ascon: Ascon requires a full 128-bit nonce - no compression like with ChaCha. Even with a truncated 64-bit tag, Ascon overhead is 24 bytes vs 12 bytes. (CPU stats, but they doesn't really matter, chacha is 10x faster than AES-ECB already) conclusion: chacha is better, more homogenous, battle-tested |
|
Some tests |
My pet project outgrew itself, so I thought I share it here, maybe someone will have use for the information and stuff I learned along the way in the future.
MeshCore v2 Encryption: ChaCha20-Poly1305 Implementation
Requirements
This implementation requires repeaters to forward PAYLOAD_VER_2 packets! (currently in dev everything is dropped above VER_1)
Decisions
I decided to use ChaCha20-Poly1305 because we are using software for decrypt anyway (ESP's can do hardware accelerated stuff, but I tried to be universal, chacha is 10x faster than the current AES-ECB+HMAC anyway, it was designed for "low-end" systems like our embedded variants)
I decided to use 12 byte nonce and 12 byte tag because it's the lowest that adheres to standards. (Nonce can be lowered to 8 to save some minor airtime)
Draft PR, if anyone have anything to teach me more I'd be glad to hear it.
TL;DR
ChaCha20-Poly1305 authenticated encryption, replacing AES-128-ECB scheme for enhanced security.
The implementation maintains backward compatibility with v1 packets while providing stronger cryptographic guarantees for "v2-capable" nodes, as minimal airtime increase as I could squeeze out, no handshakes no nothing "additional" packets.
This was a huge project, I worked on it in "one section at a time" to preserve context windows and try to understand everything I did along the way.
I'm not a crypto expert nor a coding guru, so read everything with this in mind.
I've tested everything I could on my daily driver companion and my repeater (the code is still running on them, I'm using our mesh with this right now, of course v2 encryptes talk just between my repeater's admin commands and my other test companion).
And for the masochist people, the full changelog, I "enchanced" my scribbles with claude:
What Changed
Core Cryptographic Changes
New Encryption Algorithm: ChaCha20-Poly1305 AEAD cipher
Payload Version System
PAYLOAD_VER_1: Legacy AES-128-ECB (unchanged, remains default)PAYLOAD_VER_2: New ChaCha20-Poly1305 encryptionADV_FEAT1_CHACHA_CAPABLE)Channel Tagging
CHANNEL_FLAG_V2toGroupChannel.flagsbytePacket Types Migrated to v2
PAYLOAD_TYPE_REQ(request packets)PAYLOAD_TYPE_RESPONSE(response packets)PAYLOAD_TYPE_TXT_MSG(text messages)PAYLOAD_TYPE_GRP_TXT(group text messages)PAYLOAD_TYPE_GRP_DATA(group data messages)PAYLOAD_TYPE_PATH(path return packets)PAYLOAD_TYPE_ANON_REQ(anonymous request packets)Forwarding Logic Updated
PAYLOAD_VER_2packets (previously dropped)Security Hardening (Additional Fixes)
This PR also includes critical security hardening fixes identified during code audit:
Packet Parsing Hardening (
Packet::readFrom())uint8_ttouint16_tto prevent truncationACK Packet Parsing
payload_len >= 4validation before readingack_crcTRACE Packet Parsing
payload_len >= 9) before reading trace fieldsBridge Compatibility
RS232BridgeandESPNowBridgenow compatible withuint16_tlength parameterDesign Decisions in full
Why ChaCha20-Poly1305?
Why 12-Byte (96-bit) Authentication Tag?
rweather/Cryptolibrary supports tag truncation viaCHACHA_TAG_SIZEWhy 12-Byte Nonce?
rweather/Cryptolibrary expectationsUtils::getHardwareRandom()AAD (Additional Authenticated Data) Implementation
AAD protects packet metadata from tampering:
dest_hash,src_hash(orchannel_hash),payload_type,payload_versionHow It Works
Encryption Flow (v2)
peerSupportsCHACHA()orCHANNEL_FLAG_V2)Utils::getHardwareRandom()(platform-specific RNG)Utils::encryptCHACHA()which:[nonce (12)] [ciphertext] [tag (12)]PAYLOAD_VER_2in headerDecryption Flow (v2)
PAYLOAD_VER_2from packet headerUtils::decryptCHACHA()which:secure_compare())Capability Negotiation
ADV_FEAT1_CHACHA_CAPABLEflag inPAYLOAD_TYPE_ADVERTpacketsContactInfo.supports_chachaandClientInfo.supports_chachatrack peer capabilitiesAirtime Comparison (sorry if the table is shifted)
Packet Size Overhead
Airtime (BW62.5, SF8, CR8)
Security Improvements
What v2 Provides
secure_compare()to prevent timing attacksWhat v2 Doesn't Change
PAYLOAD_TYPE_ACKpackets remain unencrypted (by design, for low overhead)Backward Compatibility
Resource Usage (CPU/RAM)
RAM Impact
CPU Impact
Known Limitations / Future Work
Breaking Changes
PAYLOAD_VER_2packets