From 432ce5617c34c6e5d89a99efe5107ff5b1dcac26 Mon Sep 17 00:00:00 2001 From: Anthony Ferrara Date: Fri, 3 May 2013 17:38:03 -0300 Subject: [PATCH 01/25] Update README.md Update version information --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e158f7d..58a8868 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ See [the RFC](https://wiki.php.net/rfc/password_hash) for more detailed informat Requirements ============ -This library requires `PHP >= 5.3.7` OR a version that has the `$2y` fix backported into it (such as Debian provides). +This library requires `PHP >= 5.3.7` OR a version that has the `$2y` fix backported into it (such as RedHat provides). Note that Debian's 5.3.3 version is **NOT** supported. The runtime checks have been removed due to this version issue. To see if password_compat is available for your system, run the included `version-test.php`. If it outputs "Pass", you can safely use the library. If not, you cannot. From 04b9a755749f0cc202d1eb5d51d0d5082b0c6cf2 Mon Sep 17 00:00:00 2001 From: johncongdon Date: Thu, 9 May 2013 19:01:28 -0600 Subject: [PATCH 02/25] Rely on checking for PASSWORD_DEFAULT, which should ALWAYS be available. Since this is supposed to be forward compatible. What happens if BCRYPT is pulled one day for any reason? This would break forward compatibility, but relying on PASSWORD_DEFAULT should be safe. I think another option would be: if ( ! function_exists('password_hash') ) { } --- lib/password.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/password.php b/lib/password.php index 4d0e8b7..faa5eaa 100644 --- a/lib/password.php +++ b/lib/password.php @@ -7,7 +7,7 @@ * @copyright 2012 The Authors */ -if (!defined('PASSWORD_BCRYPT')) { +if (!defined('PASSWORD_DEFAULT')) { define('PASSWORD_BCRYPT', 1); define('PASSWORD_DEFAULT', PASSWORD_BCRYPT); From 32af6a6547de9253c4c741474eaf2af21ef55d71 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Tue, 18 Jun 2013 11:45:18 +0200 Subject: [PATCH 03/25] updated readme to show a php 5.3 compatible example --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 58a8868..571982c 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ Note that the algorithm that we chose is `PASSWORD_BCRYPT`. That's the current s `BCRYPT` also allows for you to define a `cost` parameter in the options array. This allows for you to change the CPU cost of the algorithm: - $hash = password_hash($password, PASSWORD_BCRYPT, ["cost" => 10]); + $hash = password_hash($password, PASSWORD_BCRYPT, array("cost" => 10)); That's the same as the default. The cost can range from `4` to `31`. I would suggest that you use the highest cost that you can, while keeping response time reasonable (I target between 0.1 and 0.5 seconds for a hash, depending on use-case). From 3fb687cf950839588cb7975550470747b66dbc8d Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Mon, 24 Jun 2013 13:24:13 +0300 Subject: [PATCH 04/25] added link to php.net password_* chapter --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 571982c..3ace98c 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ password_compat [![Build Status](https://travis-ci.org/ircmaxell/password_compat.png?branch=master)](https://travis-ci.org/ircmaxell/password_compat) -This library is intended to provide forward compatibility with the password_* functions being worked on for PHP 5.5. +This library is intended to provide forward compatibility with the [password_*](http://php.net/password) functions being worked on for PHP 5.5. See [the RFC](https://wiki.php.net/rfc/password_hash) for more detailed information. From 596e0b2c6f9425e35304b1a2d653277c35617a74 Mon Sep 17 00:00:00 2001 From: Roy Ronalds Date: Mon, 9 Sep 2013 19:05:31 -0400 Subject: [PATCH 05/25] README: Update reference to the security issue with bcrypt before 5.3.7, for clarity. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3ace98c..aff8ae0 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ The runtime checks have been removed due to this version issue. To see if passwo If you attempt to use password-compat on an unsupported version, attempts to create or verify hashes will return `false`. You have been warned! -The reason for this is that PHP prior to 5.3.7 contains a security issue with its BCRYPT implementation. Therefore, it's highly recommended that you upgrade to a newer version of PHP prior to using this layer. +The reason for this is that PHP prior to 5.3.7 contains a [security issue with its BCRYPT implementation](http://php.net/security/crypt_blowfish.php). Therefore, it's highly recommended that you upgrade to a newer version of PHP prior to using this layer. Installation ============ From 0f372b684654b8c86b7b7fad7bf2db0607f99360 Mon Sep 17 00:00:00 2001 From: Jan Ewald Date: Mon, 9 Dec 2013 22:14:40 +0100 Subject: [PATCH 06/25] Fix wrong Base64 encoding (issue #38) --- lib/password.php | 16 ++++++++++++++-- test/Unit/PasswordHashTest.php | 2 +- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/password.php b/lib/password.php index faa5eaa..b5d6bf7 100644 --- a/lib/password.php +++ b/lib/password.php @@ -55,6 +55,7 @@ function password_hash($password, $algo, array $options = array()) { trigger_error(sprintf("password_hash(): Unknown password hashing algorithm: %s", $algo), E_USER_WARNING); return null; } + $salt_requires_encoding = false; if (isset($options['salt'])) { switch (gettype($options['salt'])) { case 'NULL': @@ -79,7 +80,7 @@ function password_hash($password, $algo, array $options = array()) { trigger_error(sprintf("password_hash(): Provided salt is too short: %d expecting %d", strlen($salt), $required_salt_len), E_USER_WARNING); return null; } elseif (0 == preg_match('#^[a-zA-Z0-9./]+$#D', $salt)) { - $salt = str_replace('+', '.', base64_encode($salt)); + $salt_requires_encoding = true; } } else { $buffer = ''; @@ -118,7 +119,18 @@ function password_hash($password, $algo, array $options = array()) { } } } - $salt = str_replace('+', '.', base64_encode($buffer)); + $salt = $buffer; + $salt_requires_encoding = true; + } + if ($salt_requires_encoding) { + // encode string with the Base64 variant used by crypt + $base64_digits = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + $bcrypt64_digits = + './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + + $base64_string = base64_encode($salt); + $salt = strtr(rtrim($base64_string, '='), $base64_digits, $bcrypt64_digits); } $salt = substr($salt, 0, $required_salt_len); diff --git a/test/Unit/PasswordHashTest.php b/test/Unit/PasswordHashTest.php index 9e5e9ec..b7bbc48 100644 --- a/test/Unit/PasswordHashTest.php +++ b/test/Unit/PasswordHashTest.php @@ -22,7 +22,7 @@ public function testKnownSalt() { public function testRawSalt() { $hash = password_hash("test", PASSWORD_BCRYPT, array("salt" => "123456789012345678901" . chr(0))); - $this->assertEquals('$2y$10$MTIzNDU2Nzg5MDEyMzQ1Nej0NmcAWSLR.oP7XOR9HD/vjUuOj100y', $hash); + $this->assertEquals('$2y$10$KRGxLBS0Lxe3KBCwKxOzLexLDeu0ZfqJAKTubOfy7O/yL2hjimw3u', $hash); } /** From 3615a94d839343b2bc1693cf98432f52900c5112 Mon Sep 17 00:00:00 2001 From: Jan Ewald Date: Tue, 10 Dec 2013 22:59:18 +0100 Subject: [PATCH 07/25] Fix handling of binary and ASCII strings --- lib/password.php | 58 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 12 deletions(-) diff --git a/lib/password.php b/lib/password.php index faa5eaa..c76896d 100644 --- a/lib/password.php +++ b/lib/password.php @@ -75,8 +75,8 @@ function password_hash($password, $algo, array $options = array()) { trigger_error('password_hash(): Non-string salt parameter supplied', E_USER_WARNING); return null; } - if (strlen($salt) < $required_salt_len) { - trigger_error(sprintf("password_hash(): Provided salt is too short: %d expecting %d", strlen($salt), $required_salt_len), E_USER_WARNING); + if (binary_strlen($salt) < $required_salt_len) { + trigger_error(sprintf("password_hash(): Provided salt is too short: %d expecting %d", binary_strlen($salt), $required_salt_len), E_USER_WARNING); return null; } elseif (0 == preg_match('#^[a-zA-Z0-9./]+$#D', $salt)) { $salt = str_replace('+', '.', base64_encode($salt)); @@ -98,18 +98,18 @@ function password_hash($password, $algo, array $options = array()) { } if (!$buffer_valid && is_readable('/dev/urandom')) { $f = fopen('/dev/urandom', 'r'); - $read = strlen($buffer); + $read = binary_strlen($buffer); while ($read < $raw_salt_len) { $buffer .= fread($f, $raw_salt_len - $read); - $read = strlen($buffer); + $read = binary_strlen($buffer); } fclose($f); if ($read >= $raw_salt_len) { $buffer_valid = true; } } - if (!$buffer_valid || strlen($buffer) < $raw_salt_len) { - $bl = strlen($buffer); + if (!$buffer_valid || binary_strlen($buffer) < $raw_salt_len) { + $bl = binary_strlen($buffer); for ($i = 0; $i < $raw_salt_len; $i++) { if ($i < $bl) { $buffer[$i] = $buffer[$i] ^ chr(mt_rand(0, 255)); @@ -120,13 +120,13 @@ function password_hash($password, $algo, array $options = array()) { } $salt = str_replace('+', '.', base64_encode($buffer)); } - $salt = substr($salt, 0, $required_salt_len); + $salt = binary_substr($salt, 0, $required_salt_len); $hash = $hash_format . $salt; $ret = crypt($password, $hash); - if (!is_string($ret) || strlen($ret) <= 13) { + if (!is_string($ret) || binary_strlen($ret) <= 13) { return false; } @@ -155,7 +155,7 @@ function password_get_info($hash) { 'algoName' => 'unknown', 'options' => array(), ); - if (substr($hash, 0, 4) == '$2y$' && strlen($hash) == 60) { + if (binary_substr($hash, 0, 4) == '$2y$' && binary_strlen($hash) == 60) { $return['algo'] = PASSWORD_BCRYPT; $return['algoName'] = 'bcrypt'; list($cost) = sscanf($hash, "$2y$%d$"); @@ -205,18 +205,52 @@ function password_verify($password, $hash) { return false; } $ret = crypt($password, $hash); - if (!is_string($ret) || strlen($ret) != strlen($hash) || strlen($ret) <= 13) { + if (!is_string($ret) || binary_strlen($ret) != binary_strlen($hash) || binary_strlen($ret) <= 13) { return false; } $status = 0; - for ($i = 0; $i < strlen($ret); $i++) { + for ($i = 0; $i < binary_strlen($ret); $i++) { $status |= (ord($ret[$i]) ^ ord($hash[$i])); } return $status === 0; } -} + /** + * Count the number of bytes in a string + * + * We cannot simply use strlen() for this, because it might be overwritten by the mbstring extension. + * In this case, strlen() will count the number of *characters* based on the internal encoding. A + * sequence of bytes might be regarded as a single multibyte character. + * + * @param string $binary_string The input string + * + * @return int The number of bytes + */ + function binary_strlen($binary_string) { + if (extension_loaded('mbstring')) + return mb_strlen($binary_string, '8bit'); + else + return strlen($binary_string); + } + /** + * Get a substring based on byte limits + * + * @see binary_strlen() + * + * @param string $binary_string The input string + * @param int $start + * @param int $length + * + * @return string The substring + */ + function binary_substr($binary_string, $start, $length) { + if (extension_loaded('mbstring')) + return mb_substr($binary_string, $start, $length, '8bit'); + else + return substr($binary_string, $start, $length); + } +} \ No newline at end of file From 553c957a5e8d6ed7cd2e788b6212c208e5991db4 Mon Sep 17 00:00:00 2001 From: Jan Ewald Date: Tue, 10 Dec 2013 23:23:04 +0100 Subject: [PATCH 08/25] Prevent warnings from open_basedir --- lib/password.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/password.php b/lib/password.php index faa5eaa..64cac9e 100644 --- a/lib/password.php +++ b/lib/password.php @@ -96,7 +96,7 @@ function password_hash($password, $algo, array $options = array()) { $buffer_valid = true; } } - if (!$buffer_valid && is_readable('/dev/urandom')) { + if (!$buffer_valid && @is_readable('/dev/urandom')) { $f = fopen('/dev/urandom', 'r'); $read = strlen($buffer); while ($read < $raw_salt_len) { From 88911e6abebb324cca88f546f04d6e71ce778bd3 Mon Sep 17 00:00:00 2001 From: Anthony Ferrara Date: Wed, 8 Jan 2014 13:23:25 -0500 Subject: [PATCH 09/25] Move binary implementation to separate namespace (to avoid polluting the global namespace with non-core functions) --- lib/password.php | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/lib/password.php b/lib/password.php index c76896d..0a8a348 100644 --- a/lib/password.php +++ b/lib/password.php @@ -7,6 +7,8 @@ * @copyright 2012 The Authors */ +namespace { + if (!defined('PASSWORD_DEFAULT')) { define('PASSWORD_BCRYPT', 1); @@ -75,8 +77,8 @@ function password_hash($password, $algo, array $options = array()) { trigger_error('password_hash(): Non-string salt parameter supplied', E_USER_WARNING); return null; } - if (binary_strlen($salt) < $required_salt_len) { - trigger_error(sprintf("password_hash(): Provided salt is too short: %d expecting %d", binary_strlen($salt), $required_salt_len), E_USER_WARNING); + if (PasswordCompat\binary\_strlen($salt) < $required_salt_len) { + trigger_error(sprintf("password_hash(): Provided salt is too short: %d expecting %d", PasswordCompat\binary\_strlen($salt), $required_salt_len), E_USER_WARNING); return null; } elseif (0 == preg_match('#^[a-zA-Z0-9./]+$#D', $salt)) { $salt = str_replace('+', '.', base64_encode($salt)); @@ -98,18 +100,18 @@ function password_hash($password, $algo, array $options = array()) { } if (!$buffer_valid && is_readable('/dev/urandom')) { $f = fopen('/dev/urandom', 'r'); - $read = binary_strlen($buffer); + $read = PasswordCompat\binary\_strlen($buffer); while ($read < $raw_salt_len) { $buffer .= fread($f, $raw_salt_len - $read); - $read = binary_strlen($buffer); + $read = PasswordCompat\binary\_strlen($buffer); } fclose($f); if ($read >= $raw_salt_len) { $buffer_valid = true; } } - if (!$buffer_valid || binary_strlen($buffer) < $raw_salt_len) { - $bl = binary_strlen($buffer); + if (!$buffer_valid || PasswordCompat\binary\_strlen($buffer) < $raw_salt_len) { + $bl = PasswordCompat\binary\_strlen($buffer); for ($i = 0; $i < $raw_salt_len; $i++) { if ($i < $bl) { $buffer[$i] = $buffer[$i] ^ chr(mt_rand(0, 255)); @@ -120,13 +122,13 @@ function password_hash($password, $algo, array $options = array()) { } $salt = str_replace('+', '.', base64_encode($buffer)); } - $salt = binary_substr($salt, 0, $required_salt_len); + $salt = PasswordCompat\binary\_substr($salt, 0, $required_salt_len); $hash = $hash_format . $salt; $ret = crypt($password, $hash); - if (!is_string($ret) || binary_strlen($ret) <= 13) { + if (!is_string($ret) || PasswordCompat\binary\_strlen($ret) <= 13) { return false; } @@ -155,7 +157,7 @@ function password_get_info($hash) { 'algoName' => 'unknown', 'options' => array(), ); - if (binary_substr($hash, 0, 4) == '$2y$' && binary_strlen($hash) == 60) { + if (PasswordCompat\binary\_substr($hash, 0, 4) == '$2y$' && PasswordCompat\binary\_strlen($hash) == 60) { $return['algo'] = PASSWORD_BCRYPT; $return['algoName'] = 'bcrypt'; list($cost) = sscanf($hash, "$2y$%d$"); @@ -205,18 +207,22 @@ function password_verify($password, $hash) { return false; } $ret = crypt($password, $hash); - if (!is_string($ret) || binary_strlen($ret) != binary_strlen($hash) || binary_strlen($ret) <= 13) { + if (!is_string($ret) || PasswordCompat\binary\_strlen($ret) != PasswordCompat\binary\_strlen($hash) || PasswordCompat\binary\_strlen($ret) <= 13) { return false; } $status = 0; - for ($i = 0; $i < binary_strlen($ret); $i++) { + for ($i = 0; $i < PasswordCompat\binary\_strlen($ret); $i++) { $status |= (ord($ret[$i]) ^ ord($hash[$i])); } return $status === 0; } +} + +} +namespace PasswordCompat\binary { /** * Count the number of bytes in a string * @@ -226,31 +232,33 @@ function password_verify($password, $hash) { * * @param string $binary_string The input string * + * @internal * @return int The number of bytes */ - function binary_strlen($binary_string) { - if (extension_loaded('mbstring')) + function _strlen($binary_string) { + if (function_exists('mb_strlen')) { return mb_strlen($binary_string, '8bit'); - else - return strlen($binary_string); + } + return strlen($binary_string); } /** * Get a substring based on byte limits * - * @see binary_strlen() + * @see _strlen() * * @param string $binary_string The input string * @param int $start * @param int $length * + * @internal * @return string The substring */ - function binary_substr($binary_string, $start, $length) { - if (extension_loaded('mbstring')) + function _substr($binary_string, $start, $length) { + if (function_exists('mb_substr')) { return mb_substr($binary_string, $start, $length, '8bit'); - else - return substr($binary_string, $start, $length); + } + return substr($binary_string, $start, $length); } } \ No newline at end of file From 0b60f2e91f42fa95edb5ef1093ef2af15b699517 Mon Sep 17 00:00:00 2001 From: Anthony Ferrara Date: Wed, 8 Jan 2014 13:26:23 -0500 Subject: [PATCH 10/25] Add travis build support on HHVM, for better testing --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index a960061..d764ae4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,5 +4,6 @@ php: - 5.5 - 5.4 - 5.3 + - hhvm script: phpunit --configuration phpunit.xml.dist \ No newline at end of file From 2215cf1fe9320d07ec14abbb49c7ca6a8996dc3c Mon Sep 17 00:00:00 2001 From: Anthony Ferrara Date: Wed, 8 Jan 2014 13:39:13 -0500 Subject: [PATCH 11/25] Make tests pass on current 5.5 version, need to find a better way to account for newer builds --- test/Unit/PasswordHashTest.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/Unit/PasswordHashTest.php b/test/Unit/PasswordHashTest.php index b7bbc48..a95f3ee 100644 --- a/test/Unit/PasswordHashTest.php +++ b/test/Unit/PasswordHashTest.php @@ -22,7 +22,11 @@ public function testKnownSalt() { public function testRawSalt() { $hash = password_hash("test", PASSWORD_BCRYPT, array("salt" => "123456789012345678901" . chr(0))); - $this->assertEquals('$2y$10$KRGxLBS0Lxe3KBCwKxOzLexLDeu0ZfqJAKTubOfy7O/yL2hjimw3u', $hash); + if (version_compare(PHP_VERSION, '5.5.0', '<')) { + $this->assertEquals('$2y$10$KRGxLBS0Lxe3KBCwKxOzLexLDeu0ZfqJAKTubOfy7O/yL2hjimw3u', $hash); + } else { + $this->assertEquals('$2y$10$MTIzNDU2Nzg5MDEyMzQ1Nej0NmcAWSLR.oP7XOR9HD/vjUuOj100y', $hash); + } } /** From 7b9e6516fdc1fae2f3059cef1a5727acec4541ad Mon Sep 17 00:00:00 2001 From: Anthony Ferrara Date: Wed, 8 Jan 2014 13:43:40 -0500 Subject: [PATCH 12/25] Add test to double-check that generated hash is a bcrypt hash. Partially fixes #45 --- lib/password.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/password.php b/lib/password.php index 33b9130..c24ce82 100644 --- a/lib/password.php +++ b/lib/password.php @@ -36,6 +36,7 @@ function password_hash($password, $algo, array $options = array()) { trigger_error("password_hash() expects parameter 2 to be long, " . gettype($algo) . " given", E_USER_WARNING); return null; } + $resultLength = 0; switch ($algo) { case PASSWORD_BCRYPT: // Note that this is a C constant, but not exposed to PHP, so we don't define it here. @@ -52,6 +53,8 @@ function password_hash($password, $algo, array $options = array()) { // The length required in the final serialization $required_salt_len = 22; $hash_format = sprintf("$2y$%02d$", $cost); + // The expected length of the final crypt() output + $resultLength = 60; break; default: trigger_error(sprintf("password_hash(): Unknown password hashing algorithm: %s", $algo), E_USER_WARNING); @@ -140,7 +143,7 @@ function password_hash($password, $algo, array $options = array()) { $ret = crypt($password, $hash); - if (!is_string($ret) || PasswordCompat\binary\_strlen($ret) <= 13) { + if (!is_string($ret) || PasswordCompat\binary\_strlen($ret) != $resultLength) { return false; } From 300a2448cf07dd971cabd0f48cecdb2b6e14260c Mon Sep 17 00:00:00 2001 From: Anthony Ferrara Date: Wed, 8 Jan 2014 14:44:10 -0500 Subject: [PATCH 13/25] Finish HHVM support... At least travis wise --- .gitignore | 1 + .travis.yml | 2 +- composer.json | 3 + composer.lock | 436 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 441 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 composer.lock diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5657f6e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +vendor \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index d764ae4..8b1ee57 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,4 +6,4 @@ php: - 5.3 - hhvm -script: phpunit --configuration phpunit.xml.dist \ No newline at end of file +script: vendor/bin/phpunit --configuration phpunit.xml.dist \ No newline at end of file diff --git a/composer.json b/composer.json index 7ababbf..bee5e89 100644 --- a/composer.json +++ b/composer.json @@ -12,6 +12,9 @@ "homepage": "http://blog.ircmaxell.com" } ], + "require-dev": { + "phpunit/phpunit": "3.7" + }, "autoload": { "files": ["lib/password.php"] } diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..39b904d --- /dev/null +++ b/composer.lock @@ -0,0 +1,436 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" + ], + "hash": "0c3cd22b71b9c5de791a43ddc43d3ddf", + "packages": [ + + ], + "packages-dev": [ + { + "name": "phpunit/php-code-coverage", + "version": "1.2.13", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "466e7cd2554b4e264c9e3f31216d25ac0e5f3d94" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/466e7cd2554b4e264c9e3f31216d25ac0e5f3d94", + "reference": "466e7cd2554b4e264c9e3f31216d25ac0e5f3d94", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-file-iterator": ">=1.3.0@stable", + "phpunit/php-text-template": ">=1.1.1@stable", + "phpunit/php-token-stream": ">=1.1.3@stable" + }, + "require-dev": { + "phpunit/phpunit": "3.7.*@dev" + }, + "suggest": { + "ext-dom": "*", + "ext-xdebug": ">=2.0.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "classmap": [ + "PHP/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "time": "2013-09-10 08:14:32" + }, + { + "name": "phpunit/php-file-iterator", + "version": "1.3.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb", + "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "File/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "time": "2013-10-10 15:34:57" + }, + { + "name": "phpunit/php-text-template", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "5180896f51c5b3648ac946b05f9ec02be78a0b23" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5180896f51c5b3648ac946b05f9ec02be78a0b23", + "reference": "5180896f51c5b3648ac946b05f9ec02be78a0b23", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "Text/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "time": "2012-10-31 18:15:28" + }, + { + "name": "phpunit/php-timer", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c", + "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "PHP/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "time": "2013-08-02 07:42:54" + }, + { + "name": "phpunit/php-token-stream", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "5220af2a7929aa35cf663d97c89ad3d50cf5fa3e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/5220af2a7929aa35cf663d97c89ad3d50cf5fa3e", + "reference": "5220af2a7929aa35cf663d97c89ad3d50cf5fa3e", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "classmap": [ + "PHP/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ], + "time": "2013-09-13 04:58:23" + }, + { + "name": "phpunit/phpunit", + "version": "3.7.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "f6a4872c01bab898bce4f9e211e437533f248d43" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f6a4872c01bab898bce4f9e211e437533f248d43", + "reference": "f6a4872c01bab898bce4f9e211e437533f248d43", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=5.3.3", + "phpunit/php-code-coverage": ">=1.2.0@stable", + "phpunit/php-file-iterator": ">=1.3.1@stable", + "phpunit/php-text-template": ">=1.1.1@stable", + "phpunit/php-timer": ">=1.0.2@stable", + "phpunit/phpunit-mock-objects": ">=1.2.0@stable", + "symfony/yaml": ">=2.1.0@stable" + }, + "suggest": { + "ext-json": "*", + "ext-simplexml": "*", + "ext-tokenizer": "*", + "phpunit/php-invoker": ">=1.1.0@stable" + }, + "bin": [ + "composer/bin/phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.7.x-dev" + } + }, + "autoload": { + "files": [ + "PHPUnit/Autoload.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "", + "../../symfony/yaml/" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "http://www.phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "time": "2012-09-19 05:07:48" + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/5794e3c5c5ba0fb037b11d8151add2a07fa82875", + "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-text-template": ">=1.1.1@stable" + }, + "suggest": { + "ext-soap": "*" + }, + "type": "library", + "autoload": { + "classmap": [ + "PHPUnit/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ], + "time": "2013-01-13 10:24:48" + }, + { + "name": "symfony/yaml", + "version": "v2.4.1", + "target-dir": "Symfony/Component/Yaml", + "source": { + "type": "git", + "url": "https://github.com/symfony/Yaml.git", + "reference": "4e1a237fc48145fae114b96458d799746ad89aa0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/4e1a237fc48145fae114b96458d799746ad89aa0", + "reference": "4e1a237fc48145fae114b96458d799746ad89aa0", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.4-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Yaml\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "http://symfony.com", + "time": "2013-12-28 08:12:03" + } + ], + "aliases": [ + + ], + "minimum-stability": "stable", + "stability-flags": [ + + ], + "platform": [ + + ], + "platform-dev": [ + + ] +} From 8595b55706986fe6fac2fbd8f233739882b7fb00 Mon Sep 17 00:00:00 2001 From: Anthony Ferrara Date: Wed, 8 Jan 2014 15:07:23 -0500 Subject: [PATCH 14/25] Whoops, forgot to install composer dev dependencies --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 8b1ee57..7c3b4af 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,4 +6,7 @@ php: - 5.3 - hhvm +before_script: + - composer install --dev + script: vendor/bin/phpunit --configuration phpunit.xml.dist \ No newline at end of file From 31d9e4bec5730a5eef3621804d4b8b01dca1d7b0 Mon Sep 17 00:00:00 2001 From: oO Date: Fri, 24 Jan 2014 15:05:40 +0100 Subject: [PATCH 15/25] Update README.md --- README.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index aff8ae0..6bfd6cc 100644 --- a/README.md +++ b/README.md @@ -32,21 +32,21 @@ Usage **Creating Password Hashes** To create a password hash from a password, simply use the `password_hash` function. - +````PHP $hash = password_hash($password, PASSWORD_BCRYPT); - +```` Note that the algorithm that we chose is `PASSWORD_BCRYPT`. That's the current strongest algorithm supported. This is the `BCRYPT` crypt algorithm. It produces a 60 character hash as the result. `BCRYPT` also allows for you to define a `cost` parameter in the options array. This allows for you to change the CPU cost of the algorithm: - +````PHP $hash = password_hash($password, PASSWORD_BCRYPT, array("cost" => 10)); - +```` That's the same as the default. The cost can range from `4` to `31`. I would suggest that you use the highest cost that you can, while keeping response time reasonable (I target between 0.1 and 0.5 seconds for a hash, depending on use-case). Another algorithm name is supported: - +````PHP PASSWORD_DEFAULT - +```` This will use the strongest algorithm available to PHP at the current time. Presently, this is the same as specifying `PASSWORD_BCRYPT`. But in future versions of PHP, it may be updated to use a stronger algorithm if one is introduced. It can also be changed if a problem is identified with the BCRYPT algorithm. Note that if you use this option, you are **strongly** encouraged to store it in a `VARCHAR(255)` column to avoid truncation issues if a future algorithm increases the length of the generated hash. It is very important that you should check the return value of `password_hash` prior to storing it, because a `false` may be returned if it encountered an error. @@ -54,22 +54,23 @@ It is very important that you should check the return value of `password_hash` p **Verifying Password Hashes** To verify a hash created by `password_hash`, simply call: - +````PHP if (password_verify($password, $hash)) { /* Valid */ } else { /* Invalid */ } - +```` That's all there is to it. **Rehashing Passwords** From time to time you may update your hashing parameters (algorithm, cost, etc). So a function to determine if rehashing is necessary is available: - +````PHP if (password_verify($password, $hash)) { if (password_needs_rehash($hash, $algorithm, $options)) { $hash = password_hash($password, $algorithm, $options); /* Store new hash in db */ } } +```` From c39578adc3dd78ef96f65e04408d7d87c460c29b Mon Sep 17 00:00:00 2001 From: Julius Beckmann Date: Mon, 10 Mar 2014 17:21:31 +0100 Subject: [PATCH 16/25] Added PHP 5.6 to travis. --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7c3b4af..f8894b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ language: php php: + - 5.6 - 5.5 - 5.4 - 5.3 @@ -9,4 +10,4 @@ php: before_script: - composer install --dev -script: vendor/bin/phpunit --configuration phpunit.xml.dist \ No newline at end of file +script: vendor/bin/phpunit --configuration phpunit.xml.dist From 3cf1d826447ed1a0dc9f4bfa7e8cc7d4192ce15c Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Thu, 20 Mar 2014 18:33:41 +0000 Subject: [PATCH 17/25] Testing updates --- .travis.yml | 10 +- composer.json | 4 +- composer.lock | 323 ++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 281 insertions(+), 56 deletions(-) diff --git a/.travis.yml b/.travis.yml index f8894b8..0651993 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,12 @@ php: - hhvm before_script: - - composer install --dev + - composer self-update + - composer install --no-interaction --prefer-source --dev -script: vendor/bin/phpunit --configuration phpunit.xml.dist +script: vendor/bin/phpunit --configuration phpunit.xml.dist --colors + +matrix: + allow_failures: + - php: hhvm + fast_finish: true diff --git a/composer.json b/composer.json index bee5e89..637cbdd 100644 --- a/composer.json +++ b/composer.json @@ -13,9 +13,9 @@ } ], "require-dev": { - "phpunit/phpunit": "3.7" + "phpunit/phpunit": "4.*" }, "autoload": { "files": ["lib/password.php"] } -} \ No newline at end of file +} diff --git a/composer.lock b/composer.lock index 39b904d..5d05150 100644 --- a/composer.lock +++ b/composer.lock @@ -3,47 +3,50 @@ "This file locks the dependencies of your project to a known state", "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" ], - "hash": "0c3cd22b71b9c5de791a43ddc43d3ddf", + "hash": "15ab0fbb84a186f801e4eedb4d86cb0a", "packages": [ ], "packages-dev": [ { "name": "phpunit/php-code-coverage", - "version": "1.2.13", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "466e7cd2554b4e264c9e3f31216d25ac0e5f3d94" + "reference": "a05618d03c60eb07b37432583aabf80ae5f5f447" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/466e7cd2554b4e264c9e3f31216d25ac0e5f3d94", - "reference": "466e7cd2554b4e264c9e3f31216d25ac0e5f3d94", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/a05618d03c60eb07b37432583aabf80ae5f5f447", + "reference": "a05618d03c60eb07b37432583aabf80ae5f5f447", "shasum": "" }, "require": { "php": ">=5.3.3", - "phpunit/php-file-iterator": ">=1.3.0@stable", - "phpunit/php-text-template": ">=1.1.1@stable", - "phpunit/php-token-stream": ">=1.1.3@stable" + "phpunit/php-file-iterator": "~1.3.1", + "phpunit/php-text-template": "~1.2", + "phpunit/php-token-stream": "~1.2.2", + "sebastian/environment": "~1.0", + "sebastian/version": "~1.0.3" }, "require-dev": { - "phpunit/phpunit": "3.7.*@dev" + "ext-xdebug": ">=2.1.4", + "phpunit/phpunit": ">=4.0.0,<4.1.0" }, "suggest": { "ext-dom": "*", - "ext-xdebug": ">=2.0.5" + "ext-xdebug": ">=2.2.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { "classmap": [ - "PHP/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -67,7 +70,7 @@ "testing", "xunit" ], - "time": "2013-09-10 08:14:32" + "time": "2014-03-20 16:12:25" }, { "name": "phpunit/php-file-iterator", @@ -116,16 +119,16 @@ }, { "name": "phpunit/php-text-template", - "version": "1.1.4", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5180896f51c5b3648ac946b05f9ec02be78a0b23" + "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5180896f51c5b3648ac946b05f9ec02be78a0b23", - "reference": "5180896f51c5b3648ac946b05f9ec02be78a0b23", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", + "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", "shasum": "" }, "require": { @@ -156,7 +159,7 @@ "keywords": [ "template" ], - "time": "2012-10-31 18:15:28" + "time": "2014-01-30 17:20:04" }, { "name": "phpunit/php-timer", @@ -204,16 +207,16 @@ }, { "name": "phpunit/php-token-stream", - "version": "1.2.1", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "5220af2a7929aa35cf663d97c89ad3d50cf5fa3e" + "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/5220af2a7929aa35cf663d97c89ad3d50cf5fa3e", - "reference": "5220af2a7929aa35cf663d97c89ad3d50cf5fa3e", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/ad4e1e23ae01b483c16f600ff1bebec184588e32", + "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32", "shasum": "" }, "require": { @@ -250,20 +253,20 @@ "keywords": [ "tokenizer" ], - "time": "2013-09-13 04:58:23" + "time": "2014-03-03 05:10:30" }, { "name": "phpunit/phpunit", - "version": "3.7.0", + "version": "4.0.12", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "f6a4872c01bab898bce4f9e211e437533f248d43" + "reference": "e7631ea91f9e41149c55527047b5dee94538ae1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f6a4872c01bab898bce4f9e211e437533f248d43", - "reference": "f6a4872c01bab898bce4f9e211e437533f248d43", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e7631ea91f9e41149c55527047b5dee94538ae1d", + "reference": "e7631ea91f9e41149c55527047b5dee94538ae1d", "shasum": "" }, "require": { @@ -272,31 +275,35 @@ "ext-reflection": "*", "ext-spl": "*", "php": ">=5.3.3", - "phpunit/php-code-coverage": ">=1.2.0@stable", - "phpunit/php-file-iterator": ">=1.3.1@stable", - "phpunit/php-text-template": ">=1.1.1@stable", - "phpunit/php-timer": ">=1.0.2@stable", - "phpunit/phpunit-mock-objects": ">=1.2.0@stable", - "symfony/yaml": ">=2.1.0@stable" + "phpunit/php-code-coverage": ">=2.0.0,<2.1.0", + "phpunit/php-file-iterator": "~1.3.1", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": "~1.0.2", + "phpunit/phpunit-mock-objects": ">=2.0.0,<2.1.0", + "sebastian/diff": "~1.1", + "sebastian/environment": "~1.0", + "sebastian/exporter": "~1.0.1", + "sebastian/version": "~1.0.3", + "symfony/yaml": "~2.0" }, "suggest": { "ext-json": "*", "ext-simplexml": "*", "ext-tokenizer": "*", - "phpunit/php-invoker": ">=1.1.0@stable" + "phpunit/php-invoker": "~1.1" }, "bin": [ - "composer/bin/phpunit" + "phpunit" ], "type": "library", "extra": { "branch-alias": { - "dev-master": "3.7.x-dev" + "dev-master": "4.0.x-dev" } }, "autoload": { - "files": [ - "PHPUnit/Autoload.php" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -321,33 +328,41 @@ "testing", "xunit" ], - "time": "2012-09-19 05:07:48" + "time": "2014-03-20 16:22:50" }, { "name": "phpunit/phpunit-mock-objects", - "version": "1.2.3", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875" + "reference": "c5e6274b8f2bf983cf883bb375cf44f99aff200e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/5794e3c5c5ba0fb037b11d8151add2a07fa82875", - "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/c5e6274b8f2bf983cf883bb375cf44f99aff200e", + "reference": "c5e6274b8f2bf983cf883bb375cf44f99aff200e", "shasum": "" }, "require": { "php": ">=5.3.3", - "phpunit/php-text-template": ">=1.1.1@stable" + "phpunit/php-text-template": "~1.2" + }, + "require-dev": { + "phpunit/phpunit": ">=4.0.0,<4.1.0" }, "suggest": { "ext-soap": "*" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, "autoload": { "classmap": [ - "PHPUnit/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -370,21 +385,223 @@ "mock", "xunit" ], - "time": "2013-01-13 10:24:48" + "time": "2014-03-18 08:56:48" + }, + { + "name": "sebastian/diff", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "1e091702a5a38e6b4c1ba9ca816e3dd343df2e2d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/1e091702a5a38e6b4c1ba9ca816e3dd343df2e2d", + "reference": "1e091702a5a38e6b4c1ba9ca816e3dd343df2e2d", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "http://www.github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "time": "2013-08-03 16:46:33" + }, + { + "name": "sebastian/environment", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "79517609ec01139cd7e9fded0dd7ce08c952ef6a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/79517609ec01139cd7e9fded0dd7ce08c952ef6a", + "reference": "79517609ec01139cd7e9fded0dd7ce08c952ef6a", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "4.0.*@dev" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2014-02-18 16:17:19" + }, + { + "name": "sebastian/exporter", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "1f9a98e6f5dfe0524cb8c6166f7c82f3e9ae1529" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/1f9a98e6f5dfe0524cb8c6166f7c82f3e9ae1529", + "reference": "1f9a98e6f5dfe0524cb8c6166f7c82f3e9ae1529", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "4.0.*@dev" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2014-02-16 08:26:31" + }, + { + "name": "sebastian/version", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "b6e1f0cf6b9e1ec409a0d3e2f2a5fb0998e36b43" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/b6e1f0cf6b9e1ec409a0d3e2f2a5fb0998e36b43", + "reference": "b6e1f0cf6b9e1ec409a0d3e2f2a5fb0998e36b43", + "shasum": "" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2014-03-07 15:35:33" }, { "name": "symfony/yaml", - "version": "v2.4.1", + "version": "v2.4.2", "target-dir": "Symfony/Component/Yaml", "source": { "type": "git", "url": "https://github.com/symfony/Yaml.git", - "reference": "4e1a237fc48145fae114b96458d799746ad89aa0" + "reference": "bb6ddaf8956139d1b8c360b4b713ed0138e876b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/4e1a237fc48145fae114b96458d799746ad89aa0", - "reference": "4e1a237fc48145fae114b96458d799746ad89aa0", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/bb6ddaf8956139d1b8c360b4b713ed0138e876b3", + "reference": "bb6ddaf8956139d1b8c360b4b713ed0138e876b3", "shasum": "" }, "require": { @@ -408,7 +625,9 @@ "authors": [ { "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" }, { "name": "Symfony Community", @@ -417,7 +636,7 @@ ], "description": "Symfony Yaml Component", "homepage": "http://symfony.com", - "time": "2013-12-28 08:12:03" + "time": "2014-01-07 13:28:54" } ], "aliases": [ From 1364db9776b29b5ea7f990671c0832e9aa887e0d Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Mon, 28 Jul 2014 19:34:43 +0200 Subject: [PATCH 18/25] add PasswordCompat\binary\check() in the library --- lib/password.php | 21 ++++++++++++++++++++- version-test.php | 6 ++---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/lib/password.php b/lib/password.php index e8ec028..e69bc17 100644 --- a/lib/password.php +++ b/lib/password.php @@ -274,6 +274,25 @@ function _substr($binary_string, $start, $length) { return mb_substr($binary_string, $start, $length, '8bit'); } return substr($binary_string, $start, $length); - } + } + + /** + * Check if current PHP version is compatible with the library + * + * @return boolean the check result + */ + function check() { + static $pass = NULL; + if (is_null($pass)) { + if (function_exists('crypt')) { + $hash = '$2y$04$usesomesillystringfore7hnbRJHxXVLeakoG8K30oukPsA.ztMG'; + $test = crypt("password", $hash); + $pass = $test == $hash; + } else { + $pass = false; + } + } + return $pass; + } } diff --git a/version-test.php b/version-test.php index f527e30..96f60ca 100644 --- a/version-test.php +++ b/version-test.php @@ -1,8 +1,6 @@ Date: Sat, 15 Nov 2014 19:26:38 +0100 Subject: [PATCH 19/25] Missing PASSWORD_BCRYPT_DEFAULT_COST constant This one is defined with PHP >= 5.5 and make this lib even more compatible by possibly using it. --- lib/password.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/password.php b/lib/password.php index e8ec028..a5c28d4 100644 --- a/lib/password.php +++ b/lib/password.php @@ -12,6 +12,7 @@ if (!defined('PASSWORD_DEFAULT')) { define('PASSWORD_BCRYPT', 1); + define('PASSWORD_BCRYPT_DEFAULT_COST', 10); define('PASSWORD_DEFAULT', PASSWORD_BCRYPT); /** @@ -39,8 +40,7 @@ function password_hash($password, $algo, array $options = array()) { $resultLength = 0; switch ($algo) { case PASSWORD_BCRYPT: - // Note that this is a C constant, but not exposed to PHP, so we don't define it here. - $cost = 10; + $cost = PASSWORD_BCRYPT_DEFAULT_COST; if (isset($options['cost'])) { $cost = $options['cost']; if ($cost < 4 || $cost > 31) { @@ -158,7 +158,7 @@ function password_hash($password, $algo, array $options = array()) { * 'algo' => 1, * 'algoName' => 'bcrypt', * 'options' => array( - * 'cost' => 10, + * 'cost' => PASSWORD_BCRYPT_DEFAULT_COST, * ), * ) * @@ -199,7 +199,7 @@ function password_needs_rehash($hash, $algo, array $options = array()) { } switch ($algo) { case PASSWORD_BCRYPT: - $cost = isset($options['cost']) ? $options['cost'] : 10; + $cost = isset($options['cost']) ? $options['cost'] : PASSWORD_BCRYPT_DEFAULT_COST; if ($cost != $info['options']['cost']) { return true; } From fca7c858a5367710fe2379af415ba1caf3a4f4d5 Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Sat, 15 Nov 2014 18:38:26 +0000 Subject: [PATCH 20/25] Composer fixes --- composer.json | 31 ++- composer.lock | 655 -------------------------------------------------- 2 files changed, 15 insertions(+), 671 deletions(-) delete mode 100644 composer.lock diff --git a/composer.json b/composer.json index 637cbdd..822fd1f 100644 --- a/composer.json +++ b/composer.json @@ -1,21 +1,20 @@ { - "name": "ircmaxell/password-compat", - "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash", - "version": "1.0.2", - "keywords": ["password", "hashing"], - "homepage": "https://github.com/ircmaxell/password_compat", - "license": "MIT", - "authors": [ - { - "name": "Anthony Ferrara", - "email": "ircmaxell@php.net", - "homepage": "http://blog.ircmaxell.com" - } - ], + "name": "ircmaxell/password-compat", + "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash", + "keywords": ["password", "hashing"], + "homepage": "https://github.com/ircmaxell/password_compat", + "license": "MIT", + "authors": [ + { + "name": "Anthony Ferrara", + "email": "ircmaxell@php.net", + "homepage": "http://blog.ircmaxell.com" + } + ], "require-dev": { "phpunit/phpunit": "4.*" }, - "autoload": { - "files": ["lib/password.php"] - } + "autoload": { + "files": ["lib/password.php"] + } } diff --git a/composer.lock b/composer.lock deleted file mode 100644 index 5d05150..0000000 --- a/composer.lock +++ /dev/null @@ -1,655 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" - ], - "hash": "15ab0fbb84a186f801e4eedb4d86cb0a", - "packages": [ - - ], - "packages-dev": [ - { - "name": "phpunit/php-code-coverage", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "a05618d03c60eb07b37432583aabf80ae5f5f447" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/a05618d03c60eb07b37432583aabf80ae5f5f447", - "reference": "a05618d03c60eb07b37432583aabf80ae5f5f447", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "phpunit/php-file-iterator": "~1.3.1", - "phpunit/php-text-template": "~1.2", - "phpunit/php-token-stream": "~1.2.2", - "sebastian/environment": "~1.0", - "sebastian/version": "~1.0.3" - }, - "require-dev": { - "ext-xdebug": ">=2.1.4", - "phpunit/phpunit": ">=4.0.0,<4.1.0" - }, - "suggest": { - "ext-dom": "*", - "ext-xdebug": ">=2.2.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", - "keywords": [ - "coverage", - "testing", - "xunit" - ], - "time": "2014-03-20 16:12:25" - }, - { - "name": "phpunit/php-file-iterator", - "version": "1.3.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb", - "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "File/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" - ], - "time": "2013-10-10 15:34:57" - }, - { - "name": "phpunit/php-text-template", - "version": "1.2.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", - "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "Text/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", - "keywords": [ - "template" - ], - "time": "2014-01-30 17:20:04" - }, - { - "name": "phpunit/php-timer", - "version": "1.0.5", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c", - "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "autoload": { - "classmap": [ - "PHP/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" - ], - "time": "2013-08-02 07:42:54" - }, - { - "name": "phpunit/php-token-stream", - "version": "1.2.2", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/ad4e1e23ae01b483c16f600ff1bebec184588e32", - "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=5.3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2-dev" - } - }, - "autoload": { - "classmap": [ - "PHP/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" - ], - "time": "2014-03-03 05:10:30" - }, - { - "name": "phpunit/phpunit", - "version": "4.0.12", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "e7631ea91f9e41149c55527047b5dee94538ae1d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e7631ea91f9e41149c55527047b5dee94538ae1d", - "reference": "e7631ea91f9e41149c55527047b5dee94538ae1d", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=5.3.3", - "phpunit/php-code-coverage": ">=2.0.0,<2.1.0", - "phpunit/php-file-iterator": "~1.3.1", - "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "~1.0.2", - "phpunit/phpunit-mock-objects": ">=2.0.0,<2.1.0", - "sebastian/diff": "~1.1", - "sebastian/environment": "~1.0", - "sebastian/exporter": "~1.0.1", - "sebastian/version": "~1.0.3", - "symfony/yaml": "~2.0" - }, - "suggest": { - "ext-json": "*", - "ext-simplexml": "*", - "ext-tokenizer": "*", - "phpunit/php-invoker": "~1.1" - }, - "bin": [ - "phpunit" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "", - "../../symfony/yaml/" - ], - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "The PHP Unit Testing framework.", - "homepage": "http://www.phpunit.de/", - "keywords": [ - "phpunit", - "testing", - "xunit" - ], - "time": "2014-03-20 16:22:50" - }, - { - "name": "phpunit/phpunit-mock-objects", - "version": "2.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "c5e6274b8f2bf983cf883bb375cf44f99aff200e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/c5e6274b8f2bf983cf883bb375cf44f99aff200e", - "reference": "c5e6274b8f2bf983cf883bb375cf44f99aff200e", - "shasum": "" - }, - "require": { - "php": ">=5.3.3", - "phpunit/php-text-template": "~1.2" - }, - "require-dev": { - "phpunit/phpunit": ">=4.0.0,<4.1.0" - }, - "suggest": { - "ext-soap": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", - "keywords": [ - "mock", - "xunit" - ], - "time": "2014-03-18 08:56:48" - }, - { - "name": "sebastian/diff", - "version": "1.1.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "1e091702a5a38e6b4c1ba9ca816e3dd343df2e2d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/1e091702a5a38e6b4c1ba9ca816e3dd343df2e2d", - "reference": "1e091702a5a38e6b4c1ba9ca816e3dd343df2e2d", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "Diff implementation", - "homepage": "http://www.github.com/sebastianbergmann/diff", - "keywords": [ - "diff" - ], - "time": "2013-08-03 16:46:33" - }, - { - "name": "sebastian/environment", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "79517609ec01139cd7e9fded0dd7ce08c952ef6a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/79517609ec01139cd7e9fded0dd7ce08c952ef6a", - "reference": "79517609ec01139cd7e9fded0dd7ce08c952ef6a", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "4.0.*@dev" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], - "time": "2014-02-18 16:17:19" - }, - { - "name": "sebastian/exporter", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "1f9a98e6f5dfe0524cb8c6166f7c82f3e9ae1529" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/1f9a98e6f5dfe0524cb8c6166f7c82f3e9ae1529", - "reference": "1f9a98e6f5dfe0524cb8c6166f7c82f3e9ae1529", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "4.0.*@dev" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - } - ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], - "time": "2014-02-16 08:26:31" - }, - { - "name": "sebastian/version", - "version": "1.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "b6e1f0cf6b9e1ec409a0d3e2f2a5fb0998e36b43" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/b6e1f0cf6b9e1ec409a0d3e2f2a5fb0998e36b43", - "reference": "b6e1f0cf6b9e1ec409a0d3e2f2a5fb0998e36b43", - "shasum": "" - }, - "type": "library", - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "time": "2014-03-07 15:35:33" - }, - { - "name": "symfony/yaml", - "version": "v2.4.2", - "target-dir": "Symfony/Component/Yaml", - "source": { - "type": "git", - "url": "https://github.com/symfony/Yaml.git", - "reference": "bb6ddaf8956139d1b8c360b4b713ed0138e876b3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/bb6ddaf8956139d1b8c360b4b713ed0138e876b3", - "reference": "bb6ddaf8956139d1b8c360b4b713ed0138e876b3", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.4-dev" - } - }, - "autoload": { - "psr-0": { - "Symfony\\Component\\Yaml\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, - { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" - } - ], - "description": "Symfony Yaml Component", - "homepage": "http://symfony.com", - "time": "2014-01-07 13:28:54" - } - ], - "aliases": [ - - ], - "minimum-stability": "stable", - "stability-flags": [ - - ], - "platform": [ - - ], - "platform-dev": [ - - ] -} From 9e944d8815165750b6ff59c6f92d7609e84bb43b Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Sat, 15 Nov 2014 18:38:35 +0000 Subject: [PATCH 21/25] Fixed .gitignore --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 5657f6e..81b9258 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -vendor \ No newline at end of file +composer.lock +phpunit.xml +vendor From d052c232f45a836cbf038cf4dff8eb4e1b4657d3 Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Sat, 15 Nov 2014 18:38:44 +0000 Subject: [PATCH 22/25] Added .gitattributes --- .gitattributes | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..f80340e --- /dev/null +++ b/.gitattributes @@ -0,0 +1,8 @@ +* text=auto + +/test export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore +/.travis.yml export-ignore +/phpunit.xml.dist export-ignore +/README.md export-ignore From d2edd8ce853c3cf3467e52c65330dd6328c8998d Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Sat, 15 Nov 2014 18:38:52 +0000 Subject: [PATCH 23/25] Fixed the test config --- .travis.yml | 14 +++++++------- phpunit.xml.dist | 22 ++++++++++++---------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0651993..6dd21b2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,17 +1,17 @@ language: php php: - - 5.6 - - 5.5 - - 5.4 - 5.3 + - 5.4 + - 5.5 + - 5.6 - hhvm -before_script: - - composer self-update - - composer install --no-interaction --prefer-source --dev +install: + - travis_retry composer install --no-interaction --prefer-source -script: vendor/bin/phpunit --configuration phpunit.xml.dist --colors +script: + - vendor/bin/phpunit matrix: allow_failures: diff --git a/phpunit.xml.dist b/phpunit.xml.dist index b2b3afb..33f37a1 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -2,28 +2,30 @@ + syntaxCheck="true" + strict="true" + verbose="true" +> test/Unit + + + ./test + + - - lib/ + + ./lib From 35c4dc18808fada00394dc0d5a2494534e9c877d Mon Sep 17 00:00:00 2001 From: Anthony Ferrara Date: Thu, 20 Nov 2014 11:35:09 -0500 Subject: [PATCH 24/25] Fix a bunch of minor issues, including process isolation #64, formatting issues #56, supporting null and integer passwords #63 and #48 --- lib/password.php | 514 +++++++++++++++++---------------- test/Unit/PasswordHashTest.php | 12 +- 2 files changed, 276 insertions(+), 250 deletions(-) diff --git a/lib/password.php b/lib/password.php index 63344d6..45ae4c7 100644 --- a/lib/password.php +++ b/lib/password.php @@ -9,290 +9,306 @@ namespace { -if (!defined('PASSWORD_DEFAULT')) { + if (!defined('PASSWORD_BCRYPT')) { + /** + * PHPUnit Process isolation caches constants, but not function declarations. + * So we need to check if the constants are defined separately from + * the functions to enable supporting process isolation in userland + * code. + */ + define('PASSWORD_BCRYPT', 1); + define('PASSWORD_DEFAULT', PASSWORD_BCRYPT); + define('PASSWORD_BCRYPT_DEFAULT_COST', 10); + } - define('PASSWORD_BCRYPT', 1); - define('PASSWORD_BCRYPT_DEFAULT_COST', 10); - define('PASSWORD_DEFAULT', PASSWORD_BCRYPT); + if (!function_exists('password_hash')) { - /** - * Hash the password using the specified algorithm - * - * @param string $password The password to hash - * @param int $algo The algorithm to use (Defined by PASSWORD_* constants) - * @param array $options The options for the algorithm to use - * - * @return string|false The hashed password, or false on error. - */ - function password_hash($password, $algo, array $options = array()) { - if (!function_exists('crypt')) { - trigger_error("Crypt must be loaded for password_hash to function", E_USER_WARNING); - return null; - } - if (!is_string($password)) { - trigger_error("password_hash(): Password must be a string", E_USER_WARNING); - return null; - } - if (!is_int($algo)) { - trigger_error("password_hash() expects parameter 2 to be long, " . gettype($algo) . " given", E_USER_WARNING); - return null; - } - $resultLength = 0; - switch ($algo) { - case PASSWORD_BCRYPT: - $cost = PASSWORD_BCRYPT_DEFAULT_COST; - if (isset($options['cost'])) { - $cost = $options['cost']; - if ($cost < 4 || $cost > 31) { - trigger_error(sprintf("password_hash(): Invalid bcrypt cost parameter specified: %d", $cost), E_USER_WARNING); - return null; - } - } - // The length of salt to generate - $raw_salt_len = 16; - // The length required in the final serialization - $required_salt_len = 22; - $hash_format = sprintf("$2y$%02d$", $cost); - // The expected length of the final crypt() output - $resultLength = 60; - break; - default: - trigger_error(sprintf("password_hash(): Unknown password hashing algorithm: %s", $algo), E_USER_WARNING); + /** + * Hash the password using the specified algorithm + * + * @param string $password The password to hash + * @param int $algo The algorithm to use (Defined by PASSWORD_* constants) + * @param array $options The options for the algorithm to use + * + * @return string|false The hashed password, or false on error. + */ + function password_hash($password, $algo, array $options = array()) { + if (!function_exists('crypt')) { + trigger_error("Crypt must be loaded for password_hash to function", E_USER_WARNING); return null; - } - $salt_requires_encoding = false; - if (isset($options['salt'])) { - switch (gettype($options['salt'])) { - case 'NULL': - case 'boolean': - case 'integer': - case 'double': - case 'string': - $salt = (string) $options['salt']; - break; - case 'object': - if (method_exists($options['salt'], '__tostring')) { - $salt = (string) $options['salt']; - break; + } + if (is_null($password) || is_int($password)) { + $password = (string) $password; + } + if (!is_string($password)) { + trigger_error("password_hash(): Password must be a string", E_USER_WARNING); + return null; + } + if (!is_int($algo)) { + trigger_error("password_hash() expects parameter 2 to be long, " . gettype($algo) . " given", E_USER_WARNING); + return null; + } + $resultLength = 0; + switch ($algo) { + case PASSWORD_BCRYPT: + $cost = PASSWORD_BCRYPT_DEFAULT_COST; + if (isset($options['cost'])) { + $cost = $options['cost']; + if ($cost < 4 || $cost > 31) { + trigger_error(sprintf("password_hash(): Invalid bcrypt cost parameter specified: %d", $cost), E_USER_WARNING); + return null; + } } - case 'array': - case 'resource': + // The length of salt to generate + $raw_salt_len = 16; + // The length required in the final serialization + $required_salt_len = 22; + $hash_format = sprintf("$2y$%02d$", $cost); + // The expected length of the final crypt() output + $resultLength = 60; + break; default: - trigger_error('password_hash(): Non-string salt parameter supplied', E_USER_WARNING); + trigger_error(sprintf("password_hash(): Unknown password hashing algorithm: %s", $algo), E_USER_WARNING); return null; } - if (PasswordCompat\binary\_strlen($salt) < $required_salt_len) { - trigger_error(sprintf("password_hash(): Provided salt is too short: %d expecting %d", PasswordCompat\binary\_strlen($salt), $required_salt_len), E_USER_WARNING); - return null; - } elseif (0 == preg_match('#^[a-zA-Z0-9./]+$#D', $salt)) { - $salt_requires_encoding = true; - } - } else { - $buffer = ''; - $buffer_valid = false; - if (function_exists('mcrypt_create_iv') && !defined('PHALANGER')) { - $buffer = mcrypt_create_iv($raw_salt_len, MCRYPT_DEV_URANDOM); - if ($buffer) { - $buffer_valid = true; + $salt_requires_encoding = false; + if (isset($options['salt'])) { + switch (gettype($options['salt'])) { + case 'NULL': + case 'boolean': + case 'integer': + case 'double': + case 'string': + $salt = (string) $options['salt']; + break; + case 'object': + if (method_exists($options['salt'], '__tostring')) { + $salt = (string) $options['salt']; + break; + } + case 'array': + case 'resource': + default: + trigger_error('password_hash(): Non-string salt parameter supplied', E_USER_WARNING); + return null; } - } - if (!$buffer_valid && function_exists('openssl_random_pseudo_bytes')) { - $buffer = openssl_random_pseudo_bytes($raw_salt_len); - if ($buffer) { - $buffer_valid = true; + if (PasswordCompat\binary\_strlen($salt) < $required_salt_len) { + trigger_error(sprintf("password_hash(): Provided salt is too short: %d expecting %d", PasswordCompat\binary\_strlen($salt), $required_salt_len), E_USER_WARNING); + return null; + } elseif (0 == preg_match('#^[a-zA-Z0-9./]+$#D', $salt)) { + $salt_requires_encoding = true; } - } - if (!$buffer_valid && @is_readable('/dev/urandom')) { - $f = fopen('/dev/urandom', 'r'); - $read = PasswordCompat\binary\_strlen($buffer); - while ($read < $raw_salt_len) { - $buffer .= fread($f, $raw_salt_len - $read); - $read = PasswordCompat\binary\_strlen($buffer); + } else { + $buffer = ''; + $buffer_valid = false; + if (function_exists('mcrypt_create_iv') && !defined('PHALANGER')) { + $buffer = mcrypt_create_iv($raw_salt_len, MCRYPT_DEV_URANDOM); + if ($buffer) { + $buffer_valid = true; + } } - fclose($f); - if ($read >= $raw_salt_len) { - $buffer_valid = true; + if (!$buffer_valid && function_exists('openssl_random_pseudo_bytes')) { + $buffer = openssl_random_pseudo_bytes($raw_salt_len); + if ($buffer) { + $buffer_valid = true; + } } - } - if (!$buffer_valid || PasswordCompat\binary\_strlen($buffer) < $raw_salt_len) { - $bl = PasswordCompat\binary\_strlen($buffer); - for ($i = 0; $i < $raw_salt_len; $i++) { - if ($i < $bl) { - $buffer[$i] = $buffer[$i] ^ chr(mt_rand(0, 255)); - } else { - $buffer .= chr(mt_rand(0, 255)); + if (!$buffer_valid && @is_readable('/dev/urandom')) { + $f = fopen('/dev/urandom', 'r'); + $read = PasswordCompat\binary\_strlen($buffer); + while ($read < $raw_salt_len) { + $buffer .= fread($f, $raw_salt_len - $read); + $read = PasswordCompat\binary\_strlen($buffer); + } + fclose($f); + if ($read >= $raw_salt_len) { + $buffer_valid = true; } } + if (!$buffer_valid || PasswordCompat\binary\_strlen($buffer) < $raw_salt_len) { + $bl = PasswordCompat\binary\_strlen($buffer); + for ($i = 0; $i < $raw_salt_len; $i++) { + if ($i < $bl) { + $buffer[$i] = $buffer[$i] ^ chr(mt_rand(0, 255)); + } else { + $buffer .= chr(mt_rand(0, 255)); + } + } + } + $salt = $buffer; + $salt_requires_encoding = true; } - $salt = $buffer; - $salt_requires_encoding = true; - } - if ($salt_requires_encoding) { - // encode string with the Base64 variant used by crypt - $base64_digits = - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; - $bcrypt64_digits = - './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + if ($salt_requires_encoding) { + // encode string with the Base64 variant used by crypt + $base64_digits = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + $bcrypt64_digits = + './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - $base64_string = base64_encode($salt); - $salt = strtr(rtrim($base64_string, '='), $base64_digits, $bcrypt64_digits); - } - $salt = PasswordCompat\binary\_substr($salt, 0, $required_salt_len); - - $hash = $hash_format . $salt; + $base64_string = base64_encode($salt); + $salt = strtr(rtrim($base64_string, '='), $base64_digits, $bcrypt64_digits); + } + $salt = PasswordCompat\binary\_substr($salt, 0, $required_salt_len); - $ret = crypt($password, $hash); + $hash = $hash_format . $salt; - if (!is_string($ret) || PasswordCompat\binary\_strlen($ret) != $resultLength) { - return false; - } + $ret = crypt($password, $hash); - return $ret; - } + if (!is_string($ret) || PasswordCompat\binary\_strlen($ret) != $resultLength) { + return false; + } - /** - * Get information about the password hash. Returns an array of the information - * that was used to generate the password hash. - * - * array( - * 'algo' => 1, - * 'algoName' => 'bcrypt', - * 'options' => array( - * 'cost' => PASSWORD_BCRYPT_DEFAULT_COST, - * ), - * ) - * - * @param string $hash The password hash to extract info from - * - * @return array The array of information about the hash. - */ - function password_get_info($hash) { - $return = array( - 'algo' => 0, - 'algoName' => 'unknown', - 'options' => array(), - ); - if (PasswordCompat\binary\_substr($hash, 0, 4) == '$2y$' && PasswordCompat\binary\_strlen($hash) == 60) { - $return['algo'] = PASSWORD_BCRYPT; - $return['algoName'] = 'bcrypt'; - list($cost) = sscanf($hash, "$2y$%d$"); - $return['options']['cost'] = $cost; + return $ret; } - return $return; - } - /** - * Determine if the password hash needs to be rehashed according to the options provided - * - * If the answer is true, after validating the password using password_verify, rehash it. - * - * @param string $hash The hash to test - * @param int $algo The algorithm used for new password hashes - * @param array $options The options array passed to password_hash - * - * @return boolean True if the password needs to be rehashed. - */ - function password_needs_rehash($hash, $algo, array $options = array()) { - $info = password_get_info($hash); - if ($info['algo'] != $algo) { - return true; - } - switch ($algo) { - case PASSWORD_BCRYPT: - $cost = isset($options['cost']) ? $options['cost'] : PASSWORD_BCRYPT_DEFAULT_COST; - if ($cost != $info['options']['cost']) { - return true; - } - break; + /** + * Get information about the password hash. Returns an array of the information + * that was used to generate the password hash. + * + * array( + * 'algo' => 1, + * 'algoName' => 'bcrypt', + * 'options' => array( + * 'cost' => PASSWORD_BCRYPT_DEFAULT_COST, + * ), + * ) + * + * @param string $hash The password hash to extract info from + * + * @return array The array of information about the hash. + */ + function password_get_info($hash) { + $return = array( + 'algo' => 0, + 'algoName' => 'unknown', + 'options' => array(), + ); + if (PasswordCompat\binary\_substr($hash, 0, 4) == '$2y$' && PasswordCompat\binary\_strlen($hash) == 60) { + $return['algo'] = PASSWORD_BCRYPT; + $return['algoName'] = 'bcrypt'; + list($cost) = sscanf($hash, "$2y$%d$"); + $return['options']['cost'] = $cost; + } + return $return; } - return false; - } - /** - * Verify a password against a hash using a timing attack resistant approach - * - * @param string $password The password to verify - * @param string $hash The hash to verify against - * - * @return boolean If the password matches the hash - */ - function password_verify($password, $hash) { - if (!function_exists('crypt')) { - trigger_error("Crypt must be loaded for password_verify to function", E_USER_WARNING); - return false; - } - $ret = crypt($password, $hash); - if (!is_string($ret) || PasswordCompat\binary\_strlen($ret) != PasswordCompat\binary\_strlen($hash) || PasswordCompat\binary\_strlen($ret) <= 13) { + /** + * Determine if the password hash needs to be rehashed according to the options provided + * + * If the answer is true, after validating the password using password_verify, rehash it. + * + * @param string $hash The hash to test + * @param int $algo The algorithm used for new password hashes + * @param array $options The options array passed to password_hash + * + * @return boolean True if the password needs to be rehashed. + */ + function password_needs_rehash($hash, $algo, array $options = array()) { + $info = password_get_info($hash); + if ($info['algo'] != $algo) { + return true; + } + switch ($algo) { + case PASSWORD_BCRYPT: + $cost = isset($options['cost']) ? $options['cost'] : PASSWORD_BCRYPT_DEFAULT_COST; + if ($cost != $info['options']['cost']) { + return true; + } + break; + } return false; } - $status = 0; - for ($i = 0; $i < PasswordCompat\binary\_strlen($ret); $i++) { - $status |= (ord($ret[$i]) ^ ord($hash[$i])); - } + /** + * Verify a password against a hash using a timing attack resistant approach + * + * @param string $password The password to verify + * @param string $hash The hash to verify against + * + * @return boolean If the password matches the hash + */ + function password_verify($password, $hash) { + if (!function_exists('crypt')) { + trigger_error("Crypt must be loaded for password_verify to function", E_USER_WARNING); + return false; + } + $ret = crypt($password, $hash); + if (!is_string($ret) || PasswordCompat\binary\_strlen($ret) != PasswordCompat\binary\_strlen($hash) || PasswordCompat\binary\_strlen($ret) <= 13) { + return false; + } - return $status === 0; + $status = 0; + for ($i = 0; $i < PasswordCompat\binary\_strlen($ret); $i++) { + $status |= (ord($ret[$i]) ^ ord($hash[$i])); + } + + return $status === 0; + } } -} } namespace PasswordCompat\binary { - /** - * Count the number of bytes in a string - * - * We cannot simply use strlen() for this, because it might be overwritten by the mbstring extension. - * In this case, strlen() will count the number of *characters* based on the internal encoding. A - * sequence of bytes might be regarded as a single multibyte character. - * - * @param string $binary_string The input string - * - * @internal - * @return int The number of bytes - */ - function _strlen($binary_string) { - if (function_exists('mb_strlen')) { - return mb_strlen($binary_string, '8bit'); - } - return strlen($binary_string); - } - /** - * Get a substring based on byte limits - * - * @see _strlen() - * - * @param string $binary_string The input string - * @param int $start - * @param int $length - * - * @internal - * @return string The substring - */ - function _substr($binary_string, $start, $length) { - if (function_exists('mb_substr')) { - return mb_substr($binary_string, $start, $length, '8bit'); - } - return substr($binary_string, $start, $length); - } + if (!function_exists('PasswordCompat\\binary\\_strlen')) { - /** - * Check if current PHP version is compatible with the library - * - * @return boolean the check result - */ - function check() { - static $pass = NULL; + /** + * Count the number of bytes in a string + * + * We cannot simply use strlen() for this, because it might be overwritten by the mbstring extension. + * In this case, strlen() will count the number of *characters* based on the internal encoding. A + * sequence of bytes might be regarded as a single multibyte character. + * + * @param string $binary_string The input string + * + * @internal + * @return int The number of bytes + */ + function _strlen($binary_string) { + if (function_exists('mb_strlen')) { + return mb_strlen($binary_string, '8bit'); + } + return strlen($binary_string); + } - if (is_null($pass)) { - if (function_exists('crypt')) { - $hash = '$2y$04$usesomesillystringfore7hnbRJHxXVLeakoG8K30oukPsA.ztMG'; - $test = crypt("password", $hash); - $pass = $test == $hash; - } else { - $pass = false; + /** + * Get a substring based on byte limits + * + * @see _strlen() + * + * @param string $binary_string The input string + * @param int $start + * @param int $length + * + * @internal + * @return string The substring + */ + function _substr($binary_string, $start, $length) { + if (function_exists('mb_substr')) { + return mb_substr($binary_string, $start, $length, '8bit'); + } + return substr($binary_string, $start, $length); + } + + /** + * Check if current PHP version is compatible with the library + * + * @return boolean the check result + */ + function check() { + static $pass = NULL; + + if (is_null($pass)) { + if (function_exists('crypt')) { + $hash = '$2y$04$usesomesillystringfore7hnbRJHxXVLeakoG8K30oukPsA.ztMG'; + $test = crypt("password", $hash); + $pass = $test == $hash; + } else { + $pass = false; + } } + return $pass; } - return $pass; + } -} +} \ No newline at end of file diff --git a/test/Unit/PasswordHashTest.php b/test/Unit/PasswordHashTest.php index a95f3ee..abe9109 100644 --- a/test/Unit/PasswordHashTest.php +++ b/test/Unit/PasswordHashTest.php @@ -29,6 +29,16 @@ public function testRawSalt() { } } + public function testNullBehavior() { + $hash = password_hash(null, PASSWORD_BCRYPT, array("salt" => "1234567890123456789012345678901234567890")); + $this->assertEquals('$2y$10$123456789012345678901uhihPb9QpE2n03zMu9TDdvO34jDn6mO.', $hash); + } + + public function testIntegerBehavior() { + $hash = password_hash(12345, PASSWORD_BCRYPT, array("salt" => "1234567890123456789012345678901234567890")); + $this->assertEquals('$2y$10$123456789012345678901ujczD5TiARVFtc68bZCAlbEg1fCIexfO', $hash); + } + /** * @expectedException PHPUnit_Framework_Error */ @@ -85,4 +95,4 @@ public function testInvalidBcryptSaltShort() { password_hash('foo', PASSWORD_BCRYPT, array('salt' => 'abc')); } -} \ No newline at end of file +} From 4bedaa1ccdfb333ef837f796ab6b382895e23d8f Mon Sep 17 00:00:00 2001 From: Anthony Ferrara Date: Thu, 20 Nov 2014 11:36:11 -0500 Subject: [PATCH 25/25] Fix formatting from #56 --- lib/password.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/password.php b/lib/password.php index 45ae4c7..cc6896c 100644 --- a/lib/password.php +++ b/lib/password.php @@ -265,10 +265,10 @@ function password_verify($password, $hash) { * @return int The number of bytes */ function _strlen($binary_string) { - if (function_exists('mb_strlen')) { - return mb_strlen($binary_string, '8bit'); - } - return strlen($binary_string); + if (function_exists('mb_strlen')) { + return mb_strlen($binary_string, '8bit'); + } + return strlen($binary_string); } /** @@ -284,10 +284,10 @@ function _strlen($binary_string) { * @return string The substring */ function _substr($binary_string, $start, $length) { - if (function_exists('mb_substr')) { - return mb_substr($binary_string, $start, $length, '8bit'); - } - return substr($binary_string, $start, $length); + if (function_exists('mb_substr')) { + return mb_substr($binary_string, $start, $length, '8bit'); + } + return substr($binary_string, $start, $length); } /**