Можно ли использовать CRC32 в качестве хэш-функции?
можно ли использовать CRC32 в качестве хэш-функции? Есть ли недостатки в этом подходе? Любой tradedeoffs?
3 ответов
CRC32 в строительство очень хорошо как хэш-алгоритм. The все дело CRC должен хэшировать поток байтов с как можно меньшим количеством столкновений. Тем не менее, есть несколько моментов для рассмотрения:
CRC не являются безопасными. Для безопасного хэширования вам нужен гораздо более вычислительно дорогой алгоритм. Для простого ковша hasher, безопасность, как правило, не проблема.
различные флейворы CRC существуют с различные свойства. Убедитесь, что вы используете правильный алгоритм, например, с хеш-полиномом 0x11EDC6F41 (CRC32C), который является оптимальным выбором общего назначения.
как компромисс скорости хэширования / качества, инструкция x86 CRC32 трудно превзойти. Однако эта инструкция не существует в старых процессорах, поэтому остерегайтесь проблем с переносимостью.
---- редактировать ----
Марк Адлер предоставил ссылку на полезную статью для оценки хэша по Брет Малви. Используя исходный код, приведенный в статье, я запустил "ковшовый тест" для CRC32C и Jenkins96. Эти таблицы показывают вероятность того, что действительно равномерное распределение будет хуже чем измеренный результат случайно самостоятельно. Итак,более высокие числа лучше. Автор считал 0,05 или ниже слабыми, а 0,01 или ниже-очень слабыми. Я полностью доверяю автору во всем этом и просто сообщаю результаты.
Я разместил * по всем экземплярам, где CRC32C работал лучше, чем Jenkins96. По этому простому подсчету CRC32C был более однородным хэшем, чем Jenkins96 54 из 96 раз. особенно если вы можете использовать инструкцию x86 CRC32, то компромисс представления скорости превосходен.
CRC32C (0x1EDC6F41) Uniform keys Text keys Sparse keys Bits Lower Upper Lower Upper Lower Upper 1 0.671 *0.671 *1.000 0.120 *0.572 *0.572 2 *0.706 *0.165 *0.729 *0.919 0.277 0.440 3 *0.878 *0.879 *0.556 0.362 *0.535 *0.542 4 0.573 0.332 0.433 0.462 *0.855 0.393 5 0.023 *0.681 0.470 0.907 0.266 0.059 6 *0.145 *0.523 0.354 *0.172 *0.336 0.588 7 0.424 0.722 0.172 *0.736 0.184 *0.842 8 *0.767 0.507 *0.533 0.437 0.337 0.321 9 0.480 0.725 *0.753 *0.807 *0.618 0.025 10 *0.719 0.161 *0.970 *0.740 *0.789 0.344 11 *0.610 0.225 *0.849 *0.814 *0.854 *0.003 12 *0.979 *0.239 *0.709 0.786 0.171 *0.865 13 *0.515 0.395 0.192 0.600 0.869 *0.238 14 0.089 *0.609 0.055 *0.414 *0.286 *0.398 15 *0.372 *0.719 *0.944 0.100 *0.852 *0.300 16 0.015 *0.946 *0.467 0.459 0.372 *0.793
и для Jenkins96, который автор статьи считал отличным хэшем:
Jenkins96 Uniform keys Text keys Sparse keys Bits Lower Upper Lower Upper Lower Upper 1 0.888 0.572 0.090 0.322 0.090 0.203 2 0.198 0.027 0.505 0.447 0.729 0.825 3 0.444 0.510 0.360 0.444 0.467 0.540 4 0.974 0.783 0.724 0.971 0.439 0.902 5 0.308 0.383 0.686 0.940 0.424 0.119 6 0.138 0.505 0.907 0.103 0.300 0.891 7 0.710 0.956 0.202 0.407 0.792 0.506 8 0.031 0.552 0.229 0.573 0.407 0.688 9 0.682 0.990 0.276 0.075 0.269 0.543 10 0.382 0.933 0.038 0.559 0.746 0.511 11 0.043 0.918 0.101 0.290 0.584 0.822 12 0.895 0.036 0.207 0.966 0.486 0.533 13 0.290 0.872 0.902 0.934 0.877 0.155 14 0.859 0.568 0.428 0.027 0.136 0.265 15 0.290 0.420 0.915 0.465 0.532 0.059 16 0.155 0.922 0.036 0.577 0.545 0.336
очевидно, вы могли бы, но вы не должны. Crc32 плохо распределяет входные биты по хэшу. Также он, конечно, никогда не должен использоваться в качестве одностороннего хэша, поскольку он не является таковым. Очень легко изменить сообщение для создания данного crc.
используйте хэш-алгоритм, разработанный для той цели, которую вы имеете в виду, что бы это ни было.
Я не знаю, почему Марк Адлер сказал ,что"crc32 плохо распределяет входные биты на хэш". В хэше crc32 нет одного бита, который точно равен входным битам. Любой бит хэша представляет собой линейную комбинацию входных битов. Во-вторых, crc всегда равномерно сопоставляет одно и то же количество различных входных последовательностей с заданным хэш-значением. Например, если у вас есть сообщение длиной 1000 бит, после crc32 вы всегда можете найти последовательности 2^(1000-32), которые производят заданное хэш-значение, не более, нет меньше.
Если вам не нужна функция безопасности, crc может отлично служить хэшем.
на самом деле, я думаю, что другие небезопасные хэш-функции могут быть проще, чем crc, если вам нужно иметь более длинный crc, например crc-256.