1
0
Fork 0
mirror of https://github.com/heartcombo/devise.git synced 2022-11-09 12:18:31 -05:00

Split out BCrypt hashing to make it reusable

This logic is generic and reusable -- hash a secret; and take an
unhashed secret and compare it to a hashed secret. This breaks this out
to make it reusable in other places. Specifically, we use this in our
own token auth at Bonobos that we plan to split out as a Devise
extension. This will make that possible without copy & pasting this
code.
This commit is contained in:
Magnus von Koeller 2014-03-25 09:44:40 -04:00
parent a29fee1644
commit a8769933d1
3 changed files with 29 additions and 16 deletions

22
lib/devise/encryptor.rb Normal file
View file

@ -0,0 +1,22 @@
require 'bcrypt'
module Devise
module Encryptor
def self.digest(klass, password)
if klass.pepper.present?
password = "#{password}#{klass.pepper}"
end
::BCrypt::Password.create(password, cost: klass.stretches).to_s
end
def self.compare(klass, encrypted_password, password)
return false if encrypted_password.blank?
bcrypt = ::BCrypt::Password.new(encrypted_password)
if klass.pepper.present?
password = "#{password}#{klass.pepper}"
end
password = ::BCrypt::Engine.hash_secret(password, bcrypt.salt)
Devise.secure_compare(password, encrypted_password)
end
end
end

View file

@ -1,13 +1,10 @@
require 'devise/strategies/database_authenticatable'
require 'bcrypt'
require 'devise/encryptor'
module Devise
# Digests the password using bcrypt.
def self.bcrypt(klass, password)
if klass.pepper.present?
password = "#{password}#{klass.pepper}"
end
::BCrypt::Password.create(password, cost: klass.stretches).to_s
ActiveSupport::Deprecation.warn "Devise.bcrypt is deprecated; use Devise::Encryptor.digest instead"
Devise::Encryptor.digest(klass, password)
end
module Models
@ -47,13 +44,7 @@ module Devise
# Verifies whether a password (ie from sign in) is the user password.
def valid_password?(password)
return false if encrypted_password.blank?
bcrypt = ::BCrypt::Password.new(encrypted_password)
if self.class.pepper.present?
password = "#{password}#{self.class.pepper}"
end
password = ::BCrypt::Engine.hash_secret(password, bcrypt.salt)
Devise.secure_compare(password, encrypted_password)
Devise::Encryptor.compare(self.class, encrypted_password, password)
end
# Set password and password confirmation to nil
@ -151,7 +142,7 @@ module Devise
# See https://github.com/plataformatec/devise-encryptable for examples
# of other encryption engines.
def password_digest(password)
Devise.bcrypt(self.class, password)
Devise::Encryptor.digest(self.class, password)
end
module ClassMethods

View file

@ -14,11 +14,11 @@ class DeviseTest < ActiveSupport::TestCase
test 'bcrypt on the class' do
password = "super secret"
klass = Struct.new(:pepper, :stretches).new("blahblah", 2)
hash = Devise.bcrypt(klass, password)
hash = Devise::Encryptor.digest(klass, password)
assert_equal ::BCrypt::Password.create(hash), hash
klass = Struct.new(:pepper, :stretches).new("bla", 2)
hash = Devise.bcrypt(klass, password)
hash = Devise::Encryptor.digest(klass, password)
assert_not_equal ::BCrypt::Password.new(hash), hash
end