Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MemoryStream to String, and back to MemoryStream without adding any bytes (encodings, etc.)

OK, I've come across some articles here and here, but they aren't doing quite what I need to do, and I'm running into some trouble.

I am receiving an encrypted piece of data as a memorystream. I need to somehow write the memorystream to a file (the way I wrote the mockup, as a string would be best), then retrieve the string from the file and send it, as a memorystream, to a service to be decrypted. I was just using a streamreader to store the memorystream as a string, and was reading the string into memory using an encoding.

The problem was I got an error saying that my encrypted data was corrupted. I think this means that I changed the bytes, somehow.

Here is the code reading the memorystream into a string:

using (StreamReader reader = new StreamReader(dataKeyResponse.CiphertextBlob))
{
    encryptedDataKey = reader.ReadToEnd();
}

And here is the code reading the string, retrieved from the file, into a memorystream:

MemoryStream mStream = new MemoryStream(ASCIIEncoding.Default.GetBytes(encryptedKey));

I thought the step that did it was the ASCIIEncoding, but then I implemented the workaround from above, converted the byte array to a memorystream, and got the same error.

byte[] bytes = new byte[encryptedKey.Length*sizeof (char)];
System.Buffer.BlockCopy(encryptedKey.ToCharArray(), 0, bytes, 0, bytes.Length);

string decryptedKey;
using (MemoryStream mStream = new MemoryStream())
{
    mStream.Write(bytes, 0, bytes.Length);
    var decryptRequest = new DecryptRequest()
    {CiphertextBlob = mStream};
    var decryptResponse = client.Decrypt(decryptRequest);
    using (StreamReader reader = new StreamReader(decryptResponse.Plaintext))
    {
        decryptedKey = reader.ReadToEnd();
    }
}

I am assuming (1) that there is something changing the data somehow and not some other error; (2) that it is in the stream -> string or string -> stream transition, and not the string -> file or string <- file transition; and (3) that a perfect copy of the data coming in and going out will fix the problem--the data coming in is supposed to be a "plaintext" encrypted version; maybe there is an expectation that I encode the stream coming in and going out (does encoding even change the data? I'm judging from the post that it does).

Either a confirmation that the bytes should be equivalent going in and going out, or a way to capture the memorystream in a file, and send it back out without changing anything would be awesome.

like image 792
Chris Avatar asked May 28 '15 21:05

Chris


1 Answers

Let's say, that your MemoryStream contains the following input data: [0x01, 0x02, 0x03, 0x04] When you read it with streamreader, the binary representation of your string will be: [0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04], because strings use two byte representation for a character. What you do afterwards is that you allocate 8 bytes for your "bytes" variable instead of 4, and fill it with the second (modified) data. You can use Convert.ToBase64String() to get a string representation, also you can use FromBase64String() to parse it back. Something like this:

var testData = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
var inputStream = new MemoryStream(testData);

var inputAsString = Convert.ToBase64String(inputStream.ToArray());
Console.WriteLine(inputAsString);

var outputStream = new MemoryStream(Convert.FromBase64String(inputAsString));

var result = BitConverter.ToString(outputStream.ToArray());           
Console.WriteLine(result);
like image 110
Viktor Peller Avatar answered Nov 05 '22 04:11

Viktor Peller