1 | <?php |
||||
2 | |||||
3 | /** |
||||
4 | * Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions. |
||||
5 | * |
||||
6 | * Uses hash() or mhash() if available and an internal implementation, otherwise. Currently supports the following: |
||||
7 | * |
||||
8 | * sha256, sha256-96, sha384, and sha512, sha512-96 |
||||
9 | * |
||||
10 | * If {@link self::setKey() setKey()} is called, {@link self::hash() hash()} will return the HMAC as opposed to |
||||
11 | * the hash. If no valid algorithm is provided, sha256 will be used. |
||||
12 | * |
||||
13 | * PHP version 5 |
||||
14 | * |
||||
15 | * {@internal The variable names are the same as those in |
||||
16 | * {@link http://tools.ietf.org/html/rfc2104#section-2 RFC2104}.}} |
||||
17 | * |
||||
18 | * Here's a short example of how to use this library: |
||||
19 | * <code> |
||||
20 | * <?php |
||||
21 | * include 'vendor/autoload.php'; |
||||
22 | * |
||||
23 | * $hash = new \phpseclib\Crypt\Hash('sha256'); |
||||
24 | * |
||||
25 | * $hash->setKey('abcdefg'); |
||||
26 | * |
||||
27 | * echo base64_encode($hash->hash('abcdefg')); |
||||
28 | * ?> |
||||
29 | * </code> |
||||
30 | * |
||||
31 | * @category Crypt |
||||
32 | * @package Hash |
||||
33 | * @author Jim Wigginton <[email protected]> |
||||
34 | * @copyright 2007 Jim Wigginton |
||||
35 | * @license http://www.opensource.org/licenses/mit-license.html MIT License |
||||
36 | * @link http://phpseclib.sourceforge.net |
||||
37 | */ |
||||
38 | |||||
39 | namespace phpseclib\Crypt; |
||||
40 | |||||
41 | use phpseclib\Math\BigInteger; |
||||
42 | |||||
43 | /** |
||||
44 | * Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions. |
||||
45 | * |
||||
46 | * @package Hash |
||||
47 | * @author Jim Wigginton <[email protected]> |
||||
48 | * @access public |
||||
49 | */ |
||||
50 | class Hash |
||||
51 | { |
||||
52 | /**#@+ |
||||
53 | * @access private |
||||
54 | * @see \phpseclib\Crypt\Hash::__construct() |
||||
55 | */ |
||||
56 | /** |
||||
57 | * Toggles the internal implementation |
||||
58 | */ |
||||
59 | public const MODE_INTERNAL = 1; |
||||
60 | /** |
||||
61 | * Toggles the mhash() implementation, which has been deprecated on PHP 5.3.0+. |
||||
62 | */ |
||||
63 | public const MODE_MHASH = 2; |
||||
64 | /** |
||||
65 | * Toggles the hash() implementation, which works on PHP 5.1.2+. |
||||
66 | */ |
||||
67 | public const MODE_HASH = 3; |
||||
68 | /**#@-*/ |
||||
69 | |||||
70 | /** |
||||
71 | * Hash Parameter |
||||
72 | * |
||||
73 | * @see self::setHash() |
||||
74 | * @var int |
||||
75 | * @access private |
||||
76 | */ |
||||
77 | public $hashParam; |
||||
78 | |||||
79 | /** |
||||
80 | * Byte-length of compression blocks / key (Internal HMAC) |
||||
81 | * |
||||
82 | * @see self::setAlgorithm() |
||||
83 | * @var int |
||||
84 | * @access private |
||||
85 | */ |
||||
86 | public $b; |
||||
87 | |||||
88 | /** |
||||
89 | * Byte-length of hash output (Internal HMAC) |
||||
90 | * |
||||
91 | * @see self::setHash() |
||||
92 | * @var int |
||||
93 | * @access private |
||||
94 | */ |
||||
95 | public $l = false; |
||||
96 | |||||
97 | /** |
||||
98 | * Hash Algorithm |
||||
99 | * |
||||
100 | * @see self::setHash() |
||||
101 | * @var string |
||||
102 | * @access private |
||||
103 | */ |
||||
104 | public $hash; |
||||
105 | |||||
106 | /** |
||||
107 | * Key |
||||
108 | * |
||||
109 | * @see self::setKey() |
||||
110 | * @var string |
||||
111 | * @access private |
||||
112 | */ |
||||
113 | public $key = false; |
||||
114 | |||||
115 | /** |
||||
116 | * Outer XOR (Internal HMAC) |
||||
117 | * |
||||
118 | * @see self::setKey() |
||||
119 | * @var string |
||||
120 | * @access private |
||||
121 | */ |
||||
122 | public $opad; |
||||
123 | |||||
124 | /** |
||||
125 | * Inner XOR (Internal HMAC) |
||||
126 | * |
||||
127 | * @see self::setKey() |
||||
128 | * @var string |
||||
129 | * @access private |
||||
130 | */ |
||||
131 | public $ipad; |
||||
132 | |||||
133 | /** |
||||
134 | * Default Constructor. |
||||
135 | * |
||||
136 | * @param string $hash |
||||
137 | * @return \phpseclib\Crypt\Hash |
||||
138 | * @access public |
||||
139 | */ |
||||
140 | public function __construct($hash = 'sha256') |
||||
141 | { |
||||
142 | if (!defined('CRYPT_HASH_MODE')) { |
||||
143 | switch (true) { |
||||
144 | case extension_loaded('hash'): |
||||
145 | define('CRYPT_HASH_MODE', self::MODE_HASH); |
||||
146 | break; |
||||
147 | case extension_loaded('mhash'): |
||||
148 | define('CRYPT_HASH_MODE', self::MODE_MHASH); |
||||
149 | break; |
||||
150 | default: |
||||
151 | define('CRYPT_HASH_MODE', self::MODE_INTERNAL); |
||||
152 | } |
||||
153 | } |
||||
154 | |||||
155 | $this->setHash($hash); |
||||
156 | } |
||||
157 | |||||
158 | /** |
||||
159 | * Sets the key for HMACs |
||||
160 | * |
||||
161 | * Keys can be of any length. |
||||
162 | * |
||||
163 | * @access public |
||||
164 | * @param string $key |
||||
165 | */ |
||||
166 | public function setKey($key = false) |
||||
167 | { |
||||
168 | $this->key = $key; |
||||
0 ignored issues
–
show
|
|||||
169 | } |
||||
170 | |||||
171 | /** |
||||
172 | * Gets the hash function. |
||||
173 | * |
||||
174 | * As set by the constructor or by the setHash() method. |
||||
175 | * |
||||
176 | * @access public |
||||
177 | * @return string |
||||
178 | */ |
||||
179 | public function getHash() |
||||
180 | { |
||||
181 | return $this->hashParam; |
||||
182 | } |
||||
183 | |||||
184 | /** |
||||
185 | * Sets the hash function. |
||||
186 | * |
||||
187 | * @access public |
||||
188 | * @param string $hash |
||||
189 | */ |
||||
190 | public function setHash($hash) |
||||
191 | { |
||||
192 | $this->hashParam = $hash = strtolower($hash); |
||||
0 ignored issues
–
show
The property
$hashParam was declared of type integer , but $hash = strtolower($hash) is of type string . Maybe add a type cast?
This check looks for assignments to scalar types that may be of the wrong type. To ensure the code behaves as expected, it may be a good idea to add an explicit type cast. $answer = 42;
$correct = false;
$correct = (bool) $answer;
Loading history...
|
|||||
193 | switch ($hash) { |
||||
194 | case 'sha256-96': |
||||
195 | case 'sha512-96': |
||||
196 | $hash = substr($hash, 0, -3); |
||||
197 | $this->l = 12; // 96 / 8 = 12 |
||||
198 | break; |
||||
199 | case 'sha256': |
||||
200 | $this->l = 32; |
||||
201 | break; |
||||
202 | case 'sha384': |
||||
203 | $this->l = 48; |
||||
204 | break; |
||||
205 | case 'sha512': |
||||
206 | $this->l = 64; |
||||
207 | } |
||||
208 | |||||
209 | switch ($hash) { |
||||
210 | case 'sha384': |
||||
211 | case 'sha512': |
||||
212 | $mode = CRYPT_HASH_MODE == self::MODE_MHASH ? self::MODE_INTERNAL : CRYPT_HASH_MODE; |
||||
213 | break; |
||||
214 | default: |
||||
215 | $mode = CRYPT_HASH_MODE; |
||||
216 | } |
||||
217 | |||||
218 | switch ($mode) { |
||||
219 | case self::MODE_MHASH: |
||||
220 | switch ($hash) { |
||||
221 | case 'sha256': |
||||
222 | $this->hash = MHASH_SHA256; |
||||
223 | break; |
||||
224 | default: |
||||
225 | $this->hash = MHASH_SHA256; |
||||
226 | } |
||||
227 | return; |
||||
228 | case self::MODE_HASH: |
||||
229 | switch ($hash) { |
||||
230 | case 'sha256': |
||||
231 | case 'sha384': |
||||
232 | case 'sha512': |
||||
233 | $this->hash = $hash; |
||||
234 | return; |
||||
235 | default: |
||||
236 | $this->hash = 'sha256'; |
||||
237 | } |
||||
238 | return; |
||||
239 | } |
||||
240 | |||||
241 | switch ($hash) { |
||||
242 | case 'sha256': |
||||
243 | $this->b = 64; |
||||
244 | $this->hash = array($this, '_sha256'); |
||||
0 ignored issues
–
show
It seems like
array($this, '_sha256') of type array<integer,phpseclib\Crypt\Hash|string> is incompatible with the declared type string of property $hash .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..
Loading history...
|
|||||
245 | break; |
||||
246 | case 'sha384': |
||||
247 | case 'sha512': |
||||
248 | $this->b = 128; |
||||
249 | $this->hash = array($this, '_sha512'); |
||||
250 | break; |
||||
251 | default: |
||||
252 | $this->b = 64; |
||||
253 | $this->hash = array($this, '_sha256'); |
||||
254 | } |
||||
255 | |||||
256 | $this->ipad = str_repeat(chr(0x36), $this->b); |
||||
257 | $this->opad = str_repeat(chr(0x5C), $this->b); |
||||
258 | } |
||||
259 | |||||
260 | /** |
||||
261 | * Compute the HMAC. |
||||
262 | * |
||||
263 | * @access public |
||||
264 | * @param string $text |
||||
265 | * @return string |
||||
266 | */ |
||||
267 | public function hash($text) |
||||
268 | { |
||||
269 | $mode = is_array($this->hash) ? self::MODE_INTERNAL : CRYPT_HASH_MODE; |
||||
270 | |||||
271 | if (!empty($this->key) || is_string($this->key)) { |
||||
272 | switch ($mode) { |
||||
273 | case self::MODE_MHASH: |
||||
274 | $output = mhash($this->hash, $text, $this->key); |
||||
0 ignored issues
–
show
$this->hash of type string is incompatible with the type integer expected by parameter $hash of mhash() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
275 | break; |
||||
276 | case self::MODE_HASH: |
||||
277 | $output = hash_hmac($this->hash, $text, $this->key, true); |
||||
278 | break; |
||||
279 | case self::MODE_INTERNAL: |
||||
280 | /* "Applications that use keys longer than B bytes will first hash the key using H and then use the |
||||
281 | resultant L byte string as the actual key to HMAC." |
||||
282 | |||||
283 | -- http://tools.ietf.org/html/rfc2104#section-2 */ |
||||
284 | $key = strlen($this->key) > $this->b ? call_user_func($this->hash, $this->key) : $this->key; |
||||
285 | |||||
286 | $key = str_pad($key, $this->b, chr(0)); // step 1 |
||||
287 | $temp = $this->ipad ^ $key; // step 2 |
||||
288 | $temp .= $text; // step 3 |
||||
289 | $temp = call_user_func($this->hash, $temp); // step 4 |
||||
290 | $output = $this->opad ^ $key; // step 5 |
||||
291 | $output.= $temp; // step 6 |
||||
292 | $output = call_user_func($this->hash, $output); // step 7 |
||||
293 | } |
||||
294 | } else { |
||||
295 | switch ($mode) { |
||||
296 | case self::MODE_MHASH: |
||||
297 | $output = mhash($this->hash, $text); |
||||
298 | break; |
||||
299 | case self::MODE_HASH: |
||||
300 | $output = hash($this->hash, $text, true); |
||||
301 | break; |
||||
302 | case self::MODE_INTERNAL: |
||||
303 | $output = call_user_func($this->hash, $text); |
||||
304 | } |
||||
305 | } |
||||
306 | |||||
307 | return substr($output, 0, $this->l); |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
308 | } |
||||
309 | |||||
310 | /** |
||||
311 | * Returns the hash length (in bytes) |
||||
312 | * |
||||
313 | * @access public |
||||
314 | * @return int |
||||
315 | */ |
||||
316 | public function getLength() |
||||
317 | { |
||||
318 | return $this->l; |
||||
319 | } |
||||
320 | |||||
321 | /** |
||||
322 | * Pure-PHP implementation of SHA256 |
||||
323 | * |
||||
324 | * See {@link http://en.wikipedia.org/wiki/SHA_hash_functions#SHA-256_.28a_SHA-2_variant.29_pseudocode SHA-256 (a SHA-2 variant) pseudocode - Wikipedia}. |
||||
325 | * |
||||
326 | * @access private |
||||
327 | * @param string $m |
||||
328 | */ |
||||
329 | public function _sha256($m) |
||||
330 | { |
||||
331 | if (extension_loaded('suhosin')) { |
||||
332 | return pack('H*', sha256($m)); |
||||
333 | } |
||||
334 | |||||
335 | // Initialize variables |
||||
336 | $hash = array( |
||||
337 | 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 |
||||
338 | ); |
||||
339 | // Initialize table of round constants |
||||
340 | // (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311) |
||||
341 | static $k = array( |
||||
342 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, |
||||
343 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, |
||||
344 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, |
||||
345 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, |
||||
346 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, |
||||
347 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, |
||||
348 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, |
||||
349 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 |
||||
350 | ); |
||||
351 | |||||
352 | // Pre-processing |
||||
353 | $length = strlen($m); |
||||
354 | // to round to nearest 56 mod 64, we'll add 64 - (length + (64 - 56)) % 64 |
||||
355 | $m.= str_repeat(chr(0), 64 - (($length + 8) & 0x3F)); |
||||
356 | $m[$length] = chr(0x80); |
||||
357 | // we don't support hashing strings 512MB long |
||||
358 | $m.= pack('N2', 0, $length << 3); |
||||
359 | |||||
360 | // Process the message in successive 512-bit chunks |
||||
361 | $chunks = str_split($m, 64); |
||||
362 | foreach ($chunks as $chunk) { |
||||
363 | $w = array(); |
||||
364 | for ($i = 0; $i < 16; $i++) { |
||||
365 | extract(unpack('Ntemp', $this->_string_shift($chunk, 4))); |
||||
0 ignored issues
–
show
It seems like
unpack('Ntemp', $this->_string_shift($chunk, 4)) can also be of type false ; however, parameter $var_array of extract() does only seem to accept array , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
366 | $w[] = $temp; |
||||
367 | } |
||||
368 | |||||
369 | // Extend the sixteen 32-bit words into sixty-four 32-bit words |
||||
370 | for ($i = 16; $i < 64; $i++) { |
||||
371 | // @codingStandardsIgnoreStart |
||||
372 | $s0 = $this->_rightRotate($w[$i - 15], 7) ^ |
||||
373 | $this->_rightRotate($w[$i - 15], 18) ^ |
||||
374 | $this->_rightShift($w[$i - 15], 3); |
||||
375 | $s1 = $this->_rightRotate($w[$i - 2], 17) ^ |
||||
376 | $this->_rightRotate($w[$i - 2], 19) ^ |
||||
377 | $this->_rightShift($w[$i - 2], 10); |
||||
378 | // @codingStandardsIgnoreEnd |
||||
379 | $w[$i] = $this->_add($w[$i - 16], $s0, $w[$i - 7], $s1); |
||||
380 | } |
||||
381 | |||||
382 | // Initialize hash value for this chunk |
||||
383 | list($a, $b, $c, $d, $e, $f, $g, $h) = $hash; |
||||
384 | |||||
385 | // Main loop |
||||
386 | for ($i = 0; $i < 64; $i++) { |
||||
387 | $s0 = $this->_rightRotate($a, 2) ^ |
||||
388 | $this->_rightRotate($a, 13) ^ |
||||
389 | $this->_rightRotate($a, 22); |
||||
390 | $maj = ($a & $b) ^ |
||||
391 | ($a & $c) ^ |
||||
392 | ($b & $c); |
||||
393 | $t2 = $this->_add($s0, $maj); |
||||
394 | |||||
395 | $s1 = $this->_rightRotate($e, 6) ^ |
||||
396 | $this->_rightRotate($e, 11) ^ |
||||
397 | $this->_rightRotate($e, 25); |
||||
398 | $ch = ($e & $f) ^ |
||||
399 | ($this->_not($e) & $g); |
||||
400 | $t1 = $this->_add($h, $s1, $ch, $k[$i], $w[$i]); |
||||
401 | |||||
402 | $h = $g; |
||||
403 | $g = $f; |
||||
404 | $f = $e; |
||||
405 | $e = $this->_add($d, $t1); |
||||
406 | $d = $c; |
||||
407 | $c = $b; |
||||
408 | $b = $a; |
||||
409 | $a = $this->_add($t1, $t2); |
||||
410 | } |
||||
411 | |||||
412 | // Add this chunk's hash to result so far |
||||
413 | $hash = array( |
||||
414 | $this->_add($hash[0], $a), |
||||
415 | $this->_add($hash[1], $b), |
||||
416 | $this->_add($hash[2], $c), |
||||
417 | $this->_add($hash[3], $d), |
||||
418 | $this->_add($hash[4], $e), |
||||
419 | $this->_add($hash[5], $f), |
||||
420 | $this->_add($hash[6], $g), |
||||
421 | $this->_add($hash[7], $h) |
||||
422 | ); |
||||
423 | } |
||||
424 | |||||
425 | // Produce the final hash value (big-endian) |
||||
426 | return pack('N8', $hash[0], $hash[1], $hash[2], $hash[3], $hash[4], $hash[5], $hash[6], $hash[7]); |
||||
427 | } |
||||
428 | |||||
429 | /** |
||||
430 | * Pure-PHP implementation of SHA384 and SHA512 |
||||
431 | * |
||||
432 | * @access private |
||||
433 | * @param string $m |
||||
434 | */ |
||||
435 | public function _sha512($m) |
||||
436 | { |
||||
437 | static $init384, $init512, $k; |
||||
438 | |||||
439 | if (!isset($k)) { |
||||
440 | // Initialize variables |
||||
441 | $init384 = array( // initial values for SHA384 |
||||
442 | 'cbbb9d5dc1059ed8', '629a292a367cd507', '9159015a3070dd17', '152fecd8f70e5939', |
||||
443 | '67332667ffc00b31', '8eb44a8768581511', 'db0c2e0d64f98fa7', '47b5481dbefa4fa4' |
||||
444 | ); |
||||
445 | $init512 = array( // initial values for SHA512 |
||||
446 | '6a09e667f3bcc908', 'bb67ae8584caa73b', '3c6ef372fe94f82b', 'a54ff53a5f1d36f1', |
||||
447 | '510e527fade682d1', '9b05688c2b3e6c1f', '1f83d9abfb41bd6b', '5be0cd19137e2179' |
||||
448 | ); |
||||
449 | |||||
450 | for ($i = 0; $i < 8; $i++) { |
||||
451 | $init384[$i] = new BigInteger($init384[$i], 16); |
||||
452 | $init384[$i]->setPrecision(64); |
||||
453 | $init512[$i] = new BigInteger($init512[$i], 16); |
||||
454 | $init512[$i]->setPrecision(64); |
||||
455 | } |
||||
456 | |||||
457 | // Initialize table of round constants |
||||
458 | // (first 64 bits of the fractional parts of the cube roots of the first 80 primes 2..409) |
||||
459 | $k = array( |
||||
460 | '428a2f98d728ae22', '7137449123ef65cd', 'b5c0fbcfec4d3b2f', 'e9b5dba58189dbbc', |
||||
461 | '3956c25bf348b538', '59f111f1b605d019', '923f82a4af194f9b', 'ab1c5ed5da6d8118', |
||||
462 | 'd807aa98a3030242', '12835b0145706fbe', '243185be4ee4b28c', '550c7dc3d5ffb4e2', |
||||
463 | '72be5d74f27b896f', '80deb1fe3b1696b1', '9bdc06a725c71235', 'c19bf174cf692694', |
||||
464 | 'e49b69c19ef14ad2', 'efbe4786384f25e3', '0fc19dc68b8cd5b5', '240ca1cc77ac9c65', |
||||
465 | '2de92c6f592b0275', '4a7484aa6ea6e483', '5cb0a9dcbd41fbd4', '76f988da831153b5', |
||||
466 | '983e5152ee66dfab', 'a831c66d2db43210', 'b00327c898fb213f', 'bf597fc7beef0ee4', |
||||
467 | 'c6e00bf33da88fc2', 'd5a79147930aa725', '06ca6351e003826f', '142929670a0e6e70', |
||||
468 | '27b70a8546d22ffc', '2e1b21385c26c926', '4d2c6dfc5ac42aed', '53380d139d95b3df', |
||||
469 | '650a73548baf63de', '766a0abb3c77b2a8', '81c2c92e47edaee6', '92722c851482353b', |
||||
470 | 'a2bfe8a14cf10364', 'a81a664bbc423001', 'c24b8b70d0f89791', 'c76c51a30654be30', |
||||
471 | 'd192e819d6ef5218', 'd69906245565a910', 'f40e35855771202a', '106aa07032bbd1b8', |
||||
472 | '19a4c116b8d2d0c8', '1e376c085141ab53', '2748774cdf8eeb99', '34b0bcb5e19b48a8', |
||||
473 | '391c0cb3c5c95a63', '4ed8aa4ae3418acb', '5b9cca4f7763e373', '682e6ff3d6b2b8a3', |
||||
474 | '748f82ee5defb2fc', '78a5636f43172f60', '84c87814a1f0ab72', '8cc702081a6439ec', |
||||
475 | '90befffa23631e28', 'a4506cebde82bde9', 'bef9a3f7b2c67915', 'c67178f2e372532b', |
||||
476 | 'ca273eceea26619c', 'd186b8c721c0c207', 'eada7dd6cde0eb1e', 'f57d4f7fee6ed178', |
||||
477 | '06f067aa72176fba', '0a637dc5a2c898a6', '113f9804bef90dae', '1b710b35131c471b', |
||||
478 | '28db77f523047d84', '32caab7b40c72493', '3c9ebe0a15c9bebc', '431d67c49c100d4c', |
||||
479 | '4cc5d4becb3e42b6', '597f299cfc657e2a', '5fcb6fab3ad6faec', '6c44198c4a475817' |
||||
480 | ); |
||||
481 | |||||
482 | for ($i = 0; $i < 80; $i++) { |
||||
483 | $k[$i] = new BigInteger($k[$i], 16); |
||||
484 | } |
||||
485 | } |
||||
486 | |||||
487 | $hash = $this->l == 48 ? $init384 : $init512; |
||||
488 | |||||
489 | // Pre-processing |
||||
490 | $length = strlen($m); |
||||
491 | // to round to nearest 112 mod 128, we'll add 128 - (length + (128 - 112)) % 128 |
||||
492 | $m.= str_repeat(chr(0), 128 - (($length + 16) & 0x7F)); |
||||
493 | $m[$length] = chr(0x80); |
||||
494 | // we don't support hashing strings 512MB long |
||||
495 | $m.= pack('N4', 0, 0, 0, $length << 3); |
||||
496 | |||||
497 | // Process the message in successive 1024-bit chunks |
||||
498 | $chunks = str_split($m, 128); |
||||
499 | foreach ($chunks as $chunk) { |
||||
500 | $w = array(); |
||||
501 | for ($i = 0; $i < 16; $i++) { |
||||
502 | $temp = new BigInteger($this->_string_shift($chunk, 8), 256); |
||||
503 | $temp->setPrecision(64); |
||||
504 | $w[] = $temp; |
||||
505 | } |
||||
506 | |||||
507 | // Extend the sixteen 32-bit words into eighty 32-bit words |
||||
508 | for ($i = 16; $i < 80; $i++) { |
||||
509 | $temp = array( |
||||
510 | $w[$i - 15]->bitwise_rightRotate(1), |
||||
511 | $w[$i - 15]->bitwise_rightRotate(8), |
||||
512 | $w[$i - 15]->bitwise_rightShift(7) |
||||
513 | ); |
||||
514 | $s0 = $temp[0]->bitwise_xor($temp[1]); |
||||
515 | $s0 = $s0->bitwise_xor($temp[2]); |
||||
516 | $temp = array( |
||||
517 | $w[$i - 2]->bitwise_rightRotate(19), |
||||
518 | $w[$i - 2]->bitwise_rightRotate(61), |
||||
519 | $w[$i - 2]->bitwise_rightShift(6) |
||||
520 | ); |
||||
521 | $s1 = $temp[0]->bitwise_xor($temp[1]); |
||||
522 | $s1 = $s1->bitwise_xor($temp[2]); |
||||
523 | $w[$i] = $w[$i - 16]->copy(); |
||||
524 | $w[$i] = $w[$i]->add($s0); |
||||
525 | $w[$i] = $w[$i]->add($w[$i - 7]); |
||||
526 | $w[$i] = $w[$i]->add($s1); |
||||
527 | } |
||||
528 | |||||
529 | // Initialize hash value for this chunk |
||||
530 | $a = $hash[0]->copy(); |
||||
531 | $b = $hash[1]->copy(); |
||||
532 | $c = $hash[2]->copy(); |
||||
533 | $d = $hash[3]->copy(); |
||||
534 | $e = $hash[4]->copy(); |
||||
535 | $f = $hash[5]->copy(); |
||||
536 | $g = $hash[6]->copy(); |
||||
537 | $h = $hash[7]->copy(); |
||||
538 | |||||
539 | // Main loop |
||||
540 | for ($i = 0; $i < 80; $i++) { |
||||
541 | $temp = array( |
||||
542 | $a->bitwise_rightRotate(28), |
||||
543 | $a->bitwise_rightRotate(34), |
||||
544 | $a->bitwise_rightRotate(39) |
||||
545 | ); |
||||
546 | $s0 = $temp[0]->bitwise_xor($temp[1]); |
||||
547 | $s0 = $s0->bitwise_xor($temp[2]); |
||||
548 | $temp = array( |
||||
549 | $a->bitwise_and($b), |
||||
550 | $a->bitwise_and($c), |
||||
551 | $b->bitwise_and($c) |
||||
552 | ); |
||||
553 | $maj = $temp[0]->bitwise_xor($temp[1]); |
||||
554 | $maj = $maj->bitwise_xor($temp[2]); |
||||
555 | $t2 = $s0->add($maj); |
||||
556 | |||||
557 | $temp = array( |
||||
558 | $e->bitwise_rightRotate(14), |
||||
559 | $e->bitwise_rightRotate(18), |
||||
560 | $e->bitwise_rightRotate(41) |
||||
561 | ); |
||||
562 | $s1 = $temp[0]->bitwise_xor($temp[1]); |
||||
563 | $s1 = $s1->bitwise_xor($temp[2]); |
||||
564 | $temp = array( |
||||
565 | $e->bitwise_and($f), |
||||
566 | $g->bitwise_and($e->bitwise_not()) |
||||
567 | ); |
||||
568 | $ch = $temp[0]->bitwise_xor($temp[1]); |
||||
569 | $t1 = $h->add($s1); |
||||
570 | $t1 = $t1->add($ch); |
||||
571 | $t1 = $t1->add($k[$i]); |
||||
572 | $t1 = $t1->add($w[$i]); |
||||
573 | |||||
574 | $h = $g->copy(); |
||||
575 | $g = $f->copy(); |
||||
576 | $f = $e->copy(); |
||||
577 | $e = $d->add($t1); |
||||
578 | $d = $c->copy(); |
||||
579 | $c = $b->copy(); |
||||
580 | $b = $a->copy(); |
||||
581 | $a = $t1->add($t2); |
||||
582 | } |
||||
583 | |||||
584 | // Add this chunk's hash to result so far |
||||
585 | $hash = array( |
||||
586 | $hash[0]->add($a), |
||||
587 | $hash[1]->add($b), |
||||
588 | $hash[2]->add($c), |
||||
589 | $hash[3]->add($d), |
||||
590 | $hash[4]->add($e), |
||||
591 | $hash[5]->add($f), |
||||
592 | $hash[6]->add($g), |
||||
593 | $hash[7]->add($h) |
||||
594 | ); |
||||
595 | } |
||||
596 | |||||
597 | // Produce the final hash value (big-endian) |
||||
598 | // (\phpseclib\Crypt\Hash::hash() trims the output for hashes but not for HMACs. as such, we trim the output here) |
||||
599 | $temp = $hash[0]->toBytes() . $hash[1]->toBytes() . $hash[2]->toBytes() . $hash[3]->toBytes() . |
||||
600 | $hash[4]->toBytes() . $hash[5]->toBytes(); |
||||
601 | if ($this->l != 48) { |
||||
602 | $temp.= $hash[6]->toBytes() . $hash[7]->toBytes(); |
||||
603 | } |
||||
604 | |||||
605 | return $temp; |
||||
606 | } |
||||
607 | |||||
608 | /** |
||||
609 | * Right Rotate |
||||
610 | * |
||||
611 | * @access private |
||||
612 | * @param int $int |
||||
613 | * @param int $amt |
||||
614 | * @see self::_sha256() |
||||
615 | * @return int |
||||
616 | */ |
||||
617 | public function _rightRotate($int, $amt) |
||||
618 | { |
||||
619 | $invamt = 32 - $amt; |
||||
620 | $mask = (1 << $invamt) - 1; |
||||
621 | return (($int << $invamt) & 0xFFFFFFFF) | (($int >> $amt) & $mask); |
||||
622 | } |
||||
623 | |||||
624 | /** |
||||
625 | * Right Shift |
||||
626 | * |
||||
627 | * @access private |
||||
628 | * @param int $int |
||||
629 | * @param int $amt |
||||
630 | * @see self::_sha256() |
||||
631 | * @return int |
||||
632 | */ |
||||
633 | public function _rightShift($int, $amt) |
||||
634 | { |
||||
635 | $mask = (1 << (32 - $amt)) - 1; |
||||
636 | return ($int >> $amt) & $mask; |
||||
637 | } |
||||
638 | |||||
639 | /** |
||||
640 | * Not |
||||
641 | * |
||||
642 | * @access private |
||||
643 | * @param int $int |
||||
644 | * @see self::_sha256() |
||||
645 | * @return int |
||||
646 | */ |
||||
647 | public function _not($int) |
||||
648 | { |
||||
649 | return ~$int & 0xFFFFFFFF; |
||||
650 | } |
||||
651 | |||||
652 | /** |
||||
653 | * Add |
||||
654 | * |
||||
655 | * _sha256() adds multiple unsigned 32-bit integers. Since PHP doesn't support unsigned integers and since the |
||||
656 | * possibility of overflow exists, care has to be taken. BigInteger could be used but this should be faster. |
||||
657 | * |
||||
658 | * @param int $... |
||||
659 | * @return int |
||||
660 | * @see self::_sha256() |
||||
661 | * @access private |
||||
662 | */ |
||||
663 | public function _add() |
||||
664 | { |
||||
665 | static $mod; |
||||
666 | if (!isset($mod)) { |
||||
667 | $mod = pow(2, 32); |
||||
668 | } |
||||
669 | |||||
670 | $result = 0; |
||||
671 | $arguments = func_get_args(); |
||||
672 | foreach ($arguments as $argument) { |
||||
673 | $result+= $argument < 0 ? ($argument & 0x7FFFFFFF) + 0x80000000 : $argument; |
||||
674 | } |
||||
675 | |||||
676 | return fmod($result, $mod); |
||||
677 | } |
||||
678 | |||||
679 | /** |
||||
680 | * String Shift |
||||
681 | * |
||||
682 | * Inspired by array_shift |
||||
683 | * |
||||
684 | * @param string $string |
||||
685 | * @param int $index |
||||
686 | * @return string |
||||
687 | * @access private |
||||
688 | */ |
||||
689 | public function _string_shift(&$string, $index = 1) |
||||
690 | { |
||||
691 | $substr = substr($string, 0, $index); |
||||
692 | $string = substr($string, $index); |
||||
693 | return $substr; |
||||
694 | } |
||||
695 | } |
||||
696 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.