PHP DeadFish Hashing Lib
welcome to Game-Tuts.com - Register
Results 1 to 2 of 2
  1. #1
    Code Monkey
    Join Date
    Dec 2009
    Location
    Ontario
    Posts
    848
    Thanks
    1093
    Gamertag
    catisoldnmoldy

    Default PHP DeadFish Hashing Lib

    Hey all so I coded this up a after I was in a discussion about safely storing hashes of user passwords. How salts etc... really don't help all that much so here is a implamentation of an adaptive hash using blowish and it's algorithm’s keying schedule. So as you inc work the longer it takes to gen and inversely crack. Making brute force almost uesless, or at the very least take an insanely long amount of time.

    Code:
    <?php
    
    /**
     * DeadFish Library
     * The DeadFish library is used for making a safe (or safer) storable hash of a user password. We attempt to make storing a password hash
     * a little more secure by creating an adaptive hash using blowfish and it's algorithm’s keying schedule.
     *
     * @author      Joseph Newing (jnewing [at] gmail [dot] com)
     * @copyright   Joseph Newing 2011 - 2012
     * @link        https://bitbucket.org/jnewing/deadfish-lib
     * @link        http://epicgeeks.net
     * @version     1.4
     *
     * *************************************************************************************************************************
     *
     * DeadFish lib has several options users can set to customize this library.
     *
     * Options:
     *      min_length          - the minamum required length of a user password
     *      strict_password     - require the password to follow "strict" rules (see rules below)
     *                              o min length required
     *                              o require alpha and numeric values
     *                              o require both upper and lower case values
     *      work_factor         - the work factor
     *
     * Within this class there are both static function users can use for fast access as
     * well as none static ones, see examples below.
     *
     * Static Usage Examples:
     *
     * static function example:
     * $hash = DeadFish::computeHash('some password');      // would compute a hash with default work factor
     *
     * static function check and existing hash
     * $bool = DeadFish::verifyHash('some password', 'matching hash');
     *
     * Object Usage Example:
     *
     * example with default options:
     *
     * $df = new DeadFish();
     * $df->set_password('some_password');
     * $hash = $df->hash();
     * ...
     * if ($df->verify('some_password', 'some_hash'))
     *  do stuff...
     *
     * example with diff options:
     *
     * $options = array(
     *      'min_length'        => 5,       // make the min password length 5
     *      'strict_password'   => TRUE     // use strict passwords
     * );
     *
     * $df = new DeadFish($options);
     * $hash = $df->hash('some_password')
     *
     */
    
    class DeadFish
    {
    
    // ======================================================================================
    //  class consts
    // ======================================================================================
    
        const DEFAULT_WORK_FACTOR   = 9;
    
    // ======================================================================================
    //  public variables
    // ======================================================================================
    
        /**
         * minimum lenght the password must be
         */
        public $min_length          = 8;
    
        /**
         * strict password must be at least ^ min length (see above)
         * alpha numeric and contain at least one uppercase and one lower case character
         */
        public $strict_password     = FALSE;
    
        /**
         * our work factor
         */
        public $work_factor         = 9;
    
    // ======================================================================================
    //  private variables
    // ======================================================================================
    
        /**
         * user password
         */
        private $password            = NULL;
    
    // ======================================================================================
    //  public functions
    // ======================================================================================
    
        /**
         * constructor - Sets some default PHash prefs.
         *
         * the constructor can be passed an array of config values however this is not
         * needed unless you wish to do some customization of your own.
         */
        public function __construct($options = FALSE)
        {
            if ($options)
                $this->init($options);
        }
    
        // --------------------------------------------------------------------
    
        /**
         * initialize our prefs.
         *
         * @access  public
         * @param   array
         * @return  void
         */
        public function init($options)
        {
            // setup our default options
            if (is_array($options))
            {
                foreach ($options as $key => $val)
                    $this->{$key} = $val;
            }
        }
    
        // --------------------------------------------------------------------
    
        /**
         * set_password function will set the class password while doing
         * the required checks.
         *
         * @access  public
         * @param   string
         * @return  void
         */
        public function set_password($password)
        {
            // we are forcring the user to set a strong password
            // password rules:
            //  - min length required
            //  - require alpha and numeric values
            //  - require both upper and lower case values
            if ($this->strict_password)
            {
                if (preg_match('/\A(?=[\x20-\x7E]*?[A-Z])(?=[\x20-\x7E]*?[a-z])(?=[\x20-\x7E]*?[0-9])[\x20-\x7E]{' . $this->min_length . ',}\z/', $password))
                {
                    // set the password
                    $this->password = $password;
    
                    // return
                    return;
                }
                else
                    throw new Exception('Password did not meat minamum security requirements.');
            }
    
            // if we are not forcing the user to a strict password then we should at the very least
            // make it a min. length
            if (strlen($password) >= $this->min_length)
            {
                // set our password
                $this->password = $password;
    
                // return
                return;
            }
    
            throw new Exception('Password did not meat minamum security requirements.');
        }
    
        // --------------------------------------------------------------------
    
        /**
         * set the work factor for the class
         *
         * @access  public
         * @param   int
         * @return  void
         */
        public function set_work($work)
        {
            // make sure work fact. is between 4 and 31, if not we error.
            if ($work < 4 || $work > 31)
                throw new Exception('Work factor must be between 4 and 31.');
    
            // if we are good set it
            $this->work_factor = $work;
        }
        // --------------------------------------------------------------------
    
        /**
         * hash function allows users to hash a password using the initialized class this will look to
         * $this->password (hopefully set by set_password or has been passed to this function)
         *
         * @access  public
         * @param   string (optional)
         * @return  string
         */
        public function hash($password = FALSE)
        {
            // if the user passed our password here lets try and set it
            if ($password)
                $this->set_password($password);
    
            // make sure we have a password to hash
            if (empty($this->password))
                throw new Exception('Missing a password?');
    
            // lets hash
            return self::computeHash($this->password, $this->work_factor);
        }
    
        // --------------------------------------------------------------------
    
        /**
         * verify function allows the user to verify a password and hash match, simply returns a bool value
         * user can then do what they like with the result.
         *
         * @access  public
         * @param   string (optional)
         * @param   string (optional)
         * @return  bool
         */
        public function verify($password = FALSE, $hash = FALSE)
        {
            if ($password)
                $this->password = $password;
    
            if ($hash)
                $this->hash = $hash;
    
            // make sure we have a password and hash to work with
            if (empty($this->password) || empty($this->hash))
                throw new Exception('Missing password or hash?');
    
            // compair and return
            return self::verifyHash($this->password, $this->hash);
        }
    
        // --------------------------------------------------------------------
    
    // ======================================================================================
    //  public static functions
    // ======================================================================================
    
        /**
         * compute the hash of the password using the specified work factor value, if no work factor is
         * specified then default (8) will be used
         *
         * @access  public
         * @param   string
         * @param   int
         * @return  string
         */
        public static function computeHash($password, $work = 0)
        {
            // declair our salt
            $salt = NULL;
    
            // define our work fact.
            $work = ($work < 4 || $work > 31) ? self::DEFAULT_WORK_FACTOR : $work;
    
            // random pseudo bytes
            if (function_exists('openssl_random_pseudo_bytes'))
                $random_bytes = substr(strtr(base64_encode(openssl_random_pseudo_bytes(16)), '+', '.'), 0, 22);
            else
                $random_bytes = self::gen_random();
    
            // gen our salt
            $salt = '$2a$' . str_pad($work, 2, '0', STR_PAD_LEFT) . '$' . $random_bytes;
    
            // return our hash
            return crypt($password, $salt);
        }
    
        // --------------------------------------------------------------------
    
        /**
         * verify the password and hash passed to this function
         *
         * @access  public
         * @param   string
         * @param   string
         * @return  bool
         */
        public static function verifyHash($password, $hash)
        {
            // if this is not a blowfish hash we can just error as we don't
            // understand how to deal with it
            if (substr($hash, 0, 4) != '$2a$')
                throw new Exception('Unknown or invalid hash format.');
    
            // crypt compair and return
            return crypt($password, $hash) === $hash;
        }
    
        // --------------------------------------------------------------------
    
    // ======================================================================================
    //  private functions
    // ======================================================================================
    
        /**
         * gen_random function is to be used in place of the openssl_random_pseudo_bytes function,
         * we would rather use that function however not all system will have that available so this is
         * used as a fallback
         *
         * @access  public
         * @param   int (optional)
         * @return  string
         */
        private static function gen_random($length = 22)
        {
            $ascii_array = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./';
            $random_string = '';
    
            for ($x = 0; $x < $length; $x++)
                $random_string .= $ascii_array[ rand(0, 63) ];
    
            return $random_string;
        }
    
        // --------------------------------------------------------------------
    
    }
    
    ?>
    Demo can be viewed: DeadFish.Lib Demo (Example) - Joseph Newing
    Source: https://bitbucket.org/jnewing/deadfish-lib
    Fast, simple, lightweight and FREE image capture and upload!
    Check out pixldrop.com today!

    Game-Tuts IRC Channel
    Webchat: Click here
    irc.epicgeeks.net -j #gametuts


  2. The Following User Says Thank You to synmuffin For This Useful Post:

    Olivia (07-22-2012)

  3. #2
    Code Monkey
    Join Date
    Dec 2009
    Location
    Ontario
    Posts
    848
    Thanks
    1093
    Gamertag
    catisoldnmoldy

    Default Re: PHP DeadFish Hashing Lib

    I also added a duration timer now, so you can see the change when you increment or decrement the work factor. The key to making this successfully is finding a nice work factor for server.
    Fast, simple, lightweight and FREE image capture and upload!
    Check out pixldrop.com today!

    Game-Tuts IRC Channel
    Webchat: Click here
    irc.epicgeeks.net -j #gametuts



 

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
visit GameTuts on these social networking sites