Module: Philiprehberger::Password::Hashing

Defined in:
lib/philiprehberger/password/hashing.rb

Constant Summary collapse

BCRYPT_ERROR_MESSAGE =
<<~MSG.strip
  bcrypt gem is required for password hashing.
  Add it to your Gemfile: gem 'bcrypt', '~> 3.1'
  Or install directly: gem install bcrypt
MSG
DEFAULT_COST =
12
MIN_COST =
4
MAX_COST =
31

Class Method Summary collapse

Class Method Details

.hash(password, cost: DEFAULT_COST) ⇒ String

Hash a password using bcrypt. Raises LoadError with a helpful message if bcrypt is not installed.

Parameters:

  • password (String)

    the password to hash (must be a non-empty String)

  • cost (Integer) (defaults to: DEFAULT_COST)

    bcrypt cost factor (default: 12, range: 4-31)

Returns:

  • (String)

    the bcrypt hash string

Raises:

  • (ArgumentError)

    if password is not a non-empty String or cost is out of range



23
24
25
26
27
28
29
30
31
32
# File 'lib/philiprehberger/password/hashing.rb', line 23

def self.hash(password, cost: DEFAULT_COST)
  raise ArgumentError, 'password must be a String' unless password.is_a?(String)
  raise ArgumentError, 'password must not be empty' if password.empty?
  unless cost.is_a?(Integer) && cost.between?(MIN_COST, MAX_COST)
    raise ArgumentError, "cost must be an Integer between #{MIN_COST} and #{MAX_COST}"
  end

  require_bcrypt!
  BCrypt::Password.create(password, cost: cost)
end

.verify(password, hash) ⇒ Boolean

Verify a password against a bcrypt hash. Returns false rather than raising on malformed hash strings. Raises LoadError with a helpful message if bcrypt is not installed.

Parameters:

  • password (String)

    the password to verify

  • hash (String)

    the bcrypt hash to compare against

Returns:

  • (Boolean)

    true if the password matches



41
42
43
44
45
46
47
48
49
# File 'lib/philiprehberger/password/hashing.rb', line 41

def self.verify(password, hash)
  return false unless password.is_a?(String) && hash.is_a?(String)
  return false if password.empty? || hash.empty?

  require_bcrypt!
  BCrypt::Password.new(hash) == password
rescue BCrypt::Errors::InvalidHash
  false
end