Самый быстрый хеш для не криптографического использования?


154

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

Я предполагаю, что MD5 довольно медленно обрабатывает более 100 000 запросов, поэтому я хотел бы знать, какой будет лучший способ для хеширования фраз, возможно, развертывание моей собственной хэш-функции или использование hash('md4', '...'в конечном итоге будет быстрее?

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


6
Что мешает вам сравнивать хэши?
NullUserException

3
NullUserException: Вы правы, я попробую их со фразами произвольной длины. Просто хотел понять, что будет нормой, если таковая будет иметь дело с такими вещами.
Джон

5
MD5 на самом деле не такой медленный ...
Amber

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

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

Ответы:


56

CRC32 довольно быстрый, и для него есть функция: http://www.php.net/manual/en/function.crc32.php

Но вы должны знать, что CRC32 будет иметь больше коллизий, чем MD5 или даже хэши SHA-1, просто из-за уменьшенной длины (32 бита по сравнению со 128 битами и 160 битами соответственно). Но если вы просто хотите проверить, не повреждена ли сохраненная строка, вам подойдет CRC32.


1
Ничего себе, только требуемый тип данных - это целое число без знака, это будет ЗНАЧИТЕЛЬНО быстрее, чем другое хеширование.
Джон

2
@ Джон: или нет. CRC32 оказывается медленнее, чем MD4, и не намного быстрее, чем MD5, на процессорах ARM. Кроме того, CRC32 использует 32-разрядный целочисленный тип без знака, что является именно тем, что нужно MD5 ...
Томас Порнин

3
если у вас есть преимущество / роскошь нового процессора Intel, есть команда сборки crc32c, которая ... вероятно, очень быстрая (хотя это и не традиционное значение crc32). См. Также xxhash code.google.com/p/xxhash
rogerdpack

146
fcn     time  generated hash
crc32:  0.03163  798740135
md5:    0.0731   0dbab6d0c841278d33be207f14eeab8b
sha1:   0.07331  417a9e5c9ac7c52e32727cfd25da99eca9339a80
xor:    0.65218  119
xor2:   0.29301  134217728
add:    0.57841  1105

И код, используемый для генерации это:

 $loops = 100000;
 $str = "ana are mere";

 echo "<pre>";

 $tss = microtime(true);
 for($i=0; $i<$loops; $i++){
  $x = crc32($str);
 }
 $tse = microtime(true);
 echo "\ncrc32: \t" . round($tse-$tss, 5) . " \t" . $x;

 $tss = microtime(true);
 for($i=0; $i<$loops; $i++){
  $x = md5($str);
 }
 $tse = microtime(true);
 echo "\nmd5: \t".round($tse-$tss, 5) . " \t" . $x;

 $tss = microtime(true);
 for($i=0; $i<$loops; $i++){
  $x = sha1($str);
 }
 $tse = microtime(true);
 echo "\nsha1: \t".round($tse-$tss, 5) . " \t" . $x;

 $tss = microtime(true);
 for($i=0; $i<$loops; $i++){
  $l = strlen($str);
  $x = 0x77;
  for($j=0;$j<$l;$j++){
   $x = $x xor ord($str[$j]);
  }
 }
 $tse = microtime(true);
 echo "\nxor: \t".round($tse-$tss, 5) . " \t" . $x;

 $tss = microtime(true);
 for($i=0; $i<$loops; $i++){
  $l = strlen($str);
  $x = 0x08;
  for($j=0;$j<$l;$j++){
   $x = ($x<<2) xor $str[$j];
  }
 }
 $tse = microtime(true);
 echo "\nxor2: \t".round($tse-$tss, 5) . " \t" . $x;

 $tss = microtime(true);
 for($i=0; $i<$loops; $i++){
  $l = strlen($str);
  $x = 0;
  for($j=0;$j<$l;$j++){
   $x = $x + ord($str[$j]);
  }
 }
 $tse = microtime(true);
 echo "\nadd: \t".round($tse-$tss, 5) . " \t" . $x;

3
Ах, спасибо за это понимание на самом деле, просто укрепляет мое использование CRC32, будучи самым быстрым.
Джон

@John - Вы можете получить алгоритмы хеширования с помощью: hash_algos(). Следующий код для тестирования хэшей был в комментариях PHP ==> codepad.viper-7.com/5Wdhw6
Питер Айтай

Спасибо за ваш код. Я немного улучшил это. Я не думаю, что мы должны сравнивать такие функции, как md5 (), которые обрабатывают всю строку, и циклы, которые делают побайтно, как вы сделали с помощью xor. В PHP эти циклы очень медленные и даже медленнее, чем сам md5. Мы должны сравнить одну шляпу с другой, все реализованные как функции.
Максим Масютин

1
Просто небольшое замечание - я попробовал это с гораздо более длинной строкой (~ 5000 символов), а CRC32 был медленнее, чем MD5 и SHA1 на моей машине (i7-6650U, 16 ГБ). CRC32 - 1,7 с, MD5 - 1,4 с, SHA1 - 1,5 с. Всегда проверяйте себя.
Сэм Толтон

4
@Quamis тест хорош, но может вводить в заблуждение - как заметил @samTolton, результаты отличаются и md5быстрее. Лучшим тестом будет рандомизировать содержимое и длину строк. Таким образом, мы получаем лучшее представление о реальной производительности в реальном мире. Это также позволит избежать кеширования. Посмотрите: производительность контрольной суммы хэширования php
Shlomi Hassid

43

Ранжированный список, в котором каждый цикл разделяет одно и то же для шифрования, как и все остальные.

<?php

set_time_limit(720);

$begin = startTime();
$scores = array();


foreach(hash_algos() as $algo) {
    $scores[$algo] = 0;
}

for($i=0;$i<10000;$i++) {
    $number = rand()*100000000000000;
    $string = randomString(500);

    foreach(hash_algos() as $algo) {
        $start = startTime();

        hash($algo, $number); //Number
        hash($algo, $string); //String

        $end = endTime($start);

        $scores[$algo] += $end;
    }   
}


asort($scores);

$i=1;
foreach($scores as $alg => $time) {
    print $i.' - '.$alg.' '.$time.'<br />';
    $i++;
}

echo "Entire page took ".endTime($begin).' seconds<br />';

echo "<br /><br /><h2>Hashes Compared</h2>";

foreach($scores as $alg => $time) {
    print $i.' - '.$alg.' '.hash($alg,$string).'<br />';
    $i++;
}

function startTime() {
   $mtime = microtime(); 
   $mtime = explode(" ",$mtime); 
   $mtime = $mtime[1] + $mtime[0]; 
   return $mtime;   
}

function endTime($starttime) {
   $mtime = microtime(); 
   $mtime = explode(" ",$mtime); 
   $mtime = $mtime[1] + $mtime[0]; 
   $endtime = $mtime; 
   return $totaltime = ($endtime - $starttime); 
}

function randomString($length) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyz';
    $string = '';    
    for ($p = 0; $p < $length; $p++) {
        $string .= $characters[mt_rand(0, strlen($characters) - 1)];
    }
    return $string;
}

