2015-05-28 13 views
9

OK, natknąłem się na niektóre artykuły i here, ale one nie robią tego, co muszę, a ja " m boryka się z kłopotami.MemoryStream to String, a następnie z powrotem do MemoryStream bez dodawania żadnych bajtów (kodowania itp.).

Otrzymuję zaszyfrowaną część danych jako komunikat listy. Muszę jakoś napisać memorystream do pliku (tak jak napisałem makietę, ponieważ najlepiej byłoby napisać), a następnie pobrać ciąg z pliku i wysłać go, jako komunikat memorysowy, do usługi do odszyfrowania. Używałem właśnie programu do odczytywania strumieniowego do zapisywania strumienia memorystów jako ciągu znaków i czytałem ciąg znaków w pamięci za pomocą kodowania.

Problem polegał na tym, że wystąpił błąd informujący, że moje zaszyfrowane dane zostały uszkodzone. Myślę, że to oznacza, że ​​jakoś zmieniłem bajty.

Oto kod czytanie MemoryStream na ciąg znaków:

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

A oto kod czytania ciąg, pobierane z pliku, do MemoryStream:

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

myślałem, że krokiem, który to zrobił był ASCIIEncoding, ale potem zaimplementowałem the workaround from above, skonwertowałem tablicę bajtów na memorystream i otrzymałem ten sam błąd.

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(); 
    } 
} 

Zakładam (1) że coś zmienia dane w jakiś sposób, a nie jakiś inny błąd; (2) że jest w strumieniu -> ciąg lub ciąg -> przejście strumienia, a nie ciąg -> plik lub ciąg < - przejście pliku; oraz (3) że idealna kopia danych przychodzących i wychodzących rozwiązuje problem - dane przychodzące mają być zaszyfrowaną wersją "tekstu jawnego"; być może istnieje oczekiwanie, że zakodowuję strumień przychodzący i wychodzący (czy kodowanie zmienia nawet dane?) Sądzę, że to robi z post.

Albo potwierdzenie, że bajty powinny być równoważne wchodzeniu i wychodzeniu, albo sposobowi uchwycenia memorystream w pliku i wysłaniu go z powrotem bez zmiany czegokolwiek byłoby niesamowite.

+4

Nie zapisuj danych binarnych (nietekstowych) jako ciągów znaków. Nie ma sensu. Po prostu traktuj jak strumień bajtów. – Blorgbeard

+0

Oto sposób zapisywania/ładowania stanu pamięci: http://stackoverflow.com/questions/8624071/save-and-load-memorystream-to-from-a-file – Blorgbeard

+0

Nie można przechowywać dowolnych bajtów jako ciągów, ponieważ [łańcuchy mają reguły ] (http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences) i arbitralne bajty nie. Musisz jakoś zakodować bajty (np. Base64) lub zapisać surowe bajty, a nie ciągi. –

Odpowiedz

8

Powiedzmy, że Twój MemoryStream zawiera następujące dane wejściowe: [0x01, 0x02, 0x03, 0x04] Kiedy czytasz go StreamReader, binarna reprezentacja ciąg będą: [0x00, 0x01, 0x00, 0x02 , 0x00, 0x03, 0x00, 0x04], ponieważ łańcuchy używają dwubajtowej reprezentacji dla znaku. Następnie należy przydzielić 8 bajtów dla zmiennej "bytes" zamiast 4, a następnie uzupełnić ją drugą (zmodyfikowaną) danymi. Możesz użyć Convert.ToBase64String(), aby uzyskać reprezentację łańcuchową, możesz również użyć FromBase64String(), aby ją sparsować. Coś takiego:

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);