Skip to content
Permalink
Browse files

Remove blowfish hash generation support from Security::hash().

You should use password_hash() / password_verify() instead.
  • Loading branch information...
ADmad committed Jul 6, 2014
1 parent 8c6b741 commit 2b2fa9792f44f610f88b1bf3ba5a842a4c9205c7
@@ -24,19 +24,13 @@
class Security {
/**
* Default hash method. Default to 'sha1'.
* Default hash method. If `$type` param for `Security::hash()` is not specified
* this value is used. Defaults to 'sha1'.
*
* @var string
*/
public static $hashType = 'sha1';
/**
* Default cost
*
* @var string
*/
public static $hashCost = '10';
/**
* Generate authorization hash.
*
@@ -49,27 +43,12 @@ public static function generateAuthKey() {
/**
* Create a hash from string using given method.
*
* #### Using Blowfish
*
* - Creating Hashes: *Do not supply a salt*. CakePHP handles salt creation for
* you ensuring that each hashed password will have a *unique* salt.
* - Comparing Hashes: Simply pass the originally hashed password as the salt.
* The salt is prepended to the hash and php handles the parsing automagically.
* - Do NOT use a constant salt for blowfish!
*
* Creating a blowfish/bcrypt hash:
*
* {{{
* $hash = Security::hash($password, 'blowfish');
* }}}
*
* @param string $string String to hash
* @param string $type Hashing algo to use (i.e. sha1, sha256, blowfish etc.).
* Can be any valid algo included in list returned by hash_algos() or 'blowfish'.
* @param string $type Hashing algo to use (i.e. sha1, sha256 etc.).
* Can be any valid algo included in list returned by hash_algos().
* If no value is passed the type specified by `Security::$hashType` is used.
* @param mixed $salt If true, automatically prepends the application's salt
* value to $string (Security.salt). If you are using blowfish the salt
* must be false or a previously generated salt.
* value to $string (Security.salt).
* @return string Hash
* @link http://book.cakephp.org/2.0/en/core-utility-libraries/security.html#Security::hash
*/
@@ -79,9 +58,6 @@ public static function hash($string, $type = null, $salt = false) {
}
$type = strtolower($type);
if ($type === 'blowfish') {
return static::_crypt($string, $salt);
}
if ($salt) {
if (!is_string($salt)) {
$salt = Configure::read('Security.salt');
@@ -96,31 +72,14 @@ public static function hash($string, $type = null, $salt = false) {
* Sets the default hash method for the Security object. This affects all objects
* using Security::hash().
*
* @param string $hash Method to use (sha1/sha256/md5/blowfish etc.)
* @param string $hash Method to use (sha1/sha256/md5 etc.)
* @return void
* @see Security::hash()
*/
public static function setHash($hash) {
static::$hashType = $hash;
}
/**
* Sets the cost for they blowfish hash method.
*
* @param int $cost Valid values are 4-31
* @return void
* @throws \Cake\Error\Exception When cost is invalid.
*/
public static function setCost($cost) {
if ($cost < 4 || $cost > 31) {
throw new Exception(vsprintf(
'Invalid value, cost must be between %s and %s',
array(4, 31)
));
}
static::$hashCost = $cost;
}
/**
* Encrypts/Decrypts a text using the given key using rijndael method.
*
@@ -155,51 +114,6 @@ public static function rijndael($text, $key, $operation) {
return rtrim(mcrypt_decrypt($algorithm, $cryptKey, $text, $mode, $iv), "\0");
}
/**
* Generates a pseudo random salt suitable for use with php's crypt() function.
* The salt length should not exceed 27. The salt will be composed of
* [./0-9A-Za-z]{$length}.
*
* @param int $length The length of the returned salt
* @return string The generated salt
*/
protected static function _salt($length = 22) {
$salt = str_replace(
array('+', '='),
'.',
base64_encode(sha1(uniqid(Configure::read('Security.salt'), true), true))
);
return substr($salt, 0, $length);
}
/**
* One way encryption using php's crypt() function. To use blowfish hashing see ``Security::hash()``
*
* @param string $password The string to be encrypted.
* @param mixed $salt false to generate a new salt or an existing salt.
* @return string The hashed string or an empty string on error.
* @throws \Cake\Error\Exception on invalid salt values.
*/
protected static function _crypt($password, $salt = false) {
if ($salt === false) {
$salt = static::_salt(22);
$salt = vsprintf('$2y$%02d$%s', array(static::$hashCost, $salt));
}
$invalidCipher = (
strpos($salt, '$2y$') !== 0 &&
strpos($salt, '$2x$') !== 0 &&
strpos($salt, '$2a$') !== 0
);
if ($salt === true || $invalidCipher || strlen($salt) < 29) {
throw new Exception(sprintf(
'Invalid salt: %s for blowfish Please visit http://www.php.net/crypt and read the appropriate section for building blowfish salts.',
$salt
));
}
return crypt($password, $salt);
}
/**
* Encrypt a value using AES-256.
*
@@ -1,7 +1,5 @@
<?php
/**
* BasicAuthenticateTest file
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
@@ -52,7 +50,7 @@ public function setUp() {
'realm' => 'localhost'
));
$password = Security::hash('password', 'blowfish', false);
$password = password_hash('password', PASSWORD_BCRYPT);
$User = TableRegistry::get('Users');
$User->updateAll(['password' => $password], []);
$this->response = $this->getMock('Cake\Network\Response');
@@ -1,7 +1,5 @@
<?php
/**
* FormAuthenticateTest file
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
@@ -234,7 +232,7 @@ public function testPluginModel() {
$PluginModel = TableRegistry::get('TestPlugin.AuthUsers');
$user['id'] = 1;
$user['username'] = 'gwoo';
$user['password'] = Security::hash(Configure::read('Security.salt') . 'cake', 'blowfish', false);
$user['password'] = password_hash(Configure::read('Security.salt') . 'cake', PASSWORD_BCRYPT);
$PluginModel->save(new Entity($user));
$this->auth->config('userModel', 'TestPlugin.AuthUsers');
@@ -76,7 +76,7 @@ public function setUp() {
$this->Auth = new TestAuthComponent($this->Controller->components());
$Users = TableRegistry::get('AuthUsers');
$Users->updateAll(['password' => Security::hash('cake', 'blowfish', false)], []);
$Users->updateAll(['password' => password_hash('cake', PASSWORD_BCRYPT)], []);
}
/**
@@ -33,45 +33,6 @@ public function testGenerateAuthkey() {
$this->assertEquals(strlen(Security::generateAuthKey()), 40);
}
/**
* testHashInvalidSalt method
*
* @expectedException \Cake\Error\Exception
* @return void
*/
public function testHashInvalidSalt() {
Security::hash('someKey', 'blowfish', true);
}
/**
* testHashAnotherInvalidSalt
*
* @expectedException \Cake\Error\Exception
* @return void
*/
public function testHashAnotherInvalidSalt() {
Security::hash('someKey', 'blowfish', '$1$lksdjoijfaoijs');
}
/**
* testHashYetAnotherInvalidSalt
*
* @expectedException \Cake\Error\Exception
* @return void
*/
public function testHashYetAnotherInvalidSalt() {
Security::hash('someKey', 'blowfish', '$2a$10$123');
}
/**
* testHashInvalidCost method
*
* @expectedException \Cake\Error\Exception
* @return void
*/
public function testHashInvalidCost() {
Security::setCost(1000);
}
/**
* testHash method
*
@@ -115,49 +76,6 @@ public function testHash() {
Security::setHash($_hashType);
}
/**
* Test that hash() works with blowfish.
*
* @return void
*/
public function testHashBlowfish() {
Security::setCost(10);
$test = Security::hash('password', 'blowfish');
$_hashType = Security::$hashType;
$key = 'someKey';
$hashType = 'blowfish';
Security::setHash($hashType);
$this->assertSame($hashType, Security::$hashType);
$this->assertSame(60, strlen(Security::hash($key, null, false)));
$password = $submittedPassword = $key;
$storedPassword = Security::hash($password);
$hashedPassword = Security::hash($submittedPassword, null, $storedPassword);
$this->assertSame($storedPassword, $hashedPassword);
$submittedPassword = 'someOtherKey';
$hashedPassword = Security::hash($submittedPassword, null, $storedPassword);
$this->assertNotSame($storedPassword, $hashedPassword);
$expected = sha1('customsaltsomevalue');
$result = Security::hash('somevalue', 'sha1', 'customsalt');
$this->assertSame($expected, $result);
$oldSalt = Configure::read('Security.salt');
Configure::write('Security.salt', 'customsalt');
$expected = sha1('customsaltsomevalue');
$result = Security::hash('somevalue', 'sha1', true);
$this->assertSame($expected, $result);
Configure::write('Security.salt', $oldSalt);
Security::setHash($_hashType);
}
/**
* testRijndael method
*

0 comments on commit 2b2fa97

Please sign in to comment.
You can’t perform that action at this time.