password migration

I want to upgrade password hashing from

Digest::SHA1.hexdigest(password + some_string + salt)

``

to SHA512.

Is there a way to migrate existing SHA1 password hashes to the same security level as SHA512? What about this:

hashed_pw_sha512 = Digest::SHA512.hexdigest(hashed_pw_sha1 + other_salt)

``

And then authorize existing users as follows:

Digest::SHA512.hexdigest(Digest::SHA1.hexdigest(password + some_string + salt) + other_salt) == hashed_pw_sha512

``

And as soon as users successfully login this way, then change hashing to

hashed_pw_sha512 = Digest::SHA512.hexdigest(password + other_salt)

``

and set the hashed_pw_sha1 attribute to nil in order to mark the user as migrated.

Update: I’ve learned that bcrypt, PBKDF2, etc. should be used instead of SHAxxx. So replacing SHA512 by bcrypt in my question:

I want to upgrade password hashing from
Digest::SHA1.hexdigest(password + some_string + salt)

``

to bcrypt.

Is there a way to migrate existing SHA1 password hashes to the same security level as bcrypt? What about this:

hashed_pw_bcrypt = BCrypt::Password.create(hashed_pw_sha1)

``

And then authorize existing users as follows:

BCrypt::Password.create(Digest::SHA1.hexdigest(password + some_string + salt)) == hashed_pw_bcrypt

``

And as soon as users successfully login this way, then change hashing to

hashed_pw_bcrypt = BCrypt::Password.create(password)


``

and set the hashed_pw_sha1 attribute to nil in order to mark the user as migrated.

Update: I've learned that bcrypt, PBKDF2, etc. should be used instead of SHAxxx. So replacing SHA512 by bcrypt in my question:

I want to upgrade password hashing from
Digest::SHA1.hexdigest(password + some_string + salt)
to bcrypt.

Is there a way to migrate existing SHA1 password hashes to the same security level as bcrypt? What about this:
hashed_pw_bcrypt = BCrypt::Password.create(hashed_pw_sha1)

And then authorize existing users as follows:
BCrypt::Password.create(Digest::SHA1.hexdigest(password + some_string + salt)) == hashed_pw_bcrypt

And as soon as users successfully login this way, then change hashing to
hashed_pw_bcrypt = BCrypt::Password.create(password)
and set the hashed_pw_sha1 attribute to nil in order to mark the user as migrated.

I think what I would do is add a new set of fields to the existing user record for the new password types, and a boolean column to switch between which one to use. Once all your users are migrated to the new version, you can close off the old method. Something like this pseudocode:

if the boolean is false, test given password against old hash

if it passes
  re-hash the given password with the new algorithm
  set the boolean
  set the new hash column
  save
  redirect
if not
  whatever you currently do
end

Walter

Yes, this is kind of a creeping migration, i.e. an user will be migrated as soon as he’s successfully being authenticated the first time.

What I think of is increasing the security level for all existing users before they login the first time: immediately migrating all passwords to bcrypt(old hash). The question is if this will really achieve the security level of bcrypt for existing user accounts.

br
Luma

bcrypt(oldhash(password)) cannot be easier to crack than oldhash(password), and will be harder except for degenerate cases where oldhash(password) is easier to guess than password. (Imagine for instance a "hash" function which just returned "password1" for all inputs...)