Всем привет!
Первая статья была несколько дней назад. За это время выявлено два момента, которые захотелось проработать:
В переписке активно используются голосовые сообщения. Текущая версия их не обрабатывала.
100 000 итераций PBKDF2, которые использовались в первой версии, уже не соответствуют актуальным рекомендациям (OWASP рекомендует от 600 000 для SHA-256).
Для этого потребовалось расширить функциональность и усилить криптографическую стойкость.
Голосовой рекордер
Добавлена третья вкладка интерфейса — «Голос».

Вкладка содержит:
Элементы управления записью (старт/стоп/пауза/сохранение)
Визуализатор спектра звука (эквалайзер)
Таймер записи
Список сохраненных записей с возможностью шифрования, скачивания и удаления

Реализация
Используются нативные браузерные API — никаких дополнительных библиотек не потребовалось.
Запись:
stream = await navigator.mediaDevices.getUserMedia({ audio: true }); mediaRecorder = new MediaRecorder(stream); mediaRecorder.ondataavailable = e => audioChunks.push(e.data); mediaRecorder.start();
Визуализатор:AudioContext + AnalyserNode дают массив частот, который отрисовывается на Canvas через requestAnimationFrame.
Сохранение:
Полученный файл отправляется на сервер через POST-запрос и сохраняется в соответствующую директорию.
Файловая структура
К существующим директориям temp/ и static/ добавлены две новые:
recordings/ # необработанные записи recordings_encrypted/ # зашифрованные записи
Логика работы:
Запись сохраняется в
recordings/При нажатии кнопки «Зашифровать» файл обрабатывается и перемещается в
recordings_encrypted/с расширением.cipИсходный файл удаляется
Расшифровка происходит в обратном порядке
Лимит размера файлов увеличен до 500 МБ (было 100 МБ).
Усиление криптографии
Основное изменение затронуло функцию PBKDF2. Количество итераций увеличено с 100 000 до 600 000.
Это означает, что перебор паролей злоумышленником замедлится в 6 раз при сохранении всех остальных параметров атаки.
В коде:
PBKDF2_ITERATIONS = 600000 # ранее было 100000 @staticmethod def derive_key(password, salt, key_length=32): return hashlib.pbkdf2_hmac( 'sha256', password.encode(), salt, SimpleCrypto.PBKDF2_ITERATIONS, key_length )
Функция derive_key теперь используется как для генерации ключа AES, так и для ключа HMAC (ранее HMAC-ключ формировался через обычный sha256 от строки). Это дает:
Единый стандарт вывода ключей
Разделение ключей шифрования и аутентификации
Новые эндпоинты
Добавлены маршруты для работы с голосовыми записями:
@app.route('/upload_audio', methods=['POST']) # загрузка записи @app.route('/encrypt_recording/<filename>', methods=['POST']) # шифрование @app.route('/decrypt_recording/<filename>', methods=['POST']) # расшифровка @app.route('/delete_recording/<filename>', methods=['DELETE']) # удаление
Для работы с метаданными создан отдельный класс VoiceRecording, который сериализует информацию о файле в JSON.
Ограничения и производительность
Параметр | Значение |
|---|---|
Макс. размер файла | 500 МБ |
Макс. длина имени файла | 64 КБ |
Поддерживаемые форматы | любые |
Итерации PBKDF2 | 600 000 |
AES-256-GCM | ~50 МБ/с |
Простые слои | ~200 МБ/с |
Время запуска | < 2 с |
Что изменилось в работе
К базовой механике, описанной в прошлый раз, добавилась работа с голосом. Как и раньше, всё крутится на локальном Flask-сервере, который поднимается при запуске, а интерфейс открывается в браузере.
Появилось три режима работы: текст, файлы и теперь — голос. Голосовые записи обрабатываются по той же схеме, что и обычные файлы: сначала попадают в отдельную папку recordings/, а после шифрования переезжают в recordings_encrypted/ с расширением .cip.
Криптография. Многослойное шифрование осталось тем же: пять простых слоев (XOR, сдвиги, перестановки) плюс AES-256-GCM на выбранной позиции. Но ключевое изменение коснулось вывода ключей: количество итераций PBKDF2 увеличено со 100 000 до 600 000. Это основная защита от перебора паролей — теперь каждый кандидат проверяется в 6 раз дольше.
Ключи по-прежнему живут только в оперативной памяти, на диск не пишутся. Программа не собирает телеметрию, не ведет логи, не требует доступа в интернет. Временные файлы удаляются через час. После закрытия не остается ничего, кроме файлов, которые пользователь сохранил сам — будь то расшифрованные записи или зашифрованные .cip-файлы.
Всем спасибо за прочтение :-)
Если есть идеи — добро пожаловать в комменты. Всегда открыт к диалогу :-)
