CFB (Cipher Feedback) относится к потокоподобным режимам блочного шифрования, в которых зашифрованные данные формируются не путём независимого шифрования блоков, а через обратную связь от предыдущего шифротекста. В контексте CryptoJS этот режим используется для превращения блочного шифра AES в механизм, способный обрабатывать данные произвольной длины без необходимости дополнения (padding).
Основная идея CFB заключается в том, что результат шифрования предыдущего блока шифротекста используется как вход для следующего шага генерации ключевого потока.
Пусть:
E_k — функция блочного шифра (например, AES)IV — вектор инициализацииP_i — очередной блок открытого текстаC_i — соответствующий блок шифротекстаПроцесс начинается с IV:
Шифруется текущее состояние:
S_0 = E_k(IV)Формируется первый блок шифротекста:
C_1 = P_1 ⊕ S_0Далее состояние обновляется:
S_1 = E_k(C_1)Для следующего блока:
C_2 = P_2 ⊕ S_1Таким образом, каждый новый блок зависит от предыдущего шифротекста, что создаёт цепочку обратной связи.
Ключевым свойством CFB является то, что шифротекст участвует в формировании следующего шага шифрования. Это приводит к следующим характеристикам:
В CryptoJS режим CFB поддерживает параметр segmentSize,
определяющий размер обрабатываемого сегмента в битах. Это позволяет
варьировать поведение режима от блочного (128 бит) до более мелких
потоковых сегментов.
C_i = P_i E_k(C_{i-1})
При стандартной конфигурации AES используется блок 128 бит, однако CFB позволяет работать с меньшими сегментами, например 8 бит, что приближает поведение к побитовому потоку.
В библиотеке CryptoJS режим CFB включается через объект
CryptoJS.mode.CFB.
const CryptoJS = require("crypto-js");
const key = CryptoJS.enc.Utf8.parse("1234567890123456");
const iv = CryptoJS.enc.Utf8.parse("abcdef9876543210");
const plaintext = "Пример данных для шифрования";
const encrypted = CryptoJS.AES.encrypt(plaintext, key, {
iv: iv,
mode: CryptoJS.mode.CFB,
padding: CryptoJS.pad.NoPadding
});
console.log(encrypted.toString());
Важный момент — в CFB обычно используется отсутствие padding, поскольку режим не требует выравнивания данных по размеру блока.
Особенность CFB заключается в симметричности операций: процесс шифрования и расшифрования использует одну и ту же функцию AES.
При расшифровании используется тот же механизм обратной связи:
const decrypted = CryptoJS.AES.decrypt(encrypted, key, {
iv: iv,
mode: CryptoJS.mode.CFB,
padding: CryptoJS.pad.NoPadding
});
console.log(decrypted.toString(CryptoJS.enc.Utf8));
Здесь важно, что отличие между encrypt и decrypt заключается не в алгоритме AES, а в том, как интерпретируется поток XOR-операций.
IV в CFB играет критическую роль, поскольку он определяет начальное состояние цепочки. При одинаковом ключе разные IV приводят к полностью различным шифротекстам.
Основные требования к IV:
Повторное использование IV с одним и тем же ключом приводит к утечке информации о структуре данных.
В отличие от ECB и CBC режимов, CFB не требует дополнения данных до размера блока. Это связано с тем, что шифрование выполняется через XOR с потоком, а не через прямую обработку блоков.
Это делает режим удобным для:
CFB обладает свойством локального распространения ошибок:
C_i = P_i E_k(C_{i-1})
Искажение одного C_i приводит к повреждению
соответствующего P_i и частично P_{i+1}, после
чего поток восстанавливается.
В зависимости от размера сегмента различают:
В CryptoJS параметр segmentSize управляет этим
поведением:
CryptoJS.AES.encrypt(data, key, {
iv: iv,
mode: CryptoJS.mode.CFB,
segmentSize: 8
});
CFB занимает промежуточное положение между блочными и потоковыми режимами:
Ключевое отличие CFB — использование зашифрованного предыдущего состояния, а не счётчика, как в CTR.
CFB используется в сценариях, где требуется:
Типичные области:
Несмотря на гибкость, CFB имеет ряд ограничений:
Эти факторы делают его менее предпочтительным в современных высоконагруженных системах, но сохраняют актуальность в специфических потоковых задачах.