Почему эти два файла имеют одно и то же значение, когда я использую MemoryStream?
-
19-09-2019 - |
Вопрос
Я пишу процедуру С#, которая создает хеши из файлов jpg.Если я передаю массив байтов моему объекту SHA512, я получаю ожидаемое поведение, однако, если я передаю поток памяти, два файла всегда хешируются до одного и того же значения.
Пример 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");
Это дает «Хешировано то же самое».
Что здесь происходит, чего мне не хватает?
Решение
Вы не перематываете потоки памяти, поэтому хеш вычисляется из пустой последовательности байтов.Использовать
ms1.Position = 0;
ms2.Position = 0;
после звонка Save
.
Еще одно замечание:не используй GetBuffer
таким образом.Использовать ToArray
который даст вам массив байтов того же размера, что и длина потока - GetBuffer
возвращает необработанный буфер, который (обычно) имеет некоторое дополнение, которое вы бы не хотели использовать случайно.Вы можете использовать GetBuffer
если вы затем убедитесь, что используете только соответствующую его часть, конечно - это позволит избежать создания новой копии данных.