Skip to content

Commit

Permalink
Merge branch 'gg-correct-encryption-meaning'
Browse files Browse the repository at this point in the history
  • Loading branch information
georgeguimaraes committed Feb 11, 2016
2 parents 1f36946 + c4b4411 commit 014859e
Show file tree
Hide file tree
Showing 8 changed files with 35 additions and 33 deletions.
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -16,7 +16,7 @@ Devise is a flexible authentication solution for Rails based on Warden. It:

It's composed of 10 modules:

* [Database Authenticatable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/DatabaseAuthenticatable): encrypts and stores a password in the database to validate the authenticity of a user while signing in. The authentication can be done both through POST requests or HTTP Basic Authentication.
* [Database Authenticatable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/DatabaseAuthenticatable): hashes and stores a password in the database to validate the authenticity of a user while signing in. The authentication can be done both through POST requests or HTTP Basic Authentication.
* [Omniauthable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Omniauthable): adds OmniAuth (https://github.com/intridea/omniauth) support.
* [Confirmable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Confirmable): sends emails with confirmation instructions and verifies whether an account is already confirmed during sign in.
* [Recoverable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Recoverable): resets the user password and sends reset instructions.
Expand Down Expand Up @@ -173,7 +173,7 @@ member_session

### Configuring Models

The Devise method in your models also accepts some options to configure its modules. For example, you can choose the cost of the encryption algorithm with:
The Devise method in your models also accepts some options to configure its modules. For example, you can choose the cost of the hashing algorithm with:

```ruby
devise :database_authenticatable, :registerable, :confirmable, :recoverable, stretches: 20
Expand Down
4 changes: 2 additions & 2 deletions lib/devise.rb
Expand Up @@ -61,7 +61,7 @@ module Strategies
mattr_accessor :rememberable_options
@@rememberable_options = {}

# The number of times to encrypt password.
# The number of times to hash the password.
mattr_accessor :stretches
@@stretches = 11

Expand Down Expand Up @@ -146,7 +146,7 @@ module Strategies
mattr_accessor :timeout_in
@@timeout_in = 30.minutes

# Used to encrypt password. Please generate one with rake secret.
# Used to hash the password. Please generate one with rake secret.
mattr_accessor :pepper
@@pepper = nil

Expand Down
8 changes: 4 additions & 4 deletions lib/devise/encryptor.rb
Expand Up @@ -9,14 +9,14 @@ def self.digest(klass, password)
::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)
def self.compare(klass, hashed_password, password)
return false if hashed_password.blank?
bcrypt = ::BCrypt::Password.new(hashed_password)
if klass.pepper.present?
password = "#{password}#{klass.pepper}"
end
password = ::BCrypt::Engine.hash_secret(password, bcrypt.salt)
Devise.secure_compare(password, encrypted_password)
Devise.secure_compare(password, hashed_password)
end
end
end
12 changes: 7 additions & 5 deletions lib/devise/models/database_authenticatable.rb
Expand Up @@ -7,8 +7,8 @@ def self.bcrypt(klass, password)
end

module Models
# Authenticatable Module, responsible for encrypting password and validating
# authenticity of a user while signing in.
# Authenticatable Module, responsible for hashing the password and
# validating the authenticity of a user while signing in.
#
# == Options
#
Expand Down Expand Up @@ -37,7 +37,9 @@ def self.required_fields(klass)
[:encrypted_password] + klass.authentication_keys
end

# Generates password encryption based on the given value.
# Generates a hashed password based on the given value.
# For legacy reasons, we use `encrypted_password` to store
# the hashed password.
def password=(new_password)
attribute_will_change! 'password'
@password = new_password
Expand Down Expand Up @@ -142,11 +144,11 @@ def send_password_change_notification

protected

# Digests the password using bcrypt. Custom encryption should override
# Hashes the password using bcrypt. Custom hash functions should override
# this method to apply their own algorithm.
#
# See https://github.com/plataformatec/devise-encryptable for examples
# of other encryption engines.
# of other hashing engines.
def password_digest(password)
Devise::Encryptor.digest(self.class, password)
end
Expand Down
6 changes: 3 additions & 3 deletions lib/devise/strategies/database_authenticatable.rb
Expand Up @@ -6,15 +6,15 @@ module Strategies
class DatabaseAuthenticatable < Authenticatable
def authenticate!
resource = password.present? && mapping.to.find_for_database_authentication(authentication_hash)
encrypted = false
hashed = false

if validate(resource){ encrypted = true; resource.valid_password?(password) }
if validate(resource){ hashed = true; resource.valid_password?(password) }
remember_me(resource)
resource.after_database_authentication
success!(resource)
end

mapping.to.new.password = password if !encrypted && Devise.paranoid
mapping.to.new.password = password if !hashed && Devise.paranoid
fail(:not_found_in_database) unless resource
end
end
Expand Down
20 changes: 10 additions & 10 deletions lib/generators/templates/devise.rb
Expand Up @@ -91,17 +91,17 @@
# config.clean_up_csrf_token_on_authentication = true

# ==> Configuration for :database_authenticatable
# For bcrypt, this is the cost for hashing the password and defaults to 12. If
# using other encryptors, it sets how many times you want the password re-encrypted.
# For bcrypt, this is the cost for hashing the password and defaults to 11. If
# using other algorithms, it sets how many times you want the password to be hashed.
#
# Limiting the stretches to just one in testing will increase the performance of
# your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use
# a value less than 12 in other environments. Note that, for bcrypt (the default
# encryptor), the cost increases exponentially with the number of stretches (e.g.
# a value less than 10 in other environments. Note that, for bcrypt (the default
# algorithm), the cost increases exponentially with the number of stretches (e.g.
# a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation).
config.stretches = Rails.env.test? ? 1 : 11

# Set up a pepper to generate the encrypted password.
# Set up a pepper to generate the hashed password.
# config.pepper = '<%= SecureRandom.hex(64) %>'

# Send a notification email when the user's password is changed
Expand Down Expand Up @@ -201,11 +201,11 @@
# config.sign_in_after_reset_password = true

# ==> Configuration for :encryptable
# Allow you to use another encryption algorithm besides bcrypt (default). You can use
# :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1,
# :authlogic_sha512 (then you should set stretches above to 20 for default behavior)
# and :restful_authentication_sha1 (then you should set stretches to 10, and copy
# REST_AUTH_SITE_KEY to pepper).
# Allow you to use another hashing or encryption algorithm besides bcrypt (default).
# You can use :sha1, :sha512 or algorithms from others authentication tools as
# :clearance_sha1, :authlogic_sha512 (then you should set stretches above to 20
# for default behavior) and :restful_authentication_sha1 (then you should set
# stretches to 10, and copy REST_AUTH_SITE_KEY to pepper).
#
# Require the `devise-encryptable` gem when using anything other than bcrypt
# config.encryptor = :sha512
Expand Down
12 changes: 6 additions & 6 deletions test/models/database_authenticatable_test.rb
Expand Up @@ -92,28 +92,28 @@ def setup
assert user.respond_to?(:password_confirmation)
end

test 'should generate encrypted password while setting password' do
test 'should generate a hashed password while setting password' do
user = new_user
assert_present user.encrypted_password
end

test 'should support custom encryption methods' do
user = UserWithCustomEncryption.new(password: '654321')
test 'should support custom hashing methods' do
user = UserWithCustomHashing.new(password: '654321')
assert_equal user.encrypted_password, '123456'
end

test 'allow authenticatable_salt to work even with nil encrypted password' do
test 'allow authenticatable_salt to work even with nil hashed password' do
user = User.new
user.encrypted_password = nil
assert_nil user.authenticatable_salt
end

test 'should not generate encrypted password if password is blank' do
test 'should not generate a hashed password if password is blank' do
assert_blank new_user(password: nil).encrypted_password
assert_blank new_user(password: '').encrypted_password
end

test 'should encrypt password again if password has changed' do
test 'should hash password again if password has changed' do
user = create_user
encrypted_password = user.encrypted_password
user.password = user.password_confirmation = 'new_password'
Expand Down
2 changes: 1 addition & 1 deletion test/test_models.rb
Expand Up @@ -12,7 +12,7 @@ class UserWithValidation < User
validates_presence_of :username
end

class UserWithCustomEncryption < User
class UserWithCustomHashing < User
protected
def password_digest(password)
password.reverse
Expand Down

0 comments on commit 014859e

Please sign in to comment.