Безопасность PlainApp: подробный разбор

Как PlainApp защищает ваши данные в локальной сети Wi-Fi — с доказательствами из открытого исходного кода.

Почему безопасность локальной сети важна?

Когда вы управляете телефоном на Android через браузер на ПК, ваши SMS, фотографии, контакты и файлы передаются по сети Wi-Fi. Большинство приложений отправляют всё это в виде открытого текста. Любой, кто находится в той же сети, может это увидеть.

Вы можете подумать: «Это мой домашний Wi-Fi, кто будет подслушивать?» Но задумайтесь:

  • Публичный Wi-Fi — Кафе, аэропорты, гостиницы — любой поблизости может перехватить трафик
  • Общие сети — Соседи по комнате, гости или скомпрометированные IoT-устройства
  • Уязвимости роутера — Устаревшая прошивка с известными эксплойтами

Если приложение отправляет ваши SMS в виде открытого текста по HTTP, любой с бесплатным инструментом вроде Wireshark может их прочитать. Это не теория — это элементарно просто.

Именно так работает большинство приложений для управления телефоном. Откройте Chrome DevTools (F12 → вкладка Network) при использовании их веб-интерфейса, и вы увидите каждый API-запрос в открытом JSON — тексты SMS, пути к файлам, имена контактов и всё остальное.

Чем PlainApp отличается

PlainApp применяет несколько уровней шифрования и аутентификации. Вот что делает каждый уровень простым языком.

Security Architecture Comparison
1

GraphQL API — запрашивайте только то, что нужно

Большинство приложений используют устаревшие REST API: один URL на ресурс, возвращающий всё подряд, нужно вам это или нет. PlainApp использует GraphQL — современный подход, при котором браузер запрашивает ровно те данные, которые ему нужны, и ничего лишнего.

Почему это важно:

  • Меньше данных раскрывается — Если вам нужно только имя файла — только оно и передаётся
  • Одна точка входа — Вместо десятков URL используется единственный /graphql, что сокращает поверхность атаки
  • Права на уровне запроса — Каждый запрос проверяет свои права доступа (например, чтение SMS требует разрешения READ_SMS даже после входа в систему)
2

Зашифрованные API-вызовы (XChaCha20-Poly1305)

Это главное отличие PlainApp от большинства конкурентов.

Каждый API-запрос и ответ — включая HTTP и WebSocket трафик — шифруется XChaCha20-Poly1305, как в HTTP, так и в HTTPS режиме. Это современный алгоритм шифрования AEAD, используемый WireGuard VPN, Cloudflare и библиотекой Google Tink.

Простыми словами:

  1. 1Ваш браузер формирует запрос (например, «покажи мои SMS»)
  2. 2Добавляет временную метку и случайный nonce для защиты от повторного воспроизведения
  3. 3Шифрует весь payload в нечитаемые бинарные данные с помощью XChaCha20-Poly1305
  4. 4Зашифрованные бинарные данные передаются по сети — без base64, без JSON, чистый бинарный формат
  5. 5Только ваш телефон может расшифровать и проверить их

Даже если кто-то перехватит трафик, он увидит лишь бессмысленные двоичные данные, а не читаемый JSON.

Encrypted API Flow

О шифровании:

  • 256-битный ключ (чрезвычайно надёжный)
  • 192-битный nonce (защищает от определённых типов атак, которым подвержены другие шифры)
  • Встроенное обнаружение подмены — если кто-то изменит данные при передаче, расшифровка не пройдёт
  • На стороне Android: используется Google Tink
  • На стороне веба: используется @noble/ciphers (тщательно проверенная JavaScript-библиотека для криптографии)
3

Цифровые подписи (Ed25519) — межустройственная связь

Когда два устройства PlainApp обмениваются данными (например, чат телефон-телефон), одного шифрования недостаточно — каждое устройство должно убедиться, что сообщение действительно пришло от другого устройства и не было подделано.

временная метка

Принимающее устройство проверяет подпись по открытому ключу отправителя и отклоняет запросы с временной меткой старше 5 минут. Это предотвращает как подделку, так и атаки повторного воспроизведения.

4

Безопасное сопряжение устройств (обмен ключами ECDH)

Когда два устройства PlainApp сопрягаются друг с другом (например, два телефона), им нужен общий ключ шифрования. Но отправка ключа по сети сводила бы всю защиту на нет.

PlainApp решает эту задачу с помощью обмена ключами ECDH (Elliptic Curve Diffie-Hellman) — той же математики, что используется в TLS, Apple Secure Enclave и WebAuthn:

  1. 1Каждое устройство генерирует пару ключей (открытый + закрытый)
  2. 2Устройства обмениваются только открытыми ключами
  3. 3Каждое устройство комбинирует свой закрытый ключ с открытым ключом другого
  4. 4Оба получают одинаковый общий секрет — при этом он ни разу не передаётся по сети
