70

I want to use has_secure_password to store encrypted passwords in the database. I can't find on the the internet if has_secure_password uses any form of salting. If it uses salting, how does it works? Can anyone clarify this for me?

Thijs

Thijs
  • 3,015
  • 4
  • 29
  • 54

1 Answers1

93

has_secure_password uses bcrypt-ruby. bcrypt-ruby automatically handles the storage and generation of salts for you. A typical hash from bcrypt-ruby looks like this: $2a$10$4wXszTTd7ass8j5ZLpK/7.ywXXgDh7XPNmzfIWeZC1dMGpFghd92e. This hash is split internally using the following function:

def split_hash(h)
  _, v, c, mash = h.split('$')
  return v, c.to_i, h[0, 29].to_str, mash[-31, 31].to_str
end

For the example hash this function yields:

  • version: 2a
  • cost: 10
  • salt: $2a$10$4wXszTTd7ass8j5ZLpK/7.
  • hash: ywXXgDh7XPNmzfIWeZC1dMGpFghd92e

The ==-function of BCrypt::Password extracts the salt and applies it to the passed string:

BCrypt::Password.create('bla') == 'bla' # => true
fabi
  • 2,978
  • 1
  • 19
  • 23
  • 1
    I believed that author was asking about a separate column for salt. There is no way for us for controlling this salt, so for user it acts like a hash extender -- compromising just 1 column makes breaking our password just a matter of a time. – jdoe Apr 13 '12 at 15:19
  • 14
    The question was 'Does has_secure_password uses any form of salting?', and it does. I think most of the time an entire database is compromised, so it doesn't make a difference if the salt is saved in an extra column. However, you are right that it is more safe in the case that just a single column of the database is compromised. – fabi Apr 13 '12 at 15:32
  • Hi Fabi, thanks for the answer, please upvote the question as well if you think it is interesting/applicable for a larger audience. – Maarten Bodewes Apr 15 '12 at 13:40
  • 1
    To clarify what fabi is saying, bcrypt-ruby automatically generates a salt and concatenates it with the hashed password in the `password_digest` column. See https://github.com/codahale/bcrypt-ruby#salts – Ryenski Jul 08 '15 at 15:14
  • Fun fact: has_secure_password / bcrypt-ruby also hardens your password, which is basically hashing the hash. The cost is the hardening value. In this case, a cost of 10 means that the hash was hashed 1024 times. See: http://www.calebwoods.com/2014/08/26/owasp-password-hashing-ruby/ – Aaron Gray Sep 22 '15 at 08:47
  • 1
    Doesn't answer what user asked. User asked if we can add a salt ourselves? Because when I tested an example password "indu" and checked the hash generated by different versions of bcrypt, and on different machines, the hash was the same. If it was salted the different installations/applications would be generating different hashes, so if the database was hacked, but not the file where the salt was mentioned, then the hacker won't be able to check password hashes against some hash database. – Indu Pillai Aug 15 '17 at 17:06
  • 1
    I guess there is something wrong with your environment, when I run `BCrypt::Password.create('indu')` repeatedly in irb, I get a different hash with every call (as expected). – fabi Aug 15 '17 at 17:36