M
MeshTRX
Все статьи

Шифрование в 39 байтах

8 мин чтения

Сначала прямо: сегодня в MeshTRX ничего не шифруется. Ни голос, ни сообщения, ни файлы, ни координаты в маяках. Любой человек с такой же рацией на том же канале слышит разговор целиком. Соединение телефона с рацией по Bluetooth тоже открыто — PIN там защищает от случайного чужого подключения, а не от прослушивания.

Это стоит знать до того, как вы решите, для чего использовать такую связь. А дальше — почему так вышло и что мы собираемся с этим делать.

Почему шифрования нет до сих пор

Это была очерёдность, а не забытая задача. Сначала требовалось понять, доходит ли живой голос через LoRa на разумное расстояние и нужно ли это кому-то, кроме автора. Шифровать несуществующую связь смысла не было.

Условие выполнено: связь работает, её гоняют в поле посторонние люди, дальность померена. Значит задача вернулась в очередь. И тут выяснилось, что «включить шифрование» — это не одна задача, а три разные.

Скрыть содержимое. Чтобы посторонний слышал шум вместо речи.

Убедиться, что пакет не подменили. Шифр сам по себе этого не даёт: злоумышленник может изменить биты, и получатель расшифрует мусор, не заметив подмены. Для этого нужна подпись пакета — код аутентичности.

Понять, кто свой. Это уже про ключи: откуда они берутся, как попадают на устройства и что делать, когда одна рация потерялась.

Первая задача решается почти бесплатно. Вторая стоит эфирного времени. Третья — самая сложная, и именно её просят в сообществе: «шифрование на основе обмена ключами, чтобы создавать приватные каналы».

Бюджет: 39 байт и ни байтом больше

Голосовой пакет MeshTRX — 39 байт: 7 байт заголовка и 32 байта сжатой речи. Отправляется он каждые 80 миллисекунд, и это не наш выбор, а требование кодека.

Вот что происходит с эфиром, если добавлять к пакету криптографические поля:

ПакетВремя в эфиреЗанято канала
сейчас, 39 байт53,4 мс67%
+ подпись 4 байта57,0 мс71%
+ подпись 8 байт60,5 мс76%
+ подпись 16 байт (полная)71,3 мс89%
+ публичный ключ 32 байта85,6 мс107%

Последняя строка — не опечатка. Публичный ключ современного алгоритма обмена (X25519) занимает 32 байта, и пакет с ним в канал попросту не помещается: сто семь процентов означают, что передача не успевает закончиться до начала следующей.

Отсюда первые выводы.

Само шифрование бесплатно. Поточный шифр не меняет длину: 32 байта речи остаются 32 байтами. Ни одного лишнего байта в эфир.

Случайное число к каждому пакету передавать нельзя. Обычно шифру нужен уникальный nonce, и его кладут рядом с данными — это плюс 8–12 байт. Но у нас уже есть номер пакета в заголовке, а он и так уникален в пределах передачи: из номера, адреса отправителя и номера канала счётчик собирается на обеих сторонах одинаково, ничего не передавая.

Полная подпись слишком дорога. Шестнадцать байт — это 89% канала под одного говорящего: ретранслятору не остаётся места вовсе, а он и так работает на пределе. Усечённая подпись в 4–8 байт даёт защиту слабее, но реалистичную по цене. Для текста, файлов и команд, где пакеты редкие, можно позволить полную.

Потери меняют правила

Есть ещё одно ограничение, о котором в обычных системах не думают: у нас теряются пакеты. Половина голоса через ретранслятор не доходит, и это нормальный режим работы.

Значит режимы шифрования, где каждый блок зависит от предыдущего, отпадают: потеряв один пакет, приёмник не расшифрует всё остальное. Нужен режим, где каждый пакет самодостаточен — потеря одного не мешает разобрать следующий.

К счастью, это совпадает с тем, как устроен сам голос: каждый пакет уже самостоятелен, потому что иначе речь разваливалась бы от первой же потери. Номер пакета в заголовке, который сейчас служит для склейки и дедупликации, оказывается готовым счётчиком для шифра.

Что даст общий ключ на канал — и чего не даст

Минимальный рабочий вариант, с которого мы начнём: один ключ на канал, задаётся в настройках, хранится в памяти устройства.

Что это закрывает:

  • сосед с такой же рацией на том же канале больше не слушает ваш разговор;
  • случайный человек, купивший модуль и залив прошивку, не попадает в чужую группу по совпадению канала;
  • записанный эфир не расшифровывается задним числом без ключа.

Чего это не закрывает, и об этом надо говорить прямо:

  • любого, у кого есть ключ. Ключ один на группу; ушёл человек — ключ надо менять у всех;
  • утечку через устройство. Физический доступ к плате — это доступ к ключу в памяти;
  • сам факт передачи. Радиоразведка видит, что кто-то вышел в эфир, на какой частоте и как долго говорил, даже не понимая слов. Против пеленгации шифрование не помогает вообще;
  • подмену, если подписи нет. Без кода аутентичности чужой может вбросить мусор, который у вас превратится в треск.

Это честный уровень «не подслушает сосед», а не «не прочитает тот, кому очень надо». Путать эти вещи опасно: человек, который поверил в защиту, которой нет, рискует сильнее того, кто знает, что эфир открыт.

Приватные каналы: почему это отдельная задача

Запрос из сообщества звучал шире общего ключа: обмен ключами и приватные каналы, куда попадают только свои.

Здесь упираемся в ту самую строку таблицы. Классический обмен ключами требует передать 32 байта публичного ключа, а это больше одного пакета. Разбить на два-три — можно, но обмен придётся делать надёжным: с подтверждением, повторами и защитой от вклинивания посредника. В эфире, где половина пакетов теряется, это заметная работа.

Поэтому разумнее развести способы по ситуациям:

  • ключ вводится руками или считывается с экрана. Скучно, зато надёжно: обмен происходит вне эфира, подслушать нечего. Для группы, которая собирается вместе перед выходом, этого достаточно;
  • обмен при первой встрече по Bluetooth. Рации рядом, телефон видит обе — ключ передаётся коротким путём, минуя радиоканал;
  • обмен по эфиру — самый удобный и самый дорогой. Он нужен, когда людей нельзя собрать вместе, и делать его стоит последним, когда простые способы уже работают.

И отдельная деталь, которая связывает шифрование с совсем другой задачей. Чтобы ретрансляторы не повторяли чужой трафик, сети нужны зоны — понимание, какая станция своя. Идентификатор группы, который для этого нужен, и ключ группы — это одно и то же поле, если делать их вместе. Поэтому зоны и шифрование лучше не разводить по разным углам: одна задача даёт второй почти всё, что ей нужно.

Что дальше

Порядок, который мы считаем правильным: сначала общий ключ на канал с усечённой подписью для голоса и полной для текста и файлов. Потом ввод ключа руками и через экран. Потом группы и зоны на том же идентификаторе. Обмен ключами по эфиру — последним.

Сроков не называем: проект делается по вечерам, и обещать даты было бы враньём. Но пока шифрования нет, мы будем писать об этом прямо — в документации, на странице проекта и здесь.

Как устроена сеть, где всё это будет жить, — в статье про ретранслятор. Что уже умеет продукт — в документации. Спорить о том, каким должен быть обмен ключами, лучше всего в группе: эта статья написана во многом по её вопросам.