Блочное шифрование абсолютно безопасно. Это просто ЕЦБ, это проблематично. Реализация может быть написана с использованием режима OFB или CTR. Однако мне так и не удалось найти его. Может стиснуть зубы и написать это ...
UPDATE:
Итак, я написал реализацию этого. По разным причинам я не собираюсь публиковать это здесь прямо сейчас (я постараюсь в какой-то момент), но вот несколько советов для тех, кто хочет сделать это:
Использовать преобразование RijndaelManaged в режиме CBC. Вы собираетесь вычислять блок шифрованного потока блоком. Это можно сделать, инициализировав ключ и пустой (все ноль) iv в преобразовании - фактическое iv будет вычисляться для каждого блока отдельно.
Вам понадобится метод, который вычисляет входные данные для текущего блока путем объединения или иного вычисления счетчика nonce plus iv плюс. Здесь вы можете выполнить несколько оптимизаций, включая предварительные вычисления nonce & iv (этот метод будет вызываться много раз, поэтому, вероятно, оно того стоит).
например. byte [] GetCurrentCounterBlock (байт [] nonce, byte [] iv, счетчик UInt32)
(примечание: здесь под «iv» я подразумеваю то, что NIST называет IV, среднюю часть целого блока, которую другие люди называют IV вместе)
Вы собираетесь использовать этот метод внутри цикла, который шифрует ваши данные - вызывайте его сначала, а затем на границах блоков, чтобы обновить текущий поток шифров. Этот метод предоставляет вход для метода TransformBlock преобразования. Возьмите результат преобразования и присвойте результат XOR текущему блоку данных. Используйте transform.Reset () после того, как каждый блок зашифрован! В противном случае CBC попытается использовать выходные данные преобразования в качестве входных данных для следующего. Может быть более умный способ сделать это с .NET, но я не могу понять это. Я знаю, что BouncyCastle поддерживает OFB «изначально», так что это может быть лучшим вариантом, но это хороший быстрый способ получить многократно используемый криптопоток без внешних deps.
В любом случае, ключ в том, что весь этот метод (я называю его AesCtr256.Process - но вы могли бы быть более универсальным) работает с произвольным диапазоном данных внутри потока шифра. Вы можете легко использовать этот метод внутри пользовательского класса Stream. Это позволит искать произвольные местоположения внутри потока как при чтении, так и при записи, и даст вам данные с выравниванием байтов для работы (очень хорошо, поскольку теперь вы можете иметь криптопоток, который фактически сообщает истинную длину данных!) *
Другими словами, вы вычисляете поток шифра для произвольных частей потока, а затем просто добавляете xor к шифру или простому тексту для шифрования / дешифрования.
Две последние вещи: 1.) Я настоятельно рекомендую повторно использовать преобразование для жизни потока - его создание стоит дорого. 2.) Если вы собираетесь реализовать это , напишите модульные тесты для векторов NIST или аналогичные . Не думайте, что вы поняли это правильно - то, что вывод выглядит случайным, не означает, что он правильно зашифрован:).
Если у кого-то есть мысли о лучшем подходе или о том, как я полностью испортил действительно важный кусок кода, пожалуйста, напишите, спасибо!