Шифрование потока с помощью ChaCha20Poly1305

Мне было интересно, как мне зашифровать много данных, используя ChaCha20Poly1305 или AesGcm. В моем проекте работает .NET 7.

Мне нужно зашифровать данные размером от 100 МБ до 1 ГБ с помощью одного из этих алгоритмов (для меня лучше подойдет ChaCha20Poly1305). Я не хочу загружать все данные в память.

Я спрашиваю, потому что не вижу перегрузки метода для ChaCha20Poly1305.Encrypt и Decrypt, который будет брать данные из потока и записывать зашифрованные данные в поток.

Я знаю, что могу использовать библиотеки, такие как NaCl, Libsodium или BouncyCastle, но я спрашиваю, потому что хотел бы сделать это без использования каких-либо внешних библиотек. Не предлагайте мне использовать такие классы, как Aes, я хочу использовать один из вышеперечисленных.


Функция, которую я ожидал быть доступной, оказалась недоступной.

// Other code like key generation ^
byte[] nonce = new byte[12];
byte[] tag = new byte[16];

var cipher = new ChaCha20Poly1305(key);

using FileStream inputFile = File.OpenRead("plainTextFile.dat");
using FileStream outputFile = File.OpenWrite("encrypted.bin");

// Error CS1503: Cannot convert System.IO.FileStream to byte[]
cipher.Encrypt(nonce, inputFile, outputFile, tag);

Спасибо за любую помощь. Я пробовал

Используйте бинарный поток для записи: learn.microsoft.com/en-us/dotnet/api/…

jdweng 30.06.2023 14:21

Это намеренно так. Большинство этих аутентифицированных API-интерфейсов шифрования не будут возвращать шифр/открытый текст до тех пор, пока тег аутентификации не будет рассчитан/проверен. Это особенно верно для дешифрования больше, чем для шифрования. Шифрование аутентификации предназначено для данных, которые могут полностью храниться в памяти. Тот факт, что это аутентифицированное шифрование, подтверждается этикетками GCM и Poly1305.

President James K. Polk-Strike 30.06.2023 14:50

@PresidentJamesK.Polk, значит, это означает, что я должен использовать ChaCha20Poly1305 только для небольших сообщений и данных? Итак, для текущего случая, когда есть большие файлы, я должен использовать алгоритм шифрования, такой как AesCbc.

Bird2 30.06.2023 14:53
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я никогда не видел класс шифра, но, похоже, он ожидает массив байтов, а не файл, поэтому просто прочитайте файл в массив и передайте его в функцию, теперь напишите новый файл с зашифрованным массивом:

using System.IO;


byte[] fileAsBytes = File.ReadAllBytes("plainTextFile.dat");
byte[] fileAsBytesButEncypted;
cipher.Encrypt(nonce, fileAsBytes, fileAsBytesButEncypted, tag);
File.WriteAllBytes("encrypted.bin", fileAsBytesButEncypted);

Вот в чем проблема - я не могу загрузить весь файл в память, так как файл слишком большой. Может быть, шифрование по частям, но тогда я не знаю, будет ли тег работать правильно при шифровании по частям. Класс «шифр» - это не класс, а экземпляр класса, если я понял ваш ответ.

Bird2 30.06.2023 14:29
Ответ принят как подходящий

Эти алгоритмы имеют стиль, называемый AEAD, что означает аутентифицированное шифрование со связанными данными. У них есть хорошее свойство безопасности, которое обеспечивает как конфиденциальность, так и целостность, но небезопасно выпускать какой-либо открытый текст до тех пор, пока тег (который находится в конце) не будет проверен.

Таким образом, вам нужно зашифровать данные фрагментами, каждый из которых имеет отдельный одноразовый номер. Проще всего это сделать с помощью фрагмента фиксированного размера, например 64 КиБ (65536 байт), хотя последний фрагмент может быть меньше. Каждый фрагмент получает 64-битный индекс, начиная с нуля. Вы выполняете XOR индекса фрагмента с исходным одноразовым номером и используете это значение в качестве одноразового номера для шифрования вашего фрагмента. Когда вы шифруете эти данные, вы передаете этот индекс плюс один байт (1, если это последний фрагмент, 0, если нет) в качестве дополнительных данных, чтобы предотвратить изменение порядка вашего сообщения злоумышленником, и когда вы записываете каждый фрагмент, вы напишу зашифрованные данные плюс тег.

При расшифровке то же самое. Вы выполняете XOR индекса фрагмента с исходным одноразовым номером, чтобы получить одноразовый номер для этого фрагмента и передать индекс и один байт в качестве дополнительных данных. Обратите внимание, что при чтении из файла вы будете считывать 64 КиБ данных плюс 16 байт тега в каждом фрагменте.

Вы, конечно, можете использовать AES-CBC для шифрования данных, но если вы не используете отдельный MAC-адрес, такой как HMAC с безопасной хэш-функцией (например, HMAC-SHA-256), то вы позволяете злоумышленнику вмешиваться в ваши данные, которые не являются безопасными. Поскольку вы должны проверить MAC-адрес перед выпуском открытого текста, чтобы избежать проблем с безопасностью, вы столкнетесь с той же проблемой, что и с AEAD. По сути, AEAD — это просто стандартный алгоритм шифрования со встроенным MAC.

Я попробую, спасибо!

Bird2 01.07.2023 14:02

Другие вопросы по теме