Objectif
Même avec un réseau protégé, leukOS doit vérifier que chaque commande reçue par un microcontrôleur (ou envoyée au microcontrôleur) est:
- authentique (provenance légitime),
- intègre (non modifiée),
- non rejouée (anti-replay).
Le schéma recommandé est HMAC + nonce + timestamp.
Etat actuel (octobre 2026)
Le runtime générique WT32/ESP32 et leukos-node appliquent maintenant HMAC de
bout en bout. Le bridge refuse de démarrer un plugin déclaré
auth_required=true si la clé est absente, trop courte ou accessible au groupe
ou aux autres utilisateurs.
Chaque échange utilise une enveloppe AUTH1/RESP1, une clé différente par
MCU, un device_id, un key_id, un timestamp et un nonce aléatoire de 128 bits.
Le MCU mémorise les nonces récents et une borne temporelle persistée. La réponse
reprend le nonce de la requête et possède sa propre signature. Le node compare
la signature en temps constant et rejette toute réponse non signée, expirée ou
associée à une autre identité.
Le HMAC reste obligatoire à l'intérieur du tunnel WireGuard : le VPN chiffre le transport, tandis que HMAC authentifie la commande applicative et son résultat.
Le même format protège la liaison bidirectionnelle Saturn ↔ leukOS. Les commandes Saturn vers le nœud comme les synchronisations du nœud vers Saturn sont signées. Une réponse non signée, altérée, expirée ou portant un autre nonce est refusée. Lorsque ce mode est actif, aucun repli REST non signé n'est autorisé.
Principe
HMAC: signature calculée avec une clé secrète partagée entre leukOS et le MCU.nonce: identifiant unique par message.timestamp: horodatage du message, validé dans une fenêtre courte (ex: +/- 30 s).
Si une vérification échoue, la commande doit être rejetée.
Format effectivement utilisé
Requête, sur une seule ligne :
AUTH1 DEVICE_ID KEY_ID TIMESTAMP NONCE PAYLOAD_BASE64 HMAC_HEX
Réponse :
RESP1 DEVICE_ID KEY_ID TIMESTAMP NONCE PAYLOAD_BASE64 HMAC_HEX
Champs protégés pour une commande SET :
device_idcmdpayloadnoncetimestamphmac
Chaîne canonique à signer (exemple):
AUTH1\nDEVICE_ID\nKEY_ID\nTIMESTAMP\nNONCE\nPAYLOAD_BASE64
Puis:
hmac = HMAC_SHA256(shared_key, canonical_string)
Vérifications appliquées
- Vérifier format et champs obligatoires.
- Vérifier la fenêtre temporelle (
timestamp). - Vérifier l'unicité du
nonce. - Recalculer et comparer le
hmac. - Vérifier que le
device_idet lekey_idcorrespondent au plugin attendu. - Exiger le même nonce dans la réponse signée.
- Transporter le TCP uniquement sur l'interface WireGuard déclarée dans
bind_interface.
Séquence leukOS vers MCU
Bonnes pratiques
- Une clé différente par microcontrôleur.
- Rotation périodique des clés.
- Stockage des clés hors logs, hors front.
- Journaliser les rejets (hmac invalide, nonce dupliqué, horodatage expiré).
- Ne jamais réactiver le port de configuration historique
3233ni l'OTA sans restriction au tunnel. - Conserver un accès série physique de récupération avant toute rotation du firmware ou des clés.