忘记 MD5 Sha1 吧 从现在开始使用 Bcrypt 和 Argon2i 吧

  • 昨天突然发现身边还有人在使用md5进行加密,明明连php官网都不建议使用md5

  • 所以建议大家尽快抛弃 md5 和 sha1 这些不安全的算法

  • php在5.5版本以后已经为我们提供了非常安全的加密函数 bcrypt

    • 使用函数 password_hash 生成基于Bcrypt算法的hash值
      使用的具体如下
    $password = filter_input(INPUT_POST, 'password');
    $password = password_hash($password, PASSWORD_DEFAULT, ['cost' => 12]);
    
    password_hash 的第二个选项就是选择使用的加密方法,默认选用的就是Bcrypt加密
    第三个参数是工作因子cost,和 salt,不填就为默认
    password_verify ($password, $hash)
    $password为明文密码,$hash为经过 password_hash函数哈希过后的值
    相等会返回true,不相等会返回true
    
    • password_needs_rehash 函数检测指定的hash值是否实现了提供的算法和选项。 如果没有,需要重新生成hash值
  • 下面有一个完整的登录的例子可以给大家演示一下

<?php

session_start();

try {
    $email = filter_input(INPUT_POST, 'email');
    $password = filter_input(INPUT_POST, 'password');

    $user = User::findByEmail($email);

    if (password_verify($password, $user->password) === false) {
        throw new Exception('密码错误');
    }

    $currentHashAlgorithm = PASSWORD_DEFAULT;
    $currentHashOptions = ['cost' => 15];

    $passwordNeedRehash = password_needs_rehash(
        $user->password,
        $currentHashAlgorithm,
        $currentHashOptions
    );

    if ($passwordNeedRehash === true) {
        $password = password_hash(
            $password,
            $currentHashAlgorithm,
            $currentHashOptions
        );

        $user->save();
    }

    $_SESSION['user_logged_in'] = 'yes';
    $_SESSION['user_email'] = $email;

    header('HTTP/1.1 302 Redirect');
    header('Location:/index.php');

} catch (Exception $e) {
    header('HTTP/1.1 401 Unauthorized');
    echo $e->getMessage();
}
  • php7.2 提供了一个比 Bcrypt 更加安全的算法 Argon2i

    • 使用的方法也很简单 把 password_hash 的第二个参数改成PASSWORD_ARGON2I 即可
    • 当然它也有第三个选项 里面有三个参数
      • memory_cost (integer) - 计算 Argon2 散列时的最大内存
      • time_cost (integer) - 计算 Argon2 散列时最多的时间
      • threads (integer) - 计算 Argon2 散列时最多的线程数
  • 下面我们来比较一下 md5 sha1 bcrypt argon2i 算法

    bcrypt 和 argon2i 使用默认配置

<?php

$password=123456;

var_dump(md5($password));
var_dump(sha1($password));
var_dump($password = password_hash($password, PASSWORD_DEFAULT));
var_dump($password = password_hash($password, PASSWORD_ARGON2I));

结果

[root@JD ~]# php hash.php 
string(32) "e10adc3949ba59abbe56e057f20f883e"
string(40) "7c4a8d09ca3762af61e59520943dc26494f8941b"
string(60) "$2y$10$5AnWGMjHEg3cDTsH5miUTuU7wY7OpERSIfMwxZzM.mWiNwj4oOps6"
string(95) "$argon2i$v=19$m=1024,t=2,p=2$d1JQR3Z2dDdtTFZURGU2RQ$xcac0lc1Olp75uA+Zv6ICIFFLAJpUKJ0rrZKRvribaA"
[root@JD ~]# php hash.php 
string(32) "e10adc3949ba59abbe56e057f20f883e"
string(40) "7c4a8d09ca3762af61e59520943dc26494f8941b"
string(60) "$2y$10$zQlRfj.T/Qa9VkwiHBeN7.s1AUixlDtouLBkzX2jf9e3pYLgwPgGq"
string(95) "$argon2i$v=19$m=1024,t=2,p=2$WlNkU2d4dXhsSFJpbVhQYQ$t1jh8GuzRrCF+neeBfoXeZA6/Jxu2EudAg1WdbT3JJk"

