CryptoStream: Why CryptoStreamMode.Write to encrypt and CryptoStreamMode.Read to decrypt?

别来无恙 提交于 2020-08-03 09:12:31

问题


Let e = 'password' and I am transforming it to 'as9kio0736' in a CryptoStream.

Let d = 'as9kio0736' and I am transforming it to 'password in a CryptoStream.

When I am transforming d back to 'password' why is it not considered writing in a 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 is designed to perform transformation from a stream to another stream only and allows transformations chaining. For instance you can encrypt a data stream then Base 64 encode the encryption output.

Chose the mode depending on whether you want to write to the transformation input stream or read from the transformation output stream.

CryptoStream documentation is misleading.
The first CrytoStream constructor argument is described as:
"The stream on which to perform the cryptographic transformation"

This description is ok if constructor third argument value is CryptoStreamMode.Read.

But if third argument value is CryptoStreamMode.Write the first constructor argument description should be:
"The stream on which the result of cryptographic transformation is written to"

Also, documentation does not mention clearly that if you use CryptoStreamMode.Write, you MUST call FlushFinalBlock on your CryptoStream object after you finish writing.

To summarize this:

Writing to the transformation input stream:

CryptoStream constructor arguments:

  • argument 1: destination stream
  • argument 3: CryptoStreamMode.Write

CryptoStream object use:

  • Write data to the CryptoStream object
  • Call FlushFinalBlock on the CryptoStream object

Reading from the transformation output stream:

CryptoStream constructor arguments:

  • argument 1: source stream
  • argument 3: CryptoStreamMode.Read

CryptoStream object use:

  • Read data from the CryptoStream object until you reach the stream end



回答2:


You can use CryptoStream in either direction for either operation; it's just where your data is and what you want to do with it.

If the data to process is already in a Stream (and you're okay with the stream getting drained and disposed), use CryptoStream in read mode and read the data out (including by using cryptoStream.CopyTo(someOtherStream)). If the data is in a byte[] and you want to write it to a Stream, use CryptoStream.Write.

In the .NET Core tests you can find examples both ways.

  • Using Read for both encrypt and decrypt: https://github.com/dotnet/corefx/blob/61fb32299a276f1aa4103c85dcec215dfddc252d/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCipherTests.cs#L466-L480
  • Using Write for both encrypt and decrypt: https://github.com/dotnet/corefx/blob/61fb32299a276f1aa4103c85dcec215dfddc252d/src/Common/tests/System/Security/Cryptography/AlgorithmImplementations/AES/AesCipherTests.cs#L609-L631

Heck, those are even in the same files. It's all just a matter of preference.




回答3:


CryptoStream gives the flexibility to read/write for both Encrypt and Decrypt. For the case where the direction is fixed it can be changed to move in either direction regardless of the implementation.

Here's a way to do it:

https://github.com/djpai/StreamConduit



来源:https://stackoverflow.com/questions/43808411/cryptostream-why-cryptostreammode-write-to-encrypt-and-cryptostreammode-read-to

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!