ChatGPT解决这个技术问题 Extra ChatGPT

非加密用途的最快哈希?

我基本上是在准备要放入数据库的短语,它们可能格式不正确,所以我想存储它们的简短哈希(我将简单地比较它们是否存在,所以哈希是理想的)。

我假设 MD5 在 100,000 多个请求上相当慢,所以我想知道散列短语的最佳方法是什么,也许推出我自己的散列函数或使用 hash('md4', '...' 最终会更快?

我知道 MySQL 有 MD5(),所以这将在查询端补充一点速度,但也许 MySQL 中还有一个更快的散列函数,我不知道它是否适用于 PHP..

是什么阻止您对哈希进行基准测试?
NullUserException:你是对的,我会用随机长度的短语来尝试它们。只是想了解处理此类事情的规范(如果有的话)。
MD5真的没那么慢...
这是一个很好的问题,暗示它不是,或者不重要,和/或应该是明显和/或直观的评论 - 令人失望和沮丧。 (而且一点也不意外。)

Q
Quamis
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;

啊,实际上感谢您的这一见解,只是加强了我对 CRC32 的使用速度最快。
@John - 您可以使用 hash_algos() 检索散列算法。以下哈希基准代码位于 PHP 注释中 ==> codepad.viper-7.com/5Wdhw6
谢谢你的代码。我已经改进了一点。我不认为我们应该比较像 md5() 这样处理整个字符串的函数和像你用 xor 做的那样逐字节执行的循环。在 PHP 中,这些循环非常慢,甚至比 md5 本身还要慢。我们应该将一个 hases 与另一个进行比较,所有这些都作为函数实现。
快速说明一下 - 我用更长的字符串(约 5000 个字符)尝试了此操作,并且 CRC32 在我的机器(i7-6650U,16GB)上比 MD5 和 SHA1 慢。 CRC32 - 1.7s,MD5 - 1.4s,SHA1 - 1.5s。始终为自己测试。
@Quamis 测试很好,但可能会产生误导 - 正如@samTolton 指出的结果不同,md5 更快。更好的测试也是随机化字符串的内容和长度。通过这种方式,我们可以更好地了解实际的现实世界表现。这也将避免缓存。看看:php hashing checksum performance
h
hdante

xxHash 存储库上有一个速度比较。这就是它在 2021 年 1 月 12 日显示的内容。

Hash Name Width Bandwidth (GB/s) Small Data Velocity Quality Comment XXH3 (SSE2) 64 31.5 GB/s 133.1 10 XXH128 (SSE2) 128 29.6 GB/s 118.1 10 RAM 顺序读取 N/A 28.0 GB/s N/AN/ A供参考 City64 64 22.0 GB/s 76.6 10 T1ha2 64 22.0 GB/s 99.0 9 稍差【碰撞】 City128 128 21.7 GB/s 57.7 10 XXH64 64 19.4 GB/s 71.0 10 SpookyHash 64 19.3 GB/s 53.2 1 18.0 GB/s 67.0 9 稍差[碰撞] XXH32 32 9.7 GB/s 71.9 10 City32 32 9.1 GB/s 66.0 10 Murmur3 32 3.9 GB/s 56.1 10 SipHash 64 3.0 GB/s 43.2 10 FNV624 64 1.2 GB/s 6 5 雪崩特性较差 Blake2 256 1.1 GB/s 5.1 10 加密 SHA1 160 0.8 GB/s 5.6 10 加密但损坏 MD5 128 0.6 GB/s 7.8 10 加密但损坏

似乎 xxHash 是迄今为止最快的一个,而许多其他的则击败了较旧的哈希,例如 CRC32、MD5 和 SHA。


j
joschi

CRC32 非常快,并且有一个函数:http://www.php.net/manual/en/function.crc32.php

但是您应该知道,CRC32 将比 MD5 甚至 SHA-1 哈希有更多的冲突,这仅仅是因为减少了长度(32 位与 128 位和 160 位相比)。但是,如果您只想检查存储的字符串是否已损坏,则可以使用 CRC32。


哇,唯一需要的数据类型是无符号整数,这将比其他散列法快得多。
@John:或者不是。结果证明,在 ARM 处理器上,CRC32 比 MD4 慢,并且比 MD5 快不了多少。此外,CRC32 使用无符号 32 位整数类型,这正是 MD5 所需要的...
如果您拥有较新的英特尔 cpu 的好处/奢侈品,那么有一个 crc32c 汇编命令......可能非常快(尽管不是传统的 crc32 值)。另请参阅 xxhash code.google.com/p/xxhash
P
Pez Cuckow

排名列表,其中每个循环与所有其他循环共享相同的东西来加密。

<?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

最后有一个最小的错误。 strlen($characters) 应该是 strlen($characters) - 1 :)
u
user5994461

2019 年更新:此答案是最新的。支持杂音的库在很大程度上适用于所有语言。

目前的建议是使用 Murmur Hash Family(具体参见 murmur2murmur3 变体)。

Murmur 散列被设计用于以最小的冲突进行快速散列(比 CRC、MDx 和 SHAx 快得多)。查找重复项非常完美,非常适合 HashTable 索引。

事实上,许多现代数据库(Redis、ElastisSearch、Cassandra)都使用它来计算各种用途的各种哈希值。这种特定的算法是当前十年中许多性能改进的根本来源。

