Jump to navigation

Poupou's Corner of the Web

Looking for perfect security? Try a wireless brick.
Otherwise you may find some unperfect stuff here...

Weblog

CryptoStream - is 3rd time a charm ?

This is the first time I see a framework class being used so differently by so many (or so few) people. Everyone seems to use it in a slightly, or in some case very, different way.

For example I like to think that we decrypt when we read from a stream (like a file) and encrypt when we write into it. However the inverse is also perfectly valid. That is, for example, we encrypt when reading from a (memory) stream and write the encrypted result into another (file) stream.

Actually the real difficulty wasn't in the different uses but about the assumptions that I made when implementing CryptoStream - most of them based on the way I used the class.

A few things can be a lot easier with a simpler model, like read/decrypt and write/encrypt, but get more complex when you have to permit all cases. Most problems come from the fact that we must pad the last block of data before encrypting it. This requires that we know the length of the stream. So using Stream.Length and Stream.Position made sense and worked (somewhat) well until someone tried a NetworkStream (which doesn't support either Length nor Position). A similar problem occurs during decryption, as we need to remove the padding of the last block.

The solution is to give very little real control over the actual reading from / writing to the stream. CryptoStream now acts like a buffer to ensure that there is something available when you read in it (but was most probably already encrypted/decrypted in a previous call). The same is true for writing into the stream - this is why it is so important to call FlushFinalBlock (so that CryptoStream knows you finished and can pad the last block).

Well it took me 3 rewrites to get it right or so I like to think (so please don't hesitate to prove me wrong and report any failures into bugzilla) and the last one was quite a surprise. On a positive note each rewrite resulted in a simpler implementation than the previous one.

Warning: I've run into some quite scary stuff when looking for sample code using CryptoStream. Most of it doesn't involve CryptoStream but the key and/or IV generation used as the ICryptoTransform. If you care enough about your data to encrypt it you should take care about how you do it. Conclusion: stick to samples from well-known sites (who review submissions) or well-know authors. Source code containing questions are generally not a good answer!


2/8/2004 23:27:38 | Comments

The views expressed on this website/weblog are mine alone and do not necessarily reflect the views of my employer.