I am having problems to extract a string from a memory stream. The memory stream is decorated with a crypto stream. It appears, unless I flush the crypto stream, I cannot read anything from the memory stream.
I am trying to generate multiple strings (which will then be parsed to numerical values) within a for-loop. So far I can't read from a memory stream while the crypto stream is still active.
As one can see, I am trying to measure the runtime but the length of my memory stream always appears to be zero. I also need to find an efficient way to get a string from the encrypted byte array which i extract from the memory stream.
Stopwatch watch = new Stopwatch();
MemoryStream ms = new MemoryStream();
ICryptoTransform encryptor = aesInstance.CreateEncryptor(aesInstance.Key, aesInstance.IV);
CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write);
UTF8Encoding encoder = new UTF8Encoding();
int counter = (int)numericUpDown2.Value;
byte[] text;
byte[] num;
watch.Start();
for (int k = 0; k < rounds; k++) {
text = encoder.GetBytes(counter.ToString());
cs.Write(text, 0, text.Length);
cs.FlushFinalBlock();
num = new byte[ms.Length];
ms.Read(num, 0, (int)num.Length);
ms.Flush();
counter++;
}
watch.Stop();
A simple example based on what I wrote in the comment:
The length of each encrypted "packet" is prepended as an
Int32
to the packet. If you watch the output, you'll see that for the strings given the length of the packet is always 16 or 32. For longer strings it will go up by 16 at a time (48, 64, 80, 96...). Note that there is a bug with the CBC mode, so you can't correctlyTransformFinalBlock
twice or you'll get an error on decryption. To solve this I'm recreating theencryptor
/decryptor
for each string. This will cause equal strings to be encrypted in the same way. So if you encrypt"Foo"
twice, they will be the sameXXXXXXXXXYYYYYYYY
in the encrypted stream.CTR Mode
As I wrote in the comments, the best thing would be to have a CTR mode. The CTR mode has the advantage that the encrypted stream has the same length as the non-encrypted stream, and the input stream can be encrypted/decrypted one byte at a time. Using these two "characteristics" we can modify the encryption/decryption sample to encrypt/decrypt even the string length. Note that in the
AesCtr
class I've added some tests based on the vectors from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf, so the implementation should be correct.And then
Note the differences with the other example: here we reuse the
encryptor
/decryptor
, because in this way every "block" is encrypted in a chain, and even if the same string is repeated twice, the encrypted version will be different.