2009-11-11 4 views
5

Я пишу подпрограмму C#, которая создает хэши из jpg-файлов. Если я передаю массив байтов моему объекту SHA512, тогда я получу ожидаемое поведение, однако, если я передам в поток памяти, то оба файла всегда будут иметь хэш с тем же значением.Почему эти два хэша файлов имеют одинаковое значение, когда я использую MemoryStream?

Пример 1:

 SHA512 mySHA512 = SHA512.Create(); 

     Image img1 = Image.FromFile(@"d:\img1.jpg"); 
     Image img2 = Image.FromFile(@"d:\img2.jpg"); 
     MemoryStream ms1 = new MemoryStream(); 
     MemoryStream ms2 = new MemoryStream(); 

     img1.Save(ms1, ImageFormat.Jpeg); 
     byte[] buf1 = ms1.GetBuffer(); 
     byte[] hash1 = mySHA512.ComputeHash(buf1); 

     img2.Save(ms2, ImageFormat.Jpeg); 
     byte[] buf2 = ms2.GetBuffer(); 
     byte[] hash2 = mySHA512.ComputeHash(buf2); 

     if (Convert.ToBase64String(hash1) == Convert.ToBase64String(hash2)) 
      MessageBox.Show("Hashed the same"); 
     else 
      MessageBox.Show("Different hashes"); 

, который производит различные "хешей". Но одна из перегрузок метода ComputeHash принимает объект потока, и я предпочел бы использовать его. Когда я это делаю:

 SHA512 mySHA512 = SHA512.Create(); 

     Image img1 = Image.FromFile(@"d:\img1.jpg"); 
     Image img2 = Image.FromFile(@"d:\img2.jpg"); 
     MemoryStream ms1 = new MemoryStream(); 
     MemoryStream ms2 = new MemoryStream(); 

     img1.Save(ms1, ImageFormat.Jpeg); 
     byte[] hash1 = mySHA512.ComputeHash(ms1); 

     img2.Save(ms2, ImageFormat.Jpeg); 
     byte[] hash2 = mySHA512.ComputeHash(ms2); 

     if (Convert.ToBase64String(hash1) == Convert.ToBase64String(hash2)) 
      MessageBox.Show("Hashed the same"); 
     else 
      MessageBox.Show("Different hashes"); 

Это производит «Хэши же».

Что здесь происходит, что мне не хватает?

+0

Они не являются копиями изображения _same_, не так ли? –

+0

Что происходит, если вы ищете начало потока после вызова .Save? например ms1.Seek (0, SeekOrigin.Begin); – Joe

+0

В этом случае вы можете использовать 'mySHA512.ComputeHash.ComputeHash (ms1.GetBuffer(), 0, (int) ms1.Length)'. Избегает ненужных копий – CodesInChaos

ответ

14

Вы не перематываете свои MemoryStreams, поэтому хеш вычисляется из пустой последовательности байтов. Использовать

ms1.Position = 0; 
ms2.Position = 0; 

после звонка Save.

Еще одно примечание: не используйте GetBuffer таким образом. Используйте ToArray, который даст вам массив байтов того же размера, что и длина потока. GetBuffer возвращает необработанный буфер, который (как правило) будет иметь отступы, которые вы не захотите использовать случайно. Вы можете использовать GetBuffer, если вы, конечно, убедитесь, что используете только соответствующую часть, это позволяет избежать создания новой копии данных.

+0

Спасибо за совет, который работает! –