升级现有的bcrypt哈希回合计数

Aut*_*ico 1 bcrypt node.js

我有一个数据库,其中大多数哈希对于我们的用例而言,舍入计数太低。我希望将它们升级到更高的回合/迭代次数,希望使用node.bcrypt.js库。

例:

我的数据库中有类似的内容

'$2a$05$Ss068.p/.i4IRzrYoLM/U.ETLpzwrBs2vVfViqgfC5bI4i3BGClZC' 
   //From: bcrypt.hashSync("hello world", 5)
Run Code Online (Sandbox Code Playgroud)

我希望它变成这样的东西:

'$2a$10$6sZOFUEWdVMHoCsgF0k1..RhwoD7VmLlLc5.67/Qw81/XuSuNIOcO'
  //From: bcrypt.hashSync("hello world", 10)
Run Code Online (Sandbox Code Playgroud)

有没有办法做到这一点?我认为api可能看起来像这样:

//Non-existing api;
var hash = '$2a$05$Ss068.p/.i4IRzrYoLM/U.ETLpzwrBs2vVfViqgfC5bI4i3BGClZC';
const roundCount = 10
bcrypt.upgradeHashRoundCount(hash, roundCount)
  .then(function(upgradedHash){
    console.log(upgradedHash)
  })
  .catch(function(error){
    console.error("Not a bcrypt hash, or has higher round-count than provided round count")
  })
Run Code Online (Sandbox Code Playgroud)

编辑以澄清:

我想做一个批处理作业,在其中获取所有哈希,并对每个哈希进行升级,而没有原始密码可用。由于bcrypt本质上只是在循环,所以我认为从理论上讲应该可以再进行一些回合并将其存储回去。

Joh*_*erz 5

我想到了几种方法。关于bcrypt的好处是,各轮存储在salt本身中,因此彼此独立。意味着,您可以顺利过渡,而无需破坏旧密码。

所以有两个建议:

  • 您可以对所有更改的新密码/密码开始使用较高的盐。优点显然是您只需要进行哈希轮操作就可以了。缺点是,直到所有密码都存储到更高的回合中之后,它可能要花很长时间。

  • 如果每次登录仍具有较低的回合计数,则可以更新密码。您可以使用getRounds(hash)它。这样,您的密码将很快更新(一旦成功使用一次)

像这样:

function checkPw(pw, user) {
  return bcrypt.compare(pw, user.hash)
  .then(success => {
    if(success && bcrypt.getRounds(hash) < 10) {
      return updateHash(pw, user).then(() => success);
    }
    return success;
  })
}

function updateHash(pw, user) {
  return bcrypt.hash(pw, 10).then((newHash) => {
    user.hash = newHash;
    // update user in db
    return user.save();
  });
}

checkPw('abc', {
  id: 123,
  hash: '$2a$04$7AiVQRTAEPWFwldS7CB6VuQcMSenrPlpoEEGdMyQDE8BxcxcJXPgG'
})
Run Code Online (Sandbox Code Playgroud)