Skip to content

Otto17/ESP_ChaCha

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ESP_ChaCha

Лёгкая библиотека для создания защищённого TCP-сервера на ESP8266/ESP32.

Лёгкая двунаправленная зашифрованная связь между ESP8266/ESP32 и ПО на смартфоне/ПК. Поддержка до 4 одновременных клиентов, автоматическая генерация ключа с хранением в LittleFS, обмен ключом через SVG QR-код. Каждый пакет аутентифицирован с помощью Poly1305 MAC.

 

Совместимость

ESP8266, ESP32

Arduino IDE 1 и 2 версий

  Проект полностью открыт и распространяется по лицензии MIT.

Ссылки на GitFlic и GitHub.


Сценарий использования

Мобильное приложение/ПК → Интернет → ESP (умный дом/датчики/управление)
ESP → Интернет → Мобильное приложение/ПК

Возможности

Безопасность:

  • Шифрование данных — ChaCha20 (256-бит ключ)
  • Аутентификация пакетов — Poly1305 MAC (защита от подделки)
  • Уникальный nonce для каждого пакета (аппаратный RNG)
  • Защита от подмены — изменённый пакет автоматически отбрасывается
  • Простая передача ключа — QR-код в формате SVG или скопируй из FS

Удобство:

  • Автогенерация ключа — один вызов generateKey()
  • Хранение в LittleFS — ключ сохраняется между перезагрузками
  • QR-код ключа — отсканируй со смарфтона и готово (не требует сторонних библиотек)
  • Веб-интерфейс — управление ключом через браузер (для локальной сети)
  • Встроенная статистика — принято/отправлено/ошибок

Производительность:

  • До 4 одновременных клиентов (для ESP8266) / до 8 (для ESP32, требуется изменить цифру в константе CHACHA_MAX_CLIENTS в ESP_ChaCha.h)
  • Лёгкий протокол — заголовок всего 30 байт
  • Двунаправленная связь — клиент и сервер могут отправлять данные друг другу в любой момент
  • Broadcast и unicast — отправка данных всем клиентам или конкретному клиенту

Зависимости

Установка через Arduino Library Manager:

  • Crypto — содержит ChaCha20-Poly1305
  • ArduinoJson — парсинг JSON (используется в примерах)
  • ESPAsyncWebServer — веб-панель (опционально, только для примеров)
  • AsyncTCP — Асинхронная библиотека TCP для ESP32 (опционально, только для примеров)
  • ESP_Async_TCP — Асинхронная библиотека TCP для ESP8266 (опционально, только для примеров)

Быстрый старт

#include <ESP_ChaCha.h>

ESP_ChaCha chacha;  // Создаёт объект библиотеки

// Колбэк вызывается при получении расшифрованного сообщения от любого клиента
void onMessage(const char* json, uint8_t clientIdx) {
  Serial.println(json);                            // {"cmd":"ping"} — данные уже расшифрованы
  chacha.sendTo(clientIdx, "{\"res\":\"pong\"}");  // Отправляет ответ конкретному клиенту
}

void setup() {
  Serial.begin(115200);
  delay(3000);  // Пауза чтобы успеть открыть монитор порта

  WiFi.begin("YourSSID", "YourPassword");
  Serial.println(F("Подключаемся к Wi-Fi"));
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print('.');
  }
  Serial.print(F("\nIP: "));
  Serial.println(WiFi.localIP());

  chacha.generateKey();         // Автоматически создаёт и сохраняет ключ "/chacha.key" в LittleFS
  chacha.generateQR();          // Генерирует QR-код из ключа и сохраняет "/ChaChaQR.svg" в LittleFS
  chacha.onMessage(onMessage);  // Регистрирует обработчик входящих сообщений
  chacha.begin(8888);           // Запуск TCP-сервера на порту 8888

  Serial.print(F("Ключ в HEX: "));
  Serial.println(chacha.keyAsHexString());  // Вывод ключа в Serial
}

void loop() {
  chacha.loop();  // Обработка входящих подключений и пакетов (вызывать постоянно)
}

Готово! ESP принимает зашифрованные подключения на порту 8888.


Что внутри протокола?

[2 байта длина] [12 байт nonce] [N байт зашифрованных данных] [16 байт тег Poly1305]
  • Nonce уникален для каждого пакета (генерируется аппаратным RNG)
  • Тег подтверждает целостность — если пакет изменён, он будет отброшен
  • Данные зашифрованы ChaCha20 — без ключа это случайный шум

Ограничения:

  • Максимальный размер данных: 2018 байт (2048 - 30 байт заголовков)
  • Каждый пакет независим — нет автоповтора при обрыве связи
  • При обрыве TCP-соединения клиент должен переподключиться и отправить данные заново

Защита от нестабильной связи:

  • TCP гарантирует доставку и порядок байтов (автоповтор на уровне ОС)
  • Тег Poly1305 отбросит повреждённые пакеты
  • При обрыве соединения данные теряются — повтор на стороне клиента

Технические детали:

  • Алгоритм шифрования: ChaCha20 (RFC 7539)
  • Аутентификация: Poly1305 MAC
  • Размер ключа: 256 бит (32 байта)
  • Размер nonce: 96 бит (12 байт)
  • Размер тега: 128 бит (16 байт)
  • Максимальный размер пакета: 2048 байт (настраивается)
  • Тайм-аут приёма: 150 мс (настраивается)

