Node.js密码哈希化

56

目前我正在使用以下内容对密码进行哈希:

var pass_shasum = crypto.createHash('sha256').update(req.body.password).digest('hex');

你能否提出改进意见,使项目更加安全?


9
未加盐的SHA不安全,请使用bcrypt。 - SLaks
1
http://codahale.com/how-to-safely-store-a-password/ - temporary_user_name
1
优秀的有关保护密码的文章,每个开发者都应该阅读:https://crackstation.net/hashing-security.htm - flukyspore
7个回答

104

我使用以下代码对密码进行加盐和哈希处理。

var bcrypt = require('bcrypt');

exports.cryptPassword = function(password, callback) {
   bcrypt.genSalt(10, function(err, salt) {
    if (err) 
      return callback(err);

    bcrypt.hash(password, salt, function(err, hash) {
      return callback(err, hash);
    });
  });
};

exports.comparePassword = function(plainPass, hashword, callback) {
   bcrypt.compare(plainPass, hashword, function(err, isPasswordMatch) {   
       return err == null ?
           callback(null, isPasswordMatch) :
           callback(err);
   });
};

12
在return后面不要使用else,这样做没有意义。祝福! - brielov
你能否添加一个链接到你正在使用的bcrypt库(如果可能的话,是在github上)?谢谢。 - tedi
1
@Tadej,那是很久以前的事了,但我想应该是这个:https://www.npmjs.com/package/bcrypt - balazs
1
谢谢。我甚至没有检查日期。抱歉。 :/ - tedi
1
有两个模块 bcryptbcryptjs 用于此目的,如果有人能更多地介绍这两个模块那就太好了。 - Gagan

7

bcrypt也可以同步调用。示例Coffeescript:

bcrypt = require('bcrypt')

encryptionUtil = 
    encryptPassword: (password, salt) ->
        salt ?= bcrypt.genSaltSync()
        encryptedPassword = bcrypt.hashSync(password, salt)
        {salt, encryptedPassword}

    comparePassword: (password, salt, encryptedPasswordToCompareTo) ->
        {encryptedPassword} = @encryptPassword(password, salt)
        encryptedPassword == encryptedPasswordToCompareTo

module.exports = encryptionUtil

6

bcrypt with typescript

npm i bcrypt
npm i -D @types/bcrypt
 import * as bcrypt from 'bcrypt';

export const Encrypt = {

    cryptPassword: (password: string) =>
        bcrypt.genSalt(10)
        .then((salt => bcrypt.hash(password, salt)))
        .then(hash => hash),
    
        comparePassword: (password: string, hashPassword: string) =>
            bcrypt.compare(password, hashPassword)
            .then(resp => resp)
    
    }

例子:加密

const myEncryptPassword = await Encrypt.cryptPassword(password);

例子: 比较

const myBoolean = await Encrypt.comparePassword(password, passwordHash);

4

同时,也有用于Node的bcrypt-nodejs模块。 https://github.com/shaneGirish/bcrypt-nodejs.

之前我使用过在此处提到的bcrypt模块,但在win7 x64上遇到了问题。另一方面,bcrypt-nodejs是纯JS实现的bcrypt,并且完全没有任何依赖项。


很遗憾,但这个项目已经不再维护了。 - Stephan Ahlf

1

您可以使用bcrypt-js包来加密密码。

  1. 尝试npm i bcryptjs
  2. 在顶部添加var bcrypt = require('bcryptjs')
  3. 要哈希密码:
bcrypt.genSalt(10, function(err, salt) {
    bcrypt.hash("B4c0/\/", salt, function(err, hash) {
        // Store hash in your password DB.
    });
});
  1. 检查您的密码:
// Load hash from your password DB.
bcrypt.compare("B4c0/\/", hash, function(err, res) {
    // res === true
});

您可以访问https://www.npmjs.com/package/bcryptjs了解有关bcryptjs的更多信息。

1

尝试使用Bcrypt,它使用哈希算法来保护密码。

bcrypt.hash(req.body.password, salt, (err, encrypted) => {
    user.password = encrypted
    next()
})

其中的salt是成本值,用于指定哈希的强度。 在登录时,使用bcrypt.compare方法比较密码:

 bcrypt.compare(password, user.password, (err, same) => {
      if (same) {
           req.session.userId = user._id
           res.redirect('/bloglist')
      } else {
           res.end('pass wrong')
      }
 })

欲了解更多信息,请参考此博客:https://medium.com/@nitinmanocha16/bcrypt-and-nodejs-e00a0d1df91f


1

Bcrypt并不是一个坏选择,但是有几个亟待解决的问题

  1. 它会在NUL字节后截断。
  2. 它会在72个字符后截断。如果你使用口令,这可能会意外地削弱你的密码安全性。

截至2019年10月,Argon2id是最优选择。

与Argon2id进行接口交互的首选方式是通过libsodium(一个提供许多功能的加密库)。 有几种绑定可供选择,但最简单的可能是sodium-plus

const SodiumPlus = require('sodium-plus').SodiumPlus;
let sodium;
(async function(){
    if (!sodium) sodium = await SodiumPlus.auto(); // Autoload the backend

    let password = 'Your example password goes here. Provided by the user.';

    // Hashing...
    let hash = await sodium.crypto_pwhash_str(
        password,
        sodium.CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE,
        sodium.CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE
    );
    // You can safely store {hash} in a database.

    // Checking that a stored hash is still up to snuff...
    let stale = await sodium.crypto_pwhash_str_needs_rehash(
        hash,
        sodium.CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE,
        sodium.CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE
    );
    if (stale) {
        // Rehash password, update database
    }

    // Password verification
    let valid = await sodium.crypto_pwhash_str_verify(password, hash);
    if (valid) {
        // Proceed...
    }
})();

Github 上的 sodium-plus 文档 包括密码哈希和存储。


1
这个回答需要点赞! - Frederik Krautwald

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接