From d10d8964f28e98e551d39aa5bee70d2c38386dfc Mon Sep 17 00:00:00 2001 From: Graham Christensen Date: Fri, 16 Apr 2021 09:58:46 -0400 Subject: [PATCH] Users: add a validation step which lets the user's password be a Argon2 hashed sha1 hash. OWASP suggests expiring all passwords and requiring users to update their password. However, we don't have a way to do this. They suggest this mechanism as a good alternative: https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#upgrading-legacy-hashes --- src/lib/Hydra/Schema/Users.pm | 6 ++++++ t/Schema/Users.t | 11 +++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/lib/Hydra/Schema/Users.pm b/src/lib/Hydra/Schema/Users.pm index 55f0f1cb..72686367 100644 --- a/src/lib/Hydra/Schema/Users.pm +++ b/src/lib/Hydra/Schema/Users.pm @@ -238,6 +238,12 @@ sub check_password { $self->setPassword($password); } + return 1; + } elsif ($authenticator->verify_password(sha1_hex($password), $self->password)) { + # The user's database record has their old password as sha1, re-hashed as Argon2. + # Store their password hashed only with Argon2. + $self->setPassword($password); + return 1; } else { return 0; diff --git a/t/Schema/Users.t b/t/Schema/Users.t index 5f31af76..d8cbaf8c 100644 --- a/t/Schema/Users.t +++ b/t/Schema/Users.t @@ -39,4 +39,15 @@ ok($user->check_password("foobar"), "Checking the password, foobar, is right"); isnt($user->password, "8843d7f92416211de9ebb963ff4ce28125932878", "The user has had their password rehashed."); ok($user->check_password("foobar"), "Checking the password, foobar, is still right"); +# All sha1 passwords will be upgraded when `hydra-init` is run, by passing the sha1 through +# Argon2. Verify a rehashed sha1 validates too. This removes very weak password hashes +# from the database without requiring users to log in. +subtest "Hashing their sha1 as Argon2 still lets them log in with their password" => sub { + $user->setPassword("8843d7f92416211de9ebb963ff4ce28125932878"); # SHA1 of "foobar" + my $hashedHashPassword = $user->password; + isnt($user->password, "8843d7f92416211de9ebb963ff4ce28125932878", "The user has had their password's hash rehashed."); + ok($user->check_password("foobar"), "Checking the password, foobar, is still right"); + isnt($user->password, $hashedHashPassword, "The user's hashed hash was replaced with just Argon2."); +}; + done_testing;