使用节点加密 scryptSync 哈希密码

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

我需要保护电子应用程序的用户输入密码,以创建用于加密 AES 加密的密钥。正如此处所建议的那样,我已将

createHash
函数替换为
scryptSync
函数。我不确定盐的分量。

// this is the old method I've used to hash the password to obtain the correct lenght for aes-256-gcm
  // let key = crypto.createHash('sha256')
  //       .update(data.password)
  //       .digest();
// salt creation 
  let salt = crypto.randomBytes(64);
  let key = crypto.scryptSync(data.password, salt, 32);

是否需要传递给

randomBytes
函数以实现
aes-256-gcm
加密算法的预定义大小?

此外,当我将盐附加到加密输出时,我正在使用此代码

   let encryptedData = Buffer.concat([cipher.update(base64, 'utf8'), cipher.final()]);
    let payload = `${salt.toString('base64')}:${iv.toString('base64')}:${encryptedData.toString('base64')}`;

由于我使用

join()
函数来合并多个编码字符串,因此当需要对加密的输出文件进行解码时,我需要一种方法来拆分它们。目前我正在使用这种方式,但我发现我需要提取盐来检查密码。有没有办法做得更好?

const decryptData = (data) => {
  let output = [];
  // I need the salt here but the file needs to be splitted before
  let key = crypto.scryptSync(data.password, 'salt', 32);

  return new Promise( (resolve, reject) => {
    fs.readFile(data.path, 'utf8', (err, content) => {
      if(err) return reject(err);
      let fileContents = content.split(' ');
      output = fileContents.map( (file) => {
        let [salt, iv, content] = file.split(':');
        let cipher = crypto.createDecipheriv('aes-256-gcm', key, Buffer.from(iv, 'base64'));
        let decrypted = cipher.update(content, 'base64', 'utf8');
        return decryptedData;
      });
      resolve(output);
    });
  });
}
node.js encryption salt
1个回答
3
投票

正如 Node.js 所示,哈希值至少需要 128 位或 16 字节。 64 字节确实太多了,我最多可以使用 256 位,但对于密码来说 128 位确实足够了。由于您的目标似乎是最大安全性,因此请尝试 32 字节。不要忘记,要求强密码至少同样重要,甚至更重要。

当前您正在使用

scryptSync
的默认成本参数。这可能不是一个好主意,因为它默认设置为 16384。越高越好,因此请尝试看看什么最适合您的特定目标平台。

请注意,你们都知道 salt 和 IV 大小(以字节为单位)。这意味着在将二进制字符串编码为 Base 64 之前,从二进制字符串中获取它们同样容易。这也有一些优点:如果将二进制数据加载到

Buffer
中,那么您可以简单地使用
 之类的方法from
获得不同的视图,然后可以表示 IV 或盐,而无需复制数据。

这当然对于明文来说是最重要的。您希望尽可能少地复制该内容。

© www.soinside.com 2019 - 2024. All rights reserved.