Как я сделал шифрование поверх MAX, когда приватность стала роскошью

Когда единственный работающий мессенджер — в «белом списке», а тебе нужно отправить что-то, что видеть должен только получатель. История о том, как я без Mac, с помощью ИИ и GitHub Actions собрал кроссплатформенное приложение для шифрования.

Предыстория: интернет работает, но не для тебя

Представьте ситуацию. Интернет вроде есть, но работают только приложения из «белого списка». MAX, может быть ещё пара сервисов. Telegram — через раз. VPN — лотерея. А вам нужно отправить коллеге договор, другу — фотографию, или просто написать сообщение, которое не хочется показывать всему миру.

Вы открываете MAX, набираете текст... и понимаете: а кто гарантирует, что это сообщение читаете только вы и получатель? Никто. Ни один мессенджер из «белого списка» не даёт вам end-to-end шифрование, которому можно доверять. Вы просто верите на слово.

Именно в такой момент и родилась идея Dark Message.

Идея: не заменить мессенджер, а надеть на него бронежилет

Я не стал делать «убийцу Telegram» или «замену MAX». Это бессмысленно — если приложение не в белом списке, оно просто не будет работать.

Вместо этого я сделал слой шифрования поверх любого мессенджера. Схема простая:

  1. Вы пишете сообщение в Dark Message

  2. Приложение шифрует его AES-256 (тот же стандарт, что используют банки и военные)

  3. На выходе — набор символов, который вы копируете и отправляете через MAX, email, хоть голубиной почтой

  4. Получатель вставляет эту кашу в своё приложение Dark Message, вводит пароль — и читает оригинал

Мессенджер становится просто транспортом. Он передаёт зашифрованный текст, не зная, что внутри. Как конверт, который почтальон не может вскрыть.

И самое главное — приложение работает полностью офлайн. Нет разрешений на интернет. Вообще. Данные никогда не покидают ваше устройство.

Что можно шифровать

  • Текст — сообщения, заметки, пароли. Результат — строка Base64, которую можно отправить в любой чат.

  • Фотографии — зашифровать фото перед отправкой. На выходе файл .darkm, который без пароля — просто набор байтов.

  • Документы — PDF, Word, Excel, ZIP, что угодно. Тоже превращается в .darkm.

Честно про ИИ: Claude как напарник

Скажу прямо — я делал этот проект с помощью ИИ. Claude (Anthropic) был моим напарником на протяжении всей разработки. И я считаю, что скрывать это — глупо.

Вот как это выглядело на практике:

  • Архитектура — я описывал задачу, Claude предлагал структуру, я корректировал

  • Код — Claude писал основу, я тестировал на реальных устройствах и находил баги

  • Отладка — когда шифрование между Android и iOS не работало, мы вместе анализировали байты, сравнивали ключи деривации, писали тесты на Python

  • Публикация — Apple дважды отклонил приложение, и каждый раз мы разбирали причины и исправляли

ИИ не заменил разработчика — он заменил команду. Вместо бэкенд-разработчика, iOS-разработчика, Android-разработчика и тестировщика у меня был один помощник, который знает все платформы. Но финальные решения, тестирование на железе и понимание «что нужно пользователю» — это по-прежнему человек.

Без Mac? Не проблема: GitHub Actions + CI/CD

У меня нет MacBook. Совсем. А для сборки iOS-приложения нужен Xcode, который работает только на macOS.

Решение: GitHub Actions. Я настроил CI/CD pipeline, который:

  1. Берёт код из репозитория

  2. Запускает виртуальную macOS на серверах GitHub

  3. Генерирует проект через XcodeGen (чтобы не хранить тяжёлый .xcodeproj в репозитории)

  4. Собирает, подписывает и загружает билд напрямую в App Store Connect

Весь процесс — от коммита до появления билда в TestFlight — полностью автоматический. Я пишу код на Windows, пушу в GitHub, и через 15 минут получаю готовый iOS-билд на своём iPhone через TestFlight.

Для Android всё проще — Gradle собирает APK/AAB прямо на моём компьютере.

Техническая кухня: AES-256-GCM + PBKDF2

Для тех, кому интересны детали:

  • AES-256-GCM — симметричное шифрование с аутентификацией. Если кто-то изменит хотя бы один бит в зашифрованном сообщении — расшифровка не пройдёт. Это защита и от чтения, и от подмены.

  • PBKDF2-HMAC-SHA512 — деривация ключа из пароля. 600 000 итераций. Даже если кто-то получит зашифрованное сообщение, перебор паролей будет стоить очень дорого.

  • Формат пакета: [version:1B][contentType:1B][salt:16B][nonce:12B][ciphertext+GCM_tag:NB] — компактно и самодостаточно.

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

Кроссплатформенность: где я потерял неделю жизни

Самое весёлое началось, когда я решил сделать приложение и для Android, и для iOS, и для Windows.

