Всем привет! Моя первая статья тут, просьба строго не судить :-)

Предыстория

Когда-то давным-давно, в прошлом десятилетии, я учился в одном техническом университете по специальности "информационная безопасность автоматизированных систем" и один из предметов, который меня заинтересовал, был криптография. В то время для меня это был какой-то вид магии, сверхспособность - возможность передавать информацию так, чтобы ее понял только тот, кому она предназначалась. Однако после учебы, столкнувшись на практике с данной областью ИБ, романтика ушла на второй план, и осталось практическое понимание необходимости использования криптографии для обмена "конфиденциальной" информацией. Там, на месте работы (одна большая государственная организация), где использовал криптографию в практическом аспекте, и познакомился со своим другом. Почти 9 лет прошло)

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

Поэтому в определенный момент решил реализовать это на практике, создав небольшого локального помощника в данном вопросе.

От идеи к реализации

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

Слоев сделал 5 простых и 1 AES:

  • Слой 1: XOR с константой 0x55

  • Слой 2: Переворот последовательности байт (реверс)

  • Слой 3: Циклический сдвиг на 13

  • Слой 4: XOR с константой 0xAA

  • Слой 5: Обмен соседних байт местами

  • AES: AES-256-GCM с аутентификацией

В итоге собрал небольшой скрипт на python, в котором можно было выбирать слой и вводить ключ с шифрованием и дешифрованием текста, чтобы ключи хранились локально в памяти процесса.

Но позже, поговорив с другом, решил попробовать сделать небольшое приложение c использованием flask на локальном сервере. Назвали CryptoBuddy :)

Получился уютный терминал, в котором можно было шифровать и дешифровать полученный текст, используя ключ и номер слоя, о котором знаете только вы с собеседником, плюс можно очень быстро сменить ключ, при подозрении на компрометацию. Опробова��и - заработало, обменивались сообщениями через различные мессенджеры, в частности через telegram. Как выглядит переписка видно на изображении ниже:

Собственно, как выглядит переписка при использовании cryptobuddy
Собственно, как выглядит переписка при использовании cryptobuddy

В дальнейшем, после успешного тестирования, возникла идея добавить возможность шифровать-дешифровать файлы, для секьюрной пересылки. Провели испытания - завершились успешно! Файлы шифруются/дешифруются тем же способом, какой используется для текста.

По результатам: CryptoBuddy представляет собой автономное десктоп-приложение с веб-интерфейсом, построенное по принципу "все в одном". Приложение запускает локальный веб-сервер и открывает браузер для взаимодействия с пользователем.

Вскоре возникла идея собрать приложения для windows (без установки) и .apk для смартфонов на базе Android. Идея впоследствии была реализована, хоть это и было довольно непросто для меня, как человека не имеющего особого опыта в создании подобных приложений :)

Интерфейс приложения на Windows
Интерфейс приложения на Windows
Интерфейс приложения на Android
Интерфейс приложения на Android

Технологический стек:

Компонент

Технология

Назначение

Язык программирования

Python 3.8+

Основная логика

Веб-фреймворк

Flask

Локальный веб-сервер

Криптография

PyCryptodome

AES-256 шифрование

Сборка под Windows

PyInstaller

Упаковка в .exe

Шаблонизация

render_template_string

Встроенный HTML

Интерфейс

HTML/CSS/JavaScript

Пользовательский интерфейс

Криптографическая система

1. Многослойное шифрование (Layered Encryption)

Система использует конвейер из последовательных преобразований. Порядок слоев может изменяться, а AES-слой может быть вставлен на любую позицию:

LAYERS = {
    1: ('XOR 0x55', SimpleCrypto.xor1, SimpleCrypto.xor1_rev),      # Простое XOR-преобразование
    2: ('Переворот', SimpleCrypto.reverse, SimpleCrypto.reverse_rev), # Реверс байтов
    3: ('Сдвиг +13', SimpleCrypto.shift, SimpleCrypto.shift_rev),     # Циклический сдвиг
    4: ('XOR 0xAA', SimpleCrypto.xor2, SimpleCrypto.xor2_rev),        # Второй XOR-слой
    5: ('Обмен пар', SimpleCrypto.swap_pairs, SimpleCrypto.swap_pairs_rev), # Перестановка
    'aes': ('AES-256-GCM', SimpleCrypto.aes_encrypt, SimpleCrypto.aes_decrypt)
}

2. Криптографические примитивы

XOR-шифрование (слои 1 и 4)

@staticmethod
def xor1(data):
    return bytes([b ^ SimpleCrypto.XOR1 for b in data])  # XOR с 0x55

Использует фиксированные ключи 0x55 (01010101 в двоичной) и 0xAA (10101010 в двоичной) для быстрого побайтового XOR. Эти константы выбраны как взаимно-обратные (инвертирующие все биты).

Реверс (слой 2)