ECDH Pairing Flow
5

Зашифрованные URL — скрытие путей к файлам

Вот деталь, которую большинство людей не замечают: URL-адреса тоже раскрывают информацию.

Когда вы скачиваете файл, URL сообщает серверу, какой файл вам нужен. Во многих приложениях URL выглядит так:

/fs?path=/sdcard/DCIM/Camera/photo_2024.jpg

Любой, кто перехватывает трафик (или просматривает историю браузера), может точно увидеть, к какому файлу вы обращались, и структуру папок вашего телефона.

PlainApp шифрует путь к файлу в URL:

/fs?id=AxK9f2mQ7vR3xP8nWz...

Параметр id — это путь к файлу, зашифрованный алгоритмом XChaCha20-Poly1305 с помощью случайного ключа, называемого URL Token. По умолчанию этот ключ постоянный и сохраняется после перезапуска приложения, поэтому ранее отправленные ссылки продолжают работать. Без ключа никто не сможет угадать реальный путь, перечислить ваши файлы или сформировать URL для скачивания.

URL Encryption Comparison
6

HTTPS с самоподписанными сертификатами

PlainApp генерирует самоподписанный TLS-сертификат на вашем телефоне. Это создаёт зашифрованный HTTPS-туннель — ту же технологию, которую используют банки и веб-сайты.

Сертификат использует:

  • ECDSA с кривой P-256 (как у крупнейших сайтов)
  • Подпись SHA256
  • Хранится в закрытом каталоге приложения

В сочетании с шифрованием XChaCha20 на уровне приложения это даёт два независимых уровня защиты. Взлом одного бесполезен без взлома другого.

7

Защита входа в систему

PlainApp ограничивает количество попыток входа для защиты от подбора пароля:

  • 5 попыток за 60 секунд на один IP-адрес
  • После этого подключения отклоняются
  • Устаревшие записи об ограничениях автоматически очищаются

HTTP и HTTPS: честное сравнение

PlainApp поддерживает режимы HTTP и HTTPS. Вот честная разница между ними:

Режим HTTPРежим HTTPS
URL-пути к файламЗашифрованы (XChaCha20)Зашифрованы (XChaCha20)
API-вызовыЗашифрованы (XChaCha20)Зашифрованы (XChaCha20 + TLS)
Скачивание файловНе зашифровано при передачеЗашифровано через TLS
Для кого подходитДля новичков (без предупреждения SSL в браузере)Для пользователей, заботящихся о конфиденциальности

В обоих режимах API-вызовы шифруются алгоритмом XChaCha20-Poly1305 — ваши SMS, контакты и другие данные всегда зашифрованы, независимо от HTTP или HTTPS.

Режим HTTP существует потому, что самоподписанные сертификаты вызывают предупреждение в браузере («Ваше подключение не является защищённым»). Для менее технически подкованных пользователей это предупреждение выглядит пугающе. HTTP позволяет избежать этого неудобства.

Однако в режиме HTTP передача файлов не шифруется. Если вы находитесь в общей или публичной сети, всегда используйте HTTPS.

Рекомендация: используйте HTTPS при любой возможности. Примите предупреждение браузера о самоподписанном сертификате — это нормально и ожидаемо для приложения в локальной сети.

8

Безопасность цепочки поставок — меньше зависимостей, меньше рисков

Угроза безопасности, о которой многие пользователи не задумываются: атаки на цепочку поставок. Когда приложение использует сотни сторонних библиотек, любая из них может быть скомпрометирована — внедряя вредоносный код, который крадёт данные, майнит криптовалюту или открывает бэкдоры.

Это особенно опасно в экосистеме JavaScript. За последние годы популярные npm-пакеты, такие как event-stream, ua-parser-js и colors, были захвачены для внедрения вредоносного кода в миллионы проектов. Если веб-интерфейс приложения для управления телефоном подключает сотни JS-пакетов, каждый из них — потенциальный вектор атаки.

PlainApp придерживается осознанного подхода: использовать как можно меньше зависимостей и писать собственный код, когда это оправданно.

Android-приложение (plain-app)

  • Без фреймворков внедрения зависимостей (без Hilt, без Dagger) — используются простые синглтоны
  • Криптография обеспечивается только 3 проверенными библиотеками: Google Tink, Bouncy Castle и встроенным Java Cryptography Extension
  • Сервер работает на Ktor (официальный Kotlin-фреймворк от JetBrains) — никаких малоизвестных сторонних серверных библиотек

Веб-интерфейс (plain-desktop)

Всего 28 runtime-зависимости — значительно меньше, чем у типичных веб-приложений. Ряд функций, которые обычно требуют npm-пакетов, реализован с нуля:

