Найшвидший хеш для некриптографічного використання?


154

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

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

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


6
Що заважає вам порівняти хеши?
NullUserException

3
NullUserException: Ти маєш рацію, я спробую їх із випадковими фразами довжини. Просто хотілося зрозуміти, що було б нормою, якщо хтось вирішує подібні речі.
Джон

5
MD5 насправді не такий повільний ...
Бурштин,

25
Ви впевнені, що функція хешування - це вузьке місце для всієї програми? Сумніваюсь у цьому
Ваше здоровий глузд

4
Це дуже гарне запитання, а коментарі, що вказують на те, що це не є, або маловажливим, та / або повинно бути очевидним та / або інтуїтивним - розчаровує та засмучує. (І теж зовсім не несподівано.)
Майкл

Відповіді:


56

CRC32 досить швидкий і для нього є функція: http://www.php.net/manual/en/function.crc32.php

Але ви повинні знати, що CRC32 матиме більше зіткнень, ніж хешів MD5 або навіть SHA-1, просто через зменшену довжину (32 біти порівняно з 128 бітами відповідно 160 біт). Але якщо ви просто хочете перевірити, чи зберігається рядок, що зберігається, вам буде добре з CRC32.


1
Нічого, лише потрібний тип даних - це ціле число без підпису, це буде ЗНАЧЕНО швидше, ніж інші хешування.
Іван,

2
@John: чи ні. 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
Peter Ajtai

Дякуємо за Ваш код. Я його трохи покращив. Я не думаю, що ми повинні порівнювати такі функції, як md5 (), які обробляють цілий рядок і цикли, які виконують байт за байтом, як ви зробили з xor. У PHP ці петлі дуже повільні і навіть повільніші, ніж сам md5. Ми повинні порівнювати одні корпуси з іншими, всі реалізовані як функції.
Максим Масютін

1
Просто швидка примітка - я спробував це з набагато довшою струною (~ 5000 знаків), і CRC32 був повільніше, ніж MD5 і SHA1 на моїй машині (i7-6650U, 16 Гб). CRC32 - 1,7s, MD5 - 1,4s, SHA1 - 1,5s. Завжди тестуйте на собі.
Сем Толтон

4
@Quamis тест приємний, але може ввести в оману - як зазначає @samTolton, результати відрізняються і md5швидше. Кращим тестом буде рандомізація вмісту та довжини рядків. таким чином ми отримуємо краще уявлення про реальні показники реального світу. Це також дозволить уникнути кешування. Подивіться: продуктивність контрольної суми php хешування
Шломі Хасід

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 року: ця відповідь є найсучаснішою. Бібліотеки для підтримки шуму в основному доступні для всіх мов.

Поточна рекомендація полягає у використанні сімейства Hurmur Hash (див. Конкретно варіанти murmur2 або murmur3 ).

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

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

Він також використовується в реалізаціях фільтрів Bloom . Ви повинні знати, що якщо ви шукаєте "швидкі хеші", ви, мабуть, стикаєтеся з типовою проблемою, яку вирішують фільтри Bloom. ;-)

Примітка : шум - хеш загального призначення, що означає НЕ криптографічний. Це не заважає знайти вихідний "текст", який створив хеш. НЕ підходить хеш-паролів.

Ще кілька деталей: MurmurHash - що це?


2
Існує відкритий запит тут , щоб додати murmurhash на PHP, який ви можете проголосувати.
keune

8

Замість того, щоб припускати, що MD5 "досить повільний", спробуйте. Проста реалізація MD5 на простому ПК (моя, 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

Caveat

Відповідь нижче не відповідає на запитання, оскільки не рекомендує хеш-функції. Пам'ятайте: "Хеш-функція - це будь-яка функція, яку можна використовувати для зіставлення даних довільного розміру до значень фіксованого розміру." (Вікіпедія) Відповідь нижче рекомендує перетворення, які не гарантують результатів фіксованого розміру.

Якщо ви готові послабити вимогу використання хеш-функції , читайте далі ...

Оригінальний відповідь

Я пропоную urlencode () або base64_encode () з цих причин:

  • Криптографія вам не потрібна
  • Ви хочете швидкості
  • Ви хочете, щоб ідентифікувати унікальні рядки під час очищення рядків з неправильним формуванням

Адаптуючи контрольний код в інших відповідях, я продемонстрував, що будь-який з цих способів є швидшим за будь-який алгоритм хешу. Залежно від вашої програми, ви можете використовувати urlencode () або base64_encode () для очищення будь-яких "неправильно сформованих" рядків, які ви хочете зберегти.


Re: "Ви хочете, щоб ідентифікувати унікальні рядки під час очищення" неправильно сформованих "рядків": ви б хотіли розробити, будь ласка?
Девід Дж.

Важко пригадати, про що я думав понад шість років тому ... Я, можливо, натякав на те, що у вас не виникає зіткнень з urlencode або base64_encode, тому результати були б такими ж унікальними, як і оригінальні рядки.
Анахроніст

2

Крок перший: Встановіть лібсодіум (або переконайтеся, що ви використовуєте 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 впевнений, але реалізація blake2b в USERLAND PHP буде набагато повільнішою, ніж C25-реалізований sha256 для PHP ... я б хотів, щоб 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.