Более быстрая альтернатива MD5?

Я работаю над программой, которая ищет целые диски для данного файла. На данный момент я вычисляю хэш MD5 для известного файла, а затем рекурсивно просматриваю все файлы в поисках совпадения.

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

Весь код написан на C#.

Спасибо.

Обновлять

Я читал, что даже MD5 может быть довольно быстрым, и что дисковый ввод-вывод должен быть ограничивающим фактором. Это наводит меня на мысль, что мой код может быть не оптимальным. Есть ли проблемы с таким подходом?

        MD5 md5 = MD5.Create();
        StringBuilder sb = new StringBuilder();
        try
        {
            using (FileStream fs = File.Open(fileName, FileMode.Open, FileAccess.Read))
            {
                foreach (byte b in md5.ComputeHash(fs))
                    sb.Append(b.ToString("X2"));
            }
            return sb.ToString();
        }
        catch (Exception)
        {
            return "";
        }

Вместо использования .ToString ("x2") используйте blogs.msdn.com/b/blambert/archive/2009/02/22/…, что сэкономит вам время.

tcables 20.01.2011 22:18

Какой смысл называть ToLower и ToUpper?

Chibueze Opata 28.09.2013 21:38
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
14
2
16 502
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

просто читать файл линейно? Кажется довольно бессмысленным читать весь файл, вычислять хеш md5, а затем сравнивать хеш.

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

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

Я что-то упустил? Что в этом случае дает вам хеширование?

К сожалению, у меня не будет доступа к исходному файлу во время работы программы, поэтому хранение хешей (на самом деле многих хешей) - единственный способ сравнения.

Paul Beesley 14.11.2008 02:34

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

Steve Jessop 14.11.2008 05:00

Сначала подумайте, что на самом деле является вашим узким местом: сама хеш-функция или, скорее, скорость доступа к диску? Если вы ограничены диском, изменение алгоритма хеширования мало что вам даст. Из вашего описания я подразумеваю, что вы всегда сканируете весь диск, чтобы найти совпадение - сначала подумайте о создании индекса, а затем сопоставьте только заданный хэш с индексом, это будет намного быстрее.

Ответ принят как подходящий

Надеюсь, вы проверяете совпадение MD5 только в том случае, если размер файла уже совпадает.

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

Конечно, все это предполагает, что вы просто ищете совпадение / совпадение для определенного файла.

+1 за срез. Не нужно хешировать 37 гигов, когда первый байт другой.

Dan Lugg 14.11.2013 18:14

Есть одна небольшая проблема с использованием MD5 для сравнения файлов: есть известные пары файлов, которые имеют разные, но имеют такой же MD5.

Это означает, что вы можете использовать MD5, чтобы определить, являются ли файлы разные (если MD5 отличается, файлы должны быть разными), но вы не можете использовать MD5, чтобы определить, являются ли файлы равный (если файлы равны, MD5 должен быть то же самое, но если MD5 равны, файлы могут быть или не быть равными).

Вы должны либо использовать хэш-функцию, которая еще не была нарушена (например, SHA-1), либо (как упоминалось в @SoapBox) использовать MD5 только как быстрый способ найти кандидатов для более глубокого сравнения.

Использованная литература:

Верно, но это относится к хешированию в целом. Когда длина хэша равна n битам, есть только 2 ^ n возможных значений хэша. Но количество разных файлов бесконечно счетно. Таким образом, количество пар разных файлов, имеющих одинаковое хеш-значение, также бесконечно счетно.

Ingo 07.04.2009 14:50

@Ingo: да, но для MD5 мы знаем, как создать пару файлов с одинаковым хеш-значением (не только это, но уже известно несколько таких пар). Для криптографических хэшей, которые еще не были взломаны, мы не можем создать такую ​​пару специально, а создание ее случайно имеет крайне малую вероятность, достаточно мала, чтобы мы могли рассматривать ее, как если бы это было вообще невозможно (по крайней мере, до этого момента). хеш тоже ломается).

CesarB 17.04.2009 21:03

Его вариант использования, похоже, не касается атаки, поэтому это может не иметь значения.

Scott Stafford 30.03.2010 01:18

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

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

Звучит как хороший и логичный подход - спасибо за участие.

Paul Beesley 06.08.2010 13:32

Используйте MD5CryptoServiceProvider и BufferedStream

        using (FileStream stream = File.OpenRead(filePath))
        {
            using (var bufferedStream = new BufferedStream(stream, 1024 * 32))
            {
                var sha = new MD5CryptoServiceProvider();
                byte[] checksum = sha.ComputeHash(bufferedStream);
                return BitConverter.ToString(checksum).Replace("-", String.Empty);
            }
        }

-1: Это не ускоряет процесс. Чтобы сделать это быстрее, будет работать только пятилетний, принятый и высоко оцененный ответ.

Oliver 19.07.2013 14:50

Другие вопросы по теме