3

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();
        }
    }
}
gkman
  • 108
  • 1
  • 5
Ben
  • 2,122
  • 2
  • 28
  • 48
  • Because you write to, respectively read from the underlying stream? – CodeCaster May 05 '17 at 15:13
  • You write to crypto stream, it encrypts and writes result to MemoryStream (in your example). You read from crypto stream - it reads from MemoryStream, decrypts and returns result to you. – Evk May 05 '17 at 15:27

3 Answers3

11

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
figolu
  • 1,388
  • 13
  • 6
8

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.

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

bartonjs
  • 30,352
  • 2
  • 71
  • 111
0

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

user5285420
  • 37
  • 2
  • 3