Здесь написано, чем и как защищены ваши данные, и где защита заканчивается. Мы не обещаем «абсолютную безопасность»: ниже есть и слабые места, и то, чего пока нет. Независимого аудита у NiosMess ещё не было, поэтому не принимайте на веру ничего из этой страницы. Код клиента, где работает шифрование, открыт: github.com/sh20fk/NiosMess. Проверяйте там, где это возможно (раздел 9).
1. Три уровня защиты
В NiosMess сообщения защищены по-разному, и это важно понимать до того, как вы напишете что-то личное.
| Что | Как защищено | Может ли сервер прочитать |
|---|---|---|
| Секретные чаты | Сквозное шифрование (E2EE) на ваших устройствах: Double Ratchet, X25519, AES-256-GCM | Нет, на сервере только шифротекст |
| Обычные чаты, группы, каналы, комментарии | TLS при передаче, на сервере хранятся зашифрованными AES-256-GCM | Технически да: ключ хранится на сервере |
| Звонки | Аудио шифруется на устройствах AES-256-GCM, ключи согласуются между участниками | Нет, сервер пересылает шифрованные пакеты |
| Запросы к ИИ | TLS при передаче, дальше обрабатываются внешним провайдером | Да, и провайдер тоже (см. раздел 7) |
Если вам нужна приватность от самого сервера, пользуйтесь секретным чатом. Веб-версия секретные чаты не поддерживает: в ней работают только обычные чаты.
2. Соединение с сервером
Всё общение клиента с сервером идёт по TLS. Сайт и API принимают только TLS 1.2 и TLS 1.3 (TLS 1.1 и старше отключены, это проверено рукопожатием). Набор шифров ограничен современными: ECDHE с AES-GCM или ChaCha20-Poly1305, а в TLS 1.3 мы получаем AES-256-GCM. Сертификат выдаёт Let's Encrypt.
Поверх TLS в WebSocket-соединении работает ещё один слой. При подключении сервер выдаёт случайный 256-битный ключ этого соединения, и последующие кадры шифруются AES-256-GCM. Каждый запрос несёт уникальный идентификатор, а сервер отбрасывает повторы, чтобы пойманный запрос нельзя было отправить второй раз. Этот слой не заменяет TLS: ключ приходит по тому же каналу, поэтому от атакующего, который уже расшифровал TLS, он не защищает. Это дополнительная защита, а не отдельная граница безопасности.
3. Секретные чаты
Ключи
На каждом устройстве создаются две пары долговременных ключей: X25519 для согласования общего секрета и Ed25519 для подписи. Приватные части хранятся в защищённом хранилище операционной системы и не покидают устройство. На сервер уходят только публичные ключи.
Рукопожатие
- Инициатор берёт публичный X25519-ключ собеседника и считает общий секрет с собственным долговременным ключом. Из него через HKDF-SHA256 выводится корневой ключ и первая цепочка.
- Инициатор создаёт одноразовый (эфемерный) X25519-ключ и смешивает его с долговременным ключом собеседника, получая цепочку для отправки.
- Собеседник отвечает сообщением HELO со своим эфемерным публичным ключом. Оно подписано его ключом Ed25519, и инициатор проверяет подпись.
- С этого момента чат считается защищённым, а публичный Ed25519-ключ собеседника запоминается.
Сообщения
Для каждого сообщения используется алгоритм Double Ratchet:
- обмен ключами Диффи-Хеллмана на X25519 при каждой смене направления переписки;
- вывод ключей через HKDF-SHA256 (отдельные метки для корневого ключа и для цепочек);
- каждое сообщение шифруется собственным ключом AES-256-GCM со случайным 96-битным nonce, заголовок сообщения (публичный ключ шага и счётчики) включён в аутентифицируемые данные;
- если сообщения приходят не по порядку, ключи пропущенных хранятся, но не больше 100 подряд.
Файлы в секретных чатах шифруются на устройстве отдельным случайным ключом AES-256-GCM до загрузки. Ключ файла передаётся только внутри зашифрованного сообщения, на сервере лежит один шифротекст.
Защита от подмены ключей
Публичные ключи собеседника вам выдаёт сервер, поэтому честный сервер здесь нужен. Нечестный мог бы подставить свои ключи и читать переписку. От этого защищают два механизма:
- Сверка слов. Из общего секрета пары вычисляется 12 слов с цветами (по 64 слова и 8 цветов на позицию, около 108 бит). Если вы и собеседник видите одинаковые слова, между вами нет посредника. Сверяйте их голосом или при встрече, а не в том же чате.
- Запоминание ключа. После того как вы подтвердили собеседника, его ключ Ed25519 закрепляется. Если ключ позже изменится, чат помечается как скомпрометированный, и вы увидите предупреждение.
Что видит сервер
Содержимое не видит. Видны метаданные: кто с кем переписывается, когда, размеры сообщений и файлов, ваш IP-адрес, а также заголовки Double Ratchet (публичный ключ шага и номера сообщений).
4. Обычные чаты, группы и каналы
Это привычная схема «клиент — сервер»: сообщение приходит на сервер по TLS и записывается в базу данных. Текст и вложения шифруются AES-256-GCM со случайным 96-битным вектором инициализации, для каждого сообщения и файла отдельно. Ключ шифрования хранится в настройках сервера, и мы умеем менять его, не теряя старые данные.
Что это даёт: если украдут диск, копию базы или резервную копию без ключа, прочитать переписку не получится. Чего это не даёт: защиты от того, кто получил доступ к работающему серверу, и от самого Оператора. Ключ на сервере, поэтому технически мы имеем доступ к такой переписке. Мы не читаем её без причины: только по жалобе на нарушение, по требованию закона или чтобы починить сбой. Это же записано в согласии на обработку данных.
5. Звонки
Звук (кодек Opus) передаётся через наш сервер-ретранслятор, по QUIC или, если он недоступен, по WebSocket. Сервер только пересылает пакеты. Каждый пакет шифруется на устройстве AES-256-GCM со случайным nonce.
- У каждого участника есть собственный случайный 256-битный ключ отправки.
- Участники обмениваются эфемерными ключами ECDH на кривой P-256. Из общего секрета пары получается ключ, которым шифруется ключ отправки (AES-256-GCM), и именно в таком виде он проходит через сервер.
- Резервный ключ звонка выводится из общего секрета пары (X25519, HKDF-SHA256) и номера звонка.
Ключи участников тоже проходят через сервер, поэтому в звонке есть сверка эмодзи: 64 символа, и по ним можно убедиться, что вы говорите именно с этим человеком, а не с посредником. Сверяйтесь голосом.
6. Аккаунт и Nios ID
- Пароль. На сервере хранится только хэш bcrypt с индивидуальной солью. Сам пароль не сохраняется.
- Сессии. После входа выдаётся случайный токен (48 байт, около 380 бит). В базе лежит только его хэш SHA-256, поэтому утечка базы не даёт готовых токенов. У каждой сессии есть срок действия, а список ваших сессий (устройство, IP, время) можно посмотреть в приложении.
- Подтверждение почты и двухфакторный вход. Одноразовые коды приходят на почту и действуют ограниченное время (при регистрации 15 минут, при входе 10 минут).
- Nios ID. Единый аккаунт для сервисов Nios. Вход на другом устройстве или в стороннем приложении подтверждается кодом устройства, без передачи пароля этому приложению.
- Защита от перебора. Вход и регистрация ограничены по числу попыток.
7. ИИ и песочница для кода
ИИ-помощник (@ai, NiosAI, перевод и улучшение текста) работает не в режиме E2EE. Текст запроса и недавний контекст отправляются провайдеру polza.ai и выбранной модели. Не отправляйте ИИ то, что не хотите показывать третьим лицам. История диалога с NiosAI хранится только в памяти сервера и пропадает при его перезапуске.
Подписчики Nios+ могут просить ИИ запускать программы на Python. Код выполняется в отдельной изолированной среде на нашем сервере:
- одноразовый процесс под временным системным пользователем, без доступа к сети;
- файлы NiosMess и базы данных для него недоступны;
- лимиты: память, 20 секунд работы, 4000 символов вывода и не больше двух запусков одновременно.
Сам сервер NiosMess работает не от root, с отключённым повышением привилегий и защитой системных каталогов от записи.
8. Чего у нас нет
Чтобы вы знали, на что не рассчитывать:
- Нет независимого аудита. Криптографические примитивы мы берём из готовых библиотек (пакет cryptography для Dart и для Python), но сам протокол секретных чатов собран и реализован нами, и его не проверяли сторонние специалисты.
- Протокол проще, чем у Signal. Мы не используем заранее опубликованные одноразовые ключи (prekeys). Корневой ключ секретного чата строится из долговременных ключей и одного эфемерного ключа. Если у атакующего оказались и записанный трафик, и долговременный приватный ключ устройства, он может прочитать самые первые сообщения чата. После нескольких смен направления переписки защита восстанавливается.
- Серверный код закрыт. Код клиента, включая шифрование секретных чатов и звонков, открыт на GitHub. Но то, что обычные чаты шифруются на сервере и что сервер не логирует лишнего, по исходникам проверить нельзя: код сервера мы не публикуем. В репозитории пока нет лицензии, то есть код открыт для чтения, но не для повторного использования.
- Метаданные видны серверу во всех типах чатов (кто, кому, когда, сколько).
- Обычные чаты не сквозные. Это осознанный компромисс ради поиска, групп, каналов и работы с нескольких устройств.
- Заголовка HSTS на сайте пока нет. Мы собираемся его включить.
- Потеря устройства. Ключи секретных чатов хранятся на устройстве, поэтому такие переписки не восстановятся на новом.
9. Как проверить и сообщить о проблеме
- Прочитайте код клиента: github.com/sh20fk/NiosMess. Шифрование секретных чатов лежит в
pulse_flutter/lib/services/(double_ratchet_service.dart,e2ee_service.dart), шифрование файлов вcore/utils/e2ee_file_crypto.dart, звонки вservices/calls/. - Сверяйте слова в секретных чатах и эмодзи в звонках. Это единственная проверка, которая защищает даже от нечестного сервера.
- Можно проверить параметры TLS нашего сайта любым сканером, например SSL Labs, и убедиться в версиях протокола и шифрах из раздела 2.
- Нашли уязвимость или ошибку в этом описании? Напишите на privacy@ni-os.ru с темой «Безопасность». Мы читаем такие письма и отвечаем на них.
Что именно делается с вашими данными в юридическом смысле, описано в политике конфиденциальности и согласии на обработку данных.