12 KiB
Безопасность и модель угроз 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, SHA-256 и SHA-1 (SHA-512 — реализация Luma), а также в PLUS-вариантах с канальной привязкой (SCRAM-SHA-512-PLUS > SHA-256-PLUS > SHA-1-PLUS): gs2-заголовок «p=tls-exporter,» (RFC 9266) или «p=tls-server-end-point,» доказывает, что SASL-обмен идёт по тому же TLS-каналу, который видит клиент, и ломает MITM-ретрансляцию. PLUS выбирается только когда сервер рекламирует соответствующий channel-binding тип, иначе — обычный SCRAM; механизм выбирается по рекламе сервера.
-
OMEMO работает в legacy-неймспейсе
eu.siacs.conversations.axolotl(так умеет закреплённая версия MartinOMEMO) и в OMEMO 2 (urn:xmpp:omemo:2, payload AES-256-CBC + HMAC-SHA-256 в конверте SCEurn:xmpp:sce:0). Luma публикует omemo:2 bundle и список устройств, делит Double Ratchet-сессии с legacy-модулем и помечает протокол каждого ключа на экране шифрования. -
Канал шифруется STARTTLS/direct TLS собственным TLS-процессором Luma на OpenSSL 3 (SecureTransport ограничивает потоковый TLS версией 1.2 и не имеет keying exporter): минимум TLS 1.2, максимум TLS 1.3, ALPN «xmpp-client», SNI по домену XMPP. Сертификат проверяется через SecTrust с серверной политикой домена из JID (та же логика CertificateTrustEvaluator). Фактическая версия TLS, шифр и выбранный SASL-механизм (самый стойкий из рекламируемых сервером, с канальной привязкой при её доступности) показываются на экране информации о сервере.
-
Когда 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/getURL от 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-protectioncompleteUntilFirstUserAuthentication. -
Архивные эхо собственных служебных станз (receipts, chat markers, повторно доставленные копии) и собственные сообщения, которые невозможно расшифровать обратно (нет encrypt-to-self ключа или self-сессия устарела), не превращаются в пузыри «Не удалось расшифровать сообщение»: они отбрасываются, как это делают другие клиенты, чтобы не засорять историю фантомами, которых нет в виде сообщений на сервере.
-
Сохранение медиа выполняется только по явному действию пользователя: фото/видео/видеосообщения — в медиатеку, файлы и голосовые — в «Файлы» (Загрузки). Расшифрованное содержимое при этом покидает sandbox приложения.
Известные ограничения
- На 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.