ФункцияОбычное приложениеPlainApp
Звуки уведомленийhowler.js / tone.jsСобственный синтезатор на Web Audio API
Генерация UUIDnpm-пакет uuidСобственная реализация RFC 4122
Загрузка файловuppy / axiosСобственная порционная загрузка с очередью
WebRTC-видеоTwilio / Daily.co SDKСобственный код PeerConnection
HTTP-клиентaxios / kyВстроенный браузерный fetch

Криптография на стороне веба использует @noble/ciphers — тщательно проверенную JavaScript-библиотеку для криптографии без зависимостей — вместо больших и громоздких альтернатив.

Почему это важно

Каждая добавленная зависимость — это код, который вы не контролируете. Подход PlainApp означает:

  • Меньше мест для сокрытия вредоносного кода
  • Меньшая поверхность атаки
  • Проще провести аудит (весь код открыт)
  • Нет риска из-за заброшенных или захваченных npm-пакетов

Типичные ошибки конкурентов

Речь не о конкретных приложениях. Речь о распространённых паттернах в этой категории:

Аспект безопасностиPlainAppТипично для конкурентов
API-трафикЗашифрован (XChaCha20) в режимах HTTP и HTTPSОткрытый JSON по HTTP
WebSocket трафикЗашифрованные бинарные фреймы (XChaCha20)Текстовый JSON или нет WebSocket
Обработка токена аутентификацииИспользуется как ключ шифрования, никогда в заголовкахОтправляется в HTTP-заголовках (легко перехватить)
URL файловЗашифрованные идентификаторы путейПути в открытом виде
Обмен ключамиECDH (P-256)Отсутствует
Подпись запросовEd25519 (только между устройствами)Нет
Защита от повторного воспроизведения30 с + nonce (Web); 5 мин + подпись (устройства)Нет
Защита входаОграничение попыток + двухфакторное подтверждениеБез ограничений
Маршрутизация данных100% локально, без облакаНекоторые передают через облако
ЗависимостиМинимум проверенных библиотекСотни npm-пакетов
Исходный кодОткрытый (GPL-3.0)В основном закрытый

Самый простой способ проверить любое приложение: откройте Chrome DevTools (F12) → вкладку Network во время работы с приложением. Если вы можете прочитать ответы API как JSON — шифрования нет.

Проверьте сами

PlainApp полностью открыт. Каждое утверждение в этой статье можно проверить в коде.

github.com/plainhub/plain-app (GPL-3.0)
Проверяемая целостность релиза

Автоматизированный, отслеживаемый и устойчивый к подмене конвейер релиза

Все установочные пакеты автоматически собираются инфраструктурой GitHub и F-Droid. Сборки отслеживаемы, безопасны и не содержат следов ручного вмешательства. PlainApp — одно из немногих Android-приложений, где есть и проверяемые сборки (SLSA), и релизы, проверенные VirusTotal.

Автоматические сборки на GitHub и F-Droid

Релизные артефакты создаются CI-конвейерами, а не вручную локально. Каждый артефакт можно связать с исходными коммитами и воспроизводимыми workflow сборки.

SLSA Provenance (Уровень 3) + проверка VirusTotal

Каждый релиз включает attestations SLSA provenance и результаты VirusTotal, что делает цепочку поставок аудируемой и позволяет пользователям проверять целостность перед установкой.

Часто задаваемые вопросы

Правда ли PlainApp шифрует данные в режиме HTTP?

Да. Все API-вызовы (SMS, контакты, список файлов и т.д.) шифруются алгоритмом XChaCha20-Poly1305 как в режиме HTTP, так и в HTTPS. В режиме HTTP не шифруется только скачивание файлов. Для полной защиты используйте HTTPS.

Почему браузер показывает предупреждение о безопасности?

PlainApp использует самоподписанный TLS-сертификат для шифрования. Поскольку он не выдан публичным центром сертификации, браузер показывает предупреждение. Это нормально и ожидаемо для приложения в локальной сети. Нажмите «Дополнительные» и «Перейти на сайт», чтобы продолжить.

Может ли кто-то в той же сети Wi-Fi увидеть мои данные?

С PlainApp — нет. API-вызовы зашифрованы алгоритмом XChaCha20-Poly1305, а в режиме HTTPS передача файлов также защищена TLS. С большинством конкурентов — да, их API-вызовы отправляются открытым текстом в формате JSON.

Как PlainApp соотносится с VPN?

VPN шифрует трафик между вашим устройством и VPN-сервером. PlainApp шифрует трафик между телефоном и браузером в локальной сети. Они решают разные задачи — PlainApp защищает локальное управление устройством, а VPN — интернет-трафик.

Код действительно открытый?

Да. PlainApp распространяется по лицензии GPL-3.0. Полный исходный код доступен на github.com/plainhub/plain-app. Вы можете изучить каждую реализацию шифрования, собрать из исходников или внести свой вклад.

Верните себе контроль над своим телефоном.

Никаких облачных посредников. Никаких ежемесячных платежей. Только ваш телефон и браузер.