?>

И выход

1 - crc32b 0.111036300659
2 - crc32 0.112048864365
3 - md4 0.120795726776
4 - md5 0.138875722885
5 - sha1 0.146368741989
6 - adler32 0.15501332283
7 - tiger192,3 0.177447080612
8 - tiger160,3 0.179498195648
9 - tiger128,3 0.184012889862
10 - ripemd128 0.184052705765
11 - ripemd256 0.185411214828
12 - salsa20 0.198500156403
13 - salsa10 0.204956293106
14 - haval160,3 0.206098556519
15 - haval256,3 0.206891775131
16 - haval224,3 0.206954240799
17 - ripemd160 0.207638263702
18 - tiger192,4 0.208125829697
19 - tiger160,4 0.208438634872
20 - tiger128,4 0.209359407425
21 - haval128,3 0.210256814957
22 - sha256 0.212738037109
23 - ripemd320 0.215386390686
24 - haval192,3 0.215610980988
25 - sha224 0.218329429626
26 - haval192,4 0.256464719772
27 - haval160,4 0.256565093994
28 - haval128,4 0.257113456726
29 - haval224,4 0.258928537369
30 - haval256,4 0.259262084961
31 - haval192,5 0.288433790207
32 - haval160,5 0.290239810944
33 - haval256,5 0.291721343994
34 - haval224,5 0.294484138489
35 - haval128,5 0.300224781036
36 - sha384 0.352449893951
37 - sha512 0.354603528976
38 - gost 0.392376661301
39 - whirlpool 0.629067659378
40 - snefru256 0.829529047012
41 - snefru 0.833986997604
42 - md2 1.80192279816
Entire page took 22.755341053 seconds


Hashes Compared

