【问题标题】:Compare two password hashes -- nodejs比较两个密码哈希——nodejs
【发布时间】:2016-09-13 17:20:57
【问题描述】:

我正在使用密码https://nodejs.org/api/crypto.html 进行密码加密和身份验证。我正在更改密码页面上,并且无法确定用户提供的密码是否与现有密码具有相同的哈希值。下面是我的代码。

var createSalt = function createSalt() {
    return crypto.randomBytes(128).toString('base64');
};

var hashPwd = function hashPwd(salt, pwd) {
    var hmac = crypto.createHmac('sha256', salt);
    return hmac.update(pwd).digest('hex');
};

//use password , create salt, hash and compare with the existing
var salt = createSalt();
var passHash = hashPwd(salt,data.Password);
console.log('the password is', user.PassHash === passHash);

我期待上面的控制台消息在现有用户密码匹配的地方打印 true。但是,这两个哈希似乎根本不匹配。请问我错过了什么?如何做到这一点?我想确保用户密码与他现有的密码匹配,然后他才能更改新密码。任何帮助,将不胜感激。

【问题讨论】:

    标签: node.js hash cryptography


    【解决方案1】:

    我认为你的问题出在盐上。通常,您必须存储第一次用于散列的盐并在第二次重复使用它。使用盐的原因是为了确保哈希不会映射到原始通道,如果某些黑客会从受感染的系统中检索它(使用彩虹表攻击)。见Why do we use the "salt" to secure our passwords?

    如果你愿意尝试

    var salt = crypto.randomBytes(128).toString('base64');
    
    var hashPwd = function hashPwd(salt, pwd) {
        var hmac = crypto.createHmac('sha256', salt);
        return hmac.update(pwd).digest('hex');
    };
    
    //use password , create salt, hash and compare with the existing
    var passHash = hashPwd(salt,data.Password);
    console.log('the password is', user.PassHash === passHash);
    

    只要您不重新启动服务器,它就可以工作(假设您将 salt var 存储在调用以响应 http 请求的函数范围之外)。

    更好的解决方案 (imo) 是 bcrypt 正在做的事情。在那里您为每个密码生成一个盐,但要验证密码是否正确,您可以使用比较,它使用存储在哈希中的盐。这样您就可以对每个密码使用不同的盐,这意味着您不必担心盐会被泄露。

    npm install bcrypt
    

    var bcrypt = require('bcrypt');
    var hash = bcrypt.hashSync("my password");
    
    bcrypt.compareSync("my password", hash); // true
    bcrypt.compareSync("not my password", hash); // false
    

    还有compareAsync 和其他异步变体。另见:https://www.npmjs.com/package/bcrypt-nodejs

    【讨论】:

    • 哦,谢谢 iwein,所以我应该使用相同的盐。我的意思是,我应该使用现有密码中的一个,而不是创建新的盐。 ?
    • @NuruSalihu 是的,我就是这么理解的。如果您的盐被盗,您必须重置所有密码并重新生成盐。通常,加密库允许您在不再次传递盐的情况下比较通行证(它们将盐存储在散列通行证中)。 bcrypt 这样做例如 stackoverflow.com/questions/6832445/…
    • @iwein 这个链接正好相反:crackstation.net/hashing-security.htm 重复使用盐不是一个好习惯。在第 4 节中,它解释了原因。你觉得这个读法对吗?我对这一切都很陌生,但认为它可能会有所帮助。
    • 您不应该将哈希值与对定时攻击敏感的=== 进行比较。使用crypto.timingSafeEqual
    【解决方案2】:
     UserSchema.pre('save', function (next) {
      if (this.password) {
        const salt = bcrypt.genSaltSync(10);//or your salt constant
        this.password = bcrypt.hashSync(this.password, salt);
      }
      next();
    });
    

    在你的控制器中

      const result = bcrypt.compareSync(req.body.password, your_hash_password);
          if (result){
            return res.json(message: "success");
          } else {
            return res.status(400).json("Bad request. Password don't match ");
          }
    

    【讨论】:

      猜你喜欢
      • 2019-09-12
      • 2023-03-29
      • 2019-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多