none
Problems Getting CryptoStream, NetworkStream, and Rijndael To Work Together RRS feed

  • Question

  • I created a simple example to test out using CryptoStreams with Networkstreams for transferring Rijndael encrypted data, but can't get it to work properly. The problem seems to be (this is my understanding of it) that it will only send data in block sizes, which would be fine, but it seems like you need to fill up a another full block size before it will actually send the data you initially wanted to send(and then you have written stuff to the stream that hasn't been sent yet but was added just to get the previous data to send). I cannot use flushfinalblock, as I'm keeping the stream open. If you close the stream, it works properly(I assume it's forcing the flush), which is why the same code works perfectly fine with a FileStream. 

    Anyway, I've read a few things on the web where people have run into the same problems, I've just haven't found any solutions. People are calling flushfinalblock or writing to the stream twice to get it to send something, which are poor workarounds for the actual problem. And then others just say don't use Cryptostreams and networkstreams together. Does this really not work? MSDN has a small cryptostream/networkstream example, and my guess is it only works because they close the connection. 

    Below is the code I used client side for the most part. Not doing anything crazy - I feel like I'm either missing something important or CryptoStream and NetworkStream really just don't work well together. Does anyone have any working example code that sends data (and keeps the stream open), or can explain what's going on? In the below example only half the data gets sent.

    Edit: I know I can perform the steps separately and encrypt the data without the cryptostream  and send it via the networkstream, but I'd like to get this working writing data directly to the cryptostream.

    Thanks for the help.

    -dan 

    TcpClient tcpClient = new TcpClient("127.0.0.1", 7414);
    tcpClient.NoDelay = true;
    NetworkStream incomingStream = tcpClient.GetStream();

    RijndaelManaged RijndaelAlg = new RijndaelManaged();
    RijndaelAlg.Padding = PaddingMode.PKCS7;           
    RijndaelAlg = (RijndaelManaged)RijndaelManaged.Create();
    ICryptoTransform cryptTransform = RijndaelAlg.CreateEncryptor(rijndaelKey, rijndaelIV);
    CryptoStream cStream = new CryptoStream(incomingStream,cryptTransform,CryptoStreamMode.Write);
    byte [] bytesToSend = Encoding.ASCII.GetBytes("here is some data to encrypt....");
    cStream.Write(bytesToSend, 0, bytesToSend.Length);



    Thursday, February 25, 2010 4:21 PM

Answers

  •  

    Hi,

    This article provides a solution for the coexistence of NetworkStream, CryptoStream and Rijndael, hope it can help:

     

    As I'm using the Rijndael algorithm, and specifying the .BlockSize of the Rijndael provider that the ICrytoTransform uses as the maximum allowable 256 bits = 32 bytes, the CryptoStream was reading the data in .BlockSize, all the time.

    The trick here was that you must *at least* append an extra "dummy block" in .BlockSize for the ICryptoTransform to sense that there is another block. If I went for 128 bits BlockSize, the extra data required to push .Read operation would have been 16 bytes, instead.


    Sincerely,
    Eric
    MSDN Subscriber Support in Forum
    If you have any feedback of our support, please contact msdnmg@microsoft.com.
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    • Marked as answer by SamAgain Sunday, March 7, 2010 2:38 PM
    Friday, February 26, 2010 9:49 AM

All replies

  •  

    Hi,

    This article provides a solution for the coexistence of NetworkStream, CryptoStream and Rijndael, hope it can help:

     

    As I'm using the Rijndael algorithm, and specifying the .BlockSize of the Rijndael provider that the ICrytoTransform uses as the maximum allowable 256 bits = 32 bytes, the CryptoStream was reading the data in .BlockSize, all the time.

    The trick here was that you must *at least* append an extra "dummy block" in .BlockSize for the ICryptoTransform to sense that there is another block. If I went for 128 bits BlockSize, the extra data required to push .Read operation would have been 16 bytes, instead.


    Sincerely,
    Eric
    MSDN Subscriber Support in Forum
    If you have any feedback of our support, please contact msdnmg@microsoft.com.
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    • Marked as answer by SamAgain Sunday, March 7, 2010 2:38 PM
    Friday, February 26, 2010 9:49 AM
  • Hi dan,
    Does above article help? Please feel free to let us know if you have any other concerns.
    Sincerely,
    Eric
    MSDN Subscriber Support in Forum
    If you have any feedback of our support, please contact msdnmg@microsoft.com.
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Monday, March 1, 2010 2:14 AM