By default, CakePHP seems to use the SHA1 algorithm to hash passwords and only seems to offer SHA256 as an alternative:
http://api.cakephp.org/view_source/security#line-86
I wanted to switch to a more secure password hashing solution before I make my application public to save future headaches when switching to a more secure hashing algorithm. I've looked around for some guides on using bcrypt or something similar but they all seem to be for older versions of Cake, or implement the hashing poorly.
Is there a guide somewhere that can show me how to integrate better password hashing without changing any code in my models or controllers?
Also, a little side question, why did the Cake devs only include SHA password hashing in their release? It's common knowledge that SHA is a broken hashing algorithm for passwords, it just seems to me that such a reputable framework wouldn't have overlooked this.
In this ticket CakePHP contributor Mark Story mentions that bcrypt will be supported in CakePHP 2.3 (yet to be released) and will become the standard/default in 3.0.
Also, in this blog post Mark talks about what changes are needed to use bcrypt in CakePHP 2.0. Seems relatively minor, although will require changes to your user model.
Borrowing the code from that post, what Mark did was created a subclass of FormAuthenticate:
<?php
App::uses('FormAuthenticate', 'Controller/Component/Auth');
class BcryptFormAuthenticate extends FormAuthenticate {
/**
* The cost factor for the hashing.
*
* @var integer
*/
public static $cost = 10;
/**
* Password method used for logging in.
*
* @param string $password Password.
* @return string Hashed password.
*/
protected function _password($password) {
return self::hash($password);
}
/**
* Create a blowfish / bcrypt hash.
* Individual salts could/should used to be even more secure.
*
* @param string $password Password.
* @return string Hashed password.
*/
public static function hash($password) {
$salt = substr(Configure::read('Security.salt'), 0, 22);
return crypt($password, '$2a$' . self::$cost . '$' . $salt);
}
}
Then made an update to the controller components array:
<?php
public $components = array(
'Auth' => array(
'authenticate' => 'BcryptForm',
// other keys.
)
);
And finally updating the User model's beforeSave
callback:
<?php
App::uses('BcryptFormAuthenticate', 'Controller/Component/Auth');
class User extends AppModel {
function beforeSave() {
if (isset($this->data['User']['password'])) {
$this->data['User']['password'] = BcryptFormAuthenticate::hash($this->data['User']['password']);
}
return true;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With