@staticmethod
def reverse(data):
    return data[::-1]  # Полный разворот последовательности байт

Простое, но эффективное преобразование, нарушающее структуру данных.

Циклический сдвиг (слой 3)

@staticmethod
def shift(data):
    return bytes([(b + SimpleCrypto.SHIFT) % 256 for b in data])  # Сдвиг на 13

Сдвиг на 13 (0x0D) - простое арифметическое преобразование.

Обмен пар (слой 5)

@staticmethod
def swap_pairs(data):
    result = bytearray(data)
    for i in range(0, len(result) - 1, 2):
        result[i], result[i + 1] = result[i + 1], result[i]  # Меняем местами соседние байты
    return bytes(result)

Перестановка байт, нарушающая естественный порядок данных.

3. AES-256-GCM (аутентифицированное шифрование)

Используется режим GCM (Galois/Counter Mode), который обеспечивает:

  • Конфиденциальность (шифрование)

  • Аутентичность (проверка целостности)

  • Защиту от подделки (дополнительная аутентификация)

def aes_encrypt(data, password):
    salt = os.urandom(16)                                      # Соль для PBKDF2
    key = hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100000, 32)
    cipher = AES.new(key, AES.MODE_GCM)
    ciphertext, tag = cipher.encrypt_and_digest(data)
    return salt + cipher.nonce + tag + ciphertext              # Компоновка результата

Структура зашифрованных AES данных:

  • Байты 0-15: Соль (salt) - случайное значение для PBKDF2

  • Байты 16-31: Nonce - уникальное число для режима GCM

  • Байты 32-47: Тег аутентификации (tag) - 16 байт для проверки целостности

  • Байты 48+: Зашифрованные данные (ciphertext)

4. Защита метаданных и HMAC

Каждое сообщение содержит метаданные для защиты от повторов и подделки:

metadata = {
    'session': self.session_id,        # Уникальный ID сессии (8 байт в hex)
    'seq': self.message_counter,       # Счетчик сообщений (защита от повторов)
    'layers': [str(l) for l in self.layer_order],  # Конфигурация слоев
    'timestamp': datetime.now().isoformat()        # Временная метка
}

Структура сообщения с метаданными:

[2 байта длина метаданных][JSON метаданные][32 байта HMAC][данные сообщения]

HMAC-SHA256 подпись:

signature = hmac.new(self.hmac_key, meta_bytes + data, hashlib.sha256).digest()

HMAC защищает от модификации данных и подтверждает их подлинность.

5. Управление ключами

  • PBKDF2-HMAC-SHA256 для генерации ключей из пароля

  • 100,000 итераций (защита от brute-force атак)

  • Случайная соль для каждого шифрования (16 байт)

  • Ключ AES: 256 бит (32 байта)

  • Ключ HMAC: отдельный ключ, производный от пароля

key = hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100000, 32)
hmac_key = hashlib.sha256(f"{password}:hmac".encode()).digest()

Файловая система

1. Структура директорий

При запуске приложение создает следующую структуру папок:

CryptoBuddy.exe (или .py)
├── temp/           # Временные файлы (автоочистка через час)
│   └── (временные загруженные файлы)
└── static/         # Готовые для скачивания файлы
    ├── *.cip       # Зашифрованные файлы
    └── (расшифрованные файлы)

2. Форматы файлов

Тип

Расширение

Описание

Зашифрованный файл

.cip

Любые файлы после шифрования

Временные файлы

-

Удаляются после обработки

3. Формат зашифрованного файла

Для сохранения информации об исходном файле используется заголовок:

header = f"{filename}|{filesize}|".encode('utf-8')
header_len = len(header).to_bytes(2, 'big')
data_to_encrypt = header_len_bytes + header + file_data

Структура зашифрованного файла:

  • Байты 0-1: Длина заголовка (2 байта, максимальная длина 65535)

  • Байты 2..(2+header_len): Заголовок в формате "имя_файла|размер|"

  • Остальное: Данные файла (после применения всех слоев шифрования)

4. Процесс шифрования файла

  1. Чтение бинарных данных файла

  2. Создание заголовка с именем и размером

  3. Добавление длины заголовка (2 байта)

  4. Конвертация в текст через latin-1 (сохраняет все байты 0-255)

  5. Шифрование через тот же механизм, что и текст

  6. Сохранение результата в .cip файл

  7. Копирование в static/ для скачивания

5. Процесс расшифровки файла

  1. Чтение зашифрованного .cip файла

  2. Расшифровка через механизм decrypt

  3. Извлечение длины заголовка (первые 2 байта)

  4. Чтение и парсинг заголовка (имя|размер|)

  5. Проверка соответствия размера

  6. Извлечение данных файла

  7. Сохранение в static/ с оригинальным именем

  8. Разрешение конфликтов имен (добавление 1, 2 и т.д.)

Веб-интерфейс

