Skip to content
This repository has been archived by the owner on Jan 29, 2020. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'ezimuel/fix/bcrypt'
Browse files Browse the repository at this point in the history
  • Loading branch information
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 14 deletions.
24 changes: 18 additions & 6 deletions src/Password/Bcrypt.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,28 @@ public function __construct($options = array())
public function create($password)
{
if (empty($this->salt)) {
try {
$salt = Math::randBytes(self::MIN_SALT_SIZE, true);
} catch (MathException\RuntimeException $e) {
throw new Exception\RuntimeException($e->getMessage());
}
$salt = Math::randBytes(self::MIN_SALT_SIZE);
} else {
$salt = $this->salt;
}
$salt64 = substr(str_replace('+', '.', base64_encode($salt)), 0, 22);
$hash = crypt($password, '$2a$' . $this->cost . '$' . $salt64);
/**
* Check for security flaw in the bcrypt implementation used by crypt()
* @see http://php.net/security/crypt_blowfish.php
*/
if (version_compare(PHP_VERSION, '5.3.7') >= 0) {
$prefix = '$2y$';
} else {
$prefix = '$2a$';
// check if the password contains 8-bit character
if (preg_match('/[\x80-\xFF]/', $password)) {
throw new Exception\RuntimeException(
'The bcrypt implementation used by PHP can contains a security flaw using password with 8-bit character. ' .
'We suggest to upgrade to PHP 5.3.7+ or use passwords with only 7-bit characters'
);
}
}
$hash = crypt($password, $prefix . $this->cost . '$' . $salt64);
if (strlen($hash) <= 13) {
throw new Exception\RuntimeException('Error during the bcrypt generation');
}
Expand Down
32 changes: 24 additions & 8 deletions test/Password/BcryptTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,15 @@ class BcryptTest extends \PHPUnit_Framework_TestCase

public function setUp()
{
try {
$this->bcrypt = new Bcrypt();
$password = $this->bcrypt->create('test');
} catch (Exception\RuntimeException $e) {
$this->markTestSkipped('This system doesn\'t support strong random numbers, I cannot run BcryptTest');
$this->bcrypt = new Bcrypt();
$this->salt = '1234567890123456';
$this->password = 'test';
if (version_compare(PHP_VERSION, '5.3.7') >= 0) {
$this->prefix = '$2y$';
} else {
$this->prefix = '$2a$';
}
$this->salt = '1234567890123456';
$this->password = 'test';
$this->bcryptPassword = '$2a$14$MTIzNDU2Nzg5MDEyMzQ1NeWUUefVlefsTbFhsbqKFv/vPSZBrSFVm';
$this->bcryptPassword = $this->prefix . '14$MTIzNDU2Nzg5MDEyMzQ1NeWUUefVlefsTbFhsbqKFv/vPSZBrSFVm';
}

public function testConstructByOptions()
Expand Down Expand Up @@ -134,4 +134,20 @@ public function testVerify()
$this->assertTrue($this->bcrypt->verify($this->password, $this->bcryptPassword));
$this->assertFalse($this->bcrypt->verify(substr($this->password, -1), $this->bcryptPassword));
}

public function testPasswordWith8bitCharacter()
{
$password = 'test' . chr(128);
$this->bcrypt->setSalt($this->salt);

if (version_compare(PHP_VERSION, '5.3.7') >= 0) {
$this->assertEquals('$2y$14$MTIzNDU2Nzg5MDEyMzQ1NexAbOIUHkG6Ra.TK9QxHOVUhDxOe4dkW', $this->bcrypt->create($password));
} else {
$this->setExpectedException('Zend\Crypt\Password\Exception\RuntimeException',
'The bcrypt implementation used by PHP can contains a security flaw using password with 8-bit character. ' .
'We suggest to upgrade to PHP 5.3.7+ or use passwords with only 7-bit characters'
);
$output = $this->bcrypt->create($password);
}
}
}

0 comments on commit c278fcf

Please sign in to comment.