Объединение хеш-значений MD5 - PullRequest
14 голосов
/ 06 февраля 2010

При вычислении одной контрольной суммы MD5 для большого файла, какой метод обычно используется для объединения различных значений MD5 в одно значение? Вы просто добавляете их вместе? Я не очень заинтересован в каком-либо конкретном языке, библиотеке или API, которые будут это делать; скорее я просто интересуюсь техникой позади этого. Может кто-нибудь объяснить, как это делается?

Учитывая следующий алгоритм в псевдокоде:

MD5Digest X
for each file segment F
   MD5Digest Y = CalculateMD5(F)
   Combine(X,Y)

Но что именно Combine сделает? Добавляет ли он два дайджеста MD5 вместе или как?

Ответы [ 7 ]

16 голосов
/ 06 февраля 2010

Для расчета значений MD5 для файлов, которые слишком велики для размещения в памяти

Имея это в виду, вы не хотите "объединять" два хэша MD5. С любой реализацией MD5 у вас есть объект, который сохраняет текущее состояние контрольной суммы. Таким образом, вы можете извлечь контрольную сумму MD5 в любое время, что очень удобно при хешировании двух файлов с одинаковым началом. Для больших файлов вы просто продолжаете вводить данные - нет разницы, если вы хэшируете файл сразу или в блоках, поскольку состояние запоминается В обоих случаях вы получите один и тот же хеш.

6 голосов
/ 06 февраля 2010

MD5 - это итерационный алгоритм. Вам не нужно рассчитывать тонну маленьких MD5, а затем как-то их комбинировать. Вы просто читаете небольшие фрагменты файла и добавляете их в дайджест по мере того, как собираетесь, так что вам никогда не нужно иметь весь файл в памяти сразу. Вот реализация Java.

FileInputStream f = new FileInputStream(new File("bigFile.txt"));
MessageDigest digest = MessageDigest.getInstance("md5");
byte[] buffer = new byte[8192];
int len = 0;
while (-1 != (len = f.read(buffer))) {
   digest.update(buffer,0,len);
}
byte[] md5hash = digest.digest();

Et вуаля. У вас есть MD5 всего файла, но не весь файл в памяти сразу.

Стоит отметить, что если по какой-то причине вам понадобятся хеши MD5 для подразделов файла по мере продвижения (это иногда полезно для выполнения промежуточных проверок большого файла, передаваемого по соединению с низкой пропускной способностью), вы можете получить их путем клонирования объекта дайджеста в любое время, например

byte[] interimHash = ((MessageDigest)digest.clone()).digest();

Это не влияет на фактический дайджест-объект, поэтому вы можете продолжить работу с общим хешем MD5.

Стоит также отметить, что MD5 является устаревшим хешем для криптографических целей (таких как проверка подлинности файла из ненадежного источника) и должен быть заменен на что-то лучшее в большинстве случаев, например SHA-1. Для не криптографических целей, таких как проверка целостности файла между двумя доверенными источниками, MD5 по-прежнему подходит.

2 голосов
/ 06 февраля 2010

Этот вопрос не имеет большого смысла, так как алгоритм MD5 принимает любую длину ввода. Приличная библиотека должна иметь функции, чтобы вам не приходилось добавлять все сообщение за один раз, поскольку сообщение разбивается на блоки, последовательно хэшированные, причем обрабатываемый блок зависит только от результирующих хэшей из предыдущего цикл. * * 1 001

Псевдокод в статье в википедии должен дать обзор того, как работает алгоритм.

2 голосов
/ 06 февраля 2010

Библиотека openSSL позволяет вам добавлять блоки данных в текущий хеш (sha1 / md5), а затем, когда вы закончите добавлять все данные, вы вызываете метод Final, и она выведет окончательный хеш.

Вы не вычисляете md5 для каждого отдельного блока, а затем добавляете его, а добавляете данные в текущий метод хеширования из библиотеки openssl.Затем вы получите хэш md5 для всех отдельных блоков данных без ограничения размера входных данных.

http://www.openssl.org/docs/crypto/md5.html#

1 голос
/ 06 ноября 2014

Пример Python 2.7 для ответа AndiDog. Файл 123.txt имеет несколько строк.

>>> import hashlib
>>> md5_A, md5_B, md5_C = hashlib.md5(), hashlib.md5(), hashlib.md5()
>>> with open('123.txt', 'r') as f_r:
...     md5_A.update(f_r.read()) # read whole contents
... 
>>> with open('123.txt', 'r') as f_r:
...     for line in f_r: # read file line by line
...         md5_B.update(line)
... 
>>> with open('123.txt', 'r') as f_r:
...     while True: # read file chunk by chunk
...         chunk = f_r.read(10)
...         if not chunk: break
...         md5_C.update(chunk)
... 
>>> md5_A.hexdigest()
'5976ddfa19bc2e1669ac3bd836101f58'
>>> md5_B.hexdigest()
'5976ddfa19bc2e1669ac3bd836101f58'
>>> md5_C.hexdigest()
'5976ddfa19bc2e1669ac3bd836101f58'

Для больших файлов, которые не помещаются в памяти, их можно читать построчно или фрагмент за фрагментом. Одно из применений этого MD5 - сравнение двух больших файлов при сбое команды diff.

1 голос
/ 01 ноября 2013

Вот способ C # для объединения хешей. Давайте сделаем методы расширения, чтобы упростить пользовательский код.

public static class MD5Append
{
    public static int Append(this MD5 md5, byte[] data)
    {
        return md5.TransformBlock(data, 0, data.Length, data, 0);
    }

    public static void AppendFinal(this MD5 md5, byte[] data)
    {
        md5.TransformFinalBlock(data, 0, data.Length);
    }
}

Использование:

   using (var md5 = MD5CryptoServiceProvider.Create("MD5"))
        {
            md5.Initialize();

            var abcBytes = Encoding.Unicode.GetBytes("abc");
            md5.Append(abcBytes);
            md5.AppendFinal(abcBytes);

            var h1 = md5.Hash;

            md5.Initialize(); // mandatory
            var h2= md5.ComputeHash(Encoding.Unicode.GetBytes("abcabc"));

            Console.WriteLine(Convert.ToBase64String(h1));
            Console.WriteLine(Convert.ToBase64String(h2));
        }

h1 и h2 одинаковы. Вот и все.

1 голос
/ 06 февраля 2010

Большинство реализаций дайджест-расчета позволяют вам подавать им данные небольшими блоками. Вы не можете объединить несколько дайджестов MD5 так, чтобы результат был равен MD5 всего ввода. MD5 выполняет некоторые дополнения и использует количество обработанных байтов на последнем этапе, что делает исходное состояние механизма невосстановимым из окончательного значения дайджеста.

...