1 - crc32b 761331d7
2 - crc32 7e8c6d34
3 - md4 1bc8785de173e77ef28a24bd525beb68
4 - md5 9f9cfa3b5b339773b8d6dd77bbe931dd
5 - sha1 ca2bd798e47eab85655f0ce03fa46b2e6e20a31f
6 - adler32 f5f2aefc
7 - tiger192,3 d11b7615af06779259b29446948389c31d896dee25edfc50
8 - tiger160,3 d11b7615af06779259b29446948389c31d896dee
9 - tiger128,3 d11b7615af06779259b29446948389c3
10 - ripemd128 5f221a4574a072bc71518d150ae907c8
11 - ripemd256 bc89cd79f4e70b73fbb4faaf47a3caf263baa07e72dd435a0f62afe840f5c71c
12 - salsa20 91d9b963e172988a8fc2c5ff1a8d67073b2c5a09573cb03e901615dc1ea5162640f607e0d7134c981eedb761934cd8200fe90642a4608eacb82143e6e7b822c4
13 - salsa10 320b8cb8498d590ca2ec552008f1e55486116257a1e933d10d35c85a967f4a89c52158f755f775cd0b147ec64cde8934bae1e13bea81b8a4a55ac2c08efff4ce
14 - haval160,3 27ad6dd290161b883e614015b574b109233c7c0e
15 - haval256,3 03706dd2be7b1888bf9f3b151145b009859a720e3fe921a575e11be801c54c9a
16 - haval224,3 16706dd2c77b1888c29f3b151745b009879a720e4fe921a576e11be8
17 - ripemd160 f419c7c997a10aaf2d83a5fa03c58350d9f9d2e4
18 - tiger192,4 112f486d3a9000f822c050a204d284d52473f267b1247dbd
19 - tiger160,4 112f486d3a9000f822c050a204d284d52473f267
20 - tiger128,4 112f486d3a9000f822c050a204d284d5
21 - haval128,3 9d9155d430218e4dcdde1c62962ecca3
22 - sha256 6027f87b4dd4c732758aa52049257f9e9db7244f78c132d36d47f9033b5c3b09
23 - ripemd320 9ac00db553b51662826267daced37abfccca6433844f67d8f8cfd243cf78bbbf86839daf0961b61d
24 - haval192,3 7d706dd2d37c1888eaa53b154948b009e09c720effed21a5
25 - sha224 b6395266d8c7e40edde77969359e6a5d725f322e2ea4bd73d3d25768
26 - haval192,4 d87cd76e4c8006d401d7068dce5dec3d02dfa037d196ea14
27 - haval160,4 f2ddd76e156d0cd40eec0b8d09c8f23d0f47a437
28 - haval128,4 f066e6312b91e7ef69f26b2adbeba875
29 - haval224,4 1b7cd76ea97c06d439d6068d7d56ec3d73dba0373895ea14e465bc0e
30 - haval256,4 157cd76e8b7c06d432d6068d7556ec3d66dba0371c95ea14e165bc0ec31b9d37
31 - haval192,5 05f9ea219ae1b98ba33bac6b37ccfe2f248511046c80c2f0
32 - haval160,5 e054ec218637bc8b4bf1b26b2fb40230e0161904
33 - haval256,5 48f6ea210ee1b98be835ac6b7dc4fe2f39841104a37cc2f06ceb2bf58ab4fe78
34 - haval224,5 57f6ea2111e1b98bf735ac6b92c4fe2f43841104ab7cc2f076eb2bf5
35 - haval128,5 ccb8e0ac1fd12640ecd8976ab6402aa8
36 - sha384 bcf0eeaa1479bf6bef7ece0f5d7111c3aeee177aa7990926c633891464534cd8a6c69d905c36e882b3350ef40816ed02
37 - sha512 8def9a1e6e31423ef73c94251d7553f6fe3ed262c44e852bdb43e3e2a2b76254b4da5ef25aefb32aae260bb386cd133045adfa2024b067c2990b60d6f014e039
38 - gost ef6cb990b754b1d6a428f6bb5c113ee22cc9533558d203161441933d86e3b6f8
39 - whirlpool 54eb1d0667b6fdf97c01e005ac1febfacf8704da55c70f10f812b34cd9d45528b60d20f08765ced0ab3086d2bde312259aebf15d105318ae76995c4cf9a1e981
40 - snefru256 20849cbeda5ddec5043c09d36b2de4ba0ea9296b6c9efaa7c7257f30f351aea4
41 - snefru 20849cbeda5ddec5043c09d36b2de4ba0ea9296b6c9efaa7c7257f30f351aea4
42 - md2 d4864c8c95786480d1cf821f690753dc

4
В конце есть минимальная ошибка. strlen($characters)должно быть strlen($characters) - 1:)
ММ.

29

