Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 381 |
|
0.00% |
0 / 16 |
CRAP | |
0.00% |
0 / 1 |
| Crypt_Hash | |
0.00% |
0 / 378 |
|
0.00% |
0 / 16 |
8372 | |
0.00% |
0 / 1 |
| Crypt_Hash | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
30 | |||
| setKey | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| getHash | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| setHash | |
0.00% |
0 / 77 |
|
0.00% |
0 / 1 |
1482 | |||
| hash | |
0.00% |
0 / 26 |
|
0.00% |
0 / 1 |
132 | |||
| getLength | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| _md5 | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| _sha1 | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| _md2 | |
0.00% |
0 / 42 |
|
0.00% |
0 / 1 |
56 | |||
| _sha256 | |
0.00% |
0 / 67 |
|
0.00% |
0 / 1 |
42 | |||
| _sha512 | |
0.00% |
0 / 135 |
|
0.00% |
0 / 1 |
132 | |||
| _rightRotate | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
| _rightShift | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
| _not | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| _add | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
20 | |||
| _string_shift | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
| 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 | * md2, md5, md5-96, sha1, sha1-96, sha256, sha256-96, sha384, and sha512, sha512-96 |
| 9 | * |
| 10 | * If {@link Crypt_Hash::setKey() setKey()} is called, {@link Crypt_Hash::hash() hash()} will return the HMAC as opposed to |
| 11 | * the hash. If no valid algorithm is provided, sha1 will be used. |
| 12 | * |
| 13 | * PHP versions 4 and 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 'Crypt/Hash.php'; |
| 22 | * |
| 23 | * $hash = new Crypt_Hash('sha1'); |
| 24 | * |
| 25 | * $hash->setKey('abcdefg'); |
| 26 | * |
| 27 | * echo base64_encode($hash->hash('abcdefg')); |
| 28 | * ?> |
| 29 | * </code> |
| 30 | * |
| 31 | * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy |
| 32 | * of this software and associated documentation files (the "Software"), to deal |
| 33 | * in the Software without restriction, including without limitation the rights |
| 34 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 35 | * copies of the Software, and to permit persons to whom the Software is |
| 36 | * furnished to do so, subject to the following conditions: |
| 37 | * |
| 38 | * The above copyright notice and this permission notice shall be included in |
| 39 | * all copies or substantial portions of the Software. |
| 40 | * |
| 41 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 42 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 43 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 44 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 45 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 46 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| 47 | * THE SOFTWARE. |
| 48 | * |
| 49 | * @category Crypt |
| 50 | * @package Crypt_Hash |
| 51 | * @author Jim Wigginton <terrafrost@php.net> |
| 52 | * @copyright 2007 Jim Wigginton |
| 53 | * @license http://www.opensource.org/licenses/mit-license.html MIT License |
| 54 | * @link http://phpseclib.sourceforge.net |
| 55 | */ |
| 56 | |
| 57 | /**#@+ |
| 58 | * @access private |
| 59 | * @see Crypt_Hash::Crypt_Hash() |
| 60 | */ |
| 61 | /** |
| 62 | * Toggles the internal implementation |
| 63 | */ |
| 64 | define('CRYPT_HASH_MODE_INTERNAL', 1); |
| 65 | /** |
| 66 | * Toggles the mhash() implementation, which has been deprecated on PHP 5.3.0+. |
| 67 | */ |
| 68 | define('CRYPT_HASH_MODE_MHASH', 2); |
| 69 | /** |
| 70 | * Toggles the hash() implementation, which works on PHP 5.1.2+. |
| 71 | */ |
| 72 | define('CRYPT_HASH_MODE_HASH', 3); |
| 73 | /**#@-*/ |
| 74 | |
| 75 | /** |
| 76 | * Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions. |
| 77 | * |
| 78 | * @package Crypt_Hash |
| 79 | * @author Jim Wigginton <terrafrost@php.net> |
| 80 | * @access public |
| 81 | */ |
| 82 | class Crypt_Hash |
| 83 | { |
| 84 | /** |
| 85 | * Hash Parameter |
| 86 | * |
| 87 | * @see Crypt_Hash::setHash() |
| 88 | * @var Integer |
| 89 | * @access private |
| 90 | */ |
| 91 | var $hashParam; |
| 92 | |
| 93 | /** |
| 94 | * Byte-length of compression blocks / key (Internal HMAC) |
| 95 | * |
| 96 | * @see Crypt_Hash::setAlgorithm() |
| 97 | * @var Integer |
| 98 | * @access private |
| 99 | */ |
| 100 | var $b; |
| 101 | |
| 102 | /** |
| 103 | * Byte-length of hash output (Internal HMAC) |
| 104 | * |
| 105 | * @see Crypt_Hash::setHash() |
| 106 | * @var Integer |
| 107 | * @access private |
| 108 | */ |
| 109 | var $l = false; |
| 110 | |
| 111 | /** |
| 112 | * Hash Algorithm |
| 113 | * |
| 114 | * @see Crypt_Hash::setHash() |
| 115 | * @var String |
| 116 | * @access private |
| 117 | */ |
| 118 | var $hash; |
| 119 | |
| 120 | /** |
| 121 | * Key |
| 122 | * |
| 123 | * @see Crypt_Hash::setKey() |
| 124 | * @var String |
| 125 | * @access private |
| 126 | */ |
| 127 | var $key = false; |
| 128 | |
| 129 | /** |
| 130 | * Outer XOR (Internal HMAC) |
| 131 | * |
| 132 | * @see Crypt_Hash::setKey() |
| 133 | * @var String |
| 134 | * @access private |
| 135 | */ |
| 136 | var $opad; |
| 137 | |
| 138 | /** |
| 139 | * Inner XOR (Internal HMAC) |
| 140 | * |
| 141 | * @see Crypt_Hash::setKey() |
| 142 | * @var String |
| 143 | * @access private |
| 144 | */ |
| 145 | var $ipad; |
| 146 | |
| 147 | /** |
| 148 | * Default Constructor. |
| 149 | * |
| 150 | * @param optional String $hash |
| 151 | * @return Crypt_Hash |
| 152 | * @access public |
| 153 | */ |
| 154 | function Crypt_Hash($hash = 'sha1') |
| 155 | { |
| 156 | if (!defined('CRYPT_HASH_MODE')) { |
| 157 | switch (true) { |
| 158 | case extension_loaded('hash'): |
| 159 | define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_HASH); |
| 160 | break; |
| 161 | case extension_loaded('mhash'): |
| 162 | define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_MHASH); |
| 163 | break; |
| 164 | default: |
| 165 | define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_INTERNAL); |
| 166 | } |
| 167 | } |
| 168 | |
| 169 | $this->setHash($hash); |
| 170 | } |
| 171 | |
| 172 | /** |
| 173 | * Sets the key for HMACs |
| 174 | * |
| 175 | * Keys can be of any length. |
| 176 | * |
| 177 | * @access public |
| 178 | * @param optional String $key |
| 179 | */ |
| 180 | function setKey($key = false) |
| 181 | { |
| 182 | $this->key = $key; |
| 183 | } |
| 184 | |
| 185 | /** |
| 186 | * Gets the hash function. |
| 187 | * |
| 188 | * As set by the constructor or by the setHash() method. |
| 189 | * |
| 190 | * @access public |
| 191 | * @return String |
| 192 | */ |
| 193 | function getHash() |
| 194 | { |
| 195 | return $this->hashParam; |
| 196 | } |
| 197 | |
| 198 | /** |
| 199 | * Sets the hash function. |
| 200 | * |
| 201 | * @access public |
| 202 | * @param String $hash |
| 203 | */ |
| 204 | function setHash($hash) |
| 205 | { |
| 206 | $this->hashParam = $hash = strtolower($hash); |
| 207 | switch ($hash) { |
| 208 | case 'md5-96': |
| 209 | case 'sha1-96': |
| 210 | case 'sha256-96': |
| 211 | case 'sha512-96': |
| 212 | $hash = substr($hash, 0, -3); |
| 213 | $this->l = 12; // 96 / 8 = 12 |
| 214 | break; |
| 215 | case 'md2': |
| 216 | case 'md5': |
| 217 | $this->l = 16; |
| 218 | break; |
| 219 | case 'sha1': |
| 220 | $this->l = 20; |
| 221 | break; |
| 222 | case 'sha256': |
| 223 | $this->l = 32; |
| 224 | break; |
| 225 | case 'sha384': |
| 226 | $this->l = 48; |
| 227 | break; |
| 228 | case 'sha512': |
| 229 | $this->l = 64; |
| 230 | } |
| 231 | |
| 232 | switch ($hash) { |
| 233 | case 'md2': |
| 234 | $mode = CRYPT_HASH_MODE == CRYPT_HASH_MODE_HASH && in_array('md2', hash_algos()) ? |
| 235 | CRYPT_HASH_MODE_HASH : CRYPT_HASH_MODE_INTERNAL; |
| 236 | break; |
| 237 | case 'sha384': |
| 238 | case 'sha512': |
| 239 | $mode = CRYPT_HASH_MODE == CRYPT_HASH_MODE_MHASH ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE; |
| 240 | break; |
| 241 | default: |
| 242 | $mode = CRYPT_HASH_MODE; |
| 243 | } |
| 244 | |
| 245 | switch ($mode) { |
| 246 | case CRYPT_HASH_MODE_MHASH: |
| 247 | switch ($hash) { |
| 248 | case 'md5': |
| 249 | $this->hash = MHASH_MD5; |
| 250 | break; |
| 251 | case 'sha256': |
| 252 | $this->hash = MHASH_SHA256; |
| 253 | break; |
| 254 | case 'sha1': |
| 255 | default: |
| 256 | $this->hash = MHASH_SHA1; |
| 257 | } |
| 258 | return; |
| 259 | case CRYPT_HASH_MODE_HASH: |
| 260 | switch ($hash) { |
| 261 | case 'md5': |
| 262 | $this->hash = 'md5'; |
| 263 | return; |
| 264 | case 'md2': |
| 265 | case 'sha256': |
| 266 | case 'sha384': |
| 267 | case 'sha512': |
| 268 | $this->hash = $hash; |
| 269 | return; |
| 270 | case 'sha1': |
| 271 | default: |
| 272 | $this->hash = 'sha1'; |
| 273 | } |
| 274 | return; |
| 275 | } |
| 276 | |
| 277 | switch ($hash) { |
| 278 | case 'md2': |
| 279 | $this->b = 16; |
| 280 | $this->hash = array($this, '_md2'); |
| 281 | break; |
| 282 | case 'md5': |
| 283 | $this->b = 64; |
| 284 | $this->hash = array($this, '_md5'); |
| 285 | break; |
| 286 | case 'sha256': |
| 287 | $this->b = 64; |
| 288 | $this->hash = array($this, '_sha256'); |
| 289 | break; |
| 290 | case 'sha384': |
| 291 | case 'sha512': |
| 292 | $this->b = 128; |
| 293 | $this->hash = array($this, '_sha512'); |
| 294 | break; |
| 295 | case 'sha1': |
| 296 | default: |
| 297 | $this->b = 64; |
| 298 | $this->hash = array($this, '_sha1'); |
| 299 | } |
| 300 | |
| 301 | $this->ipad = str_repeat(chr(0x36), $this->b); |
| 302 | $this->opad = str_repeat(chr(0x5C), $this->b); |
| 303 | } |
| 304 | |
| 305 | /** |
| 306 | * Compute the HMAC. |
| 307 | * |
| 308 | * @access public |
| 309 | * @param String $text |
| 310 | * @return String |
| 311 | */ |
| 312 | function hash($text) |
| 313 | { |
| 314 | $mode = is_array($this->hash) ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE; |
| 315 | |
| 316 | if (!empty($this->key) || is_string($this->key)) { |
| 317 | switch ($mode) { |
| 318 | case CRYPT_HASH_MODE_MHASH: |
| 319 | $output = mhash($this->hash, $text, $this->key); |
| 320 | break; |
| 321 | case CRYPT_HASH_MODE_HASH: |
| 322 | $output = hash_hmac($this->hash, $text, $this->key, true); |
| 323 | break; |
| 324 | case CRYPT_HASH_MODE_INTERNAL: |
| 325 | /* "Applications that use keys longer than B bytes will first hash the key using H and then use the |
| 326 | resultant L byte string as the actual key to HMAC." |
| 327 | |
| 328 | -- http://tools.ietf.org/html/rfc2104#section-2 */ |
| 329 | $key = strlen($this->key) > $this->b ? call_user_func($this->hash, $this->key) : $this->key; |
| 330 | |
| 331 | $key = str_pad($key, $this->b, chr(0)); // step 1 |
| 332 | $temp = $this->ipad ^ $key; // step 2 |
| 333 | $temp .= $text; // step 3 |
| 334 | $temp = call_user_func($this->hash, $temp); // step 4 |
| 335 | $output = $this->opad ^ $key; // step 5 |
| 336 | $output.= $temp; // step 6 |
| 337 | $output = call_user_func($this->hash, $output); // step 7 |
| 338 | } |
| 339 | } else { |
| 340 | switch ($mode) { |
| 341 | case CRYPT_HASH_MODE_MHASH: |
| 342 | $output = mhash($this->hash, $text); |
| 343 | break; |
| 344 | case CRYPT_HASH_MODE_HASH: |
| 345 | $output = hash($this->hash, $text, true); |
| 346 | break; |
| 347 | case CRYPT_HASH_MODE_INTERNAL: |
| 348 | $output = call_user_func($this->hash, $text); |
| 349 | } |
| 350 | } |
| 351 | |
| 352 | return substr($output, 0, $this->l); |
| 353 | } |
| 354 | |
| 355 | /** |
| 356 | * Returns the hash length (in bytes) |
| 357 | * |
| 358 | * @access public |
| 359 | * @return Integer |
| 360 | */ |
| 361 | function getLength() |
| 362 | { |
| 363 | return $this->l; |
| 364 | } |
| 365 | |
| 366 | /** |
| 367 | * Wrapper for MD5 |
| 368 | * |
| 369 | * @access private |
| 370 | * @param String $m |
| 371 | */ |
| 372 | function _md5($m) |
| 373 | { |
| 374 | return pack('H*', md5($m)); |
| 375 | } |
| 376 | |
| 377 | /** |
| 378 | * Wrapper for SHA1 |
| 379 | * |
| 380 | * @access private |
| 381 | * @param String $m |
| 382 | */ |
| 383 | function _sha1($m) |
| 384 | { |
| 385 | return pack('H*', sha1($m)); |
| 386 | } |
| 387 | |
| 388 | /** |
| 389 | * Pure-PHP implementation of MD2 |
| 390 | * |
| 391 | * See {@link http://tools.ietf.org/html/rfc1319 RFC1319}. |
| 392 | * |
| 393 | * @access private |
| 394 | * @param String $m |
| 395 | */ |
| 396 | function _md2($m) |
| 397 | { |
| 398 | static $s = array( |
| 399 | 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, |
| 400 | 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, |
| 401 | 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, |
| 402 | 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, |
| 403 | 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, |
| 404 | 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, |
| 405 | 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, |
| 406 | 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, |
| 407 | 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, |
| 408 | 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, |
| 409 | 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, |
| 410 | 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, |
| 411 | 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, |
| 412 | 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, |
| 413 | 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233, |
| 414 | 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, |
| 415 | 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, |
| 416 | 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 |
| 417 | ); |
| 418 | |
| 419 | // Step 1. Append Padding Bytes |
| 420 | $pad = 16 - (strlen($m) & 0xF); |
| 421 | $m.= str_repeat(chr($pad), $pad); |
| 422 | |
| 423 | $length = strlen($m); |
| 424 | |
| 425 | // Step 2. Append Checksum |
| 426 | $c = str_repeat(chr(0), 16); |
| 427 | $l = chr(0); |
| 428 | for ($i = 0; $i < $length; $i+= 16) { |
| 429 | for ($j = 0; $j < 16; $j++) { |
| 430 | // RFC1319 incorrectly states that C[j] should be set to S[c xor L] |
| 431 | //$c[$j] = chr($s[ord($m[$i + $j] ^ $l)]); |
| 432 | // per <http://www.rfc-editor.org/errata_search.php?rfc=1319>, however, C[j] should be set to S[c xor L] xor C[j] |
| 433 | $c[$j] = chr($s[ord($m[$i + $j] ^ $l)] ^ ord($c[$j])); |
| 434 | $l = $c[$j]; |
| 435 | } |
| 436 | } |
| 437 | $m.= $c; |
| 438 | |
| 439 | $length+= 16; |
| 440 | |
| 441 | // Step 3. Initialize MD Buffer |
| 442 | $x = str_repeat(chr(0), 48); |
| 443 | |
| 444 | // Step 4. Process Message in 16-Byte Blocks |
| 445 | for ($i = 0; $i < $length; $i+= 16) { |
| 446 | for ($j = 0; $j < 16; $j++) { |
| 447 | $x[$j + 16] = $m[$i + $j]; |
| 448 | $x[$j + 32] = $x[$j + 16] ^ $x[$j]; |
| 449 | } |
| 450 | $t = chr(0); |
| 451 | for ($j = 0; $j < 18; $j++) { |
| 452 | for ($k = 0; $k < 48; $k++) { |
| 453 | $x[$k] = $t = $x[$k] ^ chr($s[ord($t)]); |
| 454 | //$t = $x[$k] = $x[$k] ^ chr($s[ord($t)]); |
| 455 | } |
| 456 | $t = chr(ord($t) + $j); |
| 457 | } |
| 458 | } |
| 459 | |
| 460 | // Step 5. Output |
| 461 | return substr($x, 0, 16); |
| 462 | } |
| 463 | |
| 464 | /** |
| 465 | * Pure-PHP implementation of SHA256 |
| 466 | * |
| 467 | * 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}. |
| 468 | * |
| 469 | * @access private |
| 470 | * @param String $m |
| 471 | */ |
| 472 | function _sha256($m) |
| 473 | { |
| 474 | if (extension_loaded('suhosin')) { |
| 475 | return pack('H*', sha256($m)); |
| 476 | } |
| 477 | |
| 478 | // Initialize variables |
| 479 | $hash = array( |
| 480 | 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 |
| 481 | ); |
| 482 | // Initialize table of round constants |
| 483 | // (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311) |
| 484 | static $k = array( |
| 485 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, |
| 486 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, |
| 487 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, |
| 488 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, |
| 489 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, |
| 490 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, |
| 491 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, |
| 492 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 |
| 493 | ); |
| 494 | |
| 495 | // Pre-processing |
| 496 | $length = strlen($m); |
| 497 | // to round to nearest 56 mod 64, we'll add 64 - (length + (64 - 56)) % 64 |
| 498 | $m.= str_repeat(chr(0), 64 - (($length + 8) & 0x3F)); |
| 499 | $m[$length] = chr(0x80); |
| 500 | // we don't support hashing strings 512MB long |
| 501 | $m.= pack('N2', 0, $length << 3); |
| 502 | |
| 503 | // Process the message in successive 512-bit chunks |
| 504 | $chunks = str_split($m, 64); |
| 505 | foreach ($chunks as $chunk) { |
| 506 | $w = array(); |
| 507 | for ($i = 0; $i < 16; $i++) { |
| 508 | extract(unpack('Ntemp', $this->_string_shift($chunk, 4))); |
| 509 | $w[] = $temp; |
| 510 | } |
| 511 | |
| 512 | // Extend the sixteen 32-bit words into sixty-four 32-bit words |
| 513 | for ($i = 16; $i < 64; $i++) { |
| 514 | // @codingStandardsIgnoreStart |
| 515 | $s0 = $this->_rightRotate($w[$i - 15], 7) ^ |
| 516 | $this->_rightRotate($w[$i - 15], 18) ^ |
| 517 | $this->_rightShift( $w[$i - 15], 3); |
| 518 | $s1 = $this->_rightRotate($w[$i - 2], 17) ^ |
| 519 | $this->_rightRotate($w[$i - 2], 19) ^ |
| 520 | $this->_rightShift( $w[$i - 2], 10); |
| 521 | // @codingStandardsIgnoreEnd |
| 522 | $w[$i] = $this->_add($w[$i - 16], $s0, $w[$i - 7], $s1); |
| 523 | |
| 524 | } |
| 525 | |
| 526 | // Initialize hash value for this chunk |
| 527 | list($a, $b, $c, $d, $e, $f, $g, $h) = $hash; |
| 528 | |
| 529 | // Main loop |
| 530 | for ($i = 0; $i < 64; $i++) { |
| 531 | $s0 = $this->_rightRotate($a, 2) ^ |
| 532 | $this->_rightRotate($a, 13) ^ |
| 533 | $this->_rightRotate($a, 22); |
| 534 | $maj = ($a & $b) ^ |
| 535 | ($a & $c) ^ |
| 536 | ($b & $c); |
| 537 | $t2 = $this->_add($s0, $maj); |
| 538 | |
| 539 | $s1 = $this->_rightRotate($e, 6) ^ |
| 540 | $this->_rightRotate($e, 11) ^ |
| 541 | $this->_rightRotate($e, 25); |
| 542 | $ch = ($e & $f) ^ |
| 543 | ($this->_not($e) & $g); |
| 544 | $t1 = $this->_add($h, $s1, $ch, $k[$i], $w[$i]); |
| 545 | |
| 546 | $h = $g; |
| 547 | $g = $f; |
| 548 | $f = $e; |
| 549 | $e = $this->_add($d, $t1); |
| 550 | $d = $c; |
| 551 | $c = $b; |
| 552 | $b = $a; |
| 553 | $a = $this->_add($t1, $t2); |
| 554 | } |
| 555 | |
| 556 | // Add this chunk's hash to result so far |
| 557 | $hash = array( |
| 558 | $this->_add($hash[0], $a), |
| 559 | $this->_add($hash[1], $b), |
| 560 | $this->_add($hash[2], $c), |
| 561 | $this->_add($hash[3], $d), |
| 562 | $this->_add($hash[4], $e), |
| 563 | $this->_add($hash[5], $f), |
| 564 | $this->_add($hash[6], $g), |
| 565 | $this->_add($hash[7], $h) |
| 566 | ); |
| 567 | } |
| 568 | |
| 569 | // Produce the final hash value (big-endian) |
| 570 | return pack('N8', $hash[0], $hash[1], $hash[2], $hash[3], $hash[4], $hash[5], $hash[6], $hash[7]); |
| 571 | } |
| 572 | |
| 573 | /** |
| 574 | * Pure-PHP implementation of SHA384 and SHA512 |
| 575 | * |
| 576 | * @access private |
| 577 | * @param String $m |
| 578 | */ |
| 579 | function _sha512($m) |
| 580 | { |
| 581 | if (!class_exists('Math_BigInteger')) { |
| 582 | include_once 'Math/BigInteger.php'; |
| 583 | } |
| 584 | |
| 585 | static $init384, $init512, $k; |
| 586 | |
| 587 | if (!isset($k)) { |
| 588 | // Initialize variables |
| 589 | $init384 = array( // initial values for SHA384 |
| 590 | 'cbbb9d5dc1059ed8', '629a292a367cd507', '9159015a3070dd17', '152fecd8f70e5939', |
| 591 | '67332667ffc00b31', '8eb44a8768581511', 'db0c2e0d64f98fa7', '47b5481dbefa4fa4' |
| 592 | ); |
| 593 | $init512 = array( // initial values for SHA512 |
| 594 | '6a09e667f3bcc908', 'bb67ae8584caa73b', '3c6ef372fe94f82b', 'a54ff53a5f1d36f1', |
| 595 | '510e527fade682d1', '9b05688c2b3e6c1f', '1f83d9abfb41bd6b', '5be0cd19137e2179' |
| 596 | ); |
| 597 | |
| 598 | for ($i = 0; $i < 8; $i++) { |
| 599 | $init384[$i] = new Math_BigInteger($init384[$i], 16); |
| 600 | $init384[$i]->setPrecision(64); |
| 601 | $init512[$i] = new Math_BigInteger($init512[$i], 16); |
| 602 | $init512[$i]->setPrecision(64); |
| 603 | } |
| 604 | |
| 605 | // Initialize table of round constants |
| 606 | // (first 64 bits of the fractional parts of the cube roots of the first 80 primes 2..409) |
| 607 | $k = array( |
| 608 | '428a2f98d728ae22', '7137449123ef65cd', 'b5c0fbcfec4d3b2f', 'e9b5dba58189dbbc', |
| 609 | '3956c25bf348b538', '59f111f1b605d019', '923f82a4af194f9b', 'ab1c5ed5da6d8118', |
| 610 | 'd807aa98a3030242', '12835b0145706fbe', '243185be4ee4b28c', '550c7dc3d5ffb4e2', |
| 611 | '72be5d74f27b896f', '80deb1fe3b1696b1', '9bdc06a725c71235', 'c19bf174cf692694', |
| 612 | 'e49b69c19ef14ad2', 'efbe4786384f25e3', '0fc19dc68b8cd5b5', '240ca1cc77ac9c65', |
| 613 | '2de92c6f592b0275', '4a7484aa6ea6e483', '5cb0a9dcbd41fbd4', '76f988da831153b5', |
| 614 | '983e5152ee66dfab', 'a831c66d2db43210', 'b00327c898fb213f', 'bf597fc7beef0ee4', |
| 615 | 'c6e00bf33da88fc2', 'd5a79147930aa725', '06ca6351e003826f', '142929670a0e6e70', |
| 616 | '27b70a8546d22ffc', '2e1b21385c26c926', '4d2c6dfc5ac42aed', '53380d139d95b3df', |
| 617 | '650a73548baf63de', '766a0abb3c77b2a8', '81c2c92e47edaee6', '92722c851482353b', |
| 618 | 'a2bfe8a14cf10364', 'a81a664bbc423001', 'c24b8b70d0f89791', 'c76c51a30654be30', |
| 619 | 'd192e819d6ef5218', 'd69906245565a910', 'f40e35855771202a', '106aa07032bbd1b8', |
| 620 | '19a4c116b8d2d0c8', '1e376c085141ab53', '2748774cdf8eeb99', '34b0bcb5e19b48a8', |
| 621 | '391c0cb3c5c95a63', '4ed8aa4ae3418acb', '5b9cca4f7763e373', '682e6ff3d6b2b8a3', |
| 622 | '748f82ee5defb2fc', '78a5636f43172f60', '84c87814a1f0ab72', '8cc702081a6439ec', |
| 623 | '90befffa23631e28', 'a4506cebde82bde9', 'bef9a3f7b2c67915', 'c67178f2e372532b', |
| 624 | 'ca273eceea26619c', 'd186b8c721c0c207', 'eada7dd6cde0eb1e', 'f57d4f7fee6ed178', |
| 625 | '06f067aa72176fba', '0a637dc5a2c898a6', '113f9804bef90dae', '1b710b35131c471b', |
| 626 | '28db77f523047d84', '32caab7b40c72493', '3c9ebe0a15c9bebc', '431d67c49c100d4c', |
| 627 | '4cc5d4becb3e42b6', '597f299cfc657e2a', '5fcb6fab3ad6faec', '6c44198c4a475817' |
| 628 | ); |
| 629 | |
| 630 | for ($i = 0; $i < 80; $i++) { |
| 631 | $k[$i] = new Math_BigInteger($k[$i], 16); |
| 632 | } |
| 633 | } |
| 634 | |
| 635 | $hash = $this->l == 48 ? $init384 : $init512; |
| 636 | |
| 637 | // Pre-processing |
| 638 | $length = strlen($m); |
| 639 | // to round to nearest 112 mod 128, we'll add 128 - (length + (128 - 112)) % 128 |
| 640 | $m.= str_repeat(chr(0), 128 - (($length + 16) & 0x7F)); |
| 641 | $m[$length] = chr(0x80); |
| 642 | // we don't support hashing strings 512MB long |
| 643 | $m.= pack('N4', 0, 0, 0, $length << 3); |
| 644 | |
| 645 | // Process the message in successive 1024-bit chunks |
| 646 | $chunks = str_split($m, 128); |
| 647 | foreach ($chunks as $chunk) { |
| 648 | $w = array(); |
| 649 | for ($i = 0; $i < 16; $i++) { |
| 650 | $temp = new Math_BigInteger($this->_string_shift($chunk, 8), 256); |
| 651 | $temp->setPrecision(64); |
| 652 | $w[] = $temp; |
| 653 | } |
| 654 | |
| 655 | // Extend the sixteen 32-bit words into eighty 32-bit words |
| 656 | for ($i = 16; $i < 80; $i++) { |
| 657 | $temp = array( |
| 658 | $w[$i - 15]->bitwise_rightRotate(1), |
| 659 | $w[$i - 15]->bitwise_rightRotate(8), |
| 660 | $w[$i - 15]->bitwise_rightShift(7) |
| 661 | ); |
| 662 | $s0 = $temp[0]->bitwise_xor($temp[1]); |
| 663 | $s0 = $s0->bitwise_xor($temp[2]); |
| 664 | $temp = array( |
| 665 | $w[$i - 2]->bitwise_rightRotate(19), |
| 666 | $w[$i - 2]->bitwise_rightRotate(61), |
| 667 | $w[$i - 2]->bitwise_rightShift(6) |
| 668 | ); |
| 669 | $s1 = $temp[0]->bitwise_xor($temp[1]); |
| 670 | $s1 = $s1->bitwise_xor($temp[2]); |
| 671 | $w[$i] = $w[$i - 16]->copy(); |
| 672 | $w[$i] = $w[$i]->add($s0); |
| 673 | $w[$i] = $w[$i]->add($w[$i - 7]); |
| 674 | $w[$i] = $w[$i]->add($s1); |
| 675 | } |
| 676 | |
| 677 | // Initialize hash value for this chunk |
| 678 | $a = $hash[0]->copy(); |
| 679 | $b = $hash[1]->copy(); |
| 680 | $c = $hash[2]->copy(); |
| 681 | $d = $hash[3]->copy(); |
| 682 | $e = $hash[4]->copy(); |
| 683 | $f = $hash[5]->copy(); |
| 684 | $g = $hash[6]->copy(); |
| 685 | $h = $hash[7]->copy(); |
| 686 | |
| 687 | // Main loop |
| 688 | for ($i = 0; $i < 80; $i++) { |
| 689 | $temp = array( |
| 690 | $a->bitwise_rightRotate(28), |
| 691 | $a->bitwise_rightRotate(34), |
| 692 | $a->bitwise_rightRotate(39) |
| 693 | ); |
| 694 | $s0 = $temp[0]->bitwise_xor($temp[1]); |
| 695 | $s0 = $s0->bitwise_xor($temp[2]); |
| 696 | $temp = array( |
| 697 | $a->bitwise_and($b), |
| 698 | $a->bitwise_and($c), |
| 699 | $b->bitwise_and($c) |
| 700 | ); |
| 701 | $maj = $temp[0]->bitwise_xor($temp[1]); |
| 702 | $maj = $maj->bitwise_xor($temp[2]); |
| 703 | $t2 = $s0->add($maj); |
| 704 | |
| 705 | $temp = array( |
| 706 | $e->bitwise_rightRotate(14), |
| 707 | $e->bitwise_rightRotate(18), |
| 708 | $e->bitwise_rightRotate(41) |
| 709 | ); |
| 710 | $s1 = $temp[0]->bitwise_xor($temp[1]); |
| 711 | $s1 = $s1->bitwise_xor($temp[2]); |
| 712 | $temp = array( |
| 713 | $e->bitwise_and($f), |
| 714 | $g->bitwise_and($e->bitwise_not()) |
| 715 | ); |
| 716 | $ch = $temp[0]->bitwise_xor($temp[1]); |
| 717 | $t1 = $h->add($s1); |
| 718 | $t1 = $t1->add($ch); |
| 719 | $t1 = $t1->add($k[$i]); |
| 720 | $t1 = $t1->add($w[$i]); |
| 721 | |
| 722 | $h = $g->copy(); |
| 723 | $g = $f->copy(); |
| 724 | $f = $e->copy(); |
| 725 | $e = $d->add($t1); |
| 726 | $d = $c->copy(); |
| 727 | $c = $b->copy(); |
| 728 | $b = $a->copy(); |
| 729 | $a = $t1->add($t2); |
| 730 | } |
| 731 | |
| 732 | // Add this chunk's hash to result so far |
| 733 | $hash = array( |
| 734 | $hash[0]->add($a), |
| 735 | $hash[1]->add($b), |
| 736 | $hash[2]->add($c), |
| 737 | $hash[3]->add($d), |
| 738 | $hash[4]->add($e), |
| 739 | $hash[5]->add($f), |
| 740 | $hash[6]->add($g), |
| 741 | $hash[7]->add($h) |
| 742 | ); |
| 743 | } |
| 744 | |
| 745 | // Produce the final hash value (big-endian) |
| 746 | // (Crypt_Hash::hash() trims the output for hashes but not for HMACs. as such, we trim the output here) |
| 747 | $temp = $hash[0]->toBytes() . $hash[1]->toBytes() . $hash[2]->toBytes() . $hash[3]->toBytes() . |
| 748 | $hash[4]->toBytes() . $hash[5]->toBytes(); |
| 749 | if ($this->l != 48) { |
| 750 | $temp.= $hash[6]->toBytes() . $hash[7]->toBytes(); |
| 751 | } |
| 752 | |
| 753 | return $temp; |
| 754 | } |
| 755 | |
| 756 | /** |
| 757 | * Right Rotate |
| 758 | * |
| 759 | * @access private |
| 760 | * @param Integer $int |
| 761 | * @param Integer $amt |
| 762 | * @see _sha256() |
| 763 | * @return Integer |
| 764 | */ |
| 765 | function _rightRotate($int, $amt) |
| 766 | { |
| 767 | $invamt = 32 - $amt; |
| 768 | $mask = (1 << $invamt) - 1; |
| 769 | return (($int << $invamt) & 0xFFFFFFFF) | (($int >> $amt) & $mask); |
| 770 | } |
| 771 | |
| 772 | /** |
| 773 | * Right Shift |
| 774 | * |
| 775 | * @access private |
| 776 | * @param Integer $int |
| 777 | * @param Integer $amt |
| 778 | * @see _sha256() |
| 779 | * @return Integer |
| 780 | */ |
| 781 | function _rightShift($int, $amt) |
| 782 | { |
| 783 | $mask = (1 << (32 - $amt)) - 1; |
| 784 | return ($int >> $amt) & $mask; |
| 785 | } |
| 786 | |
| 787 | /** |
| 788 | * Not |
| 789 | * |
| 790 | * @access private |
| 791 | * @param Integer $int |
| 792 | * @see _sha256() |
| 793 | * @return Integer |
| 794 | */ |
| 795 | function _not($int) |
| 796 | { |
| 797 | return ~$int & 0xFFFFFFFF; |
| 798 | } |
| 799 | |
| 800 | /** |
| 801 | * Add |
| 802 | * |
| 803 | * _sha256() adds multiple unsigned 32-bit integers. Since PHP doesn't support unsigned integers and since the |
| 804 | * possibility of overflow exists, care has to be taken. Math_BigInteger() could be used but this should be faster. |
| 805 | * |
| 806 | * @param Integer $... |
| 807 | * @return Integer |
| 808 | * @see _sha256() |
| 809 | * @access private |
| 810 | */ |
| 811 | function _add() |
| 812 | { |
| 813 | static $mod; |
| 814 | if (!isset($mod)) { |
| 815 | $mod = pow(2, 32); |
| 816 | } |
| 817 | |
| 818 | $result = 0; |
| 819 | $arguments = func_get_args(); |
| 820 | foreach ($arguments as $argument) { |
| 821 | $result+= $argument < 0 ? ($argument & 0x7FFFFFFF) + 0x80000000 : $argument; |
| 822 | } |
| 823 | |
| 824 | return fmod($result, $mod); |
| 825 | } |
| 826 | |
| 827 | /** |
| 828 | * String Shift |
| 829 | * |
| 830 | * Inspired by array_shift |
| 831 | * |
| 832 | * @param String $string |
| 833 | * @param optional Integer $index |
| 834 | * @return String |
| 835 | * @access private |
| 836 | */ |
| 837 | function _string_shift(&$string, $index = 1) |
| 838 | { |
| 839 | $substr = substr($string, 0, $index); |
| 840 | $string = substr($string, $index); |
| 841 | return $substr; |
| 842 | } |
| 843 | } |