add methods to decrypt return data from router
[GitHub/Stricted/speedport-hybrid-php-api.git] / CryptLib / Password / Implementation / PHPASS.php
diff --git a/CryptLib/Password/Implementation/PHPASS.php b/CryptLib/Password/Implementation/PHPASS.php
new file mode 100644 (file)
index 0000000..4522e87
--- /dev/null
@@ -0,0 +1,246 @@
+<?php
+/**
+ * The PHPASS password hashing implementation
+ *
+ * Use this class to generate and validate PHPASS password hashes.
+ *
+ * PHP version 5.3
+ *
+ * @see        http://www.openwall.com/phpass/
+ * @category   PHPCryptLib
+ * @package    Password
+ * @subpackage Implementation
+ * @author     Anthony Ferrara <ircmaxell@ircmaxell.com>
+ * @copyright  2011 The Authors
+ * @license    http://www.opensource.org/licenses/mit-license.html  MIT License
+ * @version    Build @@version@@
+ */
+
+namespace CryptLib\Password\Implementation;
+
+use CryptLib\Random\Factory as RandomFactory;
+
+/**
+ * The PHPASS password hashing implementation
+ *
+ * Use this class to generate and validate PHPASS password hashes.
+ *
+ * @see        http://www.openwall.com/phpass/
+ * @category   PHPCryptLib
+ * @package    Password
+ * @subpackage Implementation
+ * @author     Anthony Ferrara <ircmaxell@ircmaxell.com>
+ */
+class PHPASS implements \CryptLib\Password\Password {
+
+    /**
+     * @var string The ITOA string to be used for base64 conversion
+     */
+    protected static $itoa = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
+                                abcdefghijklmnopqrstuvwxyz';
+
+    /**
+     * @var Generator The random generator to use for seeds
+     */
+    protected $generator = null;
+
+    /**
+     * This is the hash function to use.  To be overriden by child classes
+     *
+     * @var string The hash function to use for this instance
+     */
+    protected $hashFunction = 'md5';
+
+    /**
+     * @var int The number of iterations to perform (base 2)
+     */
+    protected $iterations = 10;
+
+    /**
+     * @var string The prefix for the generated hash
+     */
+    protected static $prefix = '$P$';
+
+    /**
+     * Determine if the hash was made with this method
+     *
+     * @param string $hash The hashed data to check
+     *
+     * @return boolean Was the hash created by this method
+     */
+    public static function detect($hash) {
+        $prefix = preg_quote(static::$prefix, '/');
+        return 1 == preg_match('/^'.$prefix.'[a-zA-Z0-9.\/]{31}$/', $hash);
+    }
+
+    /**
+     * Return the prefix used by this hashing method
+     *
+     * @return string The prefix used
+     */
+    public static function getPrefix() {
+        return static::$prefix;
+    }
+
+    /**
+     * Initialize the password hasher by replacing away spaces in the itoa var
+     *
+     * @return void
+     */
+    public static function init() {
+        static::$itoa = preg_replace('/\s/', '', static::$itoa);
+    }
+
+    /**
+     * Load an instance of the class based upon the supplied hash
+     *
+     * @param string $hash The hash to load from
+     *
+     * @return Password the created instance
+     * @throws InvalidArgumentException if the hash wasn't created here
+     */
+    public static function loadFromHash($hash) {
+        if (!static::detect($hash)) {
+            throw new \InvalidArgumentException('Hash Not Created Here');
+        }
+        $iterations = static::decodeIterations($hash[3]);
+        return new static($iterations);
+    }
+
+    /**
+     * Decode an ITOA encoded iteration count
+     *
+     * @param string $byte The character to decode
+     *
+     * @return int The decoded iteration count (base2)
+     */
+    protected static function decodeIterations($byte) {
+        return strpos(static::$itoa, $byte);
+    }
+
+    /**
+     * Encode a base2 iteration count to a base64 character
+     *
+     * @param int $number
+     *
+     * @return string The encoded character
+     */
+    protected static function encodeIterations($number) {
+        return static::$itoa[$number];
+    }
+
+    /**
+     * Build a new instance
+     *
+     * @param int       $iterations The number of times to iterate the hash
+     * @param Generator $generator  The random generator to use for seeds
+     * @param Factory   $factory    The hash factory to use for this instance
+     *
+     * @return void
+     */
+    public function __construct(
+        $iterations = 8,
+        \CryptLib\Random\Generator $generator = null
+    ) {
+        if ($iterations > 30 || $iterations < 7) {
+            throw new \InvalidArgumentException('Invalid Iteration Count Supplied');
+        }
+        $this->iterations = $iterations;
+        if (is_null($generator)) {
+            $random    = new RandomFactory();
+            $generator = $random->getMediumStrengthGenerator();
+        }
+        $this->generator = $generator;
+    }
+
+    /**
+     * Create a password hash for a given plain text password
+     *
+     * @param string $password The password to hash
+     *
+     * @return string The formatted password hash
+     */
+    public function create($password) {
+        $salt   = $this->to64($this->generator->generate(6));
+        $prefix = static::encodeIterations($this->iterations) . $salt;
+        return static::$prefix . $prefix . $this->hash($password, $salt);
+    }
+
+    /**
+     * Verify a password hash against a given plain text password
+     *
+     * @param string $password The password to hash
+     * @param string $hash     The supplied ahsh to validate
+     *
+     * @return boolean Does the password validate against the hash
+     */
+    public function verify($password, $hash) {
+        if (!static::detect($hash)) {
+            throw new \InvalidArgumentException(
+                'The hash was not created here, we cannot verify it'
+            );
+        }
+        $iterations = static::decodeIterations($hash[3]);
+        if ($iterations != $this->iterations) {
+            throw new \InvalidArgumentException(
+                'Iteration Count Mismatch, Bailing'
+            );
+        }
+        $salt = substr($hash, 4, 8);
+        $hash = substr($hash, 12);
+        $test = $this->hash($password, $salt);
+        return $test == $hash;
+    }
+
+    /**
+     * Execute the hash function with proper iterations
+     *
+     * @param string $password The password to hash
+     * @param string $salt     The salt to use to hash
+     *
+     * @return string The base64 encoded generated hash
+     */
+    protected function hash($password, $salt) {
+        $count = 1 << $this->iterations;
+        $hash  = hash($this->hashFunction, $salt . $password, true);
+        do {
+            $hash = hash($this->hashFunction, $hash . $password, true);
+        } while (--$count);
+        return $this->to64($hash);
+    }
+
+    /**
+     * Convert the input number to a base64 number of the specified size
+     *
+     * @param int $input The number to convert
+     *
+     * @return string The converted representation
+     */
+    protected function to64($input) {
+        $output = '';
+        $count  = strlen($input);
+        $ictr   = 0;
+        do {
+            $value   = ord($input[$ictr++]);
+            $output .= static::$itoa[$value & 0x3f];
+            if ($ictr < $count) {
+                $value |= ord($input[$ictr]) << 8;
+            }
+            $output .= static::$itoa[($value >> 6) & 0x3f];
+            if ($ictr++ >= $count) {
+                break;
+            }
+            if ($ictr < $count) {
+                $value |= ord($input[$ictr]) << 16;
+            }
+            $output .= static::$itoa[($value >> 12) & 0x3f];
+            if ($ictr++ < $count) {
+                $output .= static::$itoa[($value >> 18) & 0x3f];
+            }
+        } while ($ictr < $count);
+        return $output;
+    }
+
+}
+
+PHPASS::init();
\ No newline at end of file