Repository navigation
Implement interface access codes (IFAC) - #91
Conversation
…lib C++ Arduino.h définit min/max comme des macros C, ce qui casse ensuite tout template std::min/std::max inclus plus loin dans la même unité de compilation (uniform_int_distribution, std::min sur initializer_list...). Provoque des erreurs de parsing incompréhensibles dans les en-têtes de la stdlib, sans lien apparent avec le vrai problème. Correctif standard : undef min/max juste après l'inclusion d'Arduino.h. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ission, vérification en réception Porté de la copie de microReticulum de RTNode-HeltecV4 (Apache-2.0), qui suit Python RNS : ifac_key = HKDF(64, SHA256(SHA256(nom) || SHA256(phrase)), IFAC_SALT), IFAC = fin de la signature Ed25519 du paquet (ifac_size, 8 par défaut en LoRa), en-tête et charge masqués par HKDF(ifac, sel = ifac_key). Sans IFAC, un paquet qui en porte un est rejeté au lieu d'être mal lu. Transport::ifac_mask/ifac_unmask testés contre des vecteurs produits par Python RNS 1.5.4 (test/test_ifac : clé et paquet masqué identiques octet pour octet). Utilities/Memory.h : inclusion de stdint.h manquante (GCC 15). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Firmware side (Provisioning fields + a small USB tool to set the network name / passphrase): attermann/microReticulum_Firmware#117. |
|
Thank you for this, @jmpuch. IFAC was a critical missing piece for parity with the Reticulum reference implementation. Without it, microReticulum nodes couldn't join IFAC-protected networks at all. Checking the derivation and masking byte for byte against vectors from Python RNS itself, and testing on real LoRa hardware against Python nodes, is exactly the care this kind of change needs. I really appreciate the work, including the credit to RTNode-HeltecV4 for the port. I'm happy to take this as it is. A few suggestions for future PRs, none of which hold this one up:
Thanks again, and for the matching firmware work in attermann/microReticulum_Firmware#117. |
Problem
microReticulum has no support for interface access codes (IFAC). The IFAC code in
Transport::transmit()/Transport::inbound()is a commented-out Python TODO, so:network_name/passphrase(Python RNSifac_netname/ifac_netkey, as commonly set on shared LoRa channels) — its packets carry no access code and are dropped by the other nodes;Solution
Follow Python RNS exactly:
Interface::setup_ifac(netname, netkey)derivesifac_key = HKDF(64, SHA256(SHA256(netname) || SHA256(netkey)), IFAC_SALT)and the IFAC signing identity from it.ifac_sizedefaults to 8 (the RNode/LoRa value) and can be changed withifac_size(n). Passing empty/null for both leaves IFAC off, so existing users see no change.Transport::ifac_mask(): the IFAC is the lastifac_sizebytes of the identity's signature of the packet; header and payload are masked withHKDF(ifac)salted withifac_key. Called fromtransmit().Transport::ifac_unmask(): unmask and verify.inbound()drops packets without a valid IFAC on an IFAC-enabled interface, and — as Python RNS does — drops IFAC-flagged packets on an interface without IFAC instead of misparsing them.The masking lives in two small static helpers so it can be unit-tested without a radio. The implementation is ported from the IFAC support in the microReticulum copy bundled with jrl290/RTNode-HeltecV4 (Apache-2.0), which has been running it on LoRa nodes; credit to its author. The README roadmap gets an "Implement interface access codes (IFAC)" entry.
Compatibility: no API is removed; interfaces without
setup_ifac()behave as before, except that IFAC-flagged packets are now dropped rather than misread.Testing
test/test_ifac(native): the derived key, the masked packet and the unmasked packet are checked byte for byte against vectors produced by Python RNS 1.5.4 itself (its interface key derivation andRNS.Transport.transmit()); tampered, other-network, unflagged and truncated packets are rejected.native-local):test_ifac,test_crypto,test_transport,test_rns_loopback,test_bytes,test_generalpass. (Needs Include stdint.h in Utilities/Memory.h #90 on GCC 15, independent of this change.)pio run -e ttgo-lora32-v21builds; not tested on ESP32 hardware.A follow-up PR to microReticulum_Firmware exposes the network name and passphrase as Provisioning fields.
🤖 Generated with Claude Code