Using bcrypt-ruby to validate hashed passwords using version $2y

2.4k views Asked by At

We're in a bit of a bind where we need to use Ruby to auth users against an existing db of users. The user's passwords were all generated using password_compat PHP library. All the hashed passwords start with $2y.

I've been using bcrypt-ruby to try and authenticate the users and I haven't found any success.

#This user's password is "password"
irb(main):041:0> g = BCrypt::Password.new("$2y$10$jD.PlMQwFSYSdu4imy8oCOdqKFq/FDlW./x9cMxoUmcLgdvKCDNd6")
=> "$2y$10$jD.PlMQwFSYSdu4imy8oCOdqKFq/FDlW./x9cMxoUmcLgdvKCDNd6"
irb(main):042:0> g == "password"
=> false
irb(main):044:0> g.version
=> "2y"
irb(main):045:0> g.cost
=> 10
irb(main):046:0> g.salt
=> "$2y$10$jD.PlMQwFSYSdu4imy8oCO"
irb(main):047:0> g.hash
=> -219334950017117414

I'm not very experienced with bcrypt or encryption in general. Can bcrypt-ruby handle $2y? I looked through the source and I don't think it can. Is this the fault of the underlying OS (I'm using OS X)?

1

There are 1 answers

1
Gumbo On BEST ANSWER

Yes, bcrypt-ruby can handle passwords hashed with 2y. You just need to replace the 2y by 2a:

irb(main):002:0> BCrypt::Password.new("$2a$10$jD.PlMQwFSYSdu4imy8oCOdqKFq/FDlW./x9cMxoUmcLgdvKCDNd6") == "password"
=> true

This is necessary as bcrypt-ruby seems to follow Solar Designer’s first suggestion to introduce just 2x for a backward-compatible support for the “sign extension bug”:

[…] I am considering keeping support for the broken hashes under another prefix - say, "$2x$" (where the "x" would stand for "sign eXtension bug") instead of the usual "$2a$".

Later he proposed to also introduce the 2y prefix for a better distinction between the three versions:

One idea is to allocate yet another prefix, which will mean the same thing as 2a, but "certified" as passing a certain specific test suite (which will include 8-bit chars). So we'll have:

2a - unknown correctness (may be correct, may be buggy)
2x - sign extension bug
2y - definitely correct

Newly set/changed passwords will be getting the new prefix.

PHP supports 2a, 2x, and 2y while bcrypt-ruby supports only 2a, and 2x. But if you know your implementation doesn’t have the “sign extension bug”, you can just replace 2y by 2a, as 2y means the same thing as 2a.