Потоковое шифрование в CryptoJS опирается на принцип постепенной обработки данных блоками фиксированного размера с сохранением внутреннего состояния между вызовами. В отличие от однократного шифрования строки или массива байт, потоковый режим позволяет обрабатывать данные частями, что критично для больших файлов, сетевых потоков и сценариев реального времени.
В основе работы лежит объектная модель CryptoJS, где ключевую роль
играет WordArray — структура, представляющая данные в виде
массива 32-битных слов. Любая операция шифрования или дешифрования
работает именно с этим представлением, а не с «сырыми» байтами
JavaScript.
При использовании потокового режима шифрования библиотека сохраняет несколько видов состояния:
Каждый вызов обработки данных изменяет эти структуры, поэтому корректное управление состоянием критично для целостности шифрования.
CryptoJS предоставляет возможность работать с шифрованием как с состоянием машины, а не как с функцией «вход → выход».
Типичный способ создания потокового шифра:
const key = CryptoJS.enc.Utf8.parse('secret key 123');
const iv = CryptoJS.enc.Utf8.parse('initial vector 123');
const encryptor = CryptoJS.algo.AES.createEncryptor(key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
Объект encryptor сохраняет внутреннее состояние между
вызовами process.
Основной механизм потокового шифрования реализуется через метод
process, который принимает очередной фрагмент данных и
возвращает зашифрованный результат:
const part1 = encryptor.process('Hello ');
const part2 = encryptor.process('world ');
const part3 = encryptor.process('streaming');
Каждый вызов:
Важно, что состояние не сбрасывается между вызовами.
Последний этап шифрования выполняется через finalize().
Он обрабатывает остаток данных, применяет padding (если требуется) и
завершает поток:
const finalPart = encryptor.finalize();
После вызова finalize объект считается завершённым.
Повторное использование без пересоздания приводит к некорректному
состоянию.
В потоковом режиме ключевая проблема — работа с неполными блоками.
AES оперирует блоками по 16 байт, поэтому при поступлении данных:
CryptoJS хранит этот остаток в this._data внутри объекта
cipher.
Это означает:
process может быть пустым при недостаточном
размере блокаОдной из особенностей потокового подхода является возможность продолжить шифрование позже. Для этого необходимо сохранять внутренние параметры:
Однако CryptoJS не предоставляет прямой сериализации состояния cipher-объекта, поэтому восстановление требует ручного контроля:
const state = {
key,
iv,
buffer: encryptor._data
};
При восстановлении поток должен продолжаться с тем же IV и тем же непрерывным входом.
Разные режимы AES по-разному управляют состоянием:
CBC (Cipher Block Chaining) Каждый блок зависит от предыдущего зашифрованного блока. Состояние IV постоянно изменяется.
CTR (Counter mode) Использует счётчик, который увеличивается после каждого блока. Состояние определяется текущим значением counter.
CFB (Cipher Feedback) Работает как потоковый режим, где шифрование предыдущего выхода влияет на следующий шаг.
CTR наиболее удобен для потоковой обработки, так как не требует padding и позволяет произвольное разбиение данных.
При работе с потоковым шифрованием в CryptoJS часто возникают следующие проблемы:
Повторное использование cipher-объекта
После finalize() объект нельзя использовать повторно без
пересоздания.
Потеря IV
Если IV не сохраняется, расшифрование становится невозможным даже при наличии ключа.
Неправильное разбиение данных
Разделение входа без учёта блоков может привести к смещению состояния в CBC.
Игнорирование остаточного буфера
Если не вызвать finalize, последний блок может быть
потерян.
Потоковое шифрование в CryptoJS можно представить как конвейер:
Эта модель делает возможной обработку данных любого размера без предварительной загрузки всего массива в память.
Дешифрование зеркально повторяет процесс шифрования. Важно, чтобы:
const decryptor = CryptoJS.algo.AES.createDecryptor(key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
const out1 = decryptor.process(cipherPart1);
const out2 = decryptor.process(cipherPart2);
const final = decryptor.finalize();
Любое отклонение в состоянии приводит к невозможности восстановления исходного текста.
В потоковом шифровании состояние становится частью криптографической безопасности. Ошибки в его управлении приводят к:
Правильное управление состоянием — это не техническая деталь, а обязательное условие корректной криптографии.
CryptoJS работает в среде без потоков и без нативных бинарных буферов, поэтому:
WordArrayprocessЭто накладывает ограничения на высоконагруженные сценарии, где предпочтительнее WebCrypto API или нативные реализации.
Корректный жизненный цикл потокового шифрования включает:
processfinalizeЛюбое отклонение от этого цикла приводит к неконсистентности состояния и ошибкам расшифрования.