Upgrade password hash function to a secure algorithm
|Target version:||Release 2.6.0|
|Google Code Legacy ID:||Tested version:||2.4|
AtoM is currently using SHA1 + salt to hash passwords. SHA-1 is unsuitable for password hashing primarily because the hashing algorithm is too fast, making it economical to crack the password using brute force with modern hardware (see: About Secure Password Hashing "Speed" section). Modern hashing algorithms are designed to require a lot of CPU time and/or require a lot of memory to run to make it time consuming and expensive to crack the passwords using brute force. Most modern hashing algorithms also support a variable "work factor" which allows adjusting the hashing resource requirements based on contemporary hardware capabilities.
Which hashing algorithm should we use?
The OWASP Password Storage Cheat Sheet recommends one of (retrieved 2018-04-11):
- Argon2[*7] is the winner of the password hashing competition and should be considered as your first choice for new applications;
- PBKDF2 [*4] when FIPS certification or enterprise support on many platforms is required;
- scrypt [*5] where resisting any/all hardware accelerated attacks is necessary but support isn’t.
- bcrypt where PBKDF2 or scrypt support is not available.
The PHP password_hash() functions (available in PHP 5.5.0+ and PHP 7) supports bcrypt and Argon2 (7.2+) algorithms, and automatically generates a truly random salt. We should use the Argon2 algorithm if possible, but it is only available in PHP 7.2+ which may influence the final decision.
Upgrading AtoM hashes
To upgrade AtoM's password hashing we'll need change the hashing algorithm for new passwords, and also migrate existing passwords in the database. Because we only store the SHA1 password hash in the database, we don't have the plain text password available to create a new bcrypt or Argon2 hash. One method to work around this problem is to apply the new hashing algorithm (and a new salt) to hash the existing hash (ciphertext) value. This double-hashing strategy is easy to implement (just wrap the current SHA1 hashing function with a newer hashing function) but it does have the disadvantage of requiring us to store two different salts in the database.
We'll need to add a migration script to upgrade all existing passwords in the AtoM database, to avoid a mix of secure and insecure hashes.
[Edit 2018-04-11: fixed some typos and edited for clarity]
[Edit 2018-04-12: added migration script to requirements for upgrading hashes]
#3 Updated by David Juhasz over 2 years ago
Note, the LDAP authentication module is currently using password_hash() with bcrypt
If we decide to update the required PHP version to PHP 7.2 to use the Argon2 algorithm, then we can remove the password_compat library altogether.
#10 Updated by Dan Gillean 11 months ago
Note: there are some further password hashing enhancements in PHP 7.3 - slightly more robust versions of the argon algo have been supported. See:
In an ideal world, we would work on upgrading to PHP 7.3 as a precursor to this work. Otherwise, we should remember this when we upgrade PHP in the future and consider if we want to revisit this ticket at that time.
#11 Updated by Mike Cantelon 11 months ago
- Status changed from New to Code Review
I've implemented password hashing in such a way that we can easily upgrade the algorithm (to PASSWORD_ARGON2ID for example) in subsequent releases if we'd like (and a user can change a config file to use PASSWORD_ARGON2ID right away if they'd like).
#12 Updated by Mike Cantelon 11 months ago
Something we could possibly add in the future, to support changes in hashing algorithms, is the ability to set a user-related property that will, once a user logs in, trigger the use of the password they've provided to redo their stored password hash.
Actually there should be a way to not need a user-related property to be manually set, too, given it should be easy to parse the algo/options from the password hash (here's an example of how it's encoded when stored as part of the hash string: "$argon2i$v=19$m=2048,t=4,p=3$"). If we can easily parse this info out there we can compare it to the current hash algo/options and trigger rehashing.
Edit: password_get_info should parse out the algo/options... https://www.php.net/manual/en/function.password-get-info.php
#13 Updated by Mike Cantelon 11 months ago
(The password_compat lib was previously removed: https://github.com/artefactual/atom/commit/c0d709f912f18c0667a466a24cbbf211bd1a76ca)
#16 Updated by David Juhasz 11 months ago
- Assignee set to Dan Gillean
Dan, I think one of the most important things to test is to upgrade a database (with users) from AtoM 2.5, and make sure you can still log in with the same password after the upgrade. The password hashes are rehashed using the new algorithm by running the