На сайте xxhash есть сравнение скорости. Скопируйте его здесь:

 Name            Speed       Q.Score   Author
 xxHash          5.4 GB/s     10
 MumurHash 3a    2.7 GB/s     10       Austin Appleby
 SpookyHash      2.0 GB/s     10       Bob Jenkins
 SBox            1.4 GB/s      9       Bret Mulvey
 Lookup3         1.2 GB/s      9       Bob Jenkins
 CityHash64      1.05 GB/s    10       Pike & Alakuijala
 FNV             0.55 GB/s     5       Fowler, Noll, Vo
 CRC32           0.43 GB/s     9
 MD5-32          0.33 GB/s    10       Ronald L. Rivest
 SHA1-32         0.28 GB/s    10

Похоже, что xxHash является самым быстрым, в то время как многие другие используют более старые хеши, такие как CRC32, MD5 и SHA.

https://code.google.com/p/xxhash/

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


17
+-------------------+---------+------+--------------+
|       NAME        |  LOOPS  | TIME |     OP/S     |
+-------------------+---------+------+--------------+
| sha1ShortString   | 1638400 | 2.85 | 574,877.19   |
| md5ShortString    | 2777680 | 4.11 | 675,834.55   |
| crc32ShortString  | 3847980 | 3.61 | 1,065,922.44 |
| sha1MediumString  | 602620  | 4.75 | 126,867.37   |
| md5MediumString   | 884860  | 4.69 | 188,669.51   |
| crc32MediumString | 819200  | 4.85 | 168,907.22   |
| sha1LongString    | 181800  | 4.95 | 36,727.27    |
| md5LongString     | 281680  | 4.93 | 57,135.90    |
| crc32LongString   | 226220  | 4.95 | 45,701.01    |
+-------------------+---------+------+--------------+

Кажется, что crc32 быстрее для небольших сообщений (в данном случае 26 символов), а md5 для более длинных сообщений (в данном случае> 852 символа).


17

Обновление 2019 года: этот ответ является наиболее актуальным. Библиотеки для поддержки ропота в основном доступны для всех языков.

В настоящее время рекомендуется использовать семейство Murmur Hash (см., В частности, варианты murmur2 или murmur3 ).

Хэши Murmur были разработаны для быстрого хеширования с минимальными коллизиями (намного быстрее, чем CRC, MDx и SHAx). Он идеально подходит для поиска дубликатов и очень подходит для индексов HashTable.

Фактически он используется многими современными базами данных (Redis, ElastisSearch, Cassandra) для вычисления всевозможных хэшей для различных целей. Этот конкретный алгоритм стал основным источником многих улучшений производительности в текущем десятилетии.

Это также используется в реализациях Bloom Filters . Вы должны знать, что если вы ищете «быстрые хэши», вы, вероятно, сталкиваетесь с типичной проблемой, которая решается фильтрами Блума. ;-)

Примечание : шум - это хэш общего назначения, означающий НЕ криптографический. Это не мешает найти исходный «текст», сгенерировавший хеш. НЕ подходит для хэширования паролей.

Еще несколько деталей: MurmurHash - что это?


2
Существует открытый запрос здесь , чтобы добавить murmurhash на PHP, который вы можете проголосовать.
Keune

8

Вместо того, чтобы предполагать, что MD5 «довольно медленный», попробуйте. Простая реализация MD5 на основе C на простом ПК (мой, 2,4 ГГц Core2, использующий одно ядро) может хэшировать 6 миллионов маленьких сообщений в секунду . Небольшое сообщение здесь что-нибудь до 55 байтов. Для более длинных сообщений скорость хеширования MD5 является линейной по отношению к размеру сообщения, то есть он обрабатывает данные со скоростью около 400 мегабайт в секунду. Вы можете заметить, что это в четыре раза превышает максимальную скорость хорошего жесткого диска или гигабитной сетевой карты Ethernet.

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

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


Там есть точка для рассмотрения. MD5 занимает 128 бит вместо 32. Это означает, что хранилище базы данных занимает в 4 раза больше места и, следовательно, в 4 раза медленнее ищет сравнение хэшей (я думаю ). Что меня беспокоит (для моего использования), так это то, как быстро будет выполняться запрос к базе данных позже, когда она заполнена хешами.
Камило Мартин,

3
Если вы не используете достаточно широкий вывод, вы получите случайные коллизии, которые будут плохими, поскольку цель состоит в том, чтобы запросить базу данных, чтобы узнать, известна ли данная «фраза»; столкновения здесь превращаются в ложные срабатывания. С 32 битами вы начнете видеть столкновения, как только у вас будет 60000 или около того фраз. Это верно для всех хеш-функций, криптографических или нет. При этом вы всегда можете взять выходные данные хеш-функции и обрезать их до любой длины, которую считаете нужной, в рамках ограничений, описанных выше.
Томас Порнин

