CryptoStream: почему CryptoStreamMode.Write для шифрования и CryptoStreamMode.Read для дешифрования?

Пусть e = 'пароль', и я преобразую его в 'as9kio0736' в CryptoStream.

Пусть d = 'as9kio0736', и я преобразую его в 'пароль в CryptoStream.

Когда я преобразовываю d обратно в "пароль", почему это не считается записью в CryptoStream?

using (MemoryStream msEncrypt = new MemoryStream()) {
    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) {
        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) {
            swEncrypt.Write(plainText);
        }
    }
}

using (MemoryStream msDecrypt = new MemoryStream(cipherText)) {
    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) {
        using (StreamReader srDecrypt = new StreamReader(csDecrypt)) {
            plaintext = srDecrypt.ReadToEnd();
        }
    }
}

1 ответ

Решение

Вы можете использовать CryptoStream в любом направлении для любой операции; это просто где ваши данные и что вы хотите с ними делать.

Если данные для обработки уже находятся в потоке (и вы в порядке, когда поток истощается и удаляется), используйте CryptoStream в режиме чтения и считывайте данные (в том числе с помощью cryptoStream.CopyTo(someOtherStream)). Если данные находятся в byte[] и вы хотите записать его в поток, используйте CryptoStream.Write.

В тестах.NET Core вы можете найти примеры обоих способов.

  • Использование Read как для шифрования, так и для дешифрования
  • Использование записи как для шифрования, так и для дешифрования

Черт, они даже в тех же файлах. Это всего лишь вопрос предпочтений.

CryptoStream предназначен для выполнения преобразования только из потока в другой поток и позволяет связывать преобразования. Например, вы можете зашифровать поток данных, а затем Base 64 закодировать вывод шифрования.

Выберите режим в зависимости от того, хотите ли вы записать во входной поток преобразования или прочитать из выходного потока преобразования.

Документация CryptoStream вводит в заблуждение.
Первый аргумент конструктора CrytoStream описывается так:
"Поток, на котором выполняется криптографическое преобразование"

Это описание нормально, если значением третьего аргумента конструктора является CryptoStreamMode.Read.

Но если третьим значением аргумента является CryptoStreamMode.Write, то первым описанием аргумента конструктора должно быть:
"Поток, в который записывается результат криптографического преобразования"

Кроме того, в документации четко не упоминается, что если вы используете CryptoStreamMode.Write, вы ДОЛЖНЫ вызывать FlushFinalBlock для вашего объекта CryptoStream после того, как закончите писать.

Подводя итог этого:

Запись во входной поток преобразования:

Аргументы конструктора CryptoStream:

  • аргумент 1: целевой поток
  • аргумент 3: CryptoStreamMode.Write

Использование объекта CryptoStream:

  • Записать данные в объект CryptoStream
  • Вызовите FlushFinalBlock для объекта CryptoStream

Чтение из выходного потока преобразования:

Аргументы конструктора CryptoStream:

  • аргумент 1: исходный поток
  • аргумент 3: CryptoStreamMode.Read

Использование объекта CryptoStream:

  • Чтение данных из объекта CryptoStream до достижения конца потока

CryptoStream дает гибкость для чтения / записи как для шифрования, так и для дешифрования. В случае, когда направление фиксировано, его можно изменить, чтобы двигаться в любом направлении, независимо от реализации.

Вот как это сделать:

https://github.com/djpai/StreamConduit

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