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; |
|
|
|
|
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); |
|
|
|
|
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'); |
|
|
|
|
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); |
|
|
|
|
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); |
|
|
|
|
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))); |
|
|
|
|
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.