它还用于 Bloom Filters 的实现。您应该知道,如果您正在搜索“快速哈希”,您可能会遇到一个由 Bloom 过滤器解决的典型问题。 ;-)

注意:杂音是一个通用哈希,意思是非加密的。它不会阻止找到生成哈希的源“文本”。散列密码是不合适的。

更多详细信息:MurmurHash - what is it?


有一个将 murmurhash 添加到 php 的开放请求 here,您可以对其进行投票。
c
castis
+-------------------+---------+------+--------------+
|       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 个字符)更快。


T
Thomas Pornin

不要假设 MD5 “相当慢”,而是尝试一下。在简单的 PC(我的,2.4 GHz Core2,使用单核)上简单的基于 C 的 MD5 实现每秒可以散列 600 万条小消息。一条小消息在这里最多 55 个字节。对于较长的消息,MD5 散列速度与消息大小成线性关系,即它以大约每秒 400 兆字节的速度处理数据。您可能会注意到,这是优质硬盘或千兆以太网网卡最大速度的四倍。

由于我的 PC 有四个内核,这意味着像我的硬盘一样快的散列数据可以提供或接收最多使用 6% 的可用计算能力。在非常特殊的情况下,哈希速度会成为瓶颈,甚至会在 PC 上引起显着的成本。

在散列速度可能变得有点相关的小得多的架构上,您可能希望使用 MD4。 MD4 可用于非加密目的(并且出于加密目的,您无论如何都不应该使用 MD5)。据报道,在基于 ARM 的平台上,MD4 甚至比 CRC32 还要快。


有一点需要考虑。 MD5 占用 128 位而不是 32 位。这意味着数据库存储需要多 4 倍的空间,因此查找比较散列的速度要慢 4 倍(我认为)。我关心的是(对于我的用途),当数据库充满散列时查询数据库的速度有多快。
如果您没有使用足够宽的输出,那么您将得到随机冲突,这将很糟糕,因为目标是查询数据库以了解给定的“短语”是否已知;这里的碰撞变成误报。使用 32 位,只要有 60000 个左右的短语,您就会开始看到冲突。这适用于所有散列函数,无论是否加密。话虽如此,您始终可以在上述限制范围内获取哈希函数的输出并将其截断为您认为合适的任何长度。
@ThomasPornin 如果我们采用截断方式,它不会再次面临碰撞问题,我的意思是 md5 应该不容易碰撞的唯一原因是它与 CRC32 相比具有额外的字符数,对吧?
如果您担心散列在数据库中需要多少空间,那么只使用散列的前 X 位是完全有效的。不一定推荐它,但您可以使用 MD5 并且只使用前四个字节。
C
Community

如果您正在寻找快速和独特的,我推荐 xxHash 或使用较新 cpu 的 crc32c 内置命令的东西,请参阅 https://stackoverflow.com/a/11422479/32453。如果您不太关心碰撞的可能性,它还会在那里链接到可能更快的哈希值。


D
David J.

警告

下面的答案没有回答所问的问题,因为它不推荐散列函数。请记住,“哈希函数是可用于将任意大小的数据映射到固定大小值的任何函数。” (维基百科)下面的答案推荐不保证固定大小结果的转换。

如果您愿意放宽使用哈希函数的要求,请继续阅读...

原始答案

出于以下原因,我建议使用 urlencode() 或 base64_encode():

你不需要密码学

你想要速度

您想要一种在清理“格式错误”的字符串时识别唯一字符串的方法

在这些回复的其他地方调整基准代码,我已经证明其中任何一个都比任何哈希算法都快。根据您的应用程序,您可能能够使用 urlencode() 或 base64_encode() 来清理您想要存储的任何“格式错误”的字符串。


回复:“您想要一种在清理‘畸形’字符串的同时识别唯一字符串的方法”:您能详细说明一下吗?
很难记住六年前我在想什么……我可能一直在暗示这样一个事实,即您不会与 urlencode 或 base64_encode 发生冲突,因此结果将与原始字符串一样独特。
S
Scott Arciszewski

第一步:Install libsodium(或确保您使用的是 PHP 7.2+)

第二步:使用以下方法之一:

sodium_crypto_generichash(),即 BLAKE2b,一个比 MD5 更安全但比 SHA256 更快的哈希函数。 (链接有 benchmarks 等) sodium_crypto_shorthash(),即 SipHash-2-4,适用于哈希表,但不应依赖于抗碰撞性。

_shorthash 的速度大约是 _generichash 的 3 倍,但您需要一把钥匙,而且发生碰撞的风险很小但很现实。使用 _generichash,您可能不需要担心冲突,也不需要使用密钥(但可能无论如何都需要)。


问题是“这件事有多快”?
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 实现将比 C 实现的 PHP sha256 慢很多......我希望 PHP 可以在 hash_algos() 套件中使用 blake2b ..
这里不建议使用纯 PHP 实现。
M
Max Tsepkov

Adler32 在我的机器上表现最好。 md5() 结果比 crc32() 快。


如果 MD5 比通用 CRC32 函数快,那么就大错特错了。
S
Sjoerd

CRC32 比 MD5 和 SHA1 更快,但安全性较低。 MD5 和 SHA1 之间没有太大的速度差异。


MD5 现在被认为是不安全的。它比 SHA1 更不安全。阅读 MD5 维基页面。
F
Frank

md5 inside hash 的实现比 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 看到