1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10:
11:
12: namespace PHPassLib\Application;
13:
14: use PHPassLib\Exception\RuntimeException;
15:
16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65:
66: class Context
67: {
68:
69: 70: 71:
72: protected $classMap = array ();
73:
74: 75: 76:
77: protected $configs = array ();
78:
79: 80: 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: 99: 100: 101:
102: public function registerClass($alias, $classname)
103: {
104: $this->classMap[strtolower($alias)] = $classname;
105: return $this;
106: }
107:
108: 109: 110: 111: 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: 124: 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: 134: 135: 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: 145: 146:
147: public function needsUpdate($hash)
148: {
149: $config = $this->getDefaultConfig();
150:
151:
152: $hashOptions = call_user_func(array ($config['classname'], 'parseConfig'), $hash);
153:
154:
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: 168: 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: 182: 183: 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: 202: 203: 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: