← На главную

Как устроено шифрование

Что происходит с сообщением от ввода текста до расшифровки у собеседника. Описание реализации Secure Chat 0.1.6 и форматов версии 1.

Приложение использует штатные криптографические API .NET и операционной системы. Алгоритмы AES, ChaCha20, RSA, ECDSA и генератор случайных чисел не реализованы заново. Собственный формат контейнеров и управление ключами пока не прошли независимый криптографический аудит.

Мессенджер доставляет контейнер

Secure Chat работает отдельно от Telegram, почты и других способов передачи. На устройстве отправителя текст или файл превращается в зашифрованный контейнер. Через выбранный канал передаётся этот контейнер, а получатель расшифровывает его локально своим закрытым ключом.

  1. Собеседники создают собственные профили и обмениваются публичными карточками ключей.
  2. Они независимо сверяют полные отпечатки ключей и подтверждают контакт в приложении.
  3. Отправитель выбирает свой профиль, получателя и алгоритм. Secure Chat шифрует содержимое и подписывает контейнер.
  4. Получатель открывает контейнер, вводит пароль кошелька при необходимости и получает проверенный результат.

Доступ к истории мессенджера сам по себе не даёт закрытый ключ Secure Chat. Дополнительный слой защиты полезен именно для содержимого, которое вы предварительно зашифровали. Он не скрывает факт общения, участников, время передачи или сетевые адреса и не защищает устройство, на котором уже действует вредоносная программа.

Две пары ключей в каждом профиле

Разделение назначения ключей
Назначение Механизм
Передача ключа содержимого RSA-3072 с OAEP-SHA256
Подпись контейнера ECDSA, кривая NIST P-256, хеш SHA-256
Формат публичных ключей Канонический DER SubjectPublicKeyInfo (SPKI)
Формат закрытых ключей DER PKCS#8, внутри зашифрованного кошелька

Публичная карточка .scpub содержит имя, оба публичных ключа, отпечаток и версию формата. Закрытых ключей в ней нет. Формат карточки — читаемый JSON; бинарные поля записываются в Base64.

Format: SecureChat.PublicKey
Version: 1
Name
EncryptionPublicKey
SigningPublicKey
Fingerprint

Как проверяется собеседник

Отпечаток объединяет оба публичных ключа в один SHA-256 хеш: 64 шестнадцатеричных символа. Перед отправкой его нужно полностью сверить при личной встрече или по другому доверенному каналу. Имя в импортированной карточке не является доказательством личности.

SHA256(
  UTF8("SecureChat.Identity.v1\0")
  || int32BE(length(RSA_SPKI)) || RSA_SPKI
  || int32BE(length(ECDSA_SPKI)) || ECDSA_SPKI
)

Импортированный контакт всегда получает статус непроверенного. Приложение разрешает шифрование этому контакту после подтверждения сверки. Собственные профили можно выбирать в качестве получателя для проверки работы приложения.

Корректная цифровая подпись подтверждает соответствие контейнера ключу подписи. Связь этого ключа с конкретным человеком устанавливается сверенным отпечатком. Для неизвестного или несверенного ключа приложение отдельно показывает, что личность отправителя не подтверждена.

Отдельный случайный ключ для каждого контейнера

Каждое новое сообщение и каждый файл получают новый случайный 256-битный ключ через RandomNumberGenerator.GetBytes . Пользователь выбирает один из двух режимов аутентифицированного шифрования — AEAD:

Алгоритмы шифрования содержимого
Алгоритм Ключ Nonce Тег
AES-256-GCM 32 байта 12 байт 16 байт
ChaCha20-Poly1305 32 байта 12 байт 16 байт

ChaCha20-Poly1305 предлагается только при поддержке операционной системой. Выбранный алгоритм входит в аутентифицированный заголовок; автоматического переключения на более слабый вариант нет.

Случайный ключ содержимого шифруется публичным RSA-ключом получателя. Его отдельная копия шифруется публичным RSA-ключом отправителя, поэтому отправитель также может открыть своё исходящее сообщение. При отправке самому себе создаётся один такой слот.

AEAD проверяет целостность содержимого и связанных данных. Подпись ECDSA-P256/SHA-256 дополнительно связывает контейнер с ключом отправителя. Неуспешная проверка прерывает расшифровку.

Кошелёк под паролем

Профили с закрытыми ключами, контакты, защищённые настройки и история находятся в одном файле Data/wallet.scvault рядом с программой. Для шифрования кошелька используется AES-256-GCM.

Параметры защиты кошелька версии 1
Параметр Значение
Получение ключа из пароля PBKDF2-HMAC-SHA-256, 600 000 итераций
Случайная соль 32 байта
Производный ключ 32 байта
Nonce при сохранении Новые случайные 12 байт
Тег аутентификации 16 байт
Длина пароля при создании От 12 до 1024 символов
Максимальный открытый размер кошелька 64 МиБ

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

Заголовок длиной 64 байта тоже аутентифицируется. После него записаны шифротекст и тег:

"SCVAULT1"[8]
|| version:int32LE
|| iterations:int32LE
|| salt[32]
|| nonce[12]
|| ciphertext_length:int32LE
|| ciphertext
|| tag[16]

Формат версии 1 принимает только заданные параметры KDF, ограниченный размер и точную длину файла. Запись выполняется через полностью подготовленную зашифрованную копию и замену файла. Параллельная запись и сохранение поверх обнаруженных внешних изменений отклоняются. Служебный .lock не содержит ключей.

Текст: контейнер SC1 и вложение .scmsg

Исходный текст ограничен 1 МиБ в строгой кодировке UTF-8. Бинарный контейнер имеет тип SCT1 :

"SCT1"
|| header_length:int32LE || header_json
|| ciphertext_length:int32LE || ciphertext
|| tag[16] || signature[64]

В качестве дополнительных аутентифицируемых данных (AAD) используется весь префикс: тип, длина и JSON заголовка. Подпись ECDSA-P256 вычисляется над SHA-256 всех предшествующих байт. Формат подписи — IeeeP1363FixedFieldConcatenation : r || s , по 32 байта.

Для передачи бинарный контейнер преобразуется в Base64url без символов заполнения = :

SC1:<base64url(binary_container)>
securechat://message/<base64url(binary_container)>

Прежде чем раскрыть текст, программа проверяет структуру, точную длину и подпись, затем расшифровывает RSA-обёртку и проверяет AEAD. Недопустимые символы, переносы внутри конверта, дополнительные URI-параметры и повреждённые данные отклоняются.

Передача через Telegram

Кнопка «Файл для чата» копирует зашифрованный .scmsg в файловый буфер Windows. Вставьте его в чат через Ctrl + V и отправьте вложение. Получатель скачивает файл и открывает его в Secure Chat. Заблокированное приложение сначала запросит пароль.

Обычный конверт SC1:… также можно копировать и вставлять вручную. Windows-ссылка securechat://… ограничена 8000 символами и становится кликабельной не во всех клиентах. Telegram Desktop не превращает эту произвольную схему в обычную автоссылку; для него предназначено вложение .scmsg . Старые .sct открываются явно внутри приложения.

Файлы: блоки, подпись и два прохода проверки

Зашифрованный файл получает расширение .scx и тип SCF1 . Предел исходного файла в формате — 1 ТиБ. Обработка потоковая: файл целиком не загружается в память, содержимое разделено на блоки по 1 МиБ.

"SCF1" || header_length:int32LE || header_json
|| (chunk_length:int32LE || ciphertext[chunk_length] || tag[16])*
|| 0:int32LE || terminal_tag[16]
|| signature[64]

Для каждого блока получается собственный 12-байтовый nonce. Он составлен из случайного четырёхбайтового префикса контейнера и восьмибайтового индекса блока:

nonce = Nonce[4] || uint64BE(chunk_index)
AAD   = SHA256(full_prefix)[32]
        || uint64BE(chunk_index)
        || int32LE(chunk_length)

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

В подпись входят все байты от SCF1 до завершающего AEAD-тега включительно. Проверяются порядок и размер блоков, точная длина контейнера и конец файла. Перестановка, дублирование, удаление блоков, усечение или дописывание приводят к отказу.

Что происходит при расшифровке

  1. Проверяются ограниченный заголовок, длина файла и наличие подходящего закрытого ключа.
  2. Первый проход читает контейнер и проверяет полную подпись. Открытый временный файл ещё не создаётся.
  3. Второй проход проверяет AEAD каждого блока, пишет расшифрованные данные во временный файл и повторно проверяет итоговую подпись.
  4. После успешного завершения результат переименовывается в выбранный пользователем новый файл. Уже существующий файл не перезаписывается.

Строка состояния показывает общий процент: проверку подписи, расшифровку и сохранение. 100% означает успешное сохранение результата. Кнопка отмены доступна во время обработки; при штатной ошибке или отмене временный файл удаляется.

Исходный файл сохраняется. Расшифрованный результат не запускается автоматически. Сбой питания, принудительное завершение процесса или препятствующий удалению внешний дескриптор могут оставить временный открытый файл. Защита выходной папки и диска остаётся важной частью работы с секретами.

Локальное хранение, история и блокировка

Что остаётся рядом с программой
Файл или папка Назначение
Data/wallet.scvault Зашифрованные профили, ключи, контакты, настройки и история
Data/window-state.json Размер, положение и состояние окна; без ключей и переписок
Data/ui-preferences.json Язык и выбор проверки обновлений; без данных кошелька
Data/ClipboardAttachments Временные копии зашифрованных сообщений для вставки в чат

История содержит метаданные операций и зашифрованные текстовые конверты. Открытый текст и содержимое файлов в неё не записываются. Сохраняются последние 100 записей с общим размером конвертов около 8 МиБ; старые записи удаляются автоматически. Историю можно отключить или очистить.