1. Технологии фронтенда

  • HTML5 - структура страницы

  • CSS3 - стилизация с градиентами, анимациями и адаптивным дизайном

  • JavaScript (ES6) - клиентская логика

  • Fetch API - асинхронные запросы к Flask-серверу

  • FormData API - отправка файлов

2. Компоненты интерфейса

// Основные функции пользовательского интерфейса
- switchTab()        // Переключение между режимами (текст/файлы)
- applyConfig()      // Применение настроек шифрования
- encryptText()      // Шифрование текста
- decryptText()      // Расшифровка текста
- encryptFile()      // Шифрование файла
- decryptFile()      // Расшифровка файла
- copyToClipboard()  // Копирование результата в буфер обмена
- updateProgress()   // Обновление прогресс-бара
- handleFile()       // Обработка выбранного файла

3. Drag & Drop система

Реализована полноценная поддержка перетаскивания файлов:

// Обработчики drag & drop
function handleDragOver(e) {
    e.preventDefault();
    document.getElementById('dropZone').classList.add('dragover');
}

function handleDrop(e) {
    e.preventDefault();
    const files = e.dataTransfer.files;
    if (files.length > 0) {
        handleFile(files[0]);  // Обработка первого файла
    }
}

4. Визуальные элементы

  • Градиентный фон: линейный градиент от #667eea до #764ba2

  • Карточки с тенями: для группировки элементов

  • Адаптивная верстка: медиа-запросы для мобильных устройств

  • Анимации при наведении: трансформация кнопок

  • Прогресс-бар: визуализация процесса шифрования файлов

  • Пошаговый лог: детальное отображение каждого слоя шифрования

Процесс шифрования/расшифровки

Шифрование текста:

  1. Добавление метаданных (session_id, counter, timestamp)

  2. Последовательное применение слоев шифрования в заданном порядке

  3. Base64-кодирование результата для передачи через текстовые каналы

Дешифрование текста:

  1. Base64-декодирование входных данных

  2. Последовательное применение обратных слоев шифрования

  3. Извлечение и проверка метаданных

  4. Проверка соответствия конфигурации слоев

  5. Декодирование UTF-8 текста

Шифрование файла:

  1. Чтение бинарных данных

  2. Создание заголовка (имя|размер|)

  3. Конвертация в текст через latin-1

  4. Шифрование как текст

  5. Сохранение в .cip файл

Дешифрование файла:

  1. Чтение .cip файла

  2. Base64-декодирование

  3. Расшифровка через механизм decrypt

  4. Извлечение заголовка и проверка целостности

  5. Сохранение расшифрованного файла

Безопасность

Защита от атак:

  1. Replay attacks - уникальные session_id и счетчики сообщений

  2. Tampering - HMAC-SHA256 подписи для всех данных

  3. Brute force - PBKDF2 с 100,000 итераций

  4. Dictionary attacks - уникальная соль для каждого сообщения

  5. Bit flipping - GCM режим AES обеспечивает аутентификацию

Криптографическая стойкость:

  • AES-256: 2^256 комбинаций ключа

  • HMAC-SHA256: 2^256 комбинаций подписи

  • PBKDF2: 100,000 итераций замедляют перебор в 100,000 раз

  • Случайные значения: os.urandom для соли, nonce, session_id

Обработка ошибок

Типы проверок:

  1. Существование файла: проверка перед открытием

  2. Размер файла: не более 100 МБ

  3. Расширение файла: .cip для расшифровки

  4. Длина заголовка: не более 65535 байт

  5. Целостность данных: через HMAC

  6. Кодировка: latin-1 для бинарных данных

Сообщения об ошибках:

return {'success': False, 'error': f"Файл не найден: {file_path}"}
return {'success': False, 'error': "Файл должен иметь расширение .cip"}
return {'success': False, 'error': "Ошибка аутентификации - данные были изменены!"}

Производительность и ограничения

Ограничения:

  • Максимальный размер файла: 100 МБ (настраивается)

  • Максимальная длина имени файла: 64 КБ

  • Поддерживаемые форматы: любые файлы

  • Количество слоев: до 6 (5 простых + AES)

Производительность:

  • AES-256: ~50 МБ/с (зависит от процессора)

  • Простые слои: ~200 МБ/с

  • Время запуска: < 2 секунд

  • Потребление RAM: 50-200 МБ (зависит от размера файла)

Преимущества архитектуры

  1. Автономность - не требует доступа в интернет

  2. Кроссплатформенность - работает везде, где есть Python

  3. Прозрачность - пошаговый лог всех операций

  4. Гибкость - настраиваемая последовательность слоев

  5. Безопасность - многослойная защита с AES и HMAC

  6. Простота использования - веб-интерфейс в браузере

Сделано это для личного использования, используем с другом, шифруем и дешифруем текст и файлы через мессенджеры во время переписки, процесс увлек и теперь общаемся практически только так :-)

Всем спасибо за прочтение! Буду рад обратной связи и комментариям :-)