Regarding the specific implementation: http://svn.wikimedia.org/viewvc/mediawiki/trunk/phase3/includes/User.php?r1=...
comparePasswords() will treat future methods as Old-Style. I think it would be preferable to determine as old-style only if $type[0] != ':' and let hooks be able to handle unknown cases failing to "don't know this codification" if noone is able to detect it.
I don't like that comparePasswords and crypt are doing the same thing (knowing the intrinsecs of the hashing formats).
Same with oldCrypt, which should be a special case of crypt.
Expressed into code, it could be something like this:
static function cryptPassword( $password, $salt = false, $method = null, $showMethod = true) { $hash = ""; if ($method === null) $efectiveMethod = $wgPasswordSalt ? "B" : "A"; else $efectiveMethod = $method;
switch ($efectiveMethod) { case "A": $salt = false; $hash = md5( $password ); break; case "B": if ( $salt === false ) $salt = substr( wfGenerateToken(), 0, 8 ); $hash = md5( $salt.'-'.md5( $password ) ); break; default: if (wfRunHooks('cryptPassword', array(&$hash, $password, $salt, $method))) throw new MWException("I have no idea how to handle password method $efectiveMethod!"); }
if ($showMethod) { if ($salt !== false) $hash = "$salt:$hash"; $hash = ":$efectiveMethod:$hash"; } return $hash; }
static function comparePasswords( $hash, $password, $userId = false ) { $A = explode( ':', $hash, 4 ); if (count(A) < 4) return cryptPassword($password, $userId, null, false) == $A[0]; else return cryptPassword($password, $A[2], $A[1]) == $A[3]; }
Opinions?