Ported the relevant lazyhome.ru dokuwiki pages to markdown, verified against the code; each page carries a 'cross-check with code' section where behavior differs from or extends the wiki.
6.5 KiB
Криптоподпись команды
Источник: Wiki LightHub (lazyhome.ru), страница «криптоподпись_команды». Снапшот от 2026-10-02.
В том случае, если надо гарантировать, что, даже получив доступ к локальной сети, MQTT брокеру или HTTP API, потенциальный злоумышленник не сможет выполнить критичную команду (например, открытие ворот), можно использовать механизм цифровой подписи команды.
Для задействования режима, необходимо пересобрать прошивку, добавив в приватный файл опций компиляции (опции компиляции) (пример custom-build-flags/build_flags_lighthub21 для сборки под lighthub21) следующие опции (приведен пример):
-D CRYPT
-D PROTECTED_PINS=16,21
-D SHAREDSECRET=big_secret
Как работает режим:
- Каждый контроллер, один раз в 30 секунд, передает в MQTT топик
<mqtt_root>/<controller_name>/$saltслучайное число, полученное с истинного датчика случайных чисел. Данное число (далее<Salt>) должно сохраняться авторизованной стороной и использоваться при создании цифровой подписи. - Авторизованная сторона, желающая выполнить команду, вычисляет SHA256 хэш от строки, содержащей
<Salt><SHAREDSECRET><Команда> - при отправке MQTT команды, авторизованная сторона добавляет в MQTT Payload полученный хэш цифровой подписи ДО команды, отделив подпись от тела команды знаком @
- Контроллер, получив команду с подписью, производит аналогичную операцию по вычислению подписи и, если значения совпали, запрос считается авторизованным
- Если команда направлена на управление пином контроллера, из перечня PROTECTED_PINS, заданного при компиляции прошивки, то она будет выполнена только том случае, если является авторизованной
Ограничения
Если пин входит в перечень, заданный при компиляции в опции PROTECTED_PINS, то для него действуют следующие ограничения, смысл которых в том, чтобы сделать крайне сложным подачу высокого логического уровня на выход контроллера (открытие мощных ключей) не имея физического доступа к самому устройству:
-
Он не будет работать на канале типа термостат (THERMO)
-
Для канала типа RELAY вывод работает только в не инверсном режиме. То есть, настройками не получится добиться перевода в состояние с высоким уровнем по-умолчанию, не получив подписанной команды. Настройки команды по умолчанию в файле конфигурации, также, будут проигнорированы. требуется цифровая подпись команде для управления таким каналом
-
Восстановление значения канала при перезагрузке контроллера из статусных топиков MQTT не будет работать
-
Форсуночный увлажнитель не будет инициализирован, если хотя бы один защищенный пин присутствует в его настройках (насос, клапана)
-
Данные пины не работают для управления моторизированными воздушными заслонками (канал MOTOR)
-
При использовании защищенных пинов в канале типа PWM требуется цифровая подпись команде для управления таким каналом
-
Канал типа RELAYPWM на этом pin работать не будет
В качестве дополнительной меры защиты, рекомендуется отключить возможность обновления прошивки по-воздуху (OTA)
Сверка с кодом (2026-10-02)
- Корректно: механизм реализован под флагом
CRYPT: ключcryptoKey[] = QUOTE(SHAREDSECRET)(lighthub/main.cpp:110), публикация$saltв топике устройства —lighthub/main.cpp:2793-2804(функцияpublishStat(), вызывается раз в 30 секунд изthermoLoop(), периодTHERMOSTAT_CHECK_PERIOD=30000,lighthub/options.h:147). - Корректно: подпись вычисляется как SHA256 от
<Salt><SHAREDSECRET><Команда>—checkToken()вlighthub/utils.cpp:901-942(sha256.update: saltStr, cryptoKey, data). - Корректно: формат payload «подпись@команда» — разбор по символу
@вlighthub/item.cpp:752(char * authPos = strchr(payload,'@'); //token@command). - Корректно: ограничения для PROTECTED_PINS подтверждены в коде: THERMO —
main.cpp:3237; RELAY —modules/out_relay.cpp:39,110; MOTOR —modules/out_motor.cpp:53,77,102; PWM требует авторизованную команду —modules/out_pwm.cpp:129-165; SPRINKLER (увлажнитель) —modules/out_sprinkler.cpp:50. Перечень пинов задается опциейPROTECTED_PINS(lighthub/options.h:390-403).