Основные функции

Управление ключами

// ИНИЦИАЛИЗАЦИЯ
chacha.begin(8888);             // Запустить TCP-сервер на порту (по умолчанию 8888)
chacha.generateKey();           // Загрузить ключ из LittleFS или создать новый (указывать false не обязательно)
chacha.generateKey(true);       // Принудительно создать новый ключ с перезаписью старого
chacha.useKey(myKey);           // Использовать свой ключ (32 байта)

// КОЛБЭКИ
chacha.onMessage(onMessage);    // Регистрация колбэка на получение сообщения
chacha.onClient(onClient);      // Регистрация колбэка подключения/отключения клиента

// ГЛАВНЫЙ ЦИКЛ
chacha.loop();                  // Вызывать в loop() скетча

// ОТПРАВКА ДАННЫХ
chacha.broadcast(jsonStr);      // Отправить всем клиентам
chacha.sendTo(index, jsonStr);  // Отправить конкретному клиенту

// СОСТОЯНИЕ СОЕДИНЕНИЙ
chacha.connectedCount();        // Количество подключённых клиентов
chacha.isConnected(index);      // Проверить подключён ли клиент по индексу

// РАБОТА С КЛЮЧОМ
chacha.keyAsHexString();        // Получить ключ в виде "0x01,0x02,..."
chacha.rawKey();                // Получить указатель на 32 байта ключа
chacha.generateQR();            // Создать QR-код ключа (SVG в LittleFS)

// СТАТИСТИКА
chacha.stats();                 // Получить структуру статистики
chacha.resetStats();            // Сбросить статистику

Отправка данных (пример)

chacha.broadcast("{\"event\":\"alarm\"}");	// Всем клиентам
chacha.sendTo(0, "{\"cmd\":\"status\"}");	// Клиенту #0

Получение данных

void onMessage(const char* json, uint8_t clientIdx) {
  // json — расшифрованная строка
  // clientIdx — номер клиента (0..3)
}
chacha.onMessage(onMessage);

Статистика

const auto& s = chacha.stats();
Serial.printf("Принято: %u, Ошибок тега: %u\n", s.rxOk, s.rxBadTag);

Обмен ключом через QR-код

chacha.generateQR();	// Генерирует QR-код из ключа и сохраняет "/ChaChaQR.svg" в LittleFS

QR-код содержит 64 HEX-символа (ключ в текстовом виде):

7333BDD51E4687C410F139FD74CD2943B455731691ABDB59691F73C0C99F1E98

Декодирование в мобильном приложении и на ПК:

Kotlin (Android):

val hex = scanQR() // "7333BDD5..."
val key = ByteArray(32)
for (i in 0..31) {
    key[i] = hex.substring(i*2, i*2+2).toInt(16).toByte()
}

Swift (iOS):

let hex = scanQR()
var key = Data()
for i in stride(from: 0, to: hex.count, by: 2) {
    let byte = UInt8(hex[i..<i+2], radix: 16)!
    key.append(byte)
}

Go:

hex := scanQR() // "7333BDD5..."
key, err := hex.DecodeString(hex)
if err != nil {
    log.Fatal(err)
}
// key теперь []byte длиной 32

C#:

string hex = ScanQR(); // "7333BDD5..."
byte[] key = Convert.FromHexString(hex);
// key теперь byte[32]

Python:

hex_str = scan_qr()  # "7333BDD5..."
key = bytes.fromhex(hex_str)
# key теперь bytes длиной 32

Логи библиотеки

Внутри библиотеки "ESP_ChaCha" предусмотрено логирование, по умолчанию оно выключено.

Для включения логирования нужно в файле библиотеки "ESP_ChaCha_Log.h" изменить в строке "#define ESP_CHACHA_DEBUG" значение с 0 на 1, сохранить и перекомпилировать скетч.


Веб-интерфейс (опционально):

Примеры скетчей включают веб-панель для управления ключом:

  • Просмотр и копирование текущего ключа
  • Генерация нового ключа одной кнопкой
  • Статистика подключений и пакетов
  • QR-код для сканирования

Тестовые, консольные программы-клиенты на Go для Linux и Windows:

  • Basic_Test — базовый тестовый клиент. Тестирует: ping, getKey, relay on/off, неизвестная команда, приём телеметрии.
  • Multiclient_Test — тест нескольких клиентов. Запускает N параллельных подключений к MultiClient примеру. Каждый клиент отправляет команды и получает broadcast от других.
  • Sensor_Client — тест клиент для SensorServer. Подключается к SensorServer, получает данные от эмитированных датчиков в реальном времени. Команды: getSensors, setInterval, ping, getStats, resetStats.
  • Test_Key_QR — тест для проверки корректности декодирования ключа ChaCha20 из QR-кода. Принимает 64-символьную HEX-строку (формат ESP_ChaCha), декодирует в 32 байта и выводит результат в нескольких форматах для визуальной сверки.

Автор Otto, г. Омск 2026

About

Лёгкая двунаправленная зашифрованная связь между ESP8266/ESP32 и ПО на смартфоне/ПК. Поддержка до 4 одновременных клиентов, автоматическая генерация ключа с хранением в LittleFS, обмен ключом через SVG QR-код. Каждый пакет аутентифицирован с помощью Poly1305 MAC.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors