For improved security given the threat of SQL injection etc., I suggest deploying the EncryptedPassword password class. This is configured with something like:
$wgPasswordConfig['E'] = [ 'class' => 'EncryptedPassword', 'underlying' => 'pbkdf2', 'secrets' => [ $wmgPasswordSecretKey ], 'cipher' => 'aes-256-cbc', ]; $wgPasswordConfig['BE'] = [ 'class' => 'LayeredParameterizedPassword', 'types' => [ 'B', 'E' ], ]; $wgPasswordDefault = 'E';
Where $wmgPasswordSecretKey is in PrivateSettings.php. I used short names (E, BE) since the name is put into the DB , and the hash size ends up being quite close to the 255 byte maximum that can fit in a tinyblob.
Then add a suitable prefix to old-style bare hashes:
UPDATE user SET user_password = CONCAT(':B:', user_id, ':', user_password) WHERE user_password RLIKE '^[0-9a-f]{32}$';
Then wrap all B-type hashes:
mwscript maintenance/wrapOldPasswords.php --type BE
Requires https://gerrit.wikimedia.org/r/#/c/321359/ and a minor update to wrapOldPasswords.php to stop it from throwing an exception due to $wgAuth->allowSetLocalPassword() being false.
Related incident: https://wikitech.wikimedia.org/wiki/Incident_documentation/20161112-OurMine