mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge pull request #527 from camspiers/9139f737b8c12587e637452a2a388a6c84a90201
Added ability to set the cost of the blowfish crypt algorithm.
This commit is contained in:
commit
51af3f6557
@ -142,10 +142,35 @@ class PasswordEncryptor_Blowfish extends PasswordEncryptor {
|
|||||||
* Higher costs will increase security, but also increase server load.
|
* Higher costs will increase security, but also increase server load.
|
||||||
* If you are using basic auth, you may need to decrease this as encryption
|
* If you are using basic auth, you may need to decrease this as encryption
|
||||||
* will be run on every request.
|
* will be run on every request.
|
||||||
* Must be between 4 and 31.
|
* The two digit cost parameter is the base-2 logarithm of the iteration
|
||||||
|
* count for the underlying Blowfish-based hashing algorithmeter and must
|
||||||
|
* be in range 04-31, values outside this range will cause crypt() to fail.
|
||||||
*/
|
*/
|
||||||
protected static $cost = 10;
|
protected static $cost = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the cost of the blowfish algorithm.
|
||||||
|
* See {@link PasswordEncryptor_Blowfish::$cost}
|
||||||
|
* Cost is set as an integer but
|
||||||
|
* Ensure that set values are from 4-31
|
||||||
|
*
|
||||||
|
* @param int $cost range 4-31
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
|
public static function set_cost($cost) {
|
||||||
|
self::$cost = max(min(31, $cost), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the cost that is set for the blowfish algorithm
|
||||||
|
*
|
||||||
|
* @param int $cost
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
|
public function get_cost() {
|
||||||
|
return self::$cost;
|
||||||
|
}
|
||||||
|
|
||||||
function encrypt($password, $salt = null, $member = null) {
|
function encrypt($password, $salt = null, $member = null) {
|
||||||
// See: http://nz.php.net/security/crypt_blowfish.php
|
// See: http://nz.php.net/security/crypt_blowfish.php
|
||||||
// There are three version of the algorithm - y, a and x, in order
|
// There are three version of the algorithm - y, a and x, in order
|
||||||
@ -246,9 +271,12 @@ class PasswordEncryptor_Blowfish extends PasswordEncryptor {
|
|||||||
return 'unknown';
|
return 'unknown';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* self::$cost param is forced to be two digits with leading zeroes for ints 4-9
|
||||||
|
*/
|
||||||
function salt($password, $member = null) {
|
function salt($password, $member = null) {
|
||||||
$generator = new RandomGenerator();
|
$generator = new RandomGenerator();
|
||||||
return self::$cost . '$' . substr($generator->generateHash('sha1'), 0, 22);
|
return sprintf('%02d', self::$cost) . '$' . substr($generator->generateHash('sha1'), 0, 22);
|
||||||
}
|
}
|
||||||
|
|
||||||
function check($hash, $password, $salt = null, $member = null) {
|
function check($hash, $password, $salt = null, $member = null) {
|
||||||
|
@ -64,13 +64,49 @@ class PasswordEncryptorTest extends SapphireTest {
|
|||||||
function testEncryptorBlowfish() {
|
function testEncryptorBlowfish() {
|
||||||
Config::inst()->update('PasswordEncryptor', 'encryptors', array('test_blowfish'=>array('PasswordEncryptor_Blowfish'=>'')));
|
Config::inst()->update('PasswordEncryptor', 'encryptors', array('test_blowfish'=>array('PasswordEncryptor_Blowfish'=>'')));
|
||||||
$e = PasswordEncryptor::create_for_algorithm('test_blowfish');
|
$e = PasswordEncryptor::create_for_algorithm('test_blowfish');
|
||||||
|
|
||||||
$password = 'mypassword';
|
$password = 'mypassword';
|
||||||
$salt = '10$mysaltmustbetwen2chars';
|
|
||||||
|
$salt = $e->salt($password);
|
||||||
|
$modSalt = substr($salt, 0, 3) . str_shuffle(substr($salt, 3, strlen($salt)));
|
||||||
|
|
||||||
$this->assertTrue($e->checkAEncryptionLevel() == 'y' || $e->checkAEncryptionLevel() == 'x' || $e->checkAEncryptionLevel() == 'a');
|
$this->assertTrue($e->checkAEncryptionLevel() == 'y' || $e->checkAEncryptionLevel() == 'x' || $e->checkAEncryptionLevel() == 'a');
|
||||||
$this->assertTrue($e->check($e->encrypt($password, $salt), "mypassword", $salt));
|
$this->assertTrue($e->check($e->encrypt($password, $salt), "mypassword", $salt));
|
||||||
$this->assertFalse($e->check($e->encrypt($password, $salt), "anotherpw", $salt));
|
$this->assertFalse($e->check($e->encrypt($password, $salt), "anotherpw", $salt));
|
||||||
$this->assertFalse($e->check($e->encrypt($password, $salt), "mypassword", '10$anothersaltetwen2chars'));
|
$this->assertFalse($e->check($e->encrypt($password, $salt), "mypassword", $modSalt));
|
||||||
|
|
||||||
|
PasswordEncryptor_Blowfish::set_cost(1);
|
||||||
|
$salt = $e->salt($password);
|
||||||
|
$modSalt = substr($salt, 0, 3) . str_shuffle(substr($salt, 3, strlen($salt)));
|
||||||
|
|
||||||
|
$this->assertNotEquals(1, PasswordEncryptor_Blowfish::get_cost());
|
||||||
|
$this->assertEquals(4, PasswordEncryptor_Blowfish::get_cost());
|
||||||
|
|
||||||
|
$this->assertTrue($e->check($e->encrypt($password, $salt), "mypassword", $salt));
|
||||||
|
$this->assertFalse($e->check($e->encrypt($password, $salt), "anotherpw", $salt));
|
||||||
|
$this->assertFalse($e->check($e->encrypt($password, $salt), "mypassword", $modSalt));
|
||||||
|
|
||||||
|
PasswordEncryptor_Blowfish::set_cost(15);
|
||||||
|
$salt = $e->salt($password);
|
||||||
|
$modSalt = substr($salt, 0, 3) . str_shuffle(substr($salt, 3, strlen($salt)));
|
||||||
|
|
||||||
|
$this->assertEquals(15, PasswordEncryptor_Blowfish::get_cost());
|
||||||
|
|
||||||
|
$this->assertTrue($e->check($e->encrypt($password, $salt), "mypassword", $salt));
|
||||||
|
$this->assertFalse($e->check($e->encrypt($password, $salt), "anotherpw", $salt));
|
||||||
|
$this->assertFalse($e->check($e->encrypt($password, $salt), "mypassword", $modSalt));
|
||||||
|
|
||||||
|
|
||||||
|
PasswordEncryptor_Blowfish::set_cost(35);
|
||||||
|
|
||||||
|
$this->assertNotEquals(35, PasswordEncryptor_Blowfish::get_cost());
|
||||||
|
$this->assertEquals(31, PasswordEncryptor_Blowfish::get_cost());
|
||||||
|
|
||||||
|
//Don't actually test this one. It takes too long. 31 takes too long to process
|
||||||
|
// $salt = $e->salt($password);
|
||||||
|
// $this->assertTrue($e->check($e->encrypt($password, $salt), "mypassword", $salt));
|
||||||
|
// $this->assertFalse($e->check($e->encrypt($password, $salt), "anotherpw", $salt));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function testEncryptorPHPHashCheck() {
|
function testEncryptorPHPHashCheck() {
|
||||||
|
Loading…
Reference in New Issue
Block a user