我正在查看 nestjs 加密和哈希文档,它显示了以下内容:
import { createCipheriv, randomBytes, scrypt } from 'crypto';
import { promisify } from 'util';
const iv = randomBytes(16);
const password = 'Password used to generate key';
// The key length is dependent on the algorithm.
// In this case for aes256, it is 32 bytes.
const key = (await promisify(scrypt)(password, 'salt', 32)) as Buffer;
const cipher = createCipheriv('aes-256-ctr', key, iv);
const textToEncrypt = 'Nest';
const encryptedText = Buffer.concat([
cipher.update(textToEncrypt),
cipher.final(),
]);
我无法理解这句话:
const key = (await promisify(scrypt)(password, 'salt', 32)) as Buffer;
这是我的问题:
arg2: BinaryLike
arg2: BinaryLike
crypto.scrypt(password, salt, keylen[, options], callback)
crypto.scrypt
是一个采用“错误优先”回调函数的函数:scrypt
将异步派生一个键并调用回调方法返回一个值,向回调传递两个参数err
和 data
(此处 data
是一个缓冲区,记录为 derivedKey
)。
util.promisfy
是一个接受 Function 并返回 Function 的实用程序:您向其传递一个使用错误优先回调的 Function,它返回一个返回 Promise 的 Function,而不是传回回调方法。这允许您使用 await
(如示例代码中所示)以及 then
链接和 Promise.all
等工具。
const key = (await promisify(scrypt)(password, 'salt', 32)) as Buffer;
// This ^^^^^^^^^^^^^^^^^ is just a function based on scrypt.
Salt 是每条记录存储的随机加密值的常用术语;对于
scrypt
,特别是盐“应该尽可能唯一”,建议“盐是随机的且至少 16 个字节长”。更多信息请访问 crypto.SE 或 Wikipedia。
promisify
是一个实用程序,可以采用节点样式回调函数(该函数的最后一个参数作为接受错误和结果的函数,例如fs.readFile('fileToRead', (err, res) => { if (err) throw err; console.log(res); })
)并使其成为承诺的方法,可以是.then
ned 或 await
ed。它有助于在现代 JS 生态系统中生成更清晰的代码。
所以有了上面的内容,而不是需要
scrypt(password, salt, 32, (err, result) => doSomethingWithTheResutlAndError(err, result))
你可以这样做
const result = await scrypt(password, salt, 32)
salt
是什么意思?我不确定你的意思
arg2: BinaryLike
。 这是来自 Node 站点的文档。
正如OP在评论中发现的,
scrypt
方法是必要的,因为它将密钥转换为createCipheriv
方法正确的32位缓冲区格式。
salt
是一个额外的(通常是随机的)字符串,在创建哈希时添加,这样当你多次哈希一个字符串时,它会得到不同的值。这有助于在数据库泄漏的情况下提供安全性,因为没有两个密码看起来是相似的,即使它们每次都碰巧是 password123
。
要了解“其他教程”的含义,您必须展示他们具体在做什么。
对于哈希,我个人使用 bcrypt 或 argon2,但是 Node 的
scrypt
模块中的 crypto
方法是另一个不错的选择。
因为 crypto.scrypt() 是异步的,但不支持 Promise 编码风格。
事实上:
const key = (await promisify(scrypt)(password, 'salt', 32)) as Buffer;
等于:
function scryptPromisify(password, salt, keylen, options) {
return new Promise((resolve, reject) => {
crypto.scrypt(password, salt, keylen, options, (err, derivedKey) => {
if (err) {
reject(err);
} else {
resolve(derivedKey);
}
});
});
}
const key = await scryptPromise(password, 'salt', 32);