Files
Luma/Docs/SECURITY.md
T
wt 0d78e02d2b
iOS CI / Build and Test SwiftUI App (push) Canceled after 0s
Build Unsigned iOS and macOS Apps / Build Unsigned iOS IPA (push) Canceled after 0s
Build Unsigned iOS and macOS Apps / Build macOS ZIP (push) Canceled after 0s
#8 add app lock with passcode and biometric unlock
- Gate every layer behind AppLockView when the lock is enabled and
  lock on launch and on backgrounding; the passcode lives only in the
  Keychain (AppLockVault) and the enable state defaults to off.
- Add the lock section to Settings: enable/setup, change passcode and
  disable all require the current passcode via a shared passcode
  sheet; Face ID / Touch ID unlock prompts automatically and can be
  toggled with passcode confirmation.
- Add NSFaceIDUsageDescription to both app targets, cover the passcode
  policy with tests, guard the feature in verify.sh and document it in
  SECURITY.md.
2026-08-29 05:59:55 +07:00

91 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Безопасность и модель угроз MVP
- Пароль XMPP сохраняется в Keychain и не попадает в `UserDefaults` или
локальное хранилище истории.
- Проверка сертификата не отключается. Ручной host меняет маршрут подключения,
но XMPP domain/JID остаётся исходной идентичностью.
- TLS trust оценивается системным Apple Security framework как сертификат
сервера (`SecPolicyCreateSSL(true, ...)`) для домена из JID; hostname и цепочка
доверия обязательны даже при ручном адресе подключения.
- Приложение можно заблокировать паролем (хранится в Keychain, выключено по
умолчанию): блокировка срабатывает при запуске и при уходе в фон, а
разблокировка возможна по Face ID/Touch ID.
- Пароль для SCRAM нормализуется по RFC 4013 (SASLprep), чтобы совпадать с
серверной нормализацией; для PLAIN пароль отправляется как введён.
- SCRAM доступен в вариантах SHA-512 (предпочтительный, реализация Luma),
SHA-256 и SHA-1 (Martin); механизм выбирается по рекламе сервера.
- Канал шифруется STARTTLS/direct TLS через SecureTransport с уровнем
`negotiatedSSL` (исключает TLS ниже 1.2) и ALPN «xmpp-client»; на системах
с поддержкой SecureTransport договаривается TLS 1.3.
- Когда OMEMO включено глобально или для конкретного чата, исходящие сообщения
не откатываются на plaintext при ошибке: ошибка показывается пользователю.
- Пользователь может осознанно отключить OMEMO глобально или для отдельного
чата. В этом режиме сервер, MAM-хранилище и участники TLS-терминации видят текст.
- OMEMO доступно и для XEP-0045, но только в неанонимной комнате: клиенту нужны
реальные bare JID участников, чтобы зашифровать ключ для каждого устройства и
расшифровать входящее сообщение от правильной Signal identity. Luma проверяет
режим комнаты, собирает online occupants и доступные списки member/admin/owner,
а при скрытом JID или отсутствии устройств отменяет отправку без plaintext
fallback. Новые комнаты Luma создаются members-only и persistent с
`muc#roomconfig_whois=anyone`.
- Первый увиденный ключ получает доверие TOFU. Изменившийся ключ становится
undecided и требует ручной проверки отпечатка.
- При включённом OMEMO вложения шифруются до загрузки, а URL с ключом находится
внутри OMEMO payload. При выключенном OMEMO файл хранится на HTTP Upload
сервисе в исходном виде; ссылка и метаданные также не имеют E2EE.
- Даже для зашифрованного blob HTTP Upload сервис видит размер и транспортное
имя файла; у voice/video-note это имя содержит тип и округлённую длительность.
- Клиент принимает только HTTPS `put`/`get` URL от XEP-0363 компонента и не
понижает транспорт загрузки до обычного HTTP.
- В OMEMO-исправлении новое тело зашифровано, но стандартный XEP-0308
`<replace>` остаётся метаданными stanza: сервер видит id исправляемого
сообщения, но не новый текст.
- Ответ содержит id исходного сообщения и JID его автора. В зависимости от
поведения OMEMO-библиотеки и клиента эти XEP-0461 метаданные могут быть видны
серверу, даже когда текст ответа зашифрован.
- XEP-0424 не гарантирует стирание: retract может быть проигнорирован сервером
или клиентом, а получатель мог сохранить исходный текст. Fallback retraction
намеренно общий и никогда не повторяет удаляемое содержимое.
- Для inline-preview расшифрованные фото, видео, музыка и голосовые временно
записываются в sandbox `tmp`; Luma очищает известные preview-файлы при смене
аккаунта, а ОС может удалить их раньше как временные данные.
- Выбранные для пакетной отправки файлы временно копируются в `tmp` для экрана
предпросмотра и удаляются при отмене либо после завершения отправки.
- Core Location вызывается только из экрана явной отправки точки. Выбранные
координаты становятся содержимым сообщения и защищены OMEMO лишь тогда, когда
шифрование включено для этого чата; при plaintext сервер и MAM видят точку.
- Аудио/видео звонка шифруются WebRTC DTLS-SRTP между конечными клиентами.
Это не OMEMO: XMPP-сервер видит Jingle-сигналинг и адрес собеседника, а
STUN/TURN-сервис видит сетевые адреса и объём трафика. TURN ретранслирует уже
зашифрованный медиапоток. Если Prosody не публикует собственный сервис через
XEP-0215, резервный публичный STUN получает запрос на определение адреса.
- На iOS файл OMEMO-состояния и база локальной истории (SwiftData
`.store`) получают data-protection `completeUntilFirstUserAuthentication`.
## Известные ограничения
- На macOS история (SwiftData SQLite в Application Support) и OMEMO state
лежат в sandbox без дополнительного SQLCipher-слоя; защиту обеспечивает
учётная запись и FileVault пользователя. Для повышенной модели угроз нужна
зашифрованная база.
- Локальная история содержит уже расшифрованные тексты, как и у большинства
клиентов. Полное удаление требует выхода с опцией удаления истории.
- «Удалить у меня» удаляет запись только из локального SwiftData-хранилища
этого устройства и запоминает id против повторной MAM-загрузки; оно не
удаляет серверный архив, другие собственные устройства или копию собеседника.
- Глобальная политика шифрования хранится в `UserDefaults` отдельно для каждого
JID, а переопределение чата — в локальном SwiftData-хранилище. Эти значения
не являются секретами, но прямо влияют на конфиденциальность следующей
отправки.
- Аватары XEP-0084/vCard не шифруются OMEMO. Их видимость определяется
настройками PEP и roster на сервере; не используйте аватар как секретное фото.
- Используемая реализация MartinOMEMO поддерживает распространённый legacy
namespace. Она не должна называться полной реализацией новой редакции
XEP-0384 без отдельного interoperability test suite.
- В открытой или плохо настроенной сторонней MUC списки офлайн-участников могут
быть недоступны. Для предсказуемого группового OMEMO используйте members-only
комнату, разрешающую участникам получать affiliation lists; иначе отключите
OMEMO именно для этой комнаты осознанно.
- Jailbreak/root, скомпрометированный endpoint и запись экрана находятся вне
модели угроз MVP.