From c4b441151300b86ec7ebbb973b88fad9689617c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?George=20Guimara=CC=83es?= Date: Wed, 10 Feb 2016 17:00:49 -0200 Subject: [PATCH] Change encryption for hashing in the documentation. Throughout the documentations, we are using 'encrypt' incorrectly. Encrypt means that someone will eventually decrypt the message, which is obviously not the case for Devise. I'm changing the docs to use 'hashing' instead. However, I left the database field as `encrypted_password` for now. I'll update the db field in an upcoming PR. --- README.md | 4 ++-- lib/devise.rb | 4 ++-- lib/devise/encryptor.rb | 8 ++++---- lib/devise/models/database_authenticatable.rb | 12 +++++++----- .../strategies/database_authenticatable.rb | 6 +++--- lib/generators/templates/devise.rb | 16 ++++++++-------- test/models/database_authenticatable_test.rb | 12 ++++++------ test/test_models.rb | 2 +- 8 files changed, 33 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index fd1db053..6603eebe 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,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. @@ -174,7 +174,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 diff --git a/lib/devise.rb b/lib/devise.rb index 4652c1ab..dca9af6c 100644 --- a/lib/devise.rb +++ b/lib/devise.rb @@ -61,7 +61,7 @@ module Devise 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 = 10 @@ -146,7 +146,7 @@ module Devise 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 diff --git a/lib/devise/encryptor.rb b/lib/devise/encryptor.rb index 751db106..19651d7b 100644 --- a/lib/devise/encryptor.rb +++ b/lib/devise/encryptor.rb @@ -9,14 +9,14 @@ module Devise ::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 diff --git a/lib/devise/models/database_authenticatable.rb b/lib/devise/models/database_authenticatable.rb index 27a8646d..2816a813 100644 --- a/lib/devise/models/database_authenticatable.rb +++ b/lib/devise/models/database_authenticatable.rb @@ -7,8 +7,8 @@ module Devise 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 # @@ -37,7 +37,9 @@ module Devise [: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 @@ -142,11 +144,11 @@ module Devise 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 diff --git a/lib/devise/strategies/database_authenticatable.rb b/lib/devise/strategies/database_authenticatable.rb index 42880acf..3d8f4072 100644 --- a/lib/devise/strategies/database_authenticatable.rb +++ b/lib/devise/strategies/database_authenticatable.rb @@ -6,15 +6,15 @@ module Devise 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 diff --git a/lib/generators/templates/devise.rb b/lib/generators/templates/devise.rb index 818eebe5..64a22c89 100644 --- a/lib/generators/templates/devise.rb +++ b/lib/generators/templates/devise.rb @@ -92,16 +92,16 @@ Devise.setup do |config| # ==> Configuration for :database_authenticatable # For bcrypt, this is the cost for hashing the password and defaults to 10. If - # using other encryptors, it sets how many times you want the password re-encrypted. + # 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 10 in other environments. Note that, for bcrypt (the default - # encryptor), the cost increases exponentially with the number of stretches (e.g. + # 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 : 10 - # 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 @@ -201,11 +201,11 @@ Devise.setup do |config| # 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 diff --git a/test/models/database_authenticatable_test.rb b/test/models/database_authenticatable_test.rb index 5daca424..8c12d93c 100644 --- a/test/models/database_authenticatable_test.rb +++ b/test/models/database_authenticatable_test.rb @@ -92,28 +92,28 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase 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' diff --git a/test/test_models.rb b/test/test_models.rb index 3c1f1787..d65648d9 100644 --- a/test/test_models.rb +++ b/test/test_models.rb @@ -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