From eb2385ad17fdee73576be65115036e6b292990fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Tue, 15 Feb 2011 20:17:15 +0100 Subject: [PATCH] Use secure compare. --- lib/devise.rb | 11 +++++++++++ lib/devise/models/database_authenticatable.rb | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/devise.rb b/lib/devise.rb index 5cf2ed79..f4ae7820 100644 --- a/lib/devise.rb +++ b/lib/devise.rb @@ -210,6 +210,17 @@ module Devise ActiveSupport::SecureRandom.base64(15).tr('+/=', '-_ ').strip.delete("\n") end + # constant-time comparison algorithm to prevent timing attacks + def secure_compare(a, b) + return false unless a.present? && b.present? + return false unless a.bytesize == b.bytesize + l = a.unpack "C#{a.bytesize}" + + res = 0 + b.each_byte { |byte| res |= byte ^ l.shift } + res == 0 + end + # Make Devise aware of an 3rd party Devise-module. For convenience. # # == Options: diff --git a/lib/devise/models/database_authenticatable.rb b/lib/devise/models/database_authenticatable.rb index 9c6d52ba..d804e86a 100644 --- a/lib/devise/models/database_authenticatable.rb +++ b/lib/devise/models/database_authenticatable.rb @@ -55,7 +55,7 @@ module Devise # Verifies whether an incoming_password (ie from sign in) is the user password. def valid_password?(incoming_password) - password_digest(incoming_password) == self.encrypted_password + Devise.secure_compare(password_digest(incoming_password), self.encrypted_password) end # Checks if a resource is valid upon authentication.