nodejs中的SALT和HASH密码w / crypto

时间:2013-06-19 21:13:20

标签: node.js node-crypto

我试图弄清楚如何使用crypto模块对nodejs中的密码进行加密和散列。我可以创建哈希密码:

UserSchema.pre('save', function(next) {
  var user = this;

  var salt = crypto.randomBytes(128).toString('base64');
  crypto.pbkdf2(user.password, salt, 10000, 512, function(err, derivedKey) {
    user.password = derivedKey;
    next();
  });
});

但是我对如何验证密码感到困惑。

UserSchema.methods.validPassword = function(password) {    
  // need to salt and hash this password I think to compare
  // how to I get the salt?
}

6 个答案:

答案 0 :(得分:41)

在您使用的任何持久性机制(数据库)中,您将存储结果哈希以及盐和迭代次数,两者都是纯文本。如果每个密码使用不同的盐(您应该这样做),您还必须保存该信息。

然后,您将比较新的纯文本密码,使用相同salt(和迭代)的哈希值,然后将字节序列与存储的字节序列进行比较。

生成密码(伪)

function hashPassword(password) {
    var salt = crypto.randomBytes(128).toString('base64');
    var iterations = 10000;
    var hash = pbkdf2(password, salt, iterations);

    return {
        salt: salt,
        hash: hash,
        iterations: iterations
    };
}

验证密码(伪)

function isPasswordCorrect(savedHash, savedSalt, savedIterations, passwordAttempt) {
    return savedHash == pbkdf2(passwordAttempt, savedSalt, savedIterations);
}

答案 1 :(得分:24)

基于nodejs文档(http://nodejs.org/api/crypto.html),看起来没有一种特定方法可以为您验证密码。要手动验证它,您需要计算当前提供的密码的哈希值,并将其与存储的密码进行比较以获得相等性。基本上,您将使用您对原始密码执行的质询密码执行相同的操作,但使用存储在数据库中的salt而不是生成新的密码,然后比较两个哈希值。

如果您不太愿意使用内置的加密库,我建议您改用bcrypt。这两个在安全方面大致相同,但我认为bcrypt具有更加用户友好的界面。如何使用它的一个示例(直接从上面链接的页面上的bcrypt文档中获取)将是:

创建哈希:

var bcrypt = require('bcrypt');
var salt = bcrypt.genSaltSync(10);
var hash = bcrypt.hashSync("B4c0/\/", salt);
// Store hash in your password DB.

检查密码:

// Load hash from your password DB.
bcrypt.compareSync("B4c0/\/", hash); // true
bcrypt.compareSync("not_bacon", hash); // false

编辑添加:

bcrypt的另一个优点是output of the genSalt function contains both the hash and the salt in one string。这意味着您可以只存储数据库中的单个项目,而不是两个。还提供了一种方法,可以在散列发生的同时生成盐,因此您根本不必担心管理盐。

编辑更新:

回应Peter Lyons的评论:你是100%正确的。我曾经假设我推荐的bcrypt模块是一个javascript实现,因此异步使用它不会真正加速节点的单线程模型。事实证明事实并非如此; bcrypt模块使用本机c ++代码进行计算,并且异步运行速度更快。 Peter Lyons是对的,您应该首先使用该方法的异步版本,并在必要时仅选择同步版本。异步方法可能与同步方法一样慢,但同步方法始终会很慢。

答案 2 :(得分:8)

将密码和salt存储在数据库的单独列中,或者(我的首选方法),将您的密码以与RFC 2307第5.3节兼容的格式存储在数据库中。一个例子是{X-PBKDF2}base64salt:base64digest。您还可以将迭代计数存储在那里,这样您就可以在未来更新密码的新帐户和帐户中增加迭代次数,而不会破坏其他人的登录。

我自己PBKDF2 module for Perl的示例哈希看起来像是 {X-PBKDF2}HMACSHA1:AAAD6A:8ODUPA==:1HSdSVVwlWSZhbPGO7GIZ4iUbrk=,其中包括使用的特定哈希算法,以及迭代次数,salt和生成的密钥。

答案 3 :(得分:6)

面对同样的问题,我将所有内容整合到一个模块中:https://www.npmjs.org/package/password-hash-and-salt

它使用pbkdf2并在单个字段中存储哈希,salt,算法和迭代。希望它有所帮助。

答案 4 :(得分:5)

我认为本教程最适合您。只是通过它,它是我发现的最好的。 Passport Tutorial with Node.js and Crypto

希望你觉得它有用。

答案 5 :(得分:1)

此方案涉及两个主要步骤

1)创建并存储密码

您必须执行以下操作。

  • 取用户密码
  • 生成一串随机字符(盐)
  • 将salt与用户输入的密码相结合
  • 哈希组合字符串。
  • 将哈希和salt存储在数据库中。

2)验证用户密码

需要此步骤来验证用户身份。

  • 用户将输入用户名/电子邮箱和密码。

  • 根据输入的用户名

  • 获取哈希值和salt
  • 将salt与用户密码结合使用

  • 使用相同的散列算法散列组合。

  • 比较结果。

本教程详细解释了如何使用nodejs加密。正是你在寻找什么。 Salt Hash passwords using NodeJS crypto