ADR-013: PBKDF2-HMAC-SHA256 ≥600k итераций (цель 1M), параметры KDF версионируются рядом с блобом; пароль от 12 символов, длина важнее состава. ADR-014: парольная фраза экспорта отменена, ключ экспорта — HKDF от 32-байтового секрета аккаунта из ключевого блоба; архив .bare криптографически бесполезен вне аккаунта-владельца. Перекрёстно обновлены ADR-006, ADR-010, architecture, threat-model; в открытые вопросы добавлен серверный «перец» для блоба. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SW4ZXtKn5NjX8NH3Lhm2ND
4.0 KiB
4.0 KiB
ADR-014: Экспорт привязан к аккаунту криптографически
Заменяет часть ADR-010: парольной фразы экспорта больше нет. Принцип «перенос истории — только ручной экспорт/импорт» в силе.
Контекст
Экспортный файл, зашифрованный отдельной парольной фразой, переносим кем угодно: файл плюс фраза — и чужой клиент импортирует чужую историю. Требование: архив должен быть бесполезен вне аккаунта-владельца. Проверка на уровне «клиент сверяет ник» неприемлема — клиент открытый, такая проверка тривиально выпиливается. Запрет должен быть криптографическим.
Решение
- В ключевом блобе аккаунта, рядом с приватным ECDH-ключом, хранится случайный 32-байтовый секрет аккаунта. Он генерируется при регистрации, доступен любому устройству, вошедшему в аккаунт, и никогда не существует в открытом виде вне клиента.
- Ключ конкретного экспорта: HKDF(секрет аккаунта, salt, info="bare-export-v1"), salt случайный на каждый экспорт. Шифрование — AES-GCM. Всё на WebCrypto: HKDF там есть нативно.
- Отдельной парольной фразы для экспорта больше нет — сущность удалена.
- Формат
.bare: заголовок открытым текстом — magic, версия формата, salt, отпечаток публичного ключа владельца; далее шифротекст. Ник владельца в заголовок не пишется — лишняя утечка. - Импорт: клиент сверяет отпечаток со своим; при несовпадении показывает «архив создан другим аккаунтом» и не пытается расшифровать. Сверка — только UX-вежливость: реальная защита в том, что у чужого клиента нет секрета аккаунта и расшифровка невозможна в принципе.
- Импорт по-прежнему идемпотентный merge по messageId.
Следствия
- Архив открывается только устройствами, вошедшими в аккаунт-владелец. Потеря пароля — потеря ключей — архив нечитаем навсегда. Это последовательное продолжение принципа «забыл — значит забыл», а не новое ограничение.
- Смена ключевой пары (например, перерегистрация под тем же ником) делает старые архивы нечитаемыми: секрет аккаунта другой.
- Привязка защищает файл, а не содержимое от самого владельца: скриншоты и модифицированный клиент никуда не деваются, а у собеседников есть собственные копии тех же сообщений. «Аналоговая дыра» криптографией не закрывается — зафиксировано в threat-model.
- Побочный плюс: исключено загрязнение чужого клиента историей чатов, в которых пользователь не участник.