Overview

Namespaces

  • PHP
  • PHPassLib
    • Application
    • Exception
    • Hash
    • Test
      • Application
      • Hash

Classes

  • Context
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * PHP Password Library
  4:  *
  5:  * @package PHPassLib\Hashes
  6:  * @author Ryan Chouinard <rchouinard@gmail.com>
  7:  * @copyright Copyright (c) 2012, Ryan Chouinard
  8:  * @license MIT License - http://www.opensource.org/licenses/mit-license.php
  9:  * @version 3.0.0-dev
 10:  */
 11: 
 12: namespace PHPassLib\Application;
 13: 
 14: use PHPassLib\Exception\RuntimeException;
 15: 
 16: /**
 17:  * Application Context
 18:  *
 19:  * This class provides an interface for using the library within an large
 20:  * application.
 21:  *
 22:  * <code>
 23:  *     <?php
 24:  *     $passlibContext = new PHPassLib\Application\Context;
 25:  *     $passlibContext->addConfig('bcrypt'); // Use bcrypt with default options
 26:  *
 27:  *     $hash = $passlibContext->hash($password);
 28:  *     if ($passlibContext->verify($password, $hash) {
 29:  *         // ...
 30:  *     }
 31:  * </code>
 32:  *
 33:  * The context also allows us to check if a user's stored hash needs to be
 34:  * updated to a newer version.
 35:  *
 36:  * <code>
 37:  *     <?php
 38:  *     $passlibContext = new PHPassLib\Application\Context;
 39:  *
 40:  *     // The first added config becomes the default
 41:  *     // This is important for methods like hash() and needsUpdate()
 42:  *     $passlibContext->addConfig('pbkdf2', array ('digest' => 'sha256'));
 43:  *
 44:  *     // Additional configs are supported by verify()
 45:  *     $passlibContext->addConfig('bcrypt');
 46:  *
 47:  *     if ($passlibContext->verify($password, $hash)) {
 48:  *         // needsUpdate() will return true if the provided hash fails to
 49:  *         // match the default config in any way. This means bcrypt hashes as
 50:  *         // well as PBKDF2 hashes which use a digest other than SHA-256.
 51:  *         if ($passlibContext->needsUpdate($hash)) {
 52:  *             // $newHash will be a PBKDF2 hash
 53:  *             $newHash = $passlibContext->hash($password);
 54:  *             // Store $newHash into the user object
 55:  *         }
 56:  *         // ...
 57:  *     }
 58:  * </code>
 59:  *
 60:  * @package PHPassLib\Hashes
 61:  * @author Ryan Chouinard <rchouinard@gmail.com>
 62:  * @copyright Copyright (c) 2012, Ryan Chouinard
 63:  * @license MIT License - http://www.opensource.org/licenses/mit-license.php
 64:  * @version 3.0.0-dev
 65:  */
 66: class Context
 67: {
 68: 
 69:     /**
 70:      * @var array
 71:      */
 72:     protected $classMap = array ();
 73: 
 74:     /**
 75:      * @var array
 76:      */
 77:     protected $configs = array ();
 78: 
 79:     /**
 80:      * @return void
 81:      */
 82:     public function __construct()
 83:     {
 84:         $defaultNamespace = 'PHPassLib\\Hash';
 85:         $this
 86:             ->registerClass('bcrypt', $defaultNamespace . '\\BCrypt')
 87:             ->registerClass('bsdicrypt', $defaultNamespace . '\\BSDiCrypt')
 88:             ->registerClass('descrypt', $defaultNamespace . '\\DESCrypt')
 89:             ->registerClass('md5crypt', $defaultNamespace . '\\MD5Crypt')
 90:             ->registerClass('pbkdf2', $defaultNamespace . '\\PBKDF2')
 91:             ->registerClass('portable', $defaultNamespace . '\\Portable')
 92:             ->registerClass('sha1crypt', $defaultNamespace . '\\SHA1Crypt')
 93:             ->registerClass('sha256crypt', $defaultNamespace . '\\SHA256Crypt')
 94:             ->registerClass('sha512crypt', $defaultNamespace . '\\SHA512Crypt');
 95:     }
 96: 
 97:     /**
 98:      * @param string $alias
 99:      * @param string $classname
100:      * @return Context
101:      */
102:     public function registerClass($alias, $classname)
103:     {
104:         $this->classMap[strtolower($alias)] = $classname;
105:         return $this;
106:     }
107: 
108:     /**
109:      * @param string $algorithm
110:      * @param array $config
111:      * @return Context
112:      */
113:     public function addConfig($algorithm, array $config = array ())
114:     {
115:         $this->configs[$algorithm] = array (
116:             'classname' => $this->getClassFromAlias($algorithm),
117:             'config' => $config
118:         );
119:         return $this;
120:     }
121: 
122:     /**
123:      * @param string $password
124:      * @return string
125:      */
126:     public function hash($password)
127:     {
128:         $config = $this->getDefaultConfig();
129:         return call_user_func(array ($config['classname'], 'hash'), $password, $config['config']);
130:     }
131: 
132:     /**
133:      * @param string $password
134:      * @param string $hash
135:      * @return boolean
136:      */
137:     public function verify($password, $hash)
138:     {
139:         $config = $this->getConfigFromHash($hash);
140:         return call_user_func(array ($config['classname'], 'verify'), $password, $hash);
141:     }
142: 
143:     /**
144:      * @param string $hash
145:      * @return boolean
146:      */
147:     public function needsUpdate($hash)
148:     {
149:         $config = $this->getDefaultConfig();
150: 
151:         // Parse the supplied hash to extract the options
152:         $hashOptions = call_user_func(array ($config['classname'], 'parseConfig'), $hash);
153: 
154:         // Parse a config string from the default config
155:         $defaultConfigString = call_user_func(array ($config['classname'], 'genConfig'), $config['config']);
156:         $defaultOptions = call_user_func(array ($config['classname'], 'parseConfig'), $defaultConfigString);
157: 
158:         if (!$hashOptions || !$defaultOptions) {
159:             return true;
160:         }
161: 
162:         unset ($hashOptions['salt'], $defaultOptions['salt']);
163:         return (array () != array_diff_assoc($hashOptions, $defaultOptions));
164:     }
165: 
166:     /**
167:      * @return array
168:      * @throws RuntimeException
169:      */
170:     protected function getDefaultConfig()
171:     {
172:         if (count($this->configs) > 0) {
173:             reset($this->configs);
174:             return current($this->configs);
175:         }
176: 
177:         throw new RuntimeException('There are no configurations defined');
178:     }
179: 
180:     /**
181:      * @param string $hash
182:      * @return array
183:      * @throws RuntimeException
184:      */
185:     protected function getConfigFromHash($hash)
186:     {
187:         if (count($this->configs) < 1) {
188:             throw new RuntimeException('There are no configurations defined');
189:         }
190: 
191:         foreach ($this->configs as $config) {
192:             if (call_user_func(array ($config['classname'], 'parseConfig'), $hash) !== false) {
193:                 return $config;
194:             }
195:         }
196: 
197:         throw new RuntimeException('Hash does not match any registered configuration');
198:     }
199: 
200:     /**
201:      * @param string $alias
202:      * @return string
203:      * @throws RuntimeException
204:      */
205:     protected function getClassFromAlias($alias)
206:     {
207:         $alias = strtolower($alias);
208:         if (!isset($this->classMap[$alias])) {
209:             throw new RuntimeException("Requested class alias '$alias' is not registered");
210:         }
211: 
212:         if (!class_exists($this->classMap[$alias], true)) {
213:             throw new RuntimeException("Failed loading class for alias '$alias'");
214:         }
215: 
216:         if (!in_array('PHPassLib\\Hash', class_implements($this->classMap[$alias]))) {
217:             throw new RuntimeException("Class alias '$alias' does not implement PHPass\Hash interface");
218:         }
219: 
220:         return $this->classMap[$alias];
221:     }
222: 
223: }
224: 
PHP Password Library API documentation generated by ApiGen 2.8.0