仅使用内置
crypto
模块在 Node.js 中实现密码哈希和验证的最佳方法是什么。
基本上需要什么:
function passwordHash(password) {} // => passwordHash
function passwordVerify(password, passwordHash) {} // => boolean
人们通常使用
bcrypt
或其他第三方库来实现此目的。我想知道内置的 crypto
模块是否已经足够大,足以满足至少所有基本需求?
scrypt()
,这似乎是实现此目的的合适人选,但没有经过验证的对应者,并且似乎没有人关心。
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));
这是一个非常有趣的线程,并且提供了不同的解决方案。 根据我的发现,我提出了一个基于以下内容的解决方案: 轻松分析 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 应用程序中用于验证用户身份的处理程序,它们纯粹用于说明目的。一般来说,您不应该尝试设计自己的加密身份验证机制。最好使用现有的、经过验证的身份验证解决方案。
如何使用“crypto”包比较密码(https://www.npmjs.com/package/crypto-js)
问题是,我有一个 REACT 应用程序,它使用节点作为后端进行身份验证。所以在节点部分,我使用 bcrypt 来比较密码。现在的挑战是使用加密来比较密码。有人可以帮忙吗? 这里附上我的脚本,使用 bcrypt 包来比较密码在此处输入图像描述
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;