【问题标题】:NodeJS implementation for Python's pbkdf2_sha256.verifyPython 的 pbkdf2_sha256.verify 的 NodeJS 实现
【发布时间】:2019-01-07 21:15:57
【问题描述】:

我必须将这段 Python 代码翻译成 NodeJS:

from passlib.hash import pbkdf2_sha256
pbkdf2_sha256.verify('12345678', '$pbkdf2-sha256$2000$8R7jHOOcs7YWImRM6V1LqQ$CIdNv8YlLlCZfeFJihZs7eQxBsauvVfV05v07Ca2Yzg')
>> True

上面的代码是整个代码,即没有其他参数/​​设置(只需运行pip install passlib,然后再运行它以安装passlib包)。

我正在寻找 Node 中 validatePassword 函数的正确实现,它将通过这个积极的实现测试:

validatePassword('12345678', '$pbkdf2-sha256$2000$8R7jHOOcs7YWImRM6V1LqQ$CIdNv8YlLlCZfeFJihZs7eQxBsauvVfV05v07Ca2Yzg')
>> true

这是 passlib.hash.pbkdf2_sha256 的 documentation 及其默认参数值。

我尝试使用上述 Python 代码中的数据来遵循 here 的答案,但该解决方案没有通过测试。

我将不胜感激有关此实现的一些帮助(最好使用内置的 NodeJS crypto 包)。

提前谢谢你。

【问题讨论】:

    标签: python node.js cryptography sha256 pbkdf2


    【解决方案1】:

    你可以使用crypto.pbkdf2原生node.js api

    const crypto = require('crypto');
    crypto.pbkdf2('secret', 'salt', 100000, 64, 'sha256', (err, derivedKey) => {
      if (err) throw err;
      console.log(derivedKey.toString('hex'));  // '3745e48...08d59ae'
    });
    

    它具有以下 api:

    • password <string>
    • salt <string>
    • iterations <number>
    • keylen <number>
    • digest <string>
    • callback <Function>
      • err <Error>
      • derivedKey <Buffer>

    所以你需要使用输入变量来获得预期的结果,就像在 python 中一样。

    另一种方法

    我玩过输入变量,但没有多大成功,我得到的最简单的想法是制作验证密码的 python 脚本,并在 node.js 中使用child_process.spawn 调用它。

    【讨论】:

    • 我知道加密包(我什至在我的问题中提到了它)。您是否成功地创建了一个函数 validatePassword ,它将像 Python 代码一样为 validatePassword('12345678', '$pbkdf2-sha256$2000$8R7jHOOcs7YWImRM6V1LqQ$CIdNv8YlLlCZfeFJihZs7eQxBsauvVfV05v07Ca2Yzg') 返回 true?我不能,这就是我问这个问题的原因。
    【解决方案2】:

    这可行:

    const crypto = require('crypto')
    function validatePassword(secret, format) {
        let parts = format.split('$')
        return parts[4] == crypto.pbkdf2Sync(secret, Buffer.from(parts[3].replace(/\./g, '+') + '='.repeat(parts[3].length % 3), 'base64'),
            +parts[2], 32, parts[1].split('-')[1]).toString('base64').replace(/=/g, '').replace(/\+/g, '.')
    }
    

    【讨论】:

      【解决方案3】:

      我无法与此处的其他答案一起使用,但它们确实将我引向了正确的方向。

      这是我降落的地方:

      // eslint-2017
      import crypto from 'crypto';
      const encode = (password, { algorithm, salt, iterations }) => {
          const hash = crypto.pbkdf2Sync(password, salt, iterations, 32, 'sha256');
          return `${algorithm}$${iterations}$${salt}$${hash.toString('base64')}`;
      };
      const decode = (encoded) => {
          const [algorithm, iterations, salt, hash] = encoded.split('$');
          return {
              algorithm,
              hash,
              iterations: parseInt(iterations, 10),
              salt,
          };
      };
      const verify = (password, encoded) => {
          const decoded = decode(encoded);
          const encodedPassword = encode(password, decoded);
          return encoded === encodedPassword;
      };
      // <algorithm>$<iterations>$<salt>$<hash>
      const encoded = 'pbkdf2_sha256$120000$bOqAASYKo3vj$BEBZfntlMJJDpgkAb81LGgdzuO35iqpig0CfJPU4TbU=';
      const password = '12345678';
      console.info(verify(password, encoded));

      我知道这是一篇旧帖子,但它是 Google 上的热门搜索结果之一,所以我想我会帮助 2020 年遇到此问题的人。

      【讨论】:

        【解决方案4】:

        这基于node-django-hasher对我有用(没有使用它,因为依赖于node-gyp)

        function validatePassword(plain, hashed) {
          const parts = hashed.split('$');
          const salt = parts[2];
          const iterations = parseInt(parts[1]);
          const keylen = 32;
          const digest = parts[0].split('_')[1];
          const value = parts[3];
          const derivedKey = crypto.pbkdf2Sync(plain, salt, iterations, keylen, digest);
          return value === Buffer.from(derivedKey, 'binary').toString('base64');
        }

        【讨论】:

          【解决方案5】:

          终于解决了。因为 passlib 对 base64 编码的字符串进行了一些转换,所以上述解决方案都不适合我。我最终编写了自己的节点模块,并使用 passlib 1.7.4 哈希进行了测试。感谢@kayluhb 将我推向正确的方向!

          请随意使用:node-passlib

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-07-06
            • 2018-02-14
            • 2021-01-14
            • 2022-01-13
            • 2020-11-14
            • 2020-04-05
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多