Problem
- The current password hashing library is a custom fork of phpass.
- It has to be maintained by Drupal. Drupal should not be in the business of developing/maintaining a password hashing library.
- The hashing algorithm is 100% custom. 0% interoperability.
- The next time we upgrade our hash algorithm or iterations count, we have to deal with it all over again. PHP's password_hash() has forward-upgrading built in to its design
Proposed resolution
- Replace the custom password hashing library with PHP 5.5's
password_hash()
. - Use
password_hash()
with default parameters (i.e.$algo = PASSWORD_DEFAULT
and$options = []
). As a result, Drupal follows improvements to the defaults made in subsequent PHP releases automatically. - Sites with special needs may specify
$algo
and$options
by overriding the arguments of thepassword
service. - Extract the existing hashing mechanism to validate passwords of user entities created with Drupal prior to version 10.1.x into an
@internal
abstract base class. - Rewrite
Drupal\Core\Password\PhpassHashedPassword
to extend the newly introduced abstract base class and deprecate it. - Additionally introduce a separate core module (
phpass
). - Enable the
phpass
core module in apost_update
hook for all existing sites. - Add
phpass
as a dependency tomigrate_drupal
. This ensures that passwords migrated from an existing site can be verified without any further action. - Keep the
phpass
core module disabled for new sites. - In Drupal 11 remove
Drupal\Core\Password\PhpassHashedPassword
(but not the code moved to thephpass
module).
Note: Whether it is acceptable to disable the phpass
module is highly individual for each existing website. Some sites have thousands of active users and breaking their logins all at the same time will result in a huge support nightmare. On other sites there is only a small circle of admin accounts. Migrating their passwords to the PHP password_hash()
format might be accomplished in a few weeks without any manual intervention and the phpass
module can be disabled without causing any problems in a subsequent deployment.
Drupal should deprecated the phpass
module in some future release and move it to contrib. That decision could be taken based on actual usage numbers - which are expected to decline over time.
Compliance
In order to simplify adoption by US government agencies, a big effort was made to eliminate most usage of md5()
shortly before Drupal 7 was released (#723802: convert to sha-256 and hmac from md5 and sha1). Especially the change in password.inc
was disputed quite a bit within the community. The switch from md5
to sha512
in the password hashing code was perceived as being technically unnecessary and political to some degree. At that time the change was justified with FIPS 180-3 and FIPS 198-1 compliance (which went into effect in 2010).
NIST published SP 800-132 Recommendation for Password-Based Key Derivation in 2010 as well. That document is currently being reviewed. They are gathering feedback on the industry need for new password-based standards, including memory-hard password-based key derivation functions and password hashing schemes.
There is PHP #81326 Support a NIST SP 800-63B compatible password hash algorithm arguing that none of the password_hash()
algorithms is NIST compliant.
OWASP currently recommends Argon2idwith a minimum configuration of 19 MiB of memory, an iteration count of 2, and 1 degree of parallelism.
Remaining tasks
None.
API changes
- A new password service (
Drupal\Core\Password\PhpPassword
) is introduced which essentially wrapspassword_hash()
,password_verify()
andpassword_needs_rehash
). - The implementation of
Drupal\Core\Password\PhpassHashedPassword
is moved to a newphpass
module. - A deprecated subclass is left at
Drupal\Core\Password\PhpassHashedPassword
and removed in Drupal 11.0
Data model changes
None
Release notes snippet
Drupal now uses the default PHP password_hash() and password_verify() functions in order to store and verify passwords securely. Backwards compatibility is provided by the new phpass module that will be installed on existing sites via an update.