在nodejs中使用内置的“crypto”进行密码散列

问题描述 投票:0回答:4

仅使用内置

crypto
模块在 Node.js 中实现密码哈希和验证的最佳方法是什么。 基本上需要什么:

function passwordHash(password) {} // => passwordHash
function passwordVerify(password, passwordHash) {} // => boolean

人们通常使用

bcrypt
或其他第三方库来实现此目的。我想知道内置的
crypto
模块是否已经足够大,足以满足至少所有基本需求?

scrypt()
,这似乎是实现此目的的合适人选,但没有经过验证的对应者,并且似乎没有人关心

javascript node.js cryptography password-hash scrypt
4个回答
23
投票
import { scrypt, randomBytes, timingSafeEqual } from "crypto";
import { promisify } from "util";

// scrypt is callback based so with promisify we can await it
const scryptAsync = promisify(scrypt);

哈希过程有两种方法。第一种方法,您对密码进行哈希处理,第二种方法,您需要将新的登录密码与存储的密码进行比较。 我用打字稿详细写下所有内容

export class Password {

  static async hashPassword(password: string) {
    const salt = randomBytes(16).toString("hex");
    const buf = (await scryptAsync(password, salt, 64)) as Buffer;
    return `${buf.toString("hex")}.${salt}`;
  }

  static async comparePassword(
    storedPassword: string,
    suppliedPassword: string
  ): Promise<boolean> {
    // split() returns array
    const [hashedPassword, salt] = storedPassword.split(".");
    // we need to pass buffer values to timingSafeEqual
    const hashedPasswordBuf = Buffer.from(hashedPassword, "hex");
    // we hash the new sign-in password
    const suppliedPasswordBuf = (await scryptAsync(suppliedPassword, salt, 64)) as Buffer;
    // compare the new supplied password with the stored hashed password
    return timingSafeEqual(hashedPasswordBuf, suppliedPasswordBuf);
  }
}

测试一下:

Password.hashPassword("123dafdas")
  .then((res) => Password.comparePassword(res, "123edafdas"))
  .then((res) => console.log(res));

5
投票

这是一个非常有趣的线程,并且提供了不同的解决方案。 根据我的发现,我提出了一个基于以下内容的解决方案: 轻松分析 Node.js 应用程序

请参阅下面的示例代码。

// add new user
app.get('/newUser', (req, res) => {
  let username = req.query.username || '';
  const password = req.query.password || '';

  username = username.replace(/[!@#$%^&*]/g, '');

  if (!username || !password || users[username]) {
    return res.sendStatus(400);
  }

  const salt = crypto.randomBytes(128).toString('base64');
  const hash = crypto.pbkdf2Sync(password, salt, 10000, 512, 'sha512');

  users[username] = { salt, hash };

  res.sendStatus(200);
});

验证用户身份验证尝试

// validating user authentication attempts
app.get('/auth', (req, res) => {
  let username = req.query.username || '';
  const password = req.query.password || '';

  username = username.replace(/[!@#$%^&*]/g, '');

  if (!username || !password || !users[username]) {
    return res.sendStatus(400);
  }

  const { salt, hash } = users[username];
  const encryptHash = crypto.pbkdf2Sync(password, salt, 10000, 512, 'sha512');

  if (crypto.timingSafeEqual(hash, encryptHash)) {
    res.sendStatus(200);
  } else {
    res.sendStatus(401);
  }
});

请注意,这些不是推荐在 Node.js 应用程序中用于验证用户身份的处理程序,它们纯粹用于说明目的。一般来说,您不应该尝试设计自己的加密身份验证机制。最好使用现有的、经过验证的身份验证解决方案。


0
投票

如何使用“crypto”包比较密码(https://www.npmjs.com/package/crypto-js)

问题是,我有一个 REACT 应用程序,它使用节点作为后端进行身份验证。所以在节点部分,我使用 bcrypt 来比较密码。现在的挑战是使用加密来比较密码。有人可以帮忙吗? 这里附上我的脚本,使用 bcrypt 包来比较密码在此处输入图像描述


-1
投票
const password = "my_password"; 

// Creating a unique salt for a particular user
const salt = crypto.randomBytes(16).toString('hex'); 
  
// Hash the salt and password with 1000 iterations, 64 length and sha512 digest 
const hash = crypto.pbkdf2Sync(password, salt, 1000, 64, 'sha512').toString('hex');

将用户的

salt
hash
存储在数据库中。

const re_entered_password = "my_password";

// To verify the same - salt (stored in DB) with same other parameters used while creating hash (1000 iterations, 64 length and sha512 digest)
const newHash = crypto.pbkdf2Sync(re_entered_password, salt, 1000, 64, 'sha512').toString('hex');

// check if hash (stored in DB) and newly generated hash (newHash) are the same
hash === newHash;
© www.soinside.com 2019 - 2024. All rights reserved.