2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
5 * Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
7 * Uses hash() or mhash() if available and an internal implementation, otherwise. Currently supports the following:
9 * md2, md5, md5-96, sha1, sha1-96, sha256, sha384, and sha512
11 * If {@link Crypt_Hash::setKey() setKey()} is called, {@link Crypt_Hash::hash() hash()} will return the HMAC as opposed to
12 * the hash. If no valid algorithm is provided, sha1 will be used.
14 * PHP versions 4 and 5
16 * {@internal The variable names are the same as those in
17 * {@link http://tools.ietf.org/html/rfc2104#section-2 RFC2104}.}}
19 * Here's a short example of how to use this library:
22 * include('Crypt/Hash.php');
24 * $hash = new Crypt_Hash('sha1');
26 * $hash->setKey('abcdefg');
28 * echo base64_encode($hash->hash('abcdefg'));
32 * LICENSE: Permission is hereby granted, free of charge, to any person obtaining a copy
33 * of this software and associated documentation files (the "Software"), to deal
34 * in the Software without restriction, including without limitation the rights
35 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
36 * copies of the Software, and to permit persons to whom the Software is
37 * furnished to do so, subject to the following conditions:
39 * The above copyright notice and this permission notice shall be included in
40 * all copies or substantial portions of the Software.
42 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
43 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
44 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
45 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
46 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
47 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
52 * @author Jim Wigginton <terrafrost@php.net>
53 * @copyright MMVII Jim Wigginton
54 * @license http://www.opensource.org/licenses/mit-license.html MIT License
55 * @link http://phpseclib.sourceforge.net
60 * @see Crypt_Hash::Crypt_Hash()
63 * Toggles the internal implementation
65 define('CRYPT_HASH_MODE_INTERNAL', 1);
67 * Toggles the mhash() implementation, which has been deprecated on PHP 5.3.0+.
69 define('CRYPT_HASH_MODE_MHASH', 2);
71 * Toggles the hash() implementation, which works on PHP 5.1.2+.
73 define('CRYPT_HASH_MODE_HASH', 3);
77 * Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
79 * @author Jim Wigginton <terrafrost@php.net>
86 * Byte-length of compression blocks / key (Internal HMAC)
88 * @see Crypt_Hash::setAlgorithm()
95 * Byte-length of hash output (Internal HMAC)
97 * @see Crypt_Hash::setHash()
106 * @see Crypt_Hash::setHash()
115 * @see Crypt_Hash::setKey()
122 * Outer XOR (Internal HMAC)
124 * @see Crypt_Hash::setKey()
131 * Inner XOR (Internal HMAC)
133 * @see Crypt_Hash::setKey()
140 * Default Constructor.
142 * @param optional String $hash
146 function Crypt_Hash($hash = 'sha1')
148 if ( !defined('CRYPT_HASH_MODE') ) {
150 case extension_loaded('hash'):
151 define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_HASH);
153 case extension_loaded('mhash'):
154 define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_MHASH);
157 define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_INTERNAL);
161 $this->setHash($hash);
165 * Sets the key for HMACs
167 * Keys can be of any length.
170 * @param optional String $key
172 function setKey($key = false)
178 * Sets the hash function.
181 * @param String $hash
183 function setHash($hash)
185 $hash = strtolower($hash);
189 $this->l = 12; // 96 / 8 = 12
210 $mode = CRYPT_HASH_MODE == CRYPT_HASH_MODE_HASH && in_array('md2', hash_algos()) ?
211 CRYPT_HASH_MODE_HASH : CRYPT_HASH_MODE_INTERNAL;
215 $mode = CRYPT_HASH_MODE == CRYPT_HASH_MODE_MHASH ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE;
218 $mode = CRYPT_HASH_MODE;
222 case CRYPT_HASH_MODE_MHASH:
226 $this->hash = MHASH_MD5;
229 $this->hash = MHASH_SHA256;
234 $this->hash = MHASH_SHA1;
237 case CRYPT_HASH_MODE_HASH:
252 $this->hash = 'sha1';
260 $this->hash = array($this, '_md2');
265 $this->hash = array($this, '_md5');
269 $this->hash = array($this, '_sha256');
274 $this->hash = array($this, '_sha512');
280 $this->hash = array($this, '_sha1');
283 $this->ipad = str_repeat(chr(0x36), $this->b);
284 $this->opad = str_repeat(chr(0x5C), $this->b);
291 * @param String $text
296 $mode = is_array($this->hash) ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE;
298 if (!empty($this->key) || is_string($this->key)) {
300 case CRYPT_HASH_MODE_MHASH:
301 $output = mhash($this->hash, $text, $this->key);
303 case CRYPT_HASH_MODE_HASH:
304 $output = hash_hmac($this->hash, $text, $this->key, true);
306 case CRYPT_HASH_MODE_INTERNAL:
307 /* "Applications that use keys longer than B bytes will first hash the key using H and then use the
308 resultant L byte string as the actual key to HMAC."
310 -- http://tools.ietf.org/html/rfc2104#section-2 */
311 $key = strlen($this->key) > $this->b ? call_user_func($this->hash, $this->key) : $this->key;
313 $key = str_pad($key, $this->b, chr(0)); // step 1
314 $temp = $this->ipad ^ $key; // step 2
315 $temp .= $text; // step 3
316 $temp = call_user_func($this->hash, $temp); // step 4
317 $output = $this->opad ^ $key; // step 5
318 $output.= $temp; // step 6
319 $output = call_user_func($this->hash, $output); // step 7
323 case CRYPT_HASH_MODE_MHASH:
324 $output = mhash($this->hash, $text);
326 case CRYPT_HASH_MODE_HASH:
327 $output = hash($this->hash, $text, true);
329 case CRYPT_HASH_MODE_INTERNAL:
330 $output = call_user_func($this->hash, $text);
334 return substr($output, 0, $this->l);
338 * Returns the hash length (in bytes)
356 return pack('H*', md5($m));
367 return pack('H*', sha1($m));
371 * Pure-PHP implementation of MD2
373 * See {@link http://tools.ietf.org/html/rfc1319 RFC1319}.
381 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
382 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
383 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
384 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
385 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
386 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
387 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
388 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
389 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
390 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
391 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
392 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
393 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
394 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
395 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
396 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
397 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
398 31, 26, 219, 153, 141, 51, 159, 17, 131, 20
401 // Step 1. Append Padding Bytes
402 $pad = 16 - (strlen($m) & 0xF);
403 $m.= str_repeat(chr($pad), $pad);
405 $length = strlen($m);
407 // Step 2. Append Checksum
408 $c = str_repeat(chr(0), 16);
410 for ($i = 0; $i < $length; $i+= 16) {
411 for ($j = 0; $j < 16; $j++) {
412 // RFC1319 incorrectly states that C[j] should be set to S[c xor L]
413 //$c[$j] = chr($s[ord($m[$i + $j] ^ $l)]);
414 // 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]
415 $c[$j] = chr($s[ord($m[$i + $j] ^ $l)] ^ ord($c[$j]));
423 // Step 3. Initialize MD Buffer
424 $x = str_repeat(chr(0), 48);
426 // Step 4. Process Message in 16-Byte Blocks
427 for ($i = 0; $i < $length; $i+= 16) {
428 for ($j = 0; $j < 16; $j++) {
429 $x[$j + 16] = $m[$i + $j];
430 $x[$j + 32] = $x[$j + 16] ^ $x[$j];
433 for ($j = 0; $j < 18; $j++) {
434 for ($k = 0; $k < 48; $k++) {
435 $x[$k] = $t = $x[$k] ^ chr($s[ord($t)]);
436 //$t = $x[$k] = $x[$k] ^ chr($s[ord($t)]);
438 $t = chr(ord($t) + $j);
443 return substr($x, 0, 16);
447 * Pure-PHP implementation of SHA256
449 * 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}.
456 if (extension_loaded('suhosin')) {
457 return pack('H*', sha256($m));
460 // Initialize variables
462 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
464 // Initialize table of round constants
465 // (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311)
467 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
468 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
469 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
470 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
471 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
472 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
473 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
474 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
478 $length = strlen($m);
479 // to round to nearest 56 mod 64, we'll add 64 - (length + (64 - 56)) % 64
480 $m.= str_repeat(chr(0), 64 - (($length + 8) & 0x3F));
481 $m[$length] = chr(0x80);
482 // we don't support hashing strings 512MB long
483 $m.= pack('N2', 0, $length << 3);
485 // Process the message in successive 512-bit chunks
486 $chunks = str_split($m, 64);
487 foreach ($chunks as $chunk) {
489 for ($i = 0; $i < 16; $i++) {
490 extract(unpack('Ntemp', $this->_string_shift($chunk, 4)));
494 // Extend the sixteen 32-bit words into sixty-four 32-bit words
495 for ($i = 16; $i < 64; $i++) {
496 $s0 = $this->_rightRotate($w[$i - 15], 7) ^
497 $this->_rightRotate($w[$i - 15], 18) ^
498 $this->_rightShift( $w[$i - 15], 3);
499 $s1 = $this->_rightRotate($w[$i - 2], 17) ^
500 $this->_rightRotate($w[$i - 2], 19) ^
501 $this->_rightShift( $w[$i - 2], 10);
502 $w[$i] = $this->_add($w[$i - 16], $s0, $w[$i - 7], $s1);
506 // Initialize hash value for this chunk
507 list($a, $b, $c, $d, $e, $f, $g, $h) = $hash;
510 for ($i = 0; $i < 64; $i++) {
511 $s0 = $this->_rightRotate($a, 2) ^
512 $this->_rightRotate($a, 13) ^
513 $this->_rightRotate($a, 22);
517 $t2 = $this->_add($s0, $maj);
519 $s1 = $this->_rightRotate($e, 6) ^
520 $this->_rightRotate($e, 11) ^
521 $this->_rightRotate($e, 25);
523 ($this->_not($e) & $g);
524 $t1 = $this->_add($h, $s1, $ch, $k[$i], $w[$i]);
529 $e = $this->_add($d, $t1);
533 $a = $this->_add($t1, $t2);
536 // Add this chunk's hash to result so far
538 $this->_add($hash[0], $a),
539 $this->_add($hash[1], $b),
540 $this->_add($hash[2], $c),
541 $this->_add($hash[3], $d),
542 $this->_add($hash[4], $e),
543 $this->_add($hash[5], $f),
544 $this->_add($hash[6], $g),
545 $this->_add($hash[7], $h)
549 // Produce the final hash value (big-endian)
550 return pack('N8', $hash[0], $hash[1], $hash[2], $hash[3], $hash[4], $hash[5], $hash[6], $hash[7]);
554 * Pure-PHP implementation of SHA384 and SHA512
561 if (!class_exists('Math_BigInteger')) {
562 require_once('Math/BigInteger.php');
565 static $init384, $init512, $k;
568 // Initialize variables
569 $init384 = array( // initial values for SHA384
570 'cbbb9d5dc1059ed8', '629a292a367cd507', '9159015a3070dd17', '152fecd8f70e5939',
571 '67332667ffc00b31', '8eb44a8768581511', 'db0c2e0d64f98fa7', '47b5481dbefa4fa4'
573 $init512 = array( // initial values for SHA512
574 '6a09e667f3bcc908', 'bb67ae8584caa73b', '3c6ef372fe94f82b', 'a54ff53a5f1d36f1',
575 '510e527fade682d1', '9b05688c2b3e6c1f', '1f83d9abfb41bd6b', '5be0cd19137e2179'
578 for ($i = 0; $i < 8; $i++) {
579 $init384[$i] = new Math_BigInteger($init384[$i], 16);
580 $init384[$i]->setPrecision(64);
581 $init512[$i] = new Math_BigInteger($init512[$i], 16);
582 $init512[$i]->setPrecision(64);
585 // Initialize table of round constants
586 // (first 64 bits of the fractional parts of the cube roots of the first 80 primes 2..409)
588 '428a2f98d728ae22', '7137449123ef65cd', 'b5c0fbcfec4d3b2f', 'e9b5dba58189dbbc',
589 '3956c25bf348b538', '59f111f1b605d019', '923f82a4af194f9b', 'ab1c5ed5da6d8118',
590 'd807aa98a3030242', '12835b0145706fbe', '243185be4ee4b28c', '550c7dc3d5ffb4e2',
591 '72be5d74f27b896f', '80deb1fe3b1696b1', '9bdc06a725c71235', 'c19bf174cf692694',
592 'e49b69c19ef14ad2', 'efbe4786384f25e3', '0fc19dc68b8cd5b5', '240ca1cc77ac9c65',
593 '2de92c6f592b0275', '4a7484aa6ea6e483', '5cb0a9dcbd41fbd4', '76f988da831153b5',
594 '983e5152ee66dfab', 'a831c66d2db43210', 'b00327c898fb213f', 'bf597fc7beef0ee4',
595 'c6e00bf33da88fc2', 'd5a79147930aa725', '06ca6351e003826f', '142929670a0e6e70',
596 '27b70a8546d22ffc', '2e1b21385c26c926', '4d2c6dfc5ac42aed', '53380d139d95b3df',
597 '650a73548baf63de', '766a0abb3c77b2a8', '81c2c92e47edaee6', '92722c851482353b',
598 'a2bfe8a14cf10364', 'a81a664bbc423001', 'c24b8b70d0f89791', 'c76c51a30654be30',
599 'd192e819d6ef5218', 'd69906245565a910', 'f40e35855771202a', '106aa07032bbd1b8',
600 '19a4c116b8d2d0c8', '1e376c085141ab53', '2748774cdf8eeb99', '34b0bcb5e19b48a8',
601 '391c0cb3c5c95a63', '4ed8aa4ae3418acb', '5b9cca4f7763e373', '682e6ff3d6b2b8a3',
602 '748f82ee5defb2fc', '78a5636f43172f60', '84c87814a1f0ab72', '8cc702081a6439ec',
603 '90befffa23631e28', 'a4506cebde82bde9', 'bef9a3f7b2c67915', 'c67178f2e372532b',
604 'ca273eceea26619c', 'd186b8c721c0c207', 'eada7dd6cde0eb1e', 'f57d4f7fee6ed178',
605 '06f067aa72176fba', '0a637dc5a2c898a6', '113f9804bef90dae', '1b710b35131c471b',
606 '28db77f523047d84', '32caab7b40c72493', '3c9ebe0a15c9bebc', '431d67c49c100d4c',
607 '4cc5d4becb3e42b6', '597f299cfc657e2a', '5fcb6fab3ad6faec', '6c44198c4a475817'
610 for ($i = 0; $i < 80; $i++) {
611 $k[$i] = new Math_BigInteger($k[$i], 16);
615 $hash = $this->l == 48 ? $init384 : $init512;
618 $length = strlen($m);
619 // to round to nearest 112 mod 128, we'll add 128 - (length + (128 - 112)) % 128
620 $m.= str_repeat(chr(0), 128 - (($length + 16) & 0x7F));
621 $m[$length] = chr(0x80);
622 // we don't support hashing strings 512MB long
623 $m.= pack('N4', 0, 0, 0, $length << 3);
625 // Process the message in successive 1024-bit chunks
626 $chunks = str_split($m, 128);
627 foreach ($chunks as $chunk) {
629 for ($i = 0; $i < 16; $i++) {
630 $temp = new Math_BigInteger($this->_string_shift($chunk, 8), 256);
631 $temp->setPrecision(64);
635 // Extend the sixteen 32-bit words into eighty 32-bit words
636 for ($i = 16; $i < 80; $i++) {
638 $w[$i - 15]->bitwise_rightRotate(1),
639 $w[$i - 15]->bitwise_rightRotate(8),
640 $w[$i - 15]->bitwise_rightShift(7)
642 $s0 = $temp[0]->bitwise_xor($temp[1]);
643 $s0 = $s0->bitwise_xor($temp[2]);
645 $w[$i - 2]->bitwise_rightRotate(19),
646 $w[$i - 2]->bitwise_rightRotate(61),
647 $w[$i - 2]->bitwise_rightShift(6)
649 $s1 = $temp[0]->bitwise_xor($temp[1]);
650 $s1 = $s1->bitwise_xor($temp[2]);
651 $w[$i] = $w[$i - 16]->copy();
652 $w[$i] = $w[$i]->add($s0);
653 $w[$i] = $w[$i]->add($w[$i - 7]);
654 $w[$i] = $w[$i]->add($s1);
657 // Initialize hash value for this chunk
658 $a = $hash[0]->copy();
659 $b = $hash[1]->copy();
660 $c = $hash[2]->copy();
661 $d = $hash[3]->copy();
662 $e = $hash[4]->copy();
663 $f = $hash[5]->copy();
664 $g = $hash[6]->copy();
665 $h = $hash[7]->copy();
668 for ($i = 0; $i < 80; $i++) {
670 $a->bitwise_rightRotate(28),
671 $a->bitwise_rightRotate(34),
672 $a->bitwise_rightRotate(39)
674 $s0 = $temp[0]->bitwise_xor($temp[1]);
675 $s0 = $s0->bitwise_xor($temp[2]);
681 $maj = $temp[0]->bitwise_xor($temp[1]);
682 $maj = $maj->bitwise_xor($temp[2]);
683 $t2 = $s0->add($maj);
686 $e->bitwise_rightRotate(14),
687 $e->bitwise_rightRotate(18),
688 $e->bitwise_rightRotate(41)
690 $s1 = $temp[0]->bitwise_xor($temp[1]);
691 $s1 = $s1->bitwise_xor($temp[2]);
694 $g->bitwise_and($e->bitwise_not())
696 $ch = $temp[0]->bitwise_xor($temp[1]);
699 $t1 = $t1->add($k[$i]);
700 $t1 = $t1->add($w[$i]);
712 // Add this chunk's hash to result so far
725 // Produce the final hash value (big-endian)
726 // (Crypt_Hash::hash() trims the output for hashes but not for HMACs. as such, we trim the output here)
727 $temp = $hash[0]->toBytes() . $hash[1]->toBytes() . $hash[2]->toBytes() . $hash[3]->toBytes() .
728 $hash[4]->toBytes() . $hash[5]->toBytes();
729 if ($this->l != 48) {
730 $temp.= $hash[6]->toBytes() . $hash[7]->toBytes();
740 * @param Integer $int
741 * @param Integer $amt
745 function _rightRotate($int, $amt)
748 $mask = (1 << $invamt) - 1;
749 return (($int << $invamt) & 0xFFFFFFFF) | (($int >> $amt) & $mask);
756 * @param Integer $int
757 * @param Integer $amt
761 function _rightShift($int, $amt)
763 $mask = (1 << (32 - $amt)) - 1;
764 return ($int >> $amt) & $mask;
771 * @param Integer $int
777 return ~$int & 0xFFFFFFFF;
783 * _sha256() adds multiple unsigned 32-bit integers. Since PHP doesn't support unsigned integers and since the
784 * possibility of overflow exists, care has to be taken. Math_BigInteger() could be used but this should be faster.
786 * @param Integer $...
799 $arguments = func_get_args();
800 foreach ($arguments as $argument) {
801 $result+= $argument < 0 ? ($argument & 0x7FFFFFFF) + 0x80000000 : $argument;
804 return fmod($result, $mod);
810 * Inspired by array_shift
812 * @param String $string
813 * @param optional Integer $index
817 function _string_shift(&$string, $index = 1)
819 $substr = substr($string, 0, $index);
820 $string = substr($string, $index);