@ThomasPornin Если мы пойдем по усеченному пути, разве он не столкнется с проблемой столкновения, я имею в виду, что единственная причина, по которой md5 не может получить легкое столкновение, это лишнее количество символов, которые он имеет по сравнению с CRC32, верно?
Мохд Абдул Муджиб

4

Предостережение

Ответ ниже не отвечает на заданный вопрос, так как не рекомендует хеш-функции. Помните: «Хеш-функция - это любая функция, которую можно использовать для сопоставления данных произвольного размера со значениями фиксированного размера». (Wikipedia) Ответ ниже рекомендует преобразования, которые не гарантируют результаты фиксированного размера.

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

Оригинальный ответ

Я предлагаю urlencode () или base64_encode () по этим причинам:

  • Вам не нужна криптография
  • Вы хотите скорость
  • Вы хотите, чтобы способ идентифицировать уникальные строки при очистке "неправильно сформированных" строк

Адаптируя тестовый код в других местах этих ответов, я продемонстрировал, что любой из них работает намного быстрее любого хэш-алгоритма. В зависимости от вашего приложения вы можете использовать urlencode () или base64_encode () для очистки любых «искаженных» строк, которые вы хотите сохранить.


Re: «Вы хотите способ идентифицировать уникальные строки при очистке« уродливых »строк»: уточните, пожалуйста?
Дэвид Дж.

Трудно вспомнить, о чем я думал шесть лет назад ... Возможно, я имел в виду тот факт, что вы не столкнетесь с urlencode или base64_encode, поэтому результаты будут такими же уникальными, как и исходные строки.
Анахронист

2

Шаг первый: установите libsodium (или убедитесь, что вы используете PHP 7.2+)

Шаг второй: используйте одно из следующего:

  1. sodium_crypto_generichash(), который является BLAKE2b , хэш - функция более надежен , чем MD5 , но быстрее , чем SHA256. (Ссылка имеет ориентиры и т. Д.)
  2. sodium_crypto_shorthash()Это SipHash-2-4 , который подходит для хеш-таблиц, но не следует полагаться на сопротивление столкновению.

_shorthashпримерно в 3 раза быстрее _generichash, но вам нужен ключ, и у вас есть небольшой, но реалистичный риск столкновения. С _generichash, вам, вероятно, не нужно беспокоиться о столкновениях, и вам не нужно использовать ключ (но может понадобиться в любом случае).


1
вопрос "как быстро эта вещь"?
My1

1
sodium_crypto_generichash(), which is BLAKE2b, a hash function more secure than MD5 but faster than SHA256. (Link has benchmarks, etc.)- конечно, blake2b, но реализация USERLAND PHP для blake2b будет намного медленнее, чем реализация sha256 для PHP на C ... я бы хотел, чтобы PHP мог использовать blake2b в пакете hash_algos () ..
hanshenrik

Чистая реализация PHP здесь не предложена.
Скотт

1

Если вы ищете быстрый и уникальный, я рекомендую xxHash или что-то, что использует встроенную команду нового процессора crc32c, смотрите https://stackoverflow.com/a/11422479/32453 . Там также есть ссылки на, возможно, даже более быстрые хэши, если вы не слишком заботитесь о возможности столкновения.


1

Adler32 работает лучше всего на моей машине. И md5()оказалось быстрее чем crc32().


3
Если MD5 быстрее, чем универсальная функция CRC32, тогда что-то не так.
nxasdf

0

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

echo '<pre>';

$run = array();

function test($algo)
{
  #static $c = 0;
  #if($c>10) return;
  #$c++;

 $tss = microtime(true);
 for($i=0; $i<100000; $i++){
  $x = hash($algo, "ana are mere");
 }
 $tse = microtime(true);

 $GLOBALS['run'][(string)round($tse-$tss, 5)] = "\nhash({$algo}): \t".round($tse-$tss, 5) . " \t" . $x;
 #echo "\n$i nhash({$algo}): \t".round($tse-$tss, 5) . " \t" . $x;
}
array_map('test', hash_algos());
ksort($run);
print_r($run);
echo '</pre>';

Вы можете увидеть на http://www.dozent.net/Tipps-Tricks/PHP/hash-performance


0

CRC32 быстрее, но менее безопасен, чем MD5 и SHA1. Между MD5 и SHA1 разница в скорости невелика.


MD5 теперь считается небезопасным. Это гораздо более небезопасно, чем SHA1. Прочитайте MD5 вики-страницу.
Ахмед
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.