diff --git a/_test/cases/inc/auth_password.test.php b/_test/cases/inc/auth_password.test.php index 77ee9eed3fd3e0b7a790b7d5efd706219c49afa0..140c7c23e75f2614c7a95b60543f35534a93f45d 100644 --- a/_test/cases/inc/auth_password.test.php +++ b/_test/cases/inc/auth_password.test.php @@ -16,6 +16,8 @@ class auth_password_test extends UnitTestCase { 'mysql' => '4a1fa3780bd6fd55', 'my411' => '*e5929347e25f82e19e4ebe92f1dc6b6e7c2dbd29', 'kmd5' => 'a579299436d7969791189acadd86fcb716', + 'pmd5' => '$P$abcdefgh1RC6Fd32heUzl7EYCG9uGw.', + 'hmd5' => '$H$abcdefgh1ZbJodHxmeXVAhEzTG7IAp.', ); @@ -39,6 +41,11 @@ class auth_password_test extends UnitTestCase { $this->assertTrue(auth_verifyPassword('foo','$1$$n1rTiFE0nRifwV/43bVon/')); } + function test_verifyPassword_fixedpmd5(){ + $this->assertTrue(auth_verifyPassword('test12345','$P$9IQRaTwmfeRo7ud9Fh4E2PdI0S3r.L0')); + $this->assertTrue(auth_verifyPassword('test12345','$H$9IQRaTwmfeRo7ud9Fh4E2PdI0S3r.L0')); + } + } //Setup VIM: ex: et ts=4 : diff --git a/inc/auth.php b/inc/auth.php index 83d1d41598c52ecebf878f7fb2fa724559bc9a83..5cdcec830f813425b94184b51eb2959bd52eb859 100644 --- a/inc/auth.php +++ b/inc/auth.php @@ -937,6 +937,8 @@ function act_resendpwd(){ * mysql - MySQL password (old method) * my411 - MySQL 4.1.1 password * kmd5 - Salted MD5 hashing as used by UNB + * pmd5 - Salted multi iteration MD5 as used by Wordpress + * hmd5 - Same as pmd5 but PhpBB3 flavour * * @author Andreas Gohr <andi@splitbrain.org> * @return string The crypted password @@ -1016,6 +1018,45 @@ function auth_cryptPassword($clear,$method='',$salt=null){ $hash1 = strtolower(md5($key . md5($clear))); $hash2 = substr($hash1, 0, 16) . $key . substr($hash1, 16); return $hash2; + case 'hmd5': + $key = 'H'; + // hmd5 is exactly the same as pmd5, but uses an H as identifier + // PhpBB3 uses it that way, so we just fall through here + case 'pmd5': + if(!$key) $key = 'P'; + $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + $iterc = $salt[0]; // pos 0 of salt is iteration count + $iter = strpos($itoa64,$iterc); + $iter = 1 << $iter; + $salt = substr($salt,1,8); + + // iterate + $hash = md5($salt . $clear, true); + do { + $hash = md5($hash . $clear, true); + } while (--$iter); + + // encode + $output = ''; + $count = 16; + $i = 0; + do { + $value = ord($hash[$i++]); + $output .= $itoa64[$value & 0x3f]; + if ($i < $count) + $value |= ord($hash[$i]) << 8; + $output .= $itoa64[($value >> 6) & 0x3f]; + if ($i++ >= $count) + break; + if ($i < $count) + $value |= ord($hash[$i]) << 16; + $output .= $itoa64[($value >> 12) & 0x3f]; + if ($i++ >= $count) + break; + $output .= $itoa64[($value >> 18) & 0x3f]; + } while ($i < $count); + + return '$'.$key.'$'.$iterc.$salt.$output; default: msg("Unsupported crypt method $method",-1); } @@ -1043,6 +1084,12 @@ function auth_verifyPassword($clear,$crypt){ }elseif(preg_match('/^\$apr1\$([^\$]{0,8})\$/',$crypt,$m)){ $method = 'apr1'; $salt = $m[1]; + }elseif(preg_match('/^\$P\$(.{31})$/',$crypt,$m)){ + $method = 'pmd5'; + $salt = $m[1]; + }elseif(preg_match('/^\$H\$(.{31})$/',$crypt,$m)){ + $method = 'hmd5'; + $salt = $m[1]; }elseif(substr($crypt,0,6) == '{SSHA}'){ $method = 'ssha'; $salt = substr(base64_decode(substr($crypt, 6)),20);