Почему эти два файла имеют одно и то же значение, когда я использую MemoryStream?

StackOverflow https://stackoverflow.com/questions/1715362

  •  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 если вы затем убедитесь, что используете только соответствующую его часть, конечно - это позволит избежать создания новой копии данных.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top