hash

(PHP 5 >= 5.1.2, PHP 7, PHP 8, PECL hash >= 1.1)

hash生成哈希值 (消息摘要)

说明

hash ( string $algo , string $data , bool $raw_output = false ) : string

参数

algo

要使用的哈希算法,例如:"md5","sha256","haval160,4" 等。 在 hash_algos() 中查看支持的算法。

data

要进行哈希运算的消息。

raw_output

设置为 true 输出原始二进制数据, 设置为 false 输出小写 16 进制字符串。

返回值

如果 raw_output 设置为 true, 则返回原始二进制数据表示的信息摘要, 否则返回 16 进制小写字符串格式表示的信息摘要。

范例

Example #1 一个 hash() 例程

<?php
echo hash('ripemd160''The quick brown fox jumped over the lazy dog.');
?>

以上例程会输出:

ec457d0a974c48d5685a7efa03d137dc8bbde7e3

Example #2 使用 PHP 5.4 或者更高版本计算 tiger 哈希值

<?php
function old_tiger($data ""$width=192$rounds 3) {
    return 
substr(
        
implode(
            
array_map(
                function (
$h) {
                    return 
str_pad(bin2hex(strrev($h)), 16"0");
                },
                
str_split(hash("tiger192,$rounds"$datatrue), 8)
            )
        ),
        
048-(192-$width)/4
    
);
}
echo 
hash('tiger192,3''a-string'), PHP_EOL;
echo 
old_tiger('a-string'), PHP_EOL;
?>

以上例程在 PHP 5.3 中的输出:

146a7492719b3564094efe7abbd40a7416fd900179d02773
64359b7192746a14740ad4bb7afe4e097327d0790190fd16

以上例程在 PHP 5.4 中的输出:

64359b7192746a14740ad4bb7afe4e097327d0790190fd16
146a7492719b3564094efe7abbd40a7416fd900179d02773

参见

  • hash_file() - 给指定文件的内容生成哈希值
  • hash_hmac() - 使用 HMAC 方法生成带有密钥的哈希值
  • hash_init() - 初始化增量哈希运算上下文
  • md5() - 计算字符串的 MD5 散列值
  • sha1() - 计算字符串的 sha1 散列值

User Contributed Notes

Anonymous 16-Apr-2020 04:19
<?PHP
function allhash($d){
    foreach(
hash_algos() as $v){
       
$r[] = "$v\t Length: ".strlen(hash($v, $d));
    }
    return
$r;
}

print_r(allhash(1));
?>
output:

Array
(
    [0] => md2   Length: 32
    [1] => md4   Length: 32
    [2] => md5   Length: 32
    [3] => sha1  Length: 40
    [4] => sha224        Length: 56
    [5] => sha256        Length: 64
    [6] => sha384        Length: 96
    [7] => sha512/224    Length: 56
    [8] => sha512/256    Length: 64
    [9] => sha512        Length: 128
    [10] => sha3-224     Length: 56
    [11] => sha3-256     Length: 64
    [12] => sha3-384     Length: 96
    [13] => sha3-512     Length: 128
    [14] => ripemd128    Length: 32
    [15] => ripemd160    Length: 40
    [16] => ripemd256    Length: 64
    [17] => ripemd320    Length: 80
    [18] => whirlpool    Length: 128
    [19] => tiger128,3   Length: 32
    [20] => tiger160,3   Length: 40
    [21] => tiger192,3   Length: 48
    [22] => tiger128,4   Length: 32
    [23] => tiger160,4   Length: 40
    [24] => tiger192,4   Length: 48
    [25] => snefru       Length: 64
    [26] => snefru256    Length: 64
    [27] => gost         Length: 64
    [28] => gost-crypto  Length: 64
    [29] => adler32      Length: 8
    [30] => crc32        Length: 8
    [31] => crc32b       Length: 8
    [32] => crc32c       Length: 8
    [33] => fnv132       Length: 8
    [34] => fnv1a32      Length: 8
    [35] => fnv164       Length: 16
    [36] => fnv1a64      Length: 16
    [37] => joaat        Length: 8
    [38] => haval128,3   Length: 32
    [39] => haval160,3   Length: 40
    [40] => haval192,3   Length: 48
    [41] => haval224,3   Length: 56
    [42] => haval256,3   Length: 64
    [43] => haval128,4   Length: 32
    [44] => haval160,4   Length: 40
    [45] => haval192,4   Length: 48
    [46] => haval224,4   Length: 56
    [47] => haval256,4   Length: 64
    [48] => haval128,5   Length: 32
    [49] => haval160,5   Length: 40
    [50] => haval192,5   Length: 48
    [51] => haval224,5   Length: 56
    [52] => haval256,5   Length: 64
)
synnus at gmail dot com 15-Dec-2019 12:07
<?php

