We're in the process of converting our site from an old PHP framework to Rails, and would really like for users to continue being able to login with their old password. On the old site, we're using password_hash and password_verify to hash and verify the passwords. However, on Rails I can't seem to get it to verify the old password.
Here is what we have in PHP:
password_hash($user['salt'] . $password . $user['salt'], PASSWORD_DEFAULT);
password_verify($user['salt'] . $password . $user['salt'], $user['password'])
if password_version == 'legacy'
hash = BCrypt::Password.new(encrypted_password)
hash_str = password_salt+password+password_salt
return hash.is_password? hash_str
The format of a PHP
password_hash password looks roughly like this:
The default Ruby Bcrypt method produces passwords of the form:
For a clean solution here you can always differentiate between the two by the
$2a prefix. There's no need for a format column when it's already baked into the format.
case (encrypted_password[0,3]) when '$2y' # Legacy PHP password BCrypt::Password.new(encrypted_password.sub(/\A\$2y/, '$2a')).is_password?(salt + password + salt) when '$2a' # Ruby BCrypt password BCrypt::Password.new(encrypted_password).is_password?(password) else # Unexpected type? end
What you'll want to do on a successful verification of password is re-write the password to the database using Ruby's method to gradually replace all the old PHP formatted ones.