From 6ac6572719038ef070ba0da8ba8ab337d2f8bb08 Mon Sep 17 00:00:00 2001 From: Enrico Zimuel Date: Fri, 6 May 2016 10:22:15 +0200 Subject: [PATCH 1/3] Added a benchmark for the bcrypt cost parameter --- src/Password/Bcrypt.php | 21 +++++++++++++++++++++ test/Password/BcryptTest.php | 7 +++++++ test/SymmetricPluginManagerTest.php | 4 ++++ 3 files changed, 32 insertions(+) diff --git a/src/Password/Bcrypt.php b/src/Password/Bcrypt.php index 0f85dbb..65a045f 100644 --- a/src/Password/Bcrypt.php +++ b/src/Password/Bcrypt.php @@ -155,4 +155,25 @@ public function getSalt() return $this->salt; } + + /** + * Benchmark the bcrypt hash generation to determine the cost parameter + * based on time to target. The default time to test is 50 milliseconds + * which is a good baseline for systems handling interactive logins. + * If you increase the time you will get high cost with better security but + * you need to be careful because you can expose your system to DoS attacks. + * + * @see php.net/manual/en/function.password-hash.php#refsect1-function.password-hash-examples + */ + public function benchmarkCost($timeTarget = 0.05) + { + $cost = 8; + do { + $cost++; + $start = microtime(true); + password_hash("test", PASSWORD_BCRYPT, [ 'cost' => $cost ]); + $end = microtime(true); + } while (($end - $start) < $timeTarget); + return $cost; + } } diff --git a/test/Password/BcryptTest.php b/test/Password/BcryptTest.php index 60a5df3..ed946f6 100644 --- a/test/Password/BcryptTest.php +++ b/test/Password/BcryptTest.php @@ -116,4 +116,11 @@ public function testGetSaltError() { $salt = $this->bcrypt->getSalt(); } + + public function testBenchmarkCost() + { + $cost = $this->bcrypt->benchmarkCost(); + $this->assertInternalType("int", $cost); + $this->assertTrue($cost > 8 && $cost < 40); + } } diff --git a/test/SymmetricPluginManagerTest.php b/test/SymmetricPluginManagerTest.php index 12a999e..f7d7cdc 100644 --- a/test/SymmetricPluginManagerTest.php +++ b/test/SymmetricPluginManagerTest.php @@ -12,6 +12,7 @@ use Interop\Container\ContainerInterface; use Zend\Crypt\SymmetricPluginManager; use Zend\Crypt\Symmetric\SymmetricInterface; +use Zend\Crypt\Symmetric\Exception; class SymmetricPluginManagerTest extends \PHPUnit_Framework_TestCase { @@ -44,6 +45,9 @@ public function testHas($symmetric) public function testGet($symmetric) { $plugin = new SymmetricPluginManager(); + if (! extension_loaded($symmetric)) { + $this->setExpectedException(Exception\RuntimeException::class); + } $this->assertInstanceof(SymmetricInterface::class, $plugin->get($symmetric)); } From f9f9b08607319dd2491b87f69ac6665d9f13cd3b Mon Sep 17 00:00:00 2001 From: Enrico Zimuel Date: Fri, 6 May 2016 10:33:06 +0200 Subject: [PATCH 2/3] Fixed the cost max value in test --- test/Password/BcryptTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Password/BcryptTest.php b/test/Password/BcryptTest.php index ed946f6..b8be506 100644 --- a/test/Password/BcryptTest.php +++ b/test/Password/BcryptTest.php @@ -121,6 +121,6 @@ public function testBenchmarkCost() { $cost = $this->bcrypt->benchmarkCost(); $this->assertInternalType("int", $cost); - $this->assertTrue($cost > 8 && $cost < 40); + $this->assertTrue($cost > 8 && $cost < 32); } } From 7fe88ff2b9d45f2b92c9f46f100fbb7885448b48 Mon Sep 17 00:00:00 2001 From: Enrico Zimuel Date: Fri, 6 May 2016 11:09:08 +0200 Subject: [PATCH 3/3] Fixed a unit test --- test/SymmetricPluginManagerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/SymmetricPluginManagerTest.php b/test/SymmetricPluginManagerTest.php index f7d7cdc..852749e 100644 --- a/test/SymmetricPluginManagerTest.php +++ b/test/SymmetricPluginManagerTest.php @@ -44,10 +44,10 @@ public function testHas($symmetric) */ public function testGet($symmetric) { - $plugin = new SymmetricPluginManager(); if (! extension_loaded($symmetric)) { $this->setExpectedException(Exception\RuntimeException::class); } + $plugin = new SymmetricPluginManager(); $this->assertInstanceof(SymmetricInterface::class, $plugin->get($symmetric)); }