Я прочитал этот вопрос: Крекинг $f(x) = Cx \oplus Dx$
Спрашивая о поиске коллизий в простом 64-битном хэше, я подумал, что попробую сам, просто для удовольствия.
Я быстро написал код для поиска коллизий:
https://gist.github.com/meirmaor/b0e59352eb73cacec47d0f95c25a25fc
И все же он находит много близких столкновений и не находит полных столкновений, это меня сбивает с толку.
Описание алгоритма:
Я хотел решить эту проблему, используя 8 ГБ оперативной памяти, поэтому я выделяю два массива Int длины $2^{30}$ *(4 байта int) каждый.
Я заполняю их, хэшируя значения Int, беру младшие 30 бит в качестве индекса в оба массива и сохраняю верхние 32 бита в первом массиве, а исходный int — во втором массиве.
я заполняю с помощью $2^{32}$ возможные значения Int (в виде массивов байтов) и получить, как и ожидалось, скорость заполнения 98%, варьируются близко к идеализированному $1-е^{-4}$ Я ожидал.
Это похоже на хеш-таблицу, но я не имею дело с коллизиями, просто сохраняю одно значение для каждого 30-битного хеш-ключа. По сути, это сопоставление усеченного 62-битного хэша с 32-битным источником.
Затем я пытаюсь хешировать более длинные значения с дополнительным префиксом Int и искать столкновения, снова используя младшие 30 бит в качестве индекса для массива, проверяя, совпадают ли верхние 32, и если они совпадают, мы обнаружили близкое столкновение. Однако при их проверке я не обнаружил полного столкновения, я нашел более 60 близких столкновений, проверил их отдельно, они действительно совпадают в 62 или 63 битах, но я ожидал, что 1/4 будет полным столкновением, я получил 0.
Я повторил тест дважды, сначала сравнив хэши из 4 байтов с хэшами из 8 байтов, начиная с байтов {маленькое число, 0,0,0}. Затем я попытался сравнить хэши одинаковой длины, предварительно заполнив хэши данных, начиная с последовательности байтов {1,0,0,0}, и снова сравнив с префиксом {2+,0,0,0}.
Как это возможно, что-то особенное в этой хеш-функции? Странная ошибка в моем коде, позволяющая мне успешно находить близкие столкновения, но не полные столкновения?
Есть ли причина, по которой близкие столкновения, найденные таким образом, не превращаются в полные столкновения.
Пример найденного ближнего столкновения (у меня их много):
Массив (24, 0, 0, 0, 14, 103, 61, 80) против
Массив (1, 0, 0, 0, -2, -81, 79, 79)