Генерация вариантов функций контрольной суммы для минимизации коллизий

Моя цель - эффективно выполнить исчерпывающее сравнение дерева каталогов. Учитывая набор файлов F, я должен вычислить классы эквивалентности EQV = [F₁, F₂, F₃, ... Fₙ] так, чтобы fⱼ, fₖ ∈ EQV[i] iff (fⱼ is identical to fₖ) for all i, j, k.

Мой общий подход состоит в том, чтобы начать с одного большого класса, содержащего все начальные файлы, EQV₀ = [[f₁, f₂, ..., fₙ]], и неоднократно разбивать его на более совершенные классы EQV₁, EQV₂... EQVₘ₋₁ на основе некоторых m эвристик, например, размер файла, функция контрольной суммы 1, контрольная сумма 2. После применения всех m эвристик (EQVₘ₋₁) необходимо провести попарное сравнение всех файлов в каждом классе в EQVₘ₋₁. Поскольку этот последний шаг является квадратичным для каждого из классов в EQVₘ₋₁, т.е.

O(sum(n² for n in map(len, EQVₘ₋₁)) )

и, вероятно, будет узким местом моего алгоритма, если каждое разбиение m выполняется за линейное время, моя цель - сделать EQVₘ₋₁ как можно более плоским.

Я хотел бы иметь доступ к множеству хороших хеш-функций, которые я могу применить для минимизации коллизий на EQVₘ₋₁. Моя текущая идея состоит в том, чтобы использовать некоторую функцию контрольной суммы, предоставляемую библиотекой, такую ​​​​как adler, и генерировать ее варианты, просто применяя ее к разным начальным байтам в файле. Другой — сначала применить быстрые хэш-функции, такие как adler, а затем более дорогие, такие как md5, только к тем классам, которые все еще слишком велики.

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

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

Редактировать: кажется, что другая идея использует «отпечаток пальца рабина» на основе фиксированного набора случайно сгенерированных входных данных. Будет ли это иметь смысл для этой цели? http://en.wikipedia.org/wiki/Rabin_fingerprint


person ealfonso    schedule 29.09.2013    source источник
comment
Спасибо @Veedrac за ваши правки, теперь я знаю, как форматировать эти математические символы.   -  person ealfonso    schedule 29.09.2013


Ответы (1)


Я бы рекомендовал сначала использовать adler32, затем crc32. Может быть много очень коротких файлов с одинаковыми adler32, но разными crc32. На самом деле, вы могли бы рассмотреть один шаг, используя crc32 для файлов меньше определенного размера при первом проходе. Этот размер может быть около 1K. Для более длинных файлов adler32 и crc32 будут иметь почти одинаковую вероятность столкновения.

В зависимости от того, сколько у вас файлов, вы можете рассмотреть следующий шаг с более крупными хэшами, например md5 или sha1. См. этот ответ для вероятности и количества ожидаемых столкновений для 32-битного контрольного значения. Грубо говоря, если у вас есть миллионы файлов, этот шаг стоит сделать.

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

person Mark Adler    schedule 29.09.2013
comment
Спасибо за подсказку о маленьких файлах, я заметил, что часто самые большие классы — это классы с маленькими файлами. Поскольку я могу вычислить постоянное число adler32 различных начальных байтов в одном и том же файле без дополнительных сложностей, я думал, например, вычислить adler32 для первых 10 блоков по 128 байт. Будут ли эти 10 adler32 отличаться, если файлы действительно различаются? - person ealfonso; 29.09.2013
comment
Также спасибо за ответ на мой вопрос! Приятно было получить ответ от того же автора этого полезного алгоритма. - person ealfonso; 29.09.2013
comment
128 байт ввода слишком мало для adler32. Вы должны сделать по крайней мере 1K блоков. Тогда вы сможете в полной мере использовать 32 бита. - person Mark Adler; 29.09.2013
comment
Я имел в виду, что 10 adler32s начинаются с каждого из первых 128 блоков, т.е. как если бы файлы были усечены до этого момента. Не adler32 только в одном блоке из 128 байт, извините, если это было неясно. - person ealfonso; 29.09.2013
comment
Проще и быстрее было бы просто сделать два adler32, каждый на половине файла. Это эффективно дает вам 64-битную проверку вместо 32-битной проверки с гораздо меньшей вероятностью коллизий для разных файлов. Выполнение более двух независимых adler32 привело бы к значительному уменьшению отдачи в этом приложении. Как и прежде, вы должны использовать crc32 для файлов размером менее 1 КБ или менее 2 КБ при разделении файла на две части для двух crc32. - person Mark Adler; 29.09.2013