From 7bb0418a68a0682c37f2b283175c7e0002856050 Mon Sep 17 00:00:00 2001 From: Yuriy Mayatnikov Date: Mon, 24 Aug 2026 11:13:51 +0300 Subject: [PATCH] =?UTF-8?q?ADR-066:=20=D1=81=D0=B5=D1=80=D0=B2=D0=B5=D1=80?= =?UTF-8?q?=D0=BD=D0=BE=D0=B3=D0=BE=20=C2=AB=D0=BF=D0=B5=D1=80=D1=86=D0=B0?= =?UTF-8?q?=C2=BB=20=D0=B4=D0=BB=D1=8F=20=D0=BA=D0=BB=D1=8E=D1=87=D0=B5?= =?UTF-8?q?=D0=B2=D0=BE=D0=B3=D0=BE=20=D0=B1=D0=BB=D0=BE=D0=B1=D0=B0=20?= =?UTF-8?q?=D0=BD=D0=B5=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Решение перенесено из закрытого PR #1 (ветка отведена до мержа v1, номера ADR там разошлись с main). Ссылки выправлены на актуальные ADR-003/006/013 и на формулировку threat-model «Слабый пароль». Заодно из open-questions.md убран пункт про сторону сообщений: его закрыл ADR-065, но вычеркнуть забыли. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01QR8uS3zGkybzWRW4GEY1oz --- docs/decisions/066-no-server-pepper.md | 25 +++++++++++++++++++++++++ docs/open-questions.md | 4 +--- 2 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 docs/decisions/066-no-server-pepper.md diff --git a/docs/decisions/066-no-server-pepper.md b/docs/decisions/066-no-server-pepper.md new file mode 100644 index 0000000..6ecb21d --- /dev/null +++ b/docs/decisions/066-no-server-pepper.md @@ -0,0 +1,25 @@ +# ADR-066: серверного «перца» для ключевого блоба нет + +Закрывает последний открытый вопрос из `docs/open-questions.md`, поставленный при [ADR-006](006-e2ee-webcrypto.md). + +## Контекст + +Идея: шифровать ключевой блоб ещё раз серверным ключом, который лежит вне базы — например в `/etc/bare/env` рядом с VAPID. Тогда украденный дамп или бэкап сам по себе не даёт материала для оффлайн-перебора паролей. Против оператора это не помогает: у него есть и база, и файл с ключом. + +Вопрос висел открытым с самого начала и мешает считать модель угроз закрытой: пока решения нет, непонятно, чего стоит ждать от следующей версии хранения. + +## Решение + +Перца нет. Блоб хранится так, как описано в [ADR-006](006-e2ee-webcrypto.md) и [ADR-013](013-password-policy-kdf.md): один слой шифрования, ключ выведен из пароля. + +Аргументы: + +- Рядом с базой появляется второй критичный артефакт. [ADR-003](003-sqlite.md) обещает «бэкап — копия одного файла»; перец это обещание ломает. Потеря файла с перцем — невозможность входа с новых устройств сразу для всех, а восстановления паролей в Bare нет by design. Для маленького самохостного инструмента риск потерять ключ при переезде выше риска, который перец закрывает. +- Сценарий «утёк бэкап, но не сервер» уже закрыт [ADR-013](013-password-policy-kdf.md): PBKDF2-HMAC-SHA256 от 600 000 итераций и пароль от 12 символов делают перебор дорогим. Словарный пароль перец тоже не спасёт — при компрометации сервера он утекает вместе с базой. +- Каждый дополнительный слой — код, который нужно аудировать, и оперативная процедура, которую нужно помнить. Простота важнее. + +## Следствия + +- Стойкость блоба в любом сценарии равна стойкости пароля, как и записано в `docs/threat-model.md`, «Слабый пароль». Новых оговорок в модели угроз не появляется. +- Развёртывание остаётся «бинарь плюс файл базы»: ничего, что нельзя потерять, кроме самой базы, у оператора нет. `/etc/bare/env` восстанавливается по `docs/deploy.md`, VAPID-пара перевыпускается. +- Решение обратимо: перец можно добавить позже отдельным ADR — он не меняет формат блоба, только оборачивает его. diff --git a/docs/open-questions.md b/docs/open-questions.md index e74f6e3..9c28610 100644 --- a/docs/open-questions.md +++ b/docs/open-questions.md @@ -2,9 +2,7 @@ Решения по этим пунктам ещё не приняты. Каждое принятое решение уходит в ADR и вычёркивается отсюда. -- Серверный «перец» для ключевого блоба: дополнительное шифрование блоба серверным ключом, хранящимся вне базы. Плюс: дамп базы сам по себе перестаёт быть материалом для оффлайн-перебора. Минус: не защищает от оператора; потеря серверного ключа — невозможность входа с новых устройств для всех. Решение отложено. - Блокировка собеседника и персональные инвайты — если общего инвайт-кода и лимитов (ADR-019, ADR-021) окажется мало. - Подписи сообщений вторым ключом — если потребуется защита от сговора участника комнаты с сервером (ADR-016). -- Выравнивание сообщений по стороне: свои — вправо, чужие — влево, как в обычных мессенджерах. Сейчас лента — общий список с колонкой автора (`docs/ui.md`, «Чат»; `docs/identity/brief.md`, «Компоновка»: сетка `132px 1fr` на десктопе, автор над группой на мобильном) — сторона у сообщения не задана нигде. Пользователям в тесте медленно читать, кто есть кто. Смена — это пересмотр принятого в ADR-024 макета ленты, нужен новый ADR, если решение — делать. Ограничение айдентики: без пузырей, скруглений и теней (`identity/brief.md`) — выравнивание, не bubble-чат. -Закрыто ADR-015…024: регистрация, контакты, лимиты, смена пароля, идентификация устройств, язык интерфейса, айдентика, доверие к ключам, протокол, схема базы, деплой, правила пушей. +Закрыто ADR-015…024: регистрация, контакты, лимиты, смена пароля, идентификация устройств, язык интерфейса, айдентика, доверие к ключам, протокол, схема базы, деплой, правила пушей. ADR-064 — панель над клавиатурой в строке ввода, ADR-065 — сторона сообщений в ленте, ADR-066 — серверный «перец». -- 2.54.0