显然易见 我们可以发现 bcrypt 和 argon2i 更加安全
如果有不相信的同学 可以到一些解密网站 如 cmd5 等去尝试解密 你会发现 md5 和 sha1 是真的非常容易被破解

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 15

那么可以使用md5("$secret".'特殊字符'.'SHA');这样来加密啊,又不是单纯的写一个md5("$secret")这样就完了。

6年前 评论

password_hash的问题是极其慢。压测执行一万次需要10余秒,MD5只需要0.3秒

6年前 评论

@XiaohuiLam bcrypt之所以慢就是为了安全 如果你想它快一点可以将cost降低

6年前 评论

@许世桓 md5 加密已经可以通过彩虹表破解,就算你加salt也没用啊

6年前 评论

@CismonX 赞一个 这个我当时看到了 没有写进来 谢谢你的补充

6年前 评论
LearnKuJ

如果使用得当,md5并不是不能使用。

前端使用加盐的慢哈希,后端使用md5,你的破解速度依然会非常慢,做到六位纯数字密码破解1个月上是没有问题的。

当然,如果你指望着换个存储方式就能高枕无忧,能防住撞库,简单密码反跑用户等。建议转行销售。

6年前 评论

@TimJuly 就像你现在要使用mysql当然也可以连接数据库,但使用mysqli和pdo不是更好吗

6年前 评论
LearnKuJ

@licheng 好不好要看场景,不能一概而论。

6年前 评论

@TimJuly 算法本身是不能保证撞库的吧?那是程序安全的工作范畴了 MD5 sha1这种算法不建议使用是因为如果数据库被扒了 密码可以被还原出来 用bcrypt 和 argon2的话不存在这种问题 至少现在还不能

6年前 评论
LearnKuJ

@CorePlusPlus 前端使用加盐慢哈希,后端用md5,一点儿问题都没有,而且服务器计算会很快。

6年前 评论
巴啦啦

首先需要了解md5的工作原理。
第一,md5的算法是哈希摘要算法,理论上来讲不可逆。
第二,同一串字符,通过md5函数多次计算出来的串是一模一样的。
第三,只要修改其中一个字符,那么md5的结果也不一样。
那么为什么会说md5能够被破解?比如说彩虹表?
其实彩虹表的原理特别简单,将常见密码串进行md5计算,然后将md5前的密码与md5后的密码存入数据库。
当你在彩虹表中输入md5后的结果后,然后再匹配到原有密码。
那么为什么一些密码在加盐后还能在彩虹表中找到呢?原因如下
这串密码与盐太过于简单,彩虹表内部会进行匹配,将简单常见的密码与简单常见的盐进行md5运算,再与你输入的加密后的串进行匹配。
第二,这串密码与盐曾今泄漏过,可能是被脱裤,且有存储明文密码。
最后,论如何安全的使用的md5存储密码(建议还是使用php自带的加密系统password_hash)?
答案:每一个新增用户,都有一个属于自己随机出来长度为5以上的盐值。

6年前 评论
巴啦啦

@仰望 我的意思是md5是安全的,要看使用方法。md5不能被破解,不可逆,只可以穷举,彩虹表的工作原理不是破解,本质上来说只是一个数据库。最后还是建议使用password_hash进行密码加密

6年前 评论

@XiaohuiLam 就是要慢,让你反算密码的人也慢,我加密1万个密码要10余秒,但我只要用户注册时加密一次。你反算不可能运气这么好只算一次吧,浪费的时间可就长了。

6年前 评论
ruke

md5修改摘要后,是可以很大程度上的加强安全性的
关于php的md5

6年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!