diff --git a/_test/cases/inc/auth_password.test.php b/_test/cases/inc/auth_password.test.php index 928552a146d304338250715c8e7e3013aaa570b3..394f0b2f5612e0c90bcc1d9a542e40a636d3eb17 100644 --- a/_test/cases/inc/auth_password.test.php +++ b/_test/cases/inc/auth_password.test.php @@ -12,6 +12,7 @@ class auth_password_test extends UnitTestCase { 'md5' => '8fa22d62408e5351553acdd91c6b7003', 'sha1' => 'b456d3b0efd105d613744ffd549514ecafcfc7e1', 'ssha' => '{SSHA}QMHG+uC7bHNYKkmoLbNsNI38/dJhYmNk', + 'lsmd5' => '{SMD5}HGbkPrkWgy9KgcRGWlrsUWFiY2RlZmdo', 'crypt' => 'ablvoGr1hvZ5k', 'mysql' => '4a1fa3780bd6fd55', 'my411' => '*e5929347e25f82e19e4ebe92f1dc6b6e7c2dbd29', @@ -48,6 +49,11 @@ class auth_password_test extends UnitTestCase { } } + function test_bcrypt_self(){ + $hash = auth_cryptPassword('foobcrypt','bcrypt'); + $this->assertTrue(auth_verifyPassword('foobcrypt',$hash)); + } + function test_verifyPassword_nohash(){ $this->assertTrue(auth_verifyPassword('foo','$1$$n1rTiFE0nRifwV/43bVon/')); } diff --git a/inc/PassHash.class.php b/inc/PassHash.class.php index 31493c02249ef6aa877d595ea25a7dd64b00d15c..2558f37c6afd11bd0dfa383f202e971547245a6f 100644 --- a/inc/PassHash.class.php +++ b/inc/PassHash.class.php @@ -47,9 +47,15 @@ class PassHash { }elseif(preg_match('/^md5\$(.{5})\$/',$hash,$m)){ $method = 'djangomd5'; $salt = $m[1]; + }elseif(preg_match('/^\$2a\$(.{2})\$/',$hash,$m)){ + $method = 'bcrypt'; + $salt = $hash; }elseif(substr($hash,0,6) == '{SSHA}'){ $method = 'ssha'; $salt = substr(base64_decode(substr($hash, 6)),20); + }elseif(substr($hash,0,6) == '{SMD5}'){ + $method = 'lsmd5'; + $salt = substr(base64_decode(substr($hash, 6)),16); }elseif($len == 32){ $method = 'md5'; }elseif($len == 40){ @@ -130,6 +136,20 @@ class PassHash { } } + + /** + * Password hashing method 'lsmd5' + * + * Uses salted MD5 hashs. Salt is 8 bytes long. + * + * This is the format used by LDAP. + */ + public function hash_lsmd5($clear, $salt=null){ + $this->init_salt($salt,8); + return "{SMD5}".base64_encode(md5($clear.$salt, true).$salt); + } + + /** * Password hashing method 'apr1' * @@ -379,4 +399,35 @@ class PassHash { return 'md5$'.$salt.'$'.md5($salt.$clear); } + + /** + * Passwordhashing method 'bcrypt' + * + * Uses a modified blowfish algorithm called eksblowfish + * This method works on PHP 5.3+ only and will throw an exception + * if the needed crypt support isn't available + * + * A full hash should be given as salt (starting with $a2$) or this + * will break. When no salt is given, the iteration count can be set + * through the $compute variable. + * + * @param string $clear - the clear text to hash + * @param string $salt - the salt to use, null for random + * @param int $compute - the iteration count (between 4 and 31) + * @returns string - hashed password + */ + public function hash_bcrypt($clear, $salt=null, $compute=8){ + if(!defined('CRYPT_BLOWFISH') || CRYPT_BLOWFISH != 1){ + throw new Exception('This PHP installation has no bcrypt support'); + } + + if(is_null($salt)){ + if($compute < 4 || $compute > 31) $compute = 8; + $salt = '$2a$'.str_pad($compute, 2, '0', STR_PAD_LEFT).'$'. + $this->gen_salt(22); + } + + return crypt($password, $salt); + } + } diff --git a/lib/plugins/config/settings/config.metadata.php b/lib/plugins/config/settings/config.metadata.php index 96451e8574b54248c494a94818a8c3eb5d4042b2..af815e8dc217972aafcc5146a8c380f25f2d6b22 100644 --- a/lib/plugins/config/settings/config.metadata.php +++ b/lib/plugins/config/settings/config.metadata.php @@ -125,7 +125,7 @@ $meta['_authentication'] = array('fieldset'); $meta['useacl'] = array('onoff'); $meta['autopasswd'] = array('onoff'); $meta['authtype'] = array('authtype'); -$meta['passcrypt'] = array('multichoice','_choices' => array('smd5','md5','apr1','sha1','ssha','crypt','mysql','my411','kmd5','pmd5','hmd5')); +$meta['passcrypt'] = array('multichoice','_choices' => array('smd5','md5','apr1','sha1','ssha','lsmd5','crypt','mysql','my411','kmd5','pmd5','hmd5','bcrypt')); $meta['defaultgroup']= array('string'); $meta['superuser'] = array('string'); $meta['manager'] = array('string');