#StackBounty: #ruby-on-rails #regex #ruby #validation #bcrypt BCrypt-3.1.11 hashed passwords suddenly have endless stream of xoo chara…

Bounty: 50

I recently started getting BCrypt “invalid hash” errors when I tried to save a record with a password, so I looked into the BCrypt code, and found the following method for validating passwords:

  def valid_hash?(h)
    h =~ /^$[0-9a-z]{2}$[0-9]{2}$[A-Za-z0-9./]{53}$/

which is called by the initialize method:

def initialize(raw_hash)
  if valid_hash?(raw_hash)
    @version, @cost, @salt, @checksum = split_hash(self)
    raise Errors::InvalidHash.new("invalid hash")

The following passwords:


all return Invalid Hash errors.


I dug deeper, and found that the regex is checking the hashed password, but the hash that is getting passed for some reason has an endless stream of /x00s after it. For example, if I type in the password “LostBlueLizard!@#1234”, the hash that is passed to challenge the regex is

"$2a$11$NcmldbbyCDfumGYALgYhfuIQt2FZ8gpbVCQfuiVlwjhCtkD2ndDFyx00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00..... and so on, for farther than I could scroll.

If I remove the x00s and just pass in $2a$11$NcmldbbyCDfumGYALgYhfuIQt2FZ8gpbVCQfuiVlwjhCtkD2ndDFy, it passes the regex.

Does anyone have any idea why the hash has those characters? I can’t prove they weren’t there before, but my passwords always were accepted until recently.


Also, it’s actually the raw_hash that’s getting input into the initialize method that’s the hash with all the x00s. So somewhere there’s code that generates the faulty hash and passes it to initialize, but I searched the entire gem’s codebase for the term “initialize” and there were no results like that, so I can’t find where the hash is actually generated.


Okay I tracked the issue further, to the BCrypt::Engine.create method, which calls the __bc_crypt method, which is what returns the faulty hash. But __bc_crypt is actually from a file called “ext/mri/bcrypt_ext.c” and is written in C, which I think is beyond my ability to investigate.

I simply updated BCrypt from 3.1.11 to 3.1.13, and now it works fine. I’m not sure whether it was a bug or not, but the point is it works now.

Get this bounty!!!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.