Кошелёк блокируется по Ctrl + L , при сворачивании, блокировке или отключении сеанса Windows, переходе в сон и по бездействию. Интервал бездействия выбирается от 1 до 15 минут, по умолчанию — 5 минут. Текущая файловая операция отменяется перед освобождением ключей.

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

Два разных режима буфера обмена

«Копировать текст» помечает собственную запись приложения и очищает её через 30 секунд либо при блокировке, если запись всё ещё принадлежит Secure Chat. Более новая запись другой программы не стирается. Обычное копирование системной командой Ctrl + C этим таймером не управляется.

«Файл для чата» помещает в Windows FileDrop путь к готовому .scmsg , содержащему только шифротекст. Эта копия остаётся доступной после блокировки и закрытия кошелька, чтобы мессенджер успел её прочитать. Каждое копирование создаёт отдельное вложение.

Копии старше 24 часов очищаются при последующем запуске или копировании. Одновременно хранится до 128 временных вложений; при достижении лимита можно явно сохранить сообщение в выбранную папку. Запреты на историю и облачный буфер передаются как подсказки Windows; сторонние менеджеры буфера могут их игнорировать.

Резервные копии, перенос и обновление

Резервная копия — полный зашифрованный кошелёк. Для её открытия нужен пароль, который действовал в момент создания. После добавления новых ключей обновите резервную копию. Восстановление доступа без пароля и закрытых ключей не предусмотрено.

Смена пароля, удаление профиля или очистка истории изменяют текущий кошелёк. Старые резервные копии сохраняют прежний пароль, ключи и историю. Удаление записи также не гарантирует физическое стирание данных с SSD, из снимков и журналируемой файловой системы.

Для обновления до 0.1.6 закройте Secure Chat и замените SecureChat.exe в прежней папке. Сохраните всю папку Data. Форматы кошелька и контейнеров остаются версии 1, миграция не требуется. Для будущих выпусков с изменением формата порядок миграции будет описан отдельно.

При переносе в другую папку переносите EXE вместе с Data и нужными внешними переводами Languages . Затем включите обработку .scmsg , .scx и ссылок в настройках заново: регистрация Windows хранит абсолютный путь. Однофайловый EXE может извлекать нативные библиотеки .NET в системный кеш пользователя.

Какие сетевые обращения есть у приложения

Для шифрования и расшифровки сервер не нужен. У Secure Chat нет транспорта сообщений, учётной записи для обмена ключами или сервиса сброса пароля. Доставку контейнеров выполняет выбранный вами мессенджер, почта или другой канал.

По кнопке «Проверить обновления» приложение получает небольшой JSON с https://itmsft.com/securechat/update/latest.json . Проверку при запуске можно включить отдельно; по умолчанию она выключена. Передаются обычные сетевые сведения HTTPS-запроса и общий User-Agent с версией программы. Пароль, ключи, профили, история и содержимое файлов в запрос не включаются.

Клиент ограничивает размер ответа 64 КиБ и время чтения 10 секундами, проверяет версию и наличие пакета для своей архитектуры. Ошибка сервера, сети или формата показывает невозможность проверки и не объявляет установленную версию актуальной.

Кнопка скачивания открывает разрешённый HTTPS-адрес пакета на itmsft.com в обычном браузере. Приложение не выполняет автоматическую установку и не запускает скачанный файл. Формат поля SHA-256 проверяется, но байты скачанного браузером ZIP приложение не проверяет. В версии 0.1.6 цифровой подписи издателя у EXE нет.

Границы, которые важно учитывать

  • Безопасность устройства. Вредоносная программа, кейлоггер, чтение памяти, подмена EXE или удалённый доступ могут раскрыть текст до шифрования и после расшифровки.
  • Метаданные. Видимы открытый заголовок контейнера и сетевые сведения канала передачи. Это не средство анонимности.
  • Статические ключи. Forward secrecy не реализована: украденный закрытый ключ позволяет читать ранее перехваченные контейнеры этому ключу.
  • Восстановление секретности. Double Ratchet и post-compromise security отсутствуют. Это собственный формат, а не реализация протокола Signal.
  • Повторы и откат. Валидный контейнер можно переслать повторно. Корректная старая копия кошелька не защищена от отката: целостность не доказывает актуальность.
  • Пароль. Минимальная длина и задержка в интерфейсе не останавливают оффлайн-перебор украденного кошелька. Основные меры — сильный пароль и KDF.
  • Удаление данных. Полное стирание из RAM, подкачки, облачного буфера и с накопителя не гарантируется.
  • Криптографические свойства. Схема не является постквантовой. Подпись доступна для проверки третьим лицам, получившим контейнер; криптографическая отрицаемость не предоставляется.
  • Статус проверки. Стандартные примитивы и автоматические тесты не заменяют независимый аудит протокола и реализации.

Secure Chat добавляет отдельный контроль над выбранным содержимым. Для использования с особо чувствительными данными необходимы оценка вашей модели угроз, защищённое устройство и независимая экспертная проверка реализации.

Запросить доступ к исходному коду →