不要再使用MD5和SHA1加密密码了!

裘兴思
2023-12-01

为什么不要用MD5和SHA1,下面会详细讲到!

<?php

define('testtime', 50000);
$algos = hash_algos(); //返回一个数值索引的数组, 包含了受支持的哈希算法名称。 
//遍历算法,每个算法计算50000次的时间
foreach ($algos as $algo) {
    $st = microtime(true);
    for ($i = 0; $i < testtime; $i++) {
        hash($algo, microtime(true) . $i);
    }
    $et = microtime(true);
    $time[$algo] = $et - $st;
}
asort($time, SORT_NUMERIC);



echo "";
print_r($time);


//CI框架建不用MD_5和SHA1加密密码,php本身由一个专门来加密密码的函数:

echo password_hash("rasmuslerdorf", PASSWORD_DEFAULT) . "\n";
//输出结果类似: $2y$10$duGmwKVqHf7sgulBOd1gb.cIikNHx3dtmlsRg9yx/YvOelJSkPmpC

//PASSWORD_DEFAULT - 使用 bcrypt 算法 (PHP 5.5.0 默认)。 注意,该常量会随着 PHP 加入更新更高强度的算法而改变。 所以,使用此常量生成结果的长度将在未来有变化。 因此,数据库里储存结果的列可超过60个字符(最好是255个字符)。 

输出结果如下:

Array
(
    [crc32b] => 0.031200170516968
    [sha1] => 0.045201063156128
    [adler32] => 0.046799898147583
    [crc32] => 0.046799898147583
    [fnv1a64] => 0.046800136566162
    [fnv1a32] => 0.046801090240479
    [md5] => 0.055202007293701
    [md4] => 0.062399864196777
    [fnv164] => 0.062399864196777
    [fnv132] => 0.062399864196777
    [joaat] => 0.062399864196777
    [ripemd160] => 0.062399864196777
    [sha256] => 0.062399864196777
    [ripemd256] => 0.062400102615356
    [tiger128,3] => 0.062400102615356
    [tiger128,4] => 0.062400102615356
    [tiger160,4] => 0.062400817871094
    [tiger192,4] => 0.064400196075439
    [tiger192,3] => 0.065399885177612
    [tiger160,3] => 0.066400051116943
    [ripemd128] => 0.068401098251343
    [haval192,3] => 0.073400974273682
    [sha224] => 0.078000068664551
    [ripemd320] => 0.079999923706055
    [haval256,3] => 0.085000991821289
    [haval160,3] => 0.089000940322876
    [haval128,4] => 0.089999914169312
    [haval224,4] => 0.093599796295166
    [haval192,5] => 0.093600034713745
    [haval192,4] => 0.093600034713745
    [haval256,4] => 0.094600200653076
    [haval256,5] => 0.094600200653076
    [haval160,4] => 0.095601081848145
    [haval128,3] => 0.096001148223877
    [haval224,3] => 0.1030011177063
    [haval128,5] => 0.10920000076294
    [whirlpool] => 0.10920095443726
    [haval160,5] => 0.11120080947876
    [haval224,5] => 0.12479996681213
    [sha384] => 0.14040017127991
    [sha512] => 0.14339995384216
    [gost-crypto] => 0.14740014076233
    [gost] => 0.15600109100342
    [snefru256] => 0.25960087776184
    [snefru] => 0.26519989967346
    [md2] => 0.36480093002319
)

补充一点,排序里面的flag值:

  • SORT_REGULAR- 正常比较单元(不改变类型)
  • SORT_NUMERIC - 单元被作为数字来比较
  • SORT_STRING - 单元被作为字符串来比较
  • SORT_LOCALE_STRING - 根据当前的区域(locale)设置来把单元当作字符串比较,可以用 setlocale() 来改变。
  • SORT_NATURAL - 和 natsort() 类似对每个单元以”自然的顺序”对字符串进行排序。 PHP 5.4.0 中新增的。
  • SORT_FLAG_CASE - 能够与 SORT_STRING 或 SORT_NATURAL 合并(OR 位运算),不区分大小写排序字符串。

验证密码:

password_verify — 验证密码是否和哈希匹配,时序攻击(timing attacks)对此函数不起作用。 注意 password_hash() 返回的哈希包含了算法、 cost 和盐值。 因此,所有需要的信息都包含内。使得验证函数不需要储存额外盐值等信息即可验证哈希。
boolean password_verify ( string $password , string $hash )

<?php
// 想知道以下字符从哪里来,可参见 password_hash() 的例子
$hash = '$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq';

if (password_verify('rasmuslerdorf', $hash)) {
    echo '密码正确!';
} else {
    echo '密码错误!';
}
  • 密码处理
  • 在你的应用程序中正确处理密码是非常关键的。
  • 但是不幸的是,许多开发者并不知道怎么去做,而且网络上充斥着大量过时的 甚至错误的建议,提供不了任何帮助。
  • 我们提供了一个清单来帮助你,告诉你什么该做,什么不该做。
  • 绝不要以明文存储密码。
  • 永远使用 哈希算法 来处理密码。
  • 绝不要使用 Base64 或其他编码方式来存储密码。
  • 这和以明文存储密码是一样的,使用 哈希 ,而不要使用 编码 。
  • 编码以及加密,都是双向的过程,而密码是保密的,应该只被它的所有者知道, 这个过程必须是单向的。哈希正是用于做这个的,从来没有解哈希这种说法, 但是编码就存在解码,加密就存在解密。
  • 绝不要使用弱哈希或已被破解的哈希算法,像 MD5 或 SHA1 。
  • 这些算法太老了,而且被证明存在缺陷,它们一开始就并不是为了保存密码而设计的。
  • 另外,绝不要自己发明算法。
  • 只使用强密码哈希算法,例如 BCrypt ,在 PHP 自己的 密码哈希 函数中也是使用它。
  • 即使你的 PHP 版本不是 5.5+ ,也请使用它们,CodeIgniter 为你提供了这些算法。
  • 如果你连升级 PHP 也无法做到,那么使用 hash_pbkdf() http://php.net/hash_pbkdf2 吧, 为实现兼容性我们提供了这个函数。
  • 绝不要以明文形式显示或发送密码。
  • 即使是对密码的所有者也应该这样。如果你需要 “忘记密码” 的功能,可以随机生成一个新的 一次性的(这点很重要)密码,然后把这个密码发送给用户。
  • 绝不要对用户的密码做一些没必要的限制。
  • 如果你使用除 BCrypt(它有最多 72 字符的限制)之外的其他哈希算法,你应该设置一个相对长一点的密码长度(例如 1024 字符),这样可以缓解 DoS 攻击。
  • 但是除此之外,对密码的其他限制诸如密码中只允许使用某些字符,或者密码中不允许包含某些字符,就没有任何意义了。
  • 这样做不仅不会提高安全性,反而 降低了 安全性,而且真的没有任何理由需要这样做。 只要你对密码进行哈希处理了,那么无论是技术上,还是在存储上都没有任何限制。
 类似资料: