Files
Luma/Docs/SECURITY.md
T
wt 8b86e33186
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
fix undecryptable self-copies by preserving the self-session
- Purge the poisoned self-session only once per account instead of on
  every connect, and rebuild it from the own published bundle when
  missing: deleting it repeatedly broke encrypt-to-self, so archived
  copies of own messages (most visibly in the self-chat) failed with
  "could not decrypt".
- Detect OMEMO 2 (urn:xmpp:omemo:2) payloads, which the pinned
  MartinOMEMO does not implement, and show them as undecryptable
  instead of empty plaintext bubbles.
- Guard both behaviours in verify.sh and document the namespace
  limitation in SECURITY.md.
2026-08-30 00:32:40 +07:00

9.8 KiB
Raw Blame History

Безопасность и модель угроз 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); механизм выбирается по рекламе сервера.
  • OMEMO работает в legacy-неймспейсе eu.siacs.conversations.axolotl (так умеет закреплённая версия MartinOMEMO); сообщения OMEMO 2 (urn:xmpp:omemo:2) показываются как нерасшифрованные, а не пустые.
  • Канал шифруется 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.