Задача звучит просто: зашифровал на Android — расшифровал на iPhone. Что может пойти не так?

Оказалось — всё.

Проблема 1: Кириллица в паролях

Пользователь вводит пароль «привет» на Android, шифрует сообщение. Отправляет другу с iPhone. Друг вводит тот же пароль «привет» — и получает ошибку. При этом с паролем «hello» всё работает идеально.

Причина: Java (Android) и Swift (iOS) по-разному конвертируют кириллические символы в байты при деривации ключа. Java использует внутреннее представление через PBEKeySpec(char[]), а iOS — честный UTF-8 через Array(passphrase.utf8).

Решение: на Android я написал собственную реализацию PBKDF2, которая принимает пароль как UTF-8 байты напрямую, минуя стандартный Java API. Три дня отладки ради одной строчки passphrase.toByteArray(Charsets.UTF_8).

Проблема 2: Буква «а»

Во время тестирования я зашифровал слово «привет» с паролем «а» на Android, отправил на iPhone — не расшифровывается. Начал копать.

Написали на Python скрипт, который попробовал расшифровать сообщение разными вариантами пароля. Выяснилось: Android использовал латинскую «a» (код 0x61), а iPhone — кириллическую «а» (код 0xD0B0). Визуально — одинаковые символы. Технически — разные вселенные.

Это не баг приложения, а особенность клавиатур. Но такие вещи вылезают только при реальном тестировании на реальных устройствах.

Проблема 3: Argon2 vs PBKDF2

Изначально на Android я использовал Argon2id для деривации ключа — более современный и стойкий алгоритм. Но на iOS библиотека Argon2 ломала CI/CD pipeline на GitHub Actions (не могла скачать зависимости при сборке).

Пришлось перейти на PBKDF2 на обеих платформах. Менее модный, но надёжный, проверенный временем, и — главное — одинаково работающий везде.

Путь в магазины приложений: отдельное приключение

Apple App Store — три попытки

Apple отклонил приложение дважды, прежде чем одобрить.

Первый отказ: в описании я упомянул Telegram, WhatsApp и другие мессенджеры. Apple считает это «неточными метаданными» — нельзя упоминать сторонние платформы. Также скриншоты были сгенерированы, а не сделаны на реальном iPhone. И ссылка «Support URL» вела просто на профиль GitHub, а не на страницу поддержки.

Второй отказ: я обновил английское описание, но забыл русское. В русской локализации всё ещё красовались «MAX, Telegram, WhatsApp...». Apple проверяет ВСЕ локализации.

Третья попытка — прошла. Чистое описание, реальные скриншоты с iPhone, нормальная страница поддержки.

Уроки от Apple:

  • Никогда не упоминайте сторонние приложения в описании

  • Скриншоты — только реальные, с реального устройства

  • Проверяйте все языковые версии метаданных

  • Support URL — должна быть реальная страница с контактами

RuStore — соотношение сторон

RuStore отклонил из-за скриншотов — они требуют строго 9:16 для телефонов. Скриншоты с современных смартфонов (9:19.5) не подходят. Пришлось масштабировать с добавлением тёмного фона.

Также versionCode должен расти с каждой загрузкой — нельзя загрузить ту же или меньшую версию.

Результат: три платформы, полная совместимость

Зашифровал на телефоне — расшифровал на компьютере. Зашифровал на iPhone — расшифровал на Android. Любая комбинация работает.

Скачать

iOS (App Store):
Dark Message Crypto Chat в App Store

Android (RuStore):
Dark Message Crypto Chat в RuStore

Windows:
Десктопная версия доступна как .exe — напишите в комментариях, если нужна ссылка.

Как пользоваться

  1. Установите приложение на своё устройство

  2. Договоритесь с получателем о парольной фразе (лично, по звонку — не через тот же мессенджер!)

  3. Напишите сообщение → нажмите «Зашифровать»

  4. Скопируйте результат → отправьте через MAX, email, SMS — как угодно

  5. Получатель вставляет текст в своё приложение → вводит пароль → читает

Для файлов — то же самое, только на выходе файл .darkm, который можно отправить как вложение.

Что дальше

  • Версия для Google Play (AAB уже собран, осталось опубликовать)

  • Возможно, open source — чтобы любой мог убедиться в отсутствии бэкдоров

  • Улучшение UX на основе отзывов

Вместо заключения

Я не призываю никого к паранойе. Но если существующие средства коммуникации не дают вам уверенности в приватности — теперь есть инструмент, который работает поверх любого из них.

Приложение не требует интернета, не собирает данных, не требует регистрации и шифрует стандартом AES-256. А сделано оно одним человеком с помощью ИИ, без единого Mac в радиусе ста километров.

Если у вас остались вопросы про реализацию, кроссплатформенную совместимость, работу с ИИ в разработке или процесс публикации в магазинах — добро пожаловать в комментарии.