/* PHP 7.4

n°   hash  results
1.   adler32 (hex)       555.992 ms
2.   adler32 (raw)       556.945 ms
3.   fnv132 (raw)        1107.931 ms
4.   fnv1a64 (raw)       1107.931 ms
5.   fnv164 (raw)        1108.169 ms
6.   fnv1a32 (raw)       1108.884 ms
7.   fnv164 (hex)        1108.884 ms
8.   fnv1a64 (hex)       1109.123 ms
9.   fnv132 (hex)        1116.991 ms
10.  fnv1a32 (hex)       1147.985 ms
11.  tiger192,3 (raw)    1523.017 ms
12.  tiger192,3 (hex)    1532.077 ms
13.  tiger128,3 (hex)    1538.038 ms
14.  tiger128,3 (raw)    1546.144 ms
15.  md4 (raw)           1554.965 ms
16.  md4 (hex)           1565.933 ms
17.  tiger160,3 (raw)    1574.039 ms
18.  tiger160,3 (hex)    1588.106 ms
19.  joaat (hex)         1661.777 ms
20.  joaat (raw)         1662.969 ms
21.  md5 (raw)           1822.948 ms
22.  md5 (hex)           1842.975 ms
23.  tiger160,4 (hex)    1996.994 ms
24.  tiger160,4 (raw)    2007.961 ms
25.  tiger128,4 (raw)    2035.14 ms
26.  tiger192,4 (raw)    2043.962 ms
27.  tiger128,4 (hex)    2065.896 ms
28.  tiger192,4 (hex)    2070.903 ms
29.  sha1 (hex)          2254.009 ms
30.  sha1 (raw)          2326.011 ms
31.  sha3-224 (hex)      2768.039 ms
32.  sha3-224 (raw)      2783.06 ms
33.  sha512 (hex)        2936.124 ms
34.  sha512 (raw)        2943.992 ms
35.  sha3-256 (hex)      2945.899 ms
36.  sha3-256 (raw)      2970.933 ms
37.  sha512/224 (raw)    2990.007 ms
38.  sha384 (raw)        3006.935 ms
39.  sha512/224 (hex)    3010.988 ms
40.  sha512/256 (raw)    3024.101 ms
41.  sha384 (hex)        3036.975 ms
42.  ripemd256 (raw)     3068.923 ms
43.  ripemd256 (hex)     3072.023 ms
44.  ripemd128 (raw)     3077.03 ms
45.  ripemd128 (hex)     3123.998 ms
46.  sha512/256 (hex)    3184.08 ms
47.  haval256,3 (hex)    3671.884 ms
48.  haval224,3 (hex)    3776.073 ms
49.  sha3-384 (hex)      3777.98 ms
50.  haval128,3 (raw)    3823.041 ms
51.  haval128,3 (hex)    3829.002 ms
52.  sha3-384 (raw)      3835.916 ms
53.  haval256,3 (raw)    3852.128 ms
54.  haval224,3 (raw)    3855.943 ms
55.  haval160,3 (raw)    3859.996 ms
56.  haval160,3 (hex)    3862.857 ms
57.  haval192,3 (raw)    3892.898 ms
58.  haval192,3 (hex)    3922.939 ms
59.  crc32c (hex)        4080.057 ms
60.  ripemd160 (hex)     4091.024 ms
61.  ripemd160 (raw)     4094.123 ms
62.  ripemd320 (raw)     4114.866 ms
63.  crc32b (hex)        4116.058 ms
64.  crc32 (raw)         4118.919 ms
65.  ripemd320 (hex)     4175.186 ms
66.  crc32c (raw)        4180.908 ms
67.  crc32 (hex)         4194.974 ms
68.  crc32b (raw)        4208.803 ms
69.  sha224 (hex)        4735.946 ms
70.  sha256 (raw)        4753.112 ms
71.  sha256 (hex)        4761.934 ms
72.  sha224 (raw)        4762.887 ms
73.  haval192,4 (raw)    5304.098 ms
74.  haval160,4 (raw)    5308.151 ms
75.  haval128,4 (raw)    5323.886 ms
76.  haval192,4 (hex)    5346.059 ms
77.  haval128,4 (hex)    5351.066 ms
78.  haval256,4 (hex)    5367.04 ms
79.  haval256,4 (raw)    5378.007 ms
80.  haval224,4 (raw)    5398.988 ms
81.  haval224,4 (hex)    5413.055 ms
82.  sha3-512 (raw)      5460.023 ms
83.  sha3-512 (hex)      5527.973 ms
84.  haval160,4 (hex)    5529.88 ms
85.  haval192,5 (hex)    6403.923 ms
86.  haval160,5 (raw)    6499.052 ms
87.  haval128,5 (raw)    6513.833 ms
88.  haval160,5 (hex)    6540.06 ms
89.  haval128,5 (hex)    6541.013 ms
90.  haval192,5 (raw)    6566.047 ms
91.  haval224,5 (raw)    6567.001 ms
92.  haval256,5 (hex)    6577.014 ms
93.  haval224,5 (hex)    6598.949 ms
94.  haval256,5 (raw)    6598.949 ms
95.  whirlpool (raw)     9627.103 ms
96.  whirlpool (hex)     9634.017 ms
97.  gost (raw)          18457.889 ms
98.  gost-crypto (raw)   18479.824 ms
99.  gost (hex)          18527.03 ms
100.  gost-crypto (hex)  18530.13 ms
101.  snefru256 (hex)    36260.843 ms
102.  snefru256 (raw)    36325.931 ms
103.  snefru (hex)       36480.903 ms
104.  snefru (raw)       36496.877 ms
105.  md2 (raw)          184617.996 ms
106.  md2 (hex)          185398.101 ms

*/
?>
Ricardo Striquer (ricardophp yohoocombr) 21-Sep-2018 04:46
I haven't done any test or actual study (I'm using crc32 and storing it in mysql signed int types), but if your algorithm of choice is bigger them the supported integer of your database I suppose it is possible that the raw_format option is the best option to store directly in the database without type casting demands for it results in a binary string value.

