Как устроен Solmu
Коротко и по фактам: из чего состоит Solmu, как шифруется переписка и звонки, как работает вход по паролю и что видит сервер.
Чем Solmu не является
- Не P2P-сеть. Телефоны не соединяются напрямую и не ищут друг друга по распределённой таблице: сообщения доставляет узел — сервер, который держит владелец. Так собеседники не видят IP-адреса друг друга, а видео работает в больших комнатах.
- Не блокчейн и без криптовалют.
- Не один центральный сервер. Узлов может быть сколько угодно, каждый на своём домене; аккаунт выглядит как
имя@домен.
Узел
Узел — это набор контейнеров Docker на VPS: сервер аккаунтов и доставки (Rust), база PostgreSQL, медиасервер звонков, TURN и HTTPS-шлюз. Ставится одной командой (install.sh), каждый день делает резервную копию. Узел хранит аккаунты, доставляет зашифрованные сообщения и держит зашифрованные файлы, пока их не скачают получатели.
Связь между узлами (федерация) — в работе: у каждого узла уже есть ключ подписи Ed25519, опубликованный в /.well-known/solmu/server.
Шифрование переписки — MLS
- Личные разговоры, группы и каналы серверов — группы MLS (Messaging Layer Security, RFC 9420). Ключи создаются и хранятся только на устройствах.
- У каждого устройства свой ключ; его сертификат подписан ключом аккаунта. Новое устройство собеседника видно в разговоре («новое устройство у …»).
- MLS даёт прямую секретность и восстановление после компрометации: ключи меняются с каждой сменой состава, утечка старого ключа не открывает новую переписку.
- Файлы, голосовые и фото шифруются на устройстве до отправки; узел хранит только шифротекст.
Звонки — SFrame
Голос и видео идут через медиасервер узла (до 25 человек в комнате), но шифруются на устройствах SFrame: у каждой дорожки свой ключ, выведенный из текущего ключа группы MLS. Медиасервер пересылает кадры, не имея ключей. Владелец канала может создать канал «без шифрования звонков» — это видно в его настройках.
Вход по паролю — OPRF + Argon2id
- Пароль не уходит на сервер. Устройство «ослепляет» его (OPRF, RFC 9497, ristretto255), узел примешивает свой секрет, не видя пароля, и возвращает «перец».
- Ключ аккаунта = Argon2id(перец + пароль), соль — из имени (19 МиБ памяти, 2 прохода). Вычисляется на устройстве.
- Перебрать пароль по украденной базе нельзя без секрета узла, а онлайн — мешает лимит: 10 попыток, дальше одна в 6 минут.
- Вместо пароля можно пользоваться секретной фразой — случайным ключом, который нигде не хранится, кроме ваших устройств.
Уведомления
Уведомление — пустой сигнал «проснись» без текста и без имени отправителя (web push или UnifiedPush/ntfy на Android, сервер ntfy можно держать у себя). Устройство само забирает и расшифровывает новое. Свёрнутое приложение без звонка не держит соединений и почти не тратит батарею.
Что видит узел
Содержимое — нет. Видит то же, что любой сервер переписки: имена аккаунтов, кто в каких разговорах, когда и какого размера сообщения, IP-адреса подключений. Подробно — «Что узел хранит о вас».
Приложения и код
Браузер (WebAssembly), Android, Windows, Linux — общий код на Rust (шифрование, протокол). Лицензия — AGPL-3.0.