Skip to content

Migrating from another hash function

Ranieri Althoff edited this page May 29, 2020 · 1 revision

If your database uses another hash function for passwords, you can gradually migrate to Argon2 to improve security. To do that, you need to rehash your user's password as they log in.

Suppose we want want to migrate from bcrypt, with the following code:

import bcrypt from 'bcrypt'

router.post('/login', async ctx => {
  const { email, password } = ctx.request.body
  const user = await User.findOne({ email })
  
  const match = await bcrypt.compare(password, user.password)
  if (!match) {
    throw new Error('Unauthorized')
  }
  // user is authorized
  ...
})

You need to branch before checking the user password and verify what function the current password uses. Then, proceed to update if the password is still using the previous function.

import argon2 from 'argon2'
import bcrypt from 'bcrypt'

router.post('/login', async ctx => {
  const { email, password } = ctx.request.body
  const user = await User.findOne({ email })
  
  // bcrypt hashes start with $2a$ or $2b$
  // argon2 hashes start with $argon2i$, $argon2d$ or $argon2id$
  if (user.password.startsWith('$2')) {
    const match = await bcrypt.compare(password, user.password)
    if (!match) {
      throw new Error('Unauthorized')
    }

    // rehash password with argon2
    user.password = await argon2.hash(password)
    await user.save()
  } else {
    const match = await argon2.verify(user.password, password)
    if (!match) {
      throw new Error('Unauthorized')
    }
  }
  // user is authorized and password is updated
  ...
})

And you're done! Your passwords will be gradually updated to use Argon2.

Clone this wiki locally