【问题标题】:Password hashing in nodejs using built-in `crypto`使用内置`crypto`的nodejs中的密码散列
【发布时间】:2020-11-04 14:29:10
【问题描述】:

仅使用内置 crypto 模块在 node.js 中实现密码哈希和验证的最佳方法是什么。 基本上需要什么:

function passwordHash(password) {} // => passwordHash
function passwordVerify(password, passwordHash) {} // => boolean

人们通常为此使用bcrypt 或其他第三方库。我想知道内置的crypto 模块还不够大,至少可以满足所有基本需求吗?

scrypt() 似乎是此目的的合适人选,但没有经过验证的对应对象和 nobody seems to care

【问题讨论】:

    标签: javascript node.js cryptography password-hash scrypt


    【解决方案1】:
    import { scrypt, randomBytes } 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 toHash(password: string) {
        const salt = randomBytes(8).toString("hex");
        const buf = (await scryptAsync(password, salt, 64)) as Buffer;
        return `${buf.toString("hex")}.${salt}`;
      }
      static async compare(storedPassword: string, suppliedPassword: string) {
       // split() returns array
        const [hashedPassword, salt] = storedPassword.split(".");
       // we hash the new sign-in password
        const buf = (await scryptAsync(suppliedPassword, salt, 64)) as Buffer;
       // compare the new supplied password with the stored hashed password
        return buf.toString("hex") === hashedPassword;
      }
    }
    

    【讨论】:

    • 您可能想使用crypto.timingSafeEqual 进行比较
    【解决方案2】:
    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');
    

    将用户的salthash 存储在DB 中。

    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;
    

    【讨论】:

    • 感谢您的贡献。我在这里看到两个缺点(虽然不是专家)。 1)需要存储盐,而我认为它已经以某种方式存储在哈希中 2)验证函数不应该具有与哈希函数相同的计算复杂度。
    • 1) 恕我直言,我们不能直接从hash 中提取salt。我们可以像other crypt libraries 一样将salthash 存储在一个字段(盐+哈希)中。 2)我不确定验证相同的快捷方法。据我所知,我们应该以相同的计算复杂度重新创建hash,以验证它是否与数据库中的hash 相同。希望this answer为你扫除空气。
    • 嘿@disfated,你有没有设法得到任何简单的解决方案?我有点想知道。如果有的话,请您帮忙发布答案。谢谢。
    • 不,我使用了您提供的链接中稍作修改的解决方案。简单的解决方案尚未到来。
    • 当然。找到更简单的解决方案后,不要忘记发布您的解决方案。谢谢:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-15
    • 1970-01-01
    • 1970-01-01
    • 2021-09-15
    • 1970-01-01
    • 2012-01-28
    • 2019-06-02
    相关资源
    最近更新 更多