To check if your algorithm of choice have the supported integer size in your database just strlen the raw_format output and see how many bytes it have (for example: crc32 have 4 bytes output, sha256 have 32 e md5 possue 16).

<?php
var_dump
(strlen(hash('md5', 'string to check', true))); // int(16)
?>

PS: You can always use floating points to store a very big number but for "common humans" binary types by and large are easier to check, understand and maintain, so i recommend to use binary, but if you are about speed them floating point could be your friend.

PS: remembering ... without the raw_format the returned value are hexadecimal values without the 'Hx' complement, so to transform the result into a decimal just hexdec as shown ...

<?php
var_dump
(hexdec(hash('crc32b', 'string to check'))); // int(1206832624)
?>

PS: Just registering ... I have noticed here some tests where 'crc32' is slower than md5, AFAIK by definition a CRC32 algorithm (there are several algorithms to calculate CRC32) is faster than MD5 and Adler-32 is faster than CRC32 (CRC32 is more consistent than Adler-32, less consistent than MD5, but if you want to safely validate the recommended would be SHA256 or better yet SHA512 because they are less likely to collide, so less vulnerable to collision attacks)
jrz [dot] agarcia [at] gmail [dot] com 31-May-2018 07:22
I was curious about hashes behavior (time and length), so i ran this code (yeah, I'm cheating because i took two examples from this page)
<?php
 
echo "Building data...";
 
$data = "";
  for(
$i = 0; $i < 1500; $i++)
   
$data .= sha1("H:k - $i - k:H");

  echo
"OK! (".strlen($data)." bytes)".PHP_EOL;

 
$res = [];

  echo
"Testing hashes.....".PHP_EOL;

  foreach (
hash_algos() as $algo) {
   
$time = microtime(1);
   
$hash = hash($algo, $data);
   
$time = (microtime(1) - $time) * 1000;
   
$length = strlen($hash);

   
$res["$time"][] = [
     
"algo"   => "HEX-$algo",
     
"length" => "$length",
     
"time"   => sprintf("%.8f", $time)
    ];

   
$time = microtime(1);
   
hash($algo, $data, 1);
   
$time = (microtime(1) - $time) * 1000;

   
$res["$time"][] = [
     
"algo"   => "RAW-$algo",
     
"length" => "$length",
     
"time"   => sprintf("%.8f", $time)
    ];
  }

 
ksort($res);
 
$i = 0;

  echo
"Results:".PHP_EOL;
  echo
"Posit.      Time in ms   Type-Hash algo        Hash length".PHP_EOL;

  foreach(
$res as $sres){
    foreach(
$sres as $result){
      echo
sprintf("%5d. %12s ms    %-20s %-2d bytes", $i++, $result['time'], $result['algo'], $result['length']).PHP_EOL;
    }
  }
?>

I found interesting that today (may 31, 2018), I found 103 algos, 65 more than 9 years ago (based on this comment: https://secure.php.net/manual/en/function.hash.php#89574 )

Also, here is my results: https://ideone.com/embed/0iwuGn

I'm not posting here due to message length limitations.
Hayley Watson 12-Jul-2017 12:13
These are hash functions. Some have been designed to act as signatures for documents, while others are simply act as checks that transmitted data hasn't been damaged or otherwise modified during transmission and don't provide any cryptographic features.

Learn their differences, and use what's appropriate, because using the wrong hash function can be worse than not using one at all.
Hayley Watson 11-Jul-2017 11:58
Of the hash algorithms currently available, SHA3 was chosen by NIST from fifty-one submitted candidates and subsequently mandated by the U.S. Department of Commerce for Federal Government use.

http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf

So if you're wanting to select a hash algorithm, you can consider SHA3 to be "good enough for government work".
Nicolas Pamart 02-Jan-2015 12:47
Be carreful ! SHA256 return plain text string for empty field !!! empty function will not work ! Make a test before hash your POST.
buar42 at gmail dot com 29-Sep-2013 08:45
I made a PHP script that will let you sort all the available hashes on your system by generation time or by the length of the hash. It shows a general correlation on my system (longer hashes take longer to calculate) but some are faster than others, for example, sha512 makes the (joint) longest hash, but is actually only ninth slowest (from 43 hashes available on my machine)

As I understand it, the strength of a hash is dependant on the number of collisions that it has (where two input values produce the same hash) so with an infinite number of input values but a finite number of hashes, there are a (theoretically) infinite number of collisions. But, if you have a longer hash, then you're dividing infinity by a larger number, so you'll have fewer collisions.

In reality the number of collisions will be limited by the minimum and maximum password lengths that you choose to allow, so that if you enforce a policy where passwords must be exactly a certain length (20 characters for example) you'll have a large number of unique passwords, but a smaller number of potential inputs than you have hashes coming out, so that should prevent collisions entirely. In theory.

Tl;dr: I think that longer hashes are better.

Anyway, here's the code:
<?php

$data
= "hello";

foreach (
hash_algos() as $v)
 {
 
$time=microtime(1);
  for (
$i = 0; $i < 10000; $i++)
   {
   
$r[$v] = strlen(hash($v, $data.$i, false));
   }
 
$t[$v] = microtime(1)-$time;
 }

switch (
$_GET['sort'])
 {
  default:
  
ksort ($r);
  
$array = 'r';
   break;
  case
'length':
  
asort ($r);
  
$array = 'r';
   break;
  case
'time':
  
asort ($t);
  
$array = 't';
   break;
 }

echo
'<pre>        <a href="?sort=alph">Name</a>        | <a href="?sort=length">Hash Length</a> | <a href="?sort=time">Time taken for 10000 hashes.</a>'."\n";
foreach ($
$array as $key => $value)
 {
  echo
$key;
  for (
$i = strlen ($key); $i <= 19; $i++)
   {
    echo
' ';
   }
  echo
'| '.$r[$key];
  for (
$i = strlen ($r[$key]); $i <= 11; $i++)
   {
    echo
' ';
   }
  echo
'| '.$t[$key]."\n";
 }

echo
'</pre>';

?>
me at akshayjoshi dot com 22-Mar-2013 03:00
Using luka8088 at gmail dot com's code on my laptop (PHP 5.4.4 on OS X), showing fastest 50 algorithms only:

Results:
   1.  adler32 (raw)                 3340.959 microseconds
   2.  adler32 (hex)                 3345.012 microseconds
   3.  fnv132 (raw)                  5178.928 microseconds
   4.  fnv164 (hex)                  5193.948 microseconds
   5.  md4 (raw)                     5207.061 microseconds
   6.  fnv132 (hex)                  5248.069 microseconds
   7.  fnv164 (raw)                  5290.985 microseconds
   8.  md4 (hex)                     5333.9 microseconds
   9.  tiger160,3 (raw)              5499.124 microseconds
  10.  tiger128,3 (hex)              5549.907 microseconds
  11.  tiger192,3 (raw)              5578.994 microseconds
  12.  tiger192,3 (hex)              5687.952 microseconds
  13.  tiger160,3 (hex)              5755.186 microseconds
  14.  tiger128,3 (raw)              5775.928 microseconds
  15.  crc32b (raw)                  6839.036 microseconds
  16.  crc32 (raw)                   6983.995 microseconds
  17.  crc32 (hex)                   7061.004 microseconds
  18.  crc32b (hex)                  7097.005 microseconds
  19.  joaat (raw)                   7505.893 microseconds
  20.  tiger160,4 (raw)              7548.093 microseconds
  21.  joaat (hex)                   7570.028 microseconds
  22.  tiger192,4 (raw)              7591.009 microseconds
  23.  tiger160,4 (hex)              7630.825 microseconds
  24.  tiger128,4 (hex)              7750.034 microseconds
  25.  tiger128,4 (raw)              7750.988 microseconds
  26.  sha1 (raw)                    8049.964 microseconds
  27.  tiger192,4 (hex)              8301.019 microseconds
  28.  haval128,3 (raw)              9046.792 microseconds
  29.  haval192,3 (raw)              9313.106 microseconds
  30.  haval224,3 (raw)              9315.013 microseconds
  31.  haval160,3 (raw)              9329.795 microseconds
  32.  haval256,3 (raw)              9404.182 microseconds
  33.  haval160,3 (hex)              9521.007 microseconds
  34.  md5 (raw)                     9599.924 microseconds
  35.  haval128,3 (hex)              9603.023 microseconds
  36.  haval192,3 (hex)              9624.004 microseconds
  37.  haval256,3 (hex)              9635.925 microseconds
  38.  haval224,3 (hex)              9652.853 microseconds
  39.  md5 (hex)                     9654.045 microseconds
  40.  haval256,4 (raw)              12173.891 microseconds
  41.  haval160,4 (raw)              12346.982 microseconds
  42.  haval256,4 (hex)              12598.037 microseconds
  43.  haval224,4 (hex)              12600.898 microseconds
  44.  haval128,4 (raw)              12680.053 microseconds
  45.  sha512 (raw)                  12681.961 microseconds
  46.  haval160,4 (hex)              12733.936 microseconds
  47.  sha384 (raw)                  12766.122 microseconds
  48.  haval192,4 (hex)              12813.091 microseconds
  49.  haval192,4 (raw)              12818.098 microseconds
  50.  haval128,4 (hex)              12836.933 microseconds

It seems that the adler32 algorithm has gotten a lot faster.
sneskid at hotmail dot com 14-Mar-2012 09:32
On two different servers I found that crc32() relates to hash('crc32b',)
This may be good to know if you are writing a crc32_file function based on hash_file.
(The example does not compensate for negative crc32 results)
<?php
$val
= 'hello';
var_dump(crc32($val) == ( '0x' . hash('crc32b', $val) ) ); // bool(true)
var_dump(crc32($val) == ( '0x' . hash('crc32', $val) ) ); // bool(false)
?>

Also if you are looking for a way to reduce collisions and still keep the hash result small (smaller than say md5) you could get a nice database friendly 64 bit value by using hash/crc32 and hash/crc32b, which is slower than a single md5 but the result may be more suitable for certain tasks.
<?php
$val
= 'hello';
$crc64 = ( '0x' . hash('crc32', $val) . hash('crc32b', $val) ) );
var_dump($crc64); // string(18) "0x3d6531193610a686"
var_dump($crc64 + 0); // int(4423996193312384646)
?>

(examples tested on php 5.2.17)
note: ('0x' . $hex . + 0) is faster than base_convert($hex,16,10)
nmmm at nmmm dot nu 20-Jul-2011 01:50
I was interested how "long" each hash is, so I did:

<?php
$data
= "hello";

foreach (
hash_algos() as $v) {
       
$r = hash($v, $data, false);
       
printf("%-12s %3d %s\n", $v, strlen($r), $r);
}
?>

which produce (long hashes are cropped)

md2           32 a9046c73e00331af68917d3804f70655                  
md4           32 866437cb7a794bce2b727acc0362ee27
md5           32 5d41402abc4b2a76b9719d911017c592
sha1          40 aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
sha256        64 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e730
sha384        96 59e1748777448c69de6b800d7a33bbfb9ff1b463e44354c3553
sha512       128 9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2d
ripemd128     32 789d569f08ed7055e94b4289a4195012
ripemd160     40 108f07b8382412612c048d07d13f814118445acd
ripemd256     64 cc1d2594aece0a064b7aed75a57283d9490fd5705ed3d66bf9a
ripemd320     80 eb0cf45114c56a8421fbcb33430fa22e0cd607560a88bbe14ce
whirlpool    128 0a25f55d7308eca6b9567a7ed3bd1b46327f0f1ffdc804dd8bb
tiger128,3    32 a78862336f7ffd2c8a3874f89b1b74f2
tiger160,3    40 a78862336f7ffd2c8a3874f89b1b74f2f27bdbca
tiger192,3    48 a78862336f7ffd2c8a3874f89b1b74f2f27bdbca39660254
tiger128,4    32 1c2a939f230ee5e828f5d0eae5947135
tiger160,4    40 1c2a939f230ee5e828f5d0eae5947135741cd0ae
tiger192,4    48 1c2a939f230ee5e828f5d0eae5947135741cd0aefeeb2adc
snefru        64 7c5f22b1a92d9470efea37ec6ed00b2357a4ce3c41aa6e28e3b
gost          64 a7eb5d08ddf2363f1ea0317a803fcef81d33863c8b2f9f6d7d1
adler32        8 062c0215
crc32          8 3d653119
crc32b         8 3610a686
haval128,3    32 85c3e4fac0ba4d85519978fdc3d1d9be
haval160,3    40 0e53b29ad41cea507a343cdd8b62106864f6b3fe
haval192,3    48 bfaf81218bbb8ee51b600f5088c4b8601558ff56e2de1c4f
haval224,3    56 92d0e3354be5d525616f217660e0f860b5d472a9cb99d6766be
haval256,3    64 26718e4fb05595cb8703a672a8ae91eea071cac5e7426173d4c
haval128,4    32 fe10754e0b31d69d4ece9c7a46e044e5
haval160,4    40 b9afd44b015f8afce44e4e02d8b908ed857afbd1
haval192,4    48 ae73833a09e84691d0214f360ee5027396f12599e3618118
haval224,4    56 e1ad67dc7a5901496b15dab92c2715de4b120af2baf661ecd92
haval256,4    64 2d39577df3a6a63168826b2a10f07a65a676f5776a0772e0a87
haval128,5    32 d20e920d5be9d9d34855accb501d1987
haval160,5    40 dac5e2024bfea142e53d1422b90c9ee2c8187cc6
haval192,5    48 bbb99b1e989ec3174019b20792fd92dd67175c2ff6ce5965
haval224,5    56 aa6551d75e33a9c5cd4141e9a068b1fc7b6d847f85c3ab16295
haval256,5    64 348298791817d5088a6de6c1b6364756d404a50bd64e645035f
rojaro at gmail dot com 15-Sep-2010 08:01
If the given algo parameter contains an algorithm that is not supported, the hash function will return bool(false) and issue a warning.
robert+nospam at robert-gonzalez dot com 17-Jan-2010 04:08
I've recently had the need to look at various hash algorithms and their values of the same string. To make my life a little easier I wrote this little script. It takes a string and runs it through all of the available hash algorithms on your server, outputting them in a clean little HTML table.

-----

<?php
/* Get the posted value of the form if there is one */
$p = empty($_POST['p']) ? null : $_POST['p'];
?>
<html>
<head><title>Hash testing</title></head>
<style type="text/css">
    table {border-collapse: collapse;}
    table, td, th {border: solid 1px #ccc;}
    th {background: #e1e1e1;border-color: #999;}
    td, th {padding: 0.25em;}
    td.algo {font-weight: bold;}
    tr.on td {background: #f0f0f0;}
</style>
<body>
    <h1>String hashing</h1>
    <form method="post" action="<?php echo basename(__FILE__) ?>">
        <p><label for="p">Enter a string to hash:</label><br /><input id="p" type="text" name="p" value="<?php echo $p ?>" /></p>
        <p><input type="submit" name="submit" value="Hash It" /></p>
    </form>
   
    <?php /* If there is a posted value use it */ ?>
    <?php if ($p): ?>
    <hr />
    <h2>Table of hash values for <em><?php echo $p ?></em> based on algorithm</h2>
    <table>
        <tr>
            <th>Algorithm</th>
            <th>Hashed value of <em><?php echo $p ?></em></th>
        </tr>
        <?php /* Loop through each hash algorithm, colorizing every other row */ ?>
        <?php $on = false; foreach (hash_algos() as $algo): ?>
        <tr<?php if ($on): ?> class="on"<?php endif; ?>>
            <td class="algo"><?php echo $algo ?></td>
            <td class="hash"><?php echo hash($algo, $p) ?></td>
        </tr>
    <?php $on = !$on; endforeach; ?>
    </table>
    <?php endif; ?>
</body>
</html>
Kai Petzke 16-Oct-2009 05:14
The well known hash functions MD5 and SHA1 should be avoided in new applications. Collission attacks against MD5 are well documented in the cryptographics literature and have already been demonstrated in practice. Therefore, MD5 is no longer secure for certain applications.

Collission attacks against SHA1 have also been published, though they still require computing power, which is somewhat out of scope. As computing power increases with time and the attacks are likely to get better, too, attacks against systems relying on SHA1 for security are likely to become feasible within the next few years.

There is no lack of potential alternative hash algorithms, as the many choices for the "algo" argument of PHPs hash() function already suggests. Unfortunately, there is lack of analysis, as to how secure these alternative algorithms are. It is rather safe to assume, though, that the SHA2 family with its most prominent members SHA-256 und SHA-512, is better than SHA1.

When storing password hashes, it is a good idea to prefix a salt to the password before hashing, to avoid the same passwords to hash to the same values and to avoid the use of rainbow tables for password recovery. Unlike suggested in other articles, there is no security advantage in putting the salt in the middle, or even at both the beginning and the end, of the combined salt-password-string.

Rather, there are two other factors, that determine the strength of the salt: Its length and its variability. For example, using the same salt for all passwords is easy to implement, but gives only very little additional security. In particular, if users type the same passwords, they will still hash to the same value!

Therefore, the salt should be random string with at least as many variable bits, as there are bits in the hash result. In the user database, store username, the randomly generated salt for that user, and the result of hashing the salt-password-string. Access authentication is then done by looking up the entry for the user, calculating the hash of the salt found in the database and the password provided by the user, and comparing the result with the one stored in the database.
luka8088 at gmail dot com 14-Mar-2009 03:20
Performance test results on my laptop:
Results are here shorten to fit php web notes ...
This was tested with 1024000 bytes (1000 KB) of random data, md4 always gets the first place, and md2 always get the last place :)

Results: (in microseconds)
   1.  md4                           5307.912
   2.  md5                           6890.058
   3.  crc32b                        7298.946
   4.  crc32                         7561.922
   5.  sha1                          8886.098
   6.  tiger128,3                    11054.992
   7.  haval192,3                    11132.955
   8.  haval224,3                    11160.135
   9.  tiger160,3                    11162.996
  10.  haval160,3                    11242.151
  11.  haval256,3                    11327.981
  12.  tiger192,3                    11630.058
  13.  haval128,3                    11880.874
  14.  tiger192,4                    14776.945
  15.  tiger128,4                    14871.12
  16.  tiger160,4                    14946.937
  17.  haval160,4                    15661.954
  18.  haval192,4                    15717.029
  19.  haval256,4                    15759.944
  20.  adler32                       15796.184
  21.  haval128,4                    15887.022
  22.  haval224,4                    16047.954
  23.  ripemd256                     16245.126
  24.  haval160,5                    17818.927
  25.  haval128,5                    17887.115
  26.  haval224,5                    18085.002
  27.  haval192,5                    18135.07
  28.  haval256,5                    18678.903
  29.  sha256                        19020.08
  30.  ripemd128                     20671.844
  31.  ripemd160                     21853.923
  32.  ripemd320                     22425.889
  33.  sha384                        45102.119
  34.  sha512                        45655.965
  35.  gost                          57237.148
  36.  whirlpool                     64682.96
  37.  snefru                        80352.783
  38.  md2                           705397.844

Code for generating this:
(compatible both with browser and cli mode)

<pre>

<?php

echo 'Building random data ...' . PHP_EOL;
@
ob_flush();flush();

$data = '';
for (
$i = 0; $i < 64000; $i++)
   
$data .= hash('md5', rand(), true);

echo
strlen($data) . ' bytes of random data built !' . PHP_EOL . PHP_EOL . 'Testing hash algorithms ...' . PHP_EOL;
@
ob_flush();flush();

$results = array();
foreach (
hash_algos() as $v) {
    echo
$v . PHP_EOL;
    @
ob_flush();flush();
   
$time = microtime(true);
   
hash($v, $data, false);
   
$time = microtime(true) - $time;
   
$results[$time * 1000000000][] = "$v (hex)";
   
$time = microtime(true);
   
hash($v, $data, true);
   
$time = microtime(true) - $time;
   
$results[$time * 1000000000][] = "$v (raw)";
}

ksort($results);

echo
PHP_EOL . PHP_EOL . 'Results: ' . PHP_EOL;

$i = 1;
foreach (
$results as $k => $v)
    foreach (
$v as $k1 => $v1)
        echo
' ' . str_pad($i++ . '.', 4, ' ', STR_PAD_LEFT) . '  ' . str_pad($v1, 30, ' ') . ($k / 1000) . ' microseconds' . PHP_EOL;

?>

</pre>
Leigh 06-Aug-2008 10:10
Just a quick note about these benchmarks and how you should apply them.

If you are hashing passwords etc for security, speed is not your friend. You should use the slowest method.

Slow to hash means slow to crack and will hopefully make generating things like rainbow tables more trouble than it's worth.
inspiration3 at gmail dot com 04-May-2008 08:12
Another comprehensive benchmark script that orders results from best to worst and includes the crc32(), md5() and sha1() standalone functions:

<?php

define
('HASH_TIMES', 1000);
define('HASH_DATA', 'The quick brown fox jumped over!'); // 32 bytes

header('Content-Type: text/plain');
echo
'Testing ' . strlen(HASH_DATA) . ' bytes of data over ' . HASH_TIMES . " iterations:\n";

foreach (
hash_algos() as $algo) {
   
$time = microtime(1);
    for (
$i = 0; $i < HASH_TIMES; $i++) hash($algo, HASH_DATA);
   
$results[$algo] = microtime(1) - $time;
}

$time = microtime(1); for ($i = 0; $i < HASH_TIMES; $i++) crc32(HASH_DATA); $results['crc32()'] = microtime(1) - $time;
$time = microtime(1); for ($i = 0; $i < HASH_TIMES; $i++) md5(HASH_DATA); $results['md5()'] = microtime(1) - $time;
$time = microtime(1); for ($i = 0; $i < HASH_TIMES; $i++) sha1(HASH_DATA); $results['sha1()'] = microtime(1) - $time;

asort($results, SORT_NUMERIC);
foreach (
$results as $algo => $time) echo "\n$time\t$algo";

?>
Marcus 27-Apr-2008 05:15
A upgrade of (dani88elx AT gmail DOT com)'s performance test [from 26-Jun-2007], this time grading them by speed (fastest first) and comparing times between hex and raw data.

<?php
function testAlgos() {
$algos = hash_algos();
$word="This will be crypted by all different algoritms";
$results = array();
foreach(
$algos as $algo)
{
   
$time=microtime(1);
   
$data = hash($algo, $word, false);
   
$results["".(microtime(1)-$time)][] = "$algo (hex)";
}
foreach(
$algos as $algo)
{
   
$time=microtime(1);
   
$data = hash($algo, $word, true);
   
$results["".(microtime(1)-$time)][] = "$algo (raw)";
}
ksort($results);
foreach(
$results as $time => &$algos) {
    echo
$time."\n";
   
sort($algos);
    foreach(
$algos as $algo)
        echo
"\t".$algo."\n";
}
}
testAlgos();
?>
mikael at webhost3 dot eu 10-Mar-2007 05:34
<?php
$time
=microtime(1);
for (
$i=0;$i<100000;$i++)
  
hash('md5', 'string');
echo
microtime(1)-$time,': hash/md5<br>';

$time=microtime(1);
for (
$i=0;$i<100000;$i++)
  
md5('string');
echo
microtime(1)-$time,': md5<br>';

$time=microtime(1);
for (
$i=0;$i<100000;$i++)
  
hash('sha1', 'string');
echo
microtime(1)-$time,': hash/sha1<br>';

$time=microtime(1);
for (
$i=0;$i<100000;$i++)
  
sha1('string');
echo
microtime(1)-$time,': sha1<br>';
?>------------------------<br><?php
$time
=microtime(1);
for (
$i=0;$i<100000;$i++)
  
hash('md5', $i);
echo
microtime(1)-$time,': hash/md5<br>';

$time=microtime(1);
for (
$i=0;$i<100000;$i++)
  
md5($i);
echo
microtime(1)-$time,': md5<br>';

$time=microtime(1);
for (
$i=0;$i<100000;$i++)
  
hash('sha1', $i);
echo
microtime(1)-$time,': hash/sha1<br>';

$time=microtime(1);
for (
$i=0;$i<100000;$i++)
  
sha1($i);
echo
microtime(1)-$time,': sha1<br>';
?>
Gives:
0.33311605453491: hash/md5
1.0671429634094: md5
0.383131980896: hash/sha1
1.3252220153809: sha1
------------------------
0.37684988975525: hash/md5
1.1258299350739: md5
0.43960785865784: hash/sha1
1.3876020908356: sha1
PHP8中文手册 站长在线 整理 版权归PHP文档组所有