summaryrefslogtreecommitdiff
path: root/vendor/ircmaxell/password-compat
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/ircmaxell/password-compat')
-rw-r--r--vendor/ircmaxell/password-compat/.travis.yml8
-rw-r--r--vendor/ircmaxell/password-compat/LICENSE.md7
-rw-r--r--vendor/ircmaxell/password-compat/README.md75
-rw-r--r--vendor/ircmaxell/password-compat/composer.json18
-rw-r--r--vendor/ircmaxell/password-compat/lib/password.php222
-rw-r--r--vendor/ircmaxell/password-compat/phpunit.xml.dist29
-rw-r--r--vendor/ircmaxell/password-compat/test/Unit/PasswordGetInfoTest.php26
-rw-r--r--vendor/ircmaxell/password-compat/test/Unit/PasswordHashTest.php84
-rw-r--r--vendor/ircmaxell/password-compat/test/Unit/PasswordNeedsRehashTest.php26
-rw-r--r--vendor/ircmaxell/password-compat/test/Unit/PasswordVerifyTest.php29
-rw-r--r--vendor/ircmaxell/password-compat/version-test.php8
11 files changed, 532 insertions, 0 deletions
diff --git a/vendor/ircmaxell/password-compat/.travis.yml b/vendor/ircmaxell/password-compat/.travis.yml
new file mode 100644
index 00000000..a960061c
--- /dev/null
+++ b/vendor/ircmaxell/password-compat/.travis.yml
@@ -0,0 +1,8 @@
+language: php
+
+php:
+ - 5.5
+ - 5.4
+ - 5.3
+
+script: phpunit --configuration phpunit.xml.dist \ No newline at end of file
diff --git a/vendor/ircmaxell/password-compat/LICENSE.md b/vendor/ircmaxell/password-compat/LICENSE.md
new file mode 100644
index 00000000..1efc565f
--- /dev/null
+++ b/vendor/ircmaxell/password-compat/LICENSE.md
@@ -0,0 +1,7 @@
+Copyright (c) 2012 Anthony Ferrara
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file
diff --git a/vendor/ircmaxell/password-compat/README.md b/vendor/ircmaxell/password-compat/README.md
new file mode 100644
index 00000000..e158f7d0
--- /dev/null
+++ b/vendor/ircmaxell/password-compat/README.md
@@ -0,0 +1,75 @@
+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.
+
+See [the RFC](https://wiki.php.net/rfc/password_hash) for more detailed information.
+
+
+Requirements
+============
+
+This library requires `PHP >= 5.3.7` OR a version that has the `$2y` fix backported into it (such as Debian provides).
+
+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.
+
+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.
+
+Installation
+============
+
+To install, simply `require` the `password.php` file under `lib`.
+
+You can also install it via `Composer` by using the [Packagist archive](http://packagist.org/packages/ircmaxell/password-compat).
+
+Usage
+=====
+
+**Creating Password Hashes**
+
+To create a password hash from a password, simply use the `password_hash` function.
+
+ $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:
+
+ $hash = password_hash($password, PASSWORD_BCRYPT, ["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:
+
+ 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.
+
+**Verifying Password Hashes**
+
+To verify a hash created by `password_hash`, simply call:
+
+ 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:
+
+ if (password_verify($password, $hash)) {
+ if (password_needs_rehash($hash, $algorithm, $options)) {
+ $hash = password_hash($password, $algorithm, $options);
+ /* Store new hash in db */
+ }
+ }
diff --git a/vendor/ircmaxell/password-compat/composer.json b/vendor/ircmaxell/password-compat/composer.json
new file mode 100644
index 00000000..e0d4f14c
--- /dev/null
+++ b/vendor/ircmaxell/password-compat/composer.json
@@ -0,0 +1,18 @@
+{
+ "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.3",
+ "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"
+ }
+ ],
+ "autoload": {
+ "files": ["lib/password.php"]
+ }
+} \ No newline at end of file
diff --git a/vendor/ircmaxell/password-compat/lib/password.php b/vendor/ircmaxell/password-compat/lib/password.php
new file mode 100644
index 00000000..4d0e8b7a
--- /dev/null
+++ b/vendor/ircmaxell/password-compat/lib/password.php
@@ -0,0 +1,222 @@
+<?php
+/**
+ * A Compatibility library with PHP 5.5's simplified password hashing API.
+ *
+ * @author Anthony Ferrara <ircmaxell@php.net>
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @copyright 2012 The Authors
+ */
+
+if (!defined('PASSWORD_BCRYPT')) {
+
+ define('PASSWORD_BCRYPT', 1);
+ define('PASSWORD_DEFAULT', PASSWORD_BCRYPT);
+
+ /**
+ * 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;
+ }
+ 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;
+ 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);
+ break;
+ default:
+ trigger_error(sprintf("password_hash(): Unknown password hashing algorithm: %s", $algo), E_USER_WARNING);
+ return null;
+ }
+ 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 (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);
+ return null;
+ } elseif (0 == preg_match('#^[a-zA-Z0-9./]+$#D', $salt)) {
+ $salt = str_replace('+', '.', base64_encode($salt));
+ }
+ } 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;
+ }
+ }
+ 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 && is_readable('/dev/urandom')) {
+ $f = fopen('/dev/urandom', 'r');
+ $read = strlen($buffer);
+ while ($read < $raw_salt_len) {
+ $buffer .= fread($f, $raw_salt_len - $read);
+ $read = strlen($buffer);
+ }
+ fclose($f);
+ if ($read >= $raw_salt_len) {
+ $buffer_valid = true;
+ }
+ }
+ if (!$buffer_valid || strlen($buffer) < $raw_salt_len) {
+ $bl = 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 = str_replace('+', '.', base64_encode($buffer));
+ }
+ $salt = substr($salt, 0, $required_salt_len);
+
+ $hash = $hash_format . $salt;
+
+ $ret = crypt($password, $hash);
+
+ if (!is_string($ret) || strlen($ret) <= 13) {
+ return false;
+ }
+
+ return $ret;
+ }
+
+ /**
+ * 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' => 10,
+ * ),
+ * )
+ *
+ * @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 (substr($hash, 0, 4) == '$2y$' && strlen($hash) == 60) {
+ $return['algo'] = PASSWORD_BCRYPT;
+ $return['algoName'] = 'bcrypt';
+ list($cost) = sscanf($hash, "$2y$%d$");
+ $return['options']['cost'] = $cost;
+ }
+ 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'] : 10;
+ if ($cost != $info['options']['cost']) {
+ return true;
+ }
+ break;
+ }
+ 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) || strlen($ret) != strlen($hash) || strlen($ret) <= 13) {
+ return false;
+ }
+
+ $status = 0;
+ for ($i = 0; $i < strlen($ret); $i++) {
+ $status |= (ord($ret[$i]) ^ ord($hash[$i]));
+ }
+
+ return $status === 0;
+ }
+}
+
+
+
diff --git a/vendor/ircmaxell/password-compat/phpunit.xml.dist b/vendor/ircmaxell/password-compat/phpunit.xml.dist
new file mode 100644
index 00000000..b2b3afbd
--- /dev/null
+++ b/vendor/ircmaxell/password-compat/phpunit.xml.dist
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit backupGlobals="true"
+ backupStaticAttributes="false"
+ bootstrap="lib/password.php"
+ colors="false"
+ convertErrorsToExceptions="true"
+ convertNoticesToExceptions="true"
+ convertWarningsToExceptions="true"
+ forceCoversAnnotation="false"
+ mapTestClassNameToCoveredClassName="false"
+ processIsolation="false"
+ stopOnError="false"
+ stopOnFailure="false"
+ stopOnIncomplete="false"
+ stopOnSkipped="false"
+ testSuiteLoaderClass="PHPUnit_Runner_StandardTestSuiteLoader"
+ strict="false"
+ verbose="false">
+ <testsuites>
+ <testsuite name="Unit">
+ <directory>test/Unit</directory>
+ </testsuite>
+ </testsuites>
+ <filter>
+ <whitelist>
+ <directory suffix=".php">lib/</directory>
+ </whitelist>
+ </filter>
+</phpunit>
diff --git a/vendor/ircmaxell/password-compat/test/Unit/PasswordGetInfoTest.php b/vendor/ircmaxell/password-compat/test/Unit/PasswordGetInfoTest.php
new file mode 100644
index 00000000..6aab976a
--- /dev/null
+++ b/vendor/ircmaxell/password-compat/test/Unit/PasswordGetInfoTest.php
@@ -0,0 +1,26 @@
+<?php
+
+class PasswordGetInfoTest extends PHPUnit_Framework_TestCase {
+
+ public static function provideInfo() {
+ return array(
+ array('foo', array('algo' => 0, 'algoName' => 'unknown', 'options' => array())),
+ array('$2y$', array('algo' => 0, 'algoName' => 'unknown', 'options' => array())),
+ array('$2y$07$usesomesillystringfore2uDLvp1Ii2e./U9C8sBjqp8I90dH6hi', array('algo' => PASSWORD_BCRYPT, 'algoName' => 'bcrypt', 'options' => array('cost' => 7))),
+ array('$2y$10$usesomesillystringfore2uDLvp1Ii2e./U9C8sBjqp8I90dH6hi', array('algo' => PASSWORD_BCRYPT, 'algoName' => 'bcrypt', 'options' => array('cost' => 10))),
+
+ );
+ }
+
+ public function testFuncExists() {
+ $this->assertTrue(function_exists('password_get_info'));
+ }
+
+ /**
+ * @dataProvider provideInfo
+ */
+ public function testInfo($hash, $info) {
+ $this->assertEquals($info, password_get_info($hash));
+ }
+
+} \ No newline at end of file
diff --git a/vendor/ircmaxell/password-compat/test/Unit/PasswordHashTest.php b/vendor/ircmaxell/password-compat/test/Unit/PasswordHashTest.php
new file mode 100644
index 00000000..9e5e9ec6
--- /dev/null
+++ b/vendor/ircmaxell/password-compat/test/Unit/PasswordHashTest.php
@@ -0,0 +1,84 @@
+<?php
+
+class PasswordHashTest extends PHPUnit_Framework_TestCase {
+
+ public function testFuncExists() {
+ $this->assertTrue(function_exists('password_hash'));
+ }
+
+ public function testStringLength() {
+ $this->assertEquals(60, strlen(password_hash('foo', PASSWORD_BCRYPT)));
+ }
+
+ public function testHash() {
+ $hash = password_hash('foo', PASSWORD_BCRYPT);
+ $this->assertEquals($hash, crypt('foo', $hash));
+ }
+
+ public function testKnownSalt() {
+ $hash = password_hash("rasmuslerdorf", PASSWORD_BCRYPT, array("cost" => 7, "salt" => "usesomesillystringforsalt"));
+ $this->assertEquals('$2y$07$usesomesillystringfore2uDLvp1Ii2e./U9C8sBjqp8I90dH6hi', $hash);
+ }
+
+ public function testRawSalt() {
+ $hash = password_hash("test", PASSWORD_BCRYPT, array("salt" => "123456789012345678901" . chr(0)));
+ $this->assertEquals('$2y$10$MTIzNDU2Nzg5MDEyMzQ1Nej0NmcAWSLR.oP7XOR9HD/vjUuOj100y', $hash);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInvalidAlgo() {
+ password_hash('foo', array());
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInvalidAlgo2() {
+ password_hash('foo', 2);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInvalidPassword() {
+ password_hash(array(), 1);
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInvalidSalt() {
+ password_hash('foo', PASSWORD_BCRYPT, array('salt' => array()));
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInvalidBcryptCostLow() {
+ password_hash('foo', PASSWORD_BCRYPT, array('cost' => 3));
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInvalidBcryptCostHigh() {
+ password_hash('foo', PASSWORD_BCRYPT, array('cost' => 32));
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInvalidBcryptCostInvalid() {
+ password_hash('foo', PASSWORD_BCRYPT, array('cost' => 'foo'));
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testInvalidBcryptSaltShort() {
+ password_hash('foo', PASSWORD_BCRYPT, array('salt' => 'abc'));
+ }
+
+} \ No newline at end of file
diff --git a/vendor/ircmaxell/password-compat/test/Unit/PasswordNeedsRehashTest.php b/vendor/ircmaxell/password-compat/test/Unit/PasswordNeedsRehashTest.php
new file mode 100644
index 00000000..c2932dc6
--- /dev/null
+++ b/vendor/ircmaxell/password-compat/test/Unit/PasswordNeedsRehashTest.php
@@ -0,0 +1,26 @@
+<?php
+
+class PasswordNeedsRehashTest extends PHPUnit_Framework_TestCase {
+
+ public static function provideCases() {
+ return array(
+ array('foo', 0, array(), false),
+ array('foo', 1, array(), true),
+ array('$2y$07$usesomesillystringfore2uDLvp1Ii2e./U9C8sBjqp8I90dH6hi', PASSWORD_BCRYPT, array(), true),
+ array('$2y$07$usesomesillystringfore2udlvp1ii2e./u9c8sbjqp8i90dh6hi', PASSWORD_BCRYPT, array('cost' => 7), false),
+ array('$2y$07$usesomesillystringfore2udlvp1ii2e./u9c8sbjqp8i90dh6hi', PASSWORD_BCRYPT, array('cost' => 5), true),
+ );
+ }
+
+ public function testFuncExists() {
+ $this->assertTrue(function_exists('password_needs_rehash'));
+ }
+
+ /**
+ * @dataProvider provideCases
+ */
+ public function testCases($hash, $algo, $options, $valid) {
+ $this->assertEquals($valid, password_needs_rehash($hash, $algo, $options));
+ }
+
+} \ No newline at end of file
diff --git a/vendor/ircmaxell/password-compat/test/Unit/PasswordVerifyTest.php b/vendor/ircmaxell/password-compat/test/Unit/PasswordVerifyTest.php
new file mode 100644
index 00000000..9f67bb9f
--- /dev/null
+++ b/vendor/ircmaxell/password-compat/test/Unit/PasswordVerifyTest.php
@@ -0,0 +1,29 @@
+<?php
+
+class PasswordVerifyTest extends PHPUnit_Framework_TestCase {
+
+ public function testFuncExists() {
+ $this->assertTrue(function_exists('password_verify'));
+ }
+
+ public function testFailedType() {
+ $this->assertFalse(password_verify(123, 123));
+ }
+
+ public function testSaltOnly() {
+ $this->assertFalse(password_verify('foo', '$2a$07$usesomesillystringforsalt$'));
+ }
+
+ public function testInvalidPassword() {
+ $this->assertFalse(password_verify('rasmusler', '$2a$07$usesomesillystringfore2uDLvp1Ii2e./U9C8sBjqp8I90dH6hi'));
+ }
+
+ public function testValidPassword() {
+ $this->assertTrue(password_verify('rasmuslerdorf', '$2a$07$usesomesillystringfore2uDLvp1Ii2e./U9C8sBjqp8I90dH6hi'));
+ }
+
+ public function testInValidHash() {
+ $this->assertFalse(password_verify('rasmuslerdorf', '$2a$07$usesomesillystringfore2uDLvp1Ii2e./U9C8sBjqp8I90dH6hj'));
+ }
+
+} \ No newline at end of file
diff --git a/vendor/ircmaxell/password-compat/version-test.php b/vendor/ircmaxell/password-compat/version-test.php
new file mode 100644
index 00000000..f527e30f
--- /dev/null
+++ b/vendor/ircmaxell/password-compat/version-test.php
@@ -0,0 +1,8 @@
+<?php
+
+$hash = '$2y$04$usesomesillystringfore7hnbRJHxXVLeakoG8K30oukPsA.ztMG';
+$test = crypt("password", $hash);
+$pass = $test == $hash;
+
+echo "Test for functionality of compat library: " . ($pass ? "Pass" : "Fail");
+echo "\n"; \ No newline at end of file