Как оценить вероятность столкновения хэша?

Я разрабатываю серверное приложение для поисковой системы. Система поиска копирует файлы во временный каталог и присваивает им случайные имена. Затем он передает имена временных файлов моему приложению. Мое приложение должно обрабатывать каждый файл в течение ограниченного периода времени, иначе оно будет закрыто - это мера безопасности, подобная сторожевой. Обработка файлов может занять много времени, поэтому мне нужно разработать приложение, способное справиться с этим сценарием. Если мое приложение будет закрыто в следующий раз, когда поисковая система захочет проиндексировать тот же файл, она, скорее всего, даст ему другое временное имя.

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

Проблема в том, как идентифицировать файлы. Их имена меняются случайным образом. Я намерен использовать хеш-функцию, такую ​​как MD5, для хеширования содержимого файла. Мне хорошо известен парадокс дня рождения, и я использовал оценку из связанной статьи для вычисления вероятности . Если я предполагаю, что у меня не более 100 000 файлов, вероятность того, что два файла будут иметь одинаковый MD5 (128 бит), составляет около 1,47x10 -29.

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


person sharptooth    schedule 14.05.2009    source источник
comment
это хеш содержимого имени файла?   -  person Sam Saffron    schedule 14.05.2009
comment
Контент хешируется. Нет смысла хешировать имена файлов - они меняются случайным образом.   -  person sharptooth    schedule 14.05.2009
comment
Если вас беспокоят коллизии, учитывайте как размер файла, так и хэш.   -  person Marcus Adams    schedule 07.05.2012


Ответы (5)


Равный хэш означает одинаковый файл, если только кто-то злонамеренный не возится с вашими файлами и не создает коллизии. (это может иметь место, если они загружают материал из Интернета). Если это так, используйте функцию на основе SHA2.

Случайных коллизий MD5 не бывает, 1,47x10 -29 - действительно очень маленькое число.

Чтобы решить проблему перефразирования больших файлов, я бы использовал трехэтапную схему идентификации.

  1. Только размер файла
  2. Размер файла + хеш 64К * 4 в разных позициях в файле
  3. Полный хеш

Итак, если вы видите файл нового размера, значит, вы точно знаете, что у вас нет дубликата. И так далее.

person Sam Saffron    schedule 14.05.2009
comment
@sharptooth см. этот вопрос, чтобы узнать о некоторых приемах, которые вы можете использовать: stackoverflow.com/questions/788761/ - person Sam Saffron; 14.05.2009
comment
У меня первая коллизия MD5 после 25К изображений уже в БД - person Valentin Heinitz; 21.01.2015
comment
Случайных коллизий MD5 нет - это утверждение неверно. - person ColinM; 30.09.2016
comment
Мне понравилась идея хеширования некоторых небольших частей перед хешированием всего файла. Может значительно ускорить проверку дубликатов файлов. - person Toni Homedes i Saun; 05.11.2019

Тот факт, что вероятность равна 1 / X, не означает, что с вами этого не случится, пока у вас не будет X записей. Это похоже на лотерею: вы вряд ли выиграете, но кто-то где-то там выиграет.

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

Если производительность действительно является проблемой, используйте BLAKE2, который на самом деле быстрее, чем MD5, но поддерживает более 256 бит, чтобы уменьшить вероятность коллизий, имея такую ​​же или лучшую производительность. Однако, хотя BLAKE2 был хорошо принят, вероятно, потребуется добавить новую зависимость в ваш проект.

person ColinM    schedule 30.09.2016
comment
Однако с лотереей у вас есть гарантированный победитель. В то время как нет известных конфликтов SHA256, и технически возможно, чтобы их никогда не было до полного исчерпания, верно? - person JamesTheAwesomeDude; 24.07.2017
comment
Хороший момент, в целом для приложения для хеширования файлов вы можете с уверенностью предположить, что SHA-256 никогда не вызовет коллизий (в отличие от SHA1, который используется git, и коллизии происходили в больших реальных проектах). Однако, если вы используете SHA-256 для хеширования случайных входных битов (например, для генерации идентификатора сеанса), вы все равно должны учитывать, что шансы коллизии RNG одинаковы для заданного количества входных битов независимо от используемого метода хеширования. То есть хеширование случайного 32-битного целого числа с помощью SHA-256 - это всего лишь 32 бита данных, поэтому вероятны коллизии. - person ColinM; 09.08.2017

Думаю, не стоит.

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

person alamar    schedule 14.05.2009
comment
Это проблема поисковой системы, а не моего приложения. Моему приложению нужно только извлекать текст из переданных файлов. - person sharptooth; 14.05.2009

Я придумал подход Монте-Карло, чтобы иметь возможность безопасно спать при использовании UUID для распределенных систем, которые должны сериализоваться без коллизий.

from random import randint
from math import log
from collections import Counter

def colltest(exp):
    uniques = []
    while True:
        r = randint(0,2**exp)
        if r in uniques:
            return log(len(uniques) + 1, 2)
        uniques.append(r)

for k,v in Counter([colltest(20) for i in xrange(1000)]):
    print k, "hash orders of magnitude events before collission:",v

напечатал бы что-то вроде:

5 hash orders of magnitude events before collission: 1
6 hash orders of magnitude events before collission: 5
7 hash orders of magnitude events before collission: 21
8 hash orders of magnitude events before collission: 91
9 hash orders of magnitude events before collission: 274
10 hash orders of magnitude events before collission: 469
11 hash orders of magnitude events before collission: 138
12 hash orders of magnitude events before collission: 1

Я слышал эту формулу раньше: если вам нужно хранить ключи журнала (x / 2), используйте функцию хеширования, которая имеет как минимум пространство ключей e ** (x).

Неоднократные эксперименты показывают, что для популяции в 1000 log-20 пространств вы иногда получаете коллизию уже в log (x / 4).

Для uuid4, который составляет 122 бита, это означает, что я спокойно сплю, в то время как несколько компьютеров выбирают случайные uuid, пока у меня не будет около 2 ** 31 элемента. Пик транзакций в системе, о которой я думаю, составляет примерно 10-20 событий в секунду, я предполагаю, что в среднем 7. Это дает мне рабочее окно примерно в 10 лет, учитывая эту крайнюю паранойю.

person Árni St. Sigurðsson    schedule 30.01.2015

Вот интерактивный калькулятор, который позволяет оценить вероятность столкновения для любого размера хэша и количества объектов - http://everydayinternetstuff.com/2015/04/hash-collision-probability-calculator/

person Ghostrider    schedule 23.04.2015
comment
Вопрос не в оценке вероятности. Я знаю вероятность. Вопрос в том, что мне делать дальше. - person sharptooth; 23.04.2015
comment
Что вы делаете дальше, просто: вы выбираете хеш-функцию с большим количеством битов и, желательно, с лучшим распределением, например sha1, а затем описываете вероятность столкновения, что происходит, когда оно происходит, и каковы последствия. - person Ellert van Koperen; 31.10.2015