I have to rebuild a project from Ruby on Rails to Node.js. Bcrypt was used to hash passwords in the Ruby project and I'm trying to rebuild the same hash so I can copy the hashed password and users can login with the same credentials on the node version.
This hash $2a$11$j2IA8cPRFFC4YOXTl5kb9eF02fwNdLyFAPOvflQ3h/QdX8mE1SNK2
is used for the password Test1234
. I've checked the Ruby on Rails code and I saw the following function to hash a password
General info
COST = 11
SALT = 1234567890
Create hash
def password_hash(password)
pwd = "#{password}#{SALT}"
::BCrypt::Password.create(pwd, cost: COST)
end
Does passwords match?
def password_match?(password = nil)
password ||= @params[:password]
encrypted_password = get_encrypted_password
return false if !encrypted_password || encrypted_password.size < 8
pwd = "#{password}#{SALT}"
BCrypt::Password.new(encrypted_password) == pwd
end
def get_encrypted_password
return unless @account
@account.encrypted_password
end
As far as I know something about Ruby this means that in the password_match
function, pwd would be Test12341234567890
and BCrypt::Password.new($2a$11$j2IA8cPRFFC4YOXTl5kb9eF02fwNdLyFAPOvflQ3h/QdX8mE1SNK2)
checks if Test12341234567890 (pwd)
matches the hash.
When I use an online Bcrypt verifier like https://bcrypt.online/ and enter the hash together with the pwd value I don't get a match.
I also tried to use the bcrypt.compare
method in the Javascript package but this didn't work either.
What am I missing?
CodePudding user response:
So we did an oopsie and solved this issue in the comments. Here is a recap of it all as an answer.
Me:
I tried your password_hash function with "Test1234" and the salt you provided. Got $2a$11$bhdYASCaEPv/0HXv3OFtIupv8CgHFoEWkMonShKnNN1fkmRIg.07S as a result, ran it through the online verifier you linked and got "The supplied hash matches with supplied plain text".
BCrypt::Password.new(password_hash("Test1234")) == "Test12341234567890" Also works out fine and returns true.
Also tried Node.js with bcryptjs and did bcrypt.compareSync('Test12341234567890', "$2a$11$bhdYASCaEPv/0HXv3OFtIupv8CgHFoEWkMonShKnNN1fkmRIg.07S"). Also works out fine and returns true.
Thore:
Yes that's a new hash you created with the same methods. But for some reason the already created hash $2a$11$j2IA8cPRFFC4YOXTl5kb9eF02fwNdLyFAPOvflQ3h/QdX8mE1SNK2 for password Test1234 that is currently stored in the database doesn't pass the online verification test and the compareSync test in node.js
Me:
That should give you the idea that the problem is not with the Ruby's hash creation function, nor is it with the Node's hash testing function, but somewhere else (which is technically outside the scope of this question). Maybe your database doesn't store the full hash for some reason, or stores it in a wrong way. Maybe something somewhere strips or escapes some characters in the hash, leaving you with incomplete one. Maybe some of the aforementioned happens to the salt. Maybe the hash in the database was generated by a different or older hash function. Maybe the salt has changed.
Thore:
Thanks for the comment! With your comment I found out that they used a different salt than the one inside the .env file. It was stored in the config variables of Heroku. Everything is working now!