From: Tom Hughes Date: Tue, 13 Aug 2013 23:13:49 +0000 (+0100) Subject: Upgrade passwords to the latest hashing scheme on login X-Git-Tag: live~4762 X-Git-Url: https://git.openstreetmap.org/rails.git/commitdiff_plain/b9daf066842c9e15489d0ccd387d694021975222?ds=sidebyside Upgrade passwords to the latest hashing scheme on login --- diff --git a/app/models/user.rb b/app/models/user.rb index 4c51089e6..b8ec9aebc 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -70,7 +70,14 @@ class User < ActiveRecord::Base end end - user = nil if user and not PasswordHash.check(user.pass_crypt, user.pass_salt, options[:password]) + if user and PasswordHash.check(user.pass_crypt, user.pass_salt, options[:password]) + if PasswordHash.upgrade?(user.pass_crypt, user.pass_salt) + user.pass_crypt, user.pass_salt = PasswordHash.create(options[:password]) + user.save + end + else + user = nil + end elsif options[:token] token = UserToken.find_by_token(options[:token]) user = token.user if token diff --git a/lib/password_hash.rb b/lib/password_hash.rb index 1bd80291a..5adfc7a34 100644 --- a/lib/password_hash.rb +++ b/lib/password_hash.rb @@ -29,6 +29,22 @@ module PasswordHash return hash == candidate end + def self.upgrade?(hash, salt) + if salt.nil? + return true + elsif salt =~ /!/ + algorithm, iterations, salt = salt.split("!") + return true if Base64.strict_decode64(salt).length != SALT_BYTE_SIZE + return true if Base64.strict_decode64(hash).length != HASH_BYTE_SIZE + return true if iterations.to_i != PBKDF2_ITERATIONS + return true if algorithm != DIGEST_ALGORITHM + else + return true + end + + return false + end + private def self.hash(password, salt, iterations, size, algorithm) diff --git a/test/unit/password_hash_test.rb b/test/unit/password_hash_test.rb index 61d3d4921..825942afa 100644 --- a/test/unit/password_hash_test.rb +++ b/test/unit/password_hash_test.rb @@ -4,12 +4,14 @@ class PasswordHashTest < ActiveSupport::TestCase def test_md5_without_salt assert_equal true, PasswordHash.check("5f4dcc3b5aa765d61d8327deb882cf99", nil, "password") assert_equal false, PasswordHash.check("5f4dcc3b5aa765d61d8327deb882cf99", nil, "wrong") + assert_equal true, PasswordHash.upgrade?("5f4dcc3b5aa765d61d8327deb882cf99", nil) end def test_md5_with_salt assert_equal true, PasswordHash.check("67a1e09bb1f83f5007dc119c14d663aa", "salt", "password") assert_equal false, PasswordHash.check("67a1e09bb1f83f5007dc119c14d663aa", "salt", "wrong") assert_equal false, PasswordHash.check("67a1e09bb1f83f5007dc119c14d663aa", "wrong", "password") + assert_equal true, PasswordHash.upgrade?("67a1e09bb1f83f5007dc119c14d663aa", "salt") end def test_default @@ -21,5 +23,7 @@ class PasswordHashTest < ActiveSupport::TestCase assert_equal false, PasswordHash.check(hash1, salt1, "wrong") assert_equal true, PasswordHash.check(hash2, salt2, "password") assert_equal false, PasswordHash.check(hash2, salt2, "wrong") + assert_equal false, PasswordHash.upgrade?(hash1, salt1) + assert_equal false, PasswordHash.upgrade?(hash2, salt2) end end