使用节点加密 scryptSync 哈希密码

hash password using node crypto scryptSync

我需要保护电子应用程序的用户输入密码,以创建用于加密 AES 加密的密钥。正如这里建议的那样,我已经用 scryptSync 函数替换了 createHash 函数。我不确定盐。

// 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 所示,哈希至少需要 128 位或 16 字节。 64 字节实在是太多了,我最多只能使用 256 位,但对于密码而言,128 位就足够了。由于您的目标似乎是最大安全性,请尝试 32 字节。不要忘记要求强密码至少同样重要,如果不是更重要的话。

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

请注意,你们都知道 salt 和 IV 的大小(以字节为单位)。这意味着在编码为 base 64 之前从二进制字符串中获取它们同样容易。这也有一些优点:如果您将二进制数据加载到 Buffer 中,那么您可以简单地使用像这样的方法from 以获得不同的视图,然后可以在不复制数据的情况下表示 IV 或盐。

当然这对密文来说是最重要的。您希望尽可能少地复制它。