Overview

Namespaces

  • None
  • Wei
    • Validator

Classes

  • Wei\Validator\All
  • Wei\Validator\AllOf
  • Wei\Validator\Alnum
  • Wei\Validator\Alpha
  • Wei\Validator\BaseValidator
  • Wei\Validator\Between
  • Wei\Validator\Blank
  • Wei\Validator\Callback
  • Wei\Validator\CharLength
  • Wei\Validator\Chinese
  • Wei\Validator\Color
  • Wei\Validator\Contains
  • Wei\Validator\CreditCard
  • Wei\Validator\Date
  • Wei\Validator\DateTime
  • Wei\Validator\Decimal
  • Wei\Validator\Digit
  • Wei\Validator\Dir
  • Wei\Validator\DivisibleBy
  • Wei\Validator\DoubleByte
  • Wei\Validator\Email
  • Wei\Validator\EndsWith
  • Wei\Validator\EqualTo
  • Wei\Validator\Exists
  • Wei\Validator\FieldExists
  • Wei\Validator\File
  • Wei\Validator\GreaterThan
  • Wei\Validator\GreaterThanOrEqual
  • Wei\Validator\IdCardCn
  • Wei\Validator\IdCardHk
  • Wei\Validator\IdCardMo
  • Wei\Validator\IdCardTw
  • Wei\Validator\IdenticalTo
  • Wei\Validator\Image
  • Wei\Validator\In
  • Wei\Validator\Ip
  • Wei\Validator\Length
  • Wei\Validator\LessThan
  • Wei\Validator\LessThanOrEqual
  • Wei\Validator\Lowercase
  • Wei\Validator\Luhn
  • Wei\Validator\MaxLength
  • Wei\Validator\MinLength
  • Wei\Validator\MobileCn
  • Wei\Validator\NaturalNumber
  • Wei\Validator\NoneOf
  • Wei\Validator\Null
  • Wei\Validator\Number
  • Wei\Validator\OneOf
  • Wei\Validator\Password
  • Wei\Validator\Phone
  • Wei\Validator\PhoneCn
  • Wei\Validator\PlateNumberCn
  • Wei\Validator\PositiveInteger
  • Wei\Validator\PostcodeCn
  • Wei\Validator\Present
  • Wei\Validator\QQ
  • Wei\Validator\RecordExists
  • Wei\Validator\Regex
  • Wei\Validator\Required
  • Wei\Validator\SomeOf
  • Wei\Validator\StartsWith
  • Wei\Validator\Time
  • Wei\Validator\Tld
  • Wei\Validator\Type
  • Wei\Validator\Uppercase
  • Wei\Validator\Url
  • Wei\Validator\Uuid
  • Overview
  • Namespace
  • Function
  1: <?php
  2: /**
  3:  * Wei Framework
  4:  *
  5:  * @copyright   Copyright (c) 2008-2015 Twin Huang
  6:  * @license     http://opensource.org/licenses/mit-license.php MIT License
  7:  */
  8: 
  9: namespace Wei;
 10: 
 11: /**
 12:  * A wrapper class for password hashing functions
 13:  *
 14:  * If you needs these original functions, please checkout
 15:  * https://github.com/ircmaxell/password_compat instead.
 16:  *
 17:  * - password_hash
 18:  * - password_get_info
 19:  * - password_needs_rehash
 20:  * - password_verify
 21:  *
 22:  * @author      Anthony Ferrara <ircmaxell@php.net>
 23:  * @author      https://github.com/ircmaxell/password_compat/graphs/contributors
 24:  * @author      Twin Huang <twinhuang@qq.com>
 25:  * @link        https://github.com/ircmaxell/password_compat/blob/master/lib/password.php
 26:  */
 27: class Password extends Base
 28: {
 29:     /**
 30:      * The cost parameter for bcrypt
 31:      *
 32:      * @var int
 33:      */
 34:     protected $cost = 10;
 35: 
 36:     /**
 37:      * Constructor
 38:      *
 39:      * @param array $options
 40:      * @throws \Exception
 41:      */
 42:     public function __construct(array $options = array())
 43:     {
 44:         parent::__construct($options);
 45: 
 46:         if (!defined('PASSWORD_BCRYPT')) {
 47:             define('PASSWORD_BCRYPT', 1);
 48:             define('PASSWORD_DEFAULT', PASSWORD_BCRYPT);
 49:         }
 50:     }
 51: 
 52:     /**
 53:      * Hash the password using the specified algorithm
 54:      *
 55:      * @param string $password The password to hash
 56:      * @param string $salt The salt string for the algorithm to use
 57:      * @throws \InvalidArgumentException
 58:      * @return string|false The hashed password, or false on error.
 59:      */
 60:     public function hash($password, $salt = null)
 61:     {
 62:         $hash_format = sprintf("$2y$%02d$", $this->cost);
 63: 
 64:         !$salt && $salt = $this->generateSalt();
 65:         if (strlen($salt) < 22) {
 66:             throw new \InvalidArgumentException(sprintf("Provided salt is too short: %d expecting %d", strlen($salt), 22));
 67:         }
 68: 
 69:         $hash = $hash_format . $salt;
 70:         $ret = crypt($password, $hash);
 71: 
 72:         if (!is_string($ret) || strlen($ret) <= 13) {
 73:             return false;
 74:         }
 75: 
 76:         return $ret;
 77:     }
 78: 
 79:     /**
 80:      * Get information about the password hash. Returns an array of the information
 81:      * that was used to generate the password hash.
 82:      *
 83:      * array(
 84:      *    'algo' => 1,
 85:      *    'algoName' => 'bcrypt',
 86:      *    'options' => array(
 87:      *        'cost' => 10,
 88:      *    ),
 89:      * )
 90:      *
 91:      * @param string $hash The password hash to extract info from
 92:      *
 93:      * @return array The array of information about the hash.
 94:      */
 95:     public function getInfo($hash)
 96:     {
 97:         $return = array(
 98:             'algo' => 0,
 99:             'algoName' => 'unknown',
100:             'options' => array(),
101:         );
102:         if (substr($hash, 0, 4) == '$2y$' && strlen($hash) == 60) {
103:             $return['algo'] = PASSWORD_BCRYPT;
104:             $return['algoName'] = 'bcrypt';
105:             list($cost) = sscanf($hash, "$2y$%d$");
106:             $return['options']['cost'] = $cost;
107:         }
108:         return $return;
109:     }
110: 
111:     /**
112:      * Determine if the password hash needs to be rehashed according to the options provided
113:      *
114:      * If the answer is true, after validating the password using password_verify, rehash it.
115:      *
116:      * @param string $hash The hash to test
117:      * @param int $algo The algorithm used for new password hashes
118:      * @param array $options The options array passed to password_hash
119:      *
120:      * @return boolean True if the password needs to be rehashed.
121:      */
122:     public function needsRehash($hash, $algo, array $options = array())
123:     {
124:         $info = $this->getInfo($hash);
125:         if ($info['algo'] != $algo) {
126:             return true;
127:         }
128:         switch ($algo) {
129:             case PASSWORD_BCRYPT:
130:                 $cost = isset($options['cost']) ? $options['cost'] : 10;
131:                 if ($cost != $info['options']['cost']) {
132:                     return true;
133:                 }
134:                 break;
135:         }
136:         return false;
137:     }
138: 
139:     /**
140:      * Verify a password against a hash using a timing attack resistant approach
141:      *
142:      * @param string $password The password to verify
143:      * @param string $hash     The hash to verify against
144:      *
145:      * @return boolean If the password matches the hash
146:      */
147:     public function verify($password, $hash)
148:     {
149:         $ret = crypt($password, $hash);
150:         if (!is_string($ret) || strlen($ret) != strlen($hash) || strlen($ret) <= 13) {
151:             return false;
152:         }
153: 
154:         $status = 0;
155:         for ($i = 0; $i < strlen($ret); $i++) {
156:             $status |= (ord($ret[$i]) ^ ord($hash[$i]));
157:         }
158: 
159:         return $status === 0;
160:     }
161: 
162:     /**
163:      * Set the cost parameter for bcrypt
164:      *
165:      * @param int $cost
166:      * @return $this
167:      * @throws \InvalidArgumentException
168:      */
169:     public function setCost($cost)
170:     {
171:         if ($cost < 4 || $cost > 31) {
172:             throw new \InvalidArgumentException(sprintf("Invalid bcrypt cost parameter specified: %s", $cost));
173:         }
174:         $this->cost = $cost;
175:         return $this;
176:     }
177: 
178:     /**
179:      * Generate a 22 bytes salt string
180:      *
181:      * @return string
182:      */
183:     public function generateSalt()
184:     {
185:         // The length of salt to generate
186:         $raw_salt_len = 16;
187:         // The length required in the final serialization
188:         $required_salt_len = 22;
189: 
190:         $buffer = mcrypt_create_iv($raw_salt_len, MCRYPT_DEV_URANDOM);
191:         $salt = str_replace('+', '.', base64_encode($buffer));
192:         $salt = substr($salt, 0, $required_salt_len);
193: 
194:         return $salt;
195:     }
196: }
197: 
Wei Framework API documentation generated by ApiGen