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: This library is free software; you can redistribute it and/or
33 * modify it under the terms of the GNU Lesser General Public
34 * License as published by the Free Software Foundation; either
35 * version 2.1 of the License, or (at your option) any later version.
37 * This library is distributed in the hope that it will be useful,
38 * but WITHOUT ANY WARRANTY; without even the implied warranty of
39 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
40 * Lesser General Public License for more details.
42 * You should have received a copy of the GNU Lesser General Public
43 * License along with this library; if not, write to the Free Software
44 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
49 * @author Jim Wigginton <terrafrost@php.net>
50 * @copyright MMVII Jim Wigginton
51 * @license http://www.gnu.org/licenses/lgpl.txt
52 * @version $Id: Hash.php,v 1.6 2009/11/23 23:37:07 terrafrost Exp $
53 * @link http://phpseclib.sourceforge.net
58 * @see Crypt_Hash::Crypt_Hash()
61 * Toggles the internal implementation
63 define('CRYPT_HASH_MODE_INTERNAL', 1);
65 * Toggles the mhash() implementation, which has been deprecated on PHP 5.3.0+.
67 define('CRYPT_HASH_MODE_MHASH', 2);
69 * Toggles the hash() implementation, which works on PHP 5.1.2+.
71 define('CRYPT_HASH_MODE_HASH', 3);
75 * Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
77 * @author Jim Wigginton <terrafrost@php.net>
84 * Byte-length of compression blocks / key (Internal HMAC)
86 * @see Crypt_Hash::setAlgorithm()
93 * Byte-length of hash output (Internal HMAC)
95 * @see Crypt_Hash::setHash()
104 * @see Crypt_Hash::setHash()
113 * @see Crypt_Hash::setKey()
120 * Outer XOR (Internal HMAC)
122 * @see Crypt_Hash::setKey()
129 * Inner XOR (Internal HMAC)
131 * @see Crypt_Hash::setKey()
138 * Default Constructor.
140 * @param optional String $hash
144 function Crypt_Hash($hash = 'sha1')
146 if ( !defined('CRYPT_HASH_MODE') ) {
148 case extension_loaded('hash'):
149 define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_HASH);
151 case extension_loaded('mhash'):
152 define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_MHASH);
155 define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_INTERNAL);
159 $this->setHash($hash);
163 * Sets the key for HMACs
165 * Keys can be of any length.
170 function setKey($key)
176 * Sets the hash function.
179 * @param String $hash
181 function setHash($hash)
186 $this->l = 12; // 96 / 8 = 12
207 $mode = CRYPT_HASH_MODE_INTERNAL;
211 $mode = CRYPT_HASH_MODE == CRYPT_HASH_MODE_MHASH ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE;
214 $mode = CRYPT_HASH_MODE;
218 case CRYPT_HASH_MODE_MHASH:
222 $this->hash = MHASH_MD5;
225 $this->hash = MHASH_SHA256;
230 $this->hash = MHASH_SHA1;
233 case CRYPT_HASH_MODE_HASH:
247 $this->hash = 'sha1';
255 $this->hash = array($this, '_md2');
260 $this->hash = array($this, '_md5');
264 $this->hash = array($this, '_sha256');
269 $this->hash = array($this, '_sha512');
275 $this->hash = array($this, '_sha1');
278 $this->ipad = str_repeat(chr(0x36), $this->b);
279 $this->opad = str_repeat(chr(0x5C), $this->b);
286 * @param String $text
291 $mode = is_array($this->hash) ? CRYPT_HASH_MODE_INTERNAL : CRYPT_HASH_MODE;
293 if (!empty($this->key)) {
295 case CRYPT_HASH_MODE_MHASH:
296 $output = mhash($this->hash, $text, $this->key);
298 case CRYPT_HASH_MODE_HASH:
299 $output = hash_hmac($this->hash, $text, $this->key, true);
301 case CRYPT_HASH_MODE_INTERNAL:
302 /* "Applications that use keys longer than B bytes will first hash the key using H and then use the
303 resultant L byte string as the actual key to HMAC."
305 -- http://tools.ietf.org/html/rfc2104#section-2 */
306 $key = strlen($this->key) > $this->b ? call_user_func($this->$hash, $this->key) : $this->key;
308 $key = str_pad($key, $this->b, chr(0)); // step 1
309 $temp = $this->ipad ^ $key; // step 2
310 $temp .= $text; // step 3
311 $temp = call_user_func($this->hash, $temp); // step 4
312 $output = $this->opad ^ $key; // step 5
313 $output.= $temp; // step 6
314 $output = call_user_func($this->hash, $output); // step 7
318 case CRYPT_HASH_MODE_MHASH:
319 $output = mhash($this->hash, $text);
321 case CRYPT_HASH_MODE_HASH:
322 $output = hash($this->hash, $text, true);
324 case CRYPT_HASH_MODE_INTERNAL:
325 $output = call_user_func($this->hash, $text);
329 return substr($output, 0, $this->l);
333 * Returns the hash length (in bytes)
347 * @param String $text
351 return pack('H*', md5($m));
358 * @param String $text
362 return pack('H*', sha1($m));
366 * Pure-PHP implementation of MD2
368 * See {@link http://tools.ietf.org/html/rfc1319 RFC1319}.
371 * @param String $text
376 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
377 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
378 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
379 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
380 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
381 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
382 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
383 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
384 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
385 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
386 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
387 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
388 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
389 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
390 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
391 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
392 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
393 31, 26, 219, 153, 141, 51, 159, 17, 131, 20
396 // Step 1. Append Padding Bytes
397 $pad = 16 - (strlen($m) & 0xF);
398 $m.= str_repeat(chr($pad), $pad);
400 $length = strlen($m);
402 // Step 2. Append Checksum
403 $c = str_repeat(chr(0), 16);
405 for ($i = 0; $i < $length; $i+= 16) {
406 for ($j = 0; $j < 16; $j++) {
407 $c[$j] = chr($s[ord($m[$i + $j] ^ $l)]);
415 // Step 3. Initialize MD Buffer
416 $x = str_repeat(chr(0), 48);
418 // Step 4. Process Message in 16-Byte Blocks
419 for ($i = 0; $i < $length; $i+= 16) {
420 for ($j = 0; $j < 16; $j++) {
421 $x[$j + 16] = $m[$i + $j];
422 $x[$j + 32] = $x[$j + 16] ^ $x[$j];
425 for ($j = 0; $j < 18; $j++) {
426 for ($k = 0; $k < 48; $k++) {
427 $x[$k] = $t = $x[$k] ^ chr($s[ord($t)]);
428 //$t = $x[$k] = $x[$k] ^ chr($s[ord($t)]);
430 $t = chr(ord($t) + $j);
435 return substr($x, 0, 16);
439 * Pure-PHP implementation of SHA256
441 * 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}.
444 * @param String $text
448 if (extension_loaded('suhosin')) {
449 return pack('H*', sha256($m));
452 // Initialize variables
454 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
456 // Initialize table of round constants
457 // (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311)
459 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
460 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
461 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
462 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
463 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
464 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
465 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
466 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
470 $length = strlen($m);
471 // to round to nearest 56 mod 64, we'll add 64 - (length + (64 - 56)) % 64
472 $m.= str_repeat(chr(0), 64 - (($length + 8) & 0x3F));
473 $m[$length] = chr(0x80);
474 // we don't support hashing strings 512MB long
475 $m.= pack('N2', 0, $length << 3);
477 // Process the message in successive 512-bit chunks
478 $chunks = str_split($m, 64);
479 foreach ($chunks as $chunk) {
481 for ($i = 0; $i < 16; $i++) {
482 extract(unpack('Ntemp', $this->_string_shift($chunk, 4)));
486 // Extend the sixteen 32-bit words into sixty-four 32-bit words
487 for ($i = 16; $i < 64; $i++) {
488 $s0 = $this->_rightRotate($w[$i - 15], 7) ^
489 $this->_rightRotate($w[$i - 15], 18) ^
490 $this->_rightShift( $w[$i - 15], 3);
491 $s1 = $this->_rightRotate($w[$i - 2], 17) ^
492 $this->_rightRotate($w[$i - 2], 19) ^
493 $this->_rightShift( $w[$i - 2], 10);
494 $w[$i] = $this->_add($w[$i - 16], $s0, $w[$i - 7], $s1);
498 // Initialize hash value for this chunk
499 list($a, $b, $c, $d, $e, $f, $g, $h) = $hash;
502 for ($i = 0; $i < 64; $i++) {
503 $s0 = $this->_rightRotate($a, 2) ^
504 $this->_rightRotate($a, 13) ^
505 $this->_rightRotate($a, 22);
509 $t2 = $this->_add($s0, $maj);
511 $s1 = $this->_rightRotate($e, 6) ^
512 $this->_rightRotate($e, 11) ^
513 $this->_rightRotate($e, 25);
515 ($this->_not($e) & $g);
516 $t1 = $this->_add($h, $s1, $ch, $k[$i], $w[$i]);
521 $e = $this->_add($d, $t1);
525 $a = $this->_add($t1, $t2);
528 // Add this chunk's hash to result so far
530 $this->_add($hash[0], $a),
531 $this->_add($hash[1], $b),
532 $this->_add($hash[2], $c),
533 $this->_add($hash[3], $d),
534 $this->_add($hash[4], $e),
535 $this->_add($hash[5], $f),
536 $this->_add($hash[6], $g),
537 $this->_add($hash[7], $h)
541 // Produce the final hash value (big-endian)
542 return pack('N8', $hash[0], $hash[1], $hash[2], $hash[3], $hash[4], $hash[5], $hash[6], $hash[7]);
546 * Pure-PHP implementation of SHA384 and SHA512
549 * @param String $text
553 if (!class_exists('Math_BigInteger')) {
554 require_once('Math/BigInteger.php');
557 static $init384, $init512, $k;
560 // Initialize variables
561 $init384 = array( // initial values for SHA384
562 'cbbb9d5dc1059ed8', '629a292a367cd507', '9159015a3070dd17', '152fecd8f70e5939',
563 '67332667ffc00b31', '8eb44a8768581511', 'db0c2e0d64f98fa7', '47b5481dbefa4fa4'
565 $init512 = array( // initial values for SHA512
566 '6a09e667f3bcc908', 'bb67ae8584caa73b', '3c6ef372fe94f82b', 'a54ff53a5f1d36f1',
567 '510e527fade682d1', '9b05688c2b3e6c1f', '1f83d9abfb41bd6b', '5be0cd19137e2179'
570 for ($i = 0; $i < 8; $i++) {
571 $init384[$i] = new Math_BigInteger($init384[$i], 16);
572 $init384[$i]->setPrecision(64);
573 $init512[$i] = new Math_BigInteger($init512[$i], 16);
574 $init512[$i]->setPrecision(64);
577 // Initialize table of round constants
578 // (first 64 bits of the fractional parts of the cube roots of the first 80 primes 2..409)
580 '428a2f98d728ae22', '7137449123ef65cd', 'b5c0fbcfec4d3b2f', 'e9b5dba58189dbbc',
581 '3956c25bf348b538', '59f111f1b605d019', '923f82a4af194f9b', 'ab1c5ed5da6d8118',
582 'd807aa98a3030242', '12835b0145706fbe', '243185be4ee4b28c', '550c7dc3d5ffb4e2',
583 '72be5d74f27b896f', '80deb1fe3b1696b1', '9bdc06a725c71235', 'c19bf174cf692694',
584 'e49b69c19ef14ad2', 'efbe4786384f25e3', '0fc19dc68b8cd5b5', '240ca1cc77ac9c65',
585 '2de92c6f592b0275', '4a7484aa6ea6e483', '5cb0a9dcbd41fbd4', '76f988da831153b5',
586 '983e5152ee66dfab', 'a831c66d2db43210', 'b00327c898fb213f', 'bf597fc7beef0ee4',
587 'c6e00bf33da88fc2', 'd5a79147930aa725', '06ca6351e003826f', '142929670a0e6e70',
588 '27b70a8546d22ffc', '2e1b21385c26c926', '4d2c6dfc5ac42aed', '53380d139d95b3df',
589 '650a73548baf63de', '766a0abb3c77b2a8', '81c2c92e47edaee6', '92722c851482353b',
590 'a2bfe8a14cf10364', 'a81a664bbc423001', 'c24b8b70d0f89791', 'c76c51a30654be30',
591 'd192e819d6ef5218', 'd69906245565a910', 'f40e35855771202a', '106aa07032bbd1b8',
592 '19a4c116b8d2d0c8', '1e376c085141ab53', '2748774cdf8eeb99', '34b0bcb5e19b48a8',
593 '391c0cb3c5c95a63', '4ed8aa4ae3418acb', '5b9cca4f7763e373', '682e6ff3d6b2b8a3',
594 '748f82ee5defb2fc', '78a5636f43172f60', '84c87814a1f0ab72', '8cc702081a6439ec',
595 '90befffa23631e28', 'a4506cebde82bde9', 'bef9a3f7b2c67915', 'c67178f2e372532b',
596 'ca273eceea26619c', 'd186b8c721c0c207', 'eada7dd6cde0eb1e', 'f57d4f7fee6ed178',
597 '06f067aa72176fba', '0a637dc5a2c898a6', '113f9804bef90dae', '1b710b35131c471b',
598 '28db77f523047d84', '32caab7b40c72493', '3c9ebe0a15c9bebc', '431d67c49c100d4c',
599 '4cc5d4becb3e42b6', '597f299cfc657e2a', '5fcb6fab3ad6faec', '6c44198c4a475817'
602 for ($i = 0; $i < 80; $i++) {
603 $k[$i] = new Math_BigInteger($k[$i], 16);
607 $hash = $this->l == 48 ? $init384 : $init512;
610 $length = strlen($m);
611 // to round to nearest 112 mod 128, we'll add 128 - (length + (128 - 112)) % 128
612 $m.= str_repeat(chr(0), 128 - (($length + 16) & 0x7F));
613 $m[$length] = chr(0x80);
614 // we don't support hashing strings 512MB long
615 $m.= pack('N4', 0, 0, 0, $length << 3);
617 // Process the message in successive 1024-bit chunks
618 $chunks = str_split($m, 128);
619 foreach ($chunks as $chunk) {
621 for ($i = 0; $i < 16; $i++) {
622 $temp = new Math_BigInteger($this->_string_shift($chunk, 8), 256);
623 $temp->setPrecision(64);
627 // Extend the sixteen 32-bit words into eighty 32-bit words
628 for ($i = 16; $i < 80; $i++) {
630 $w[$i - 15]->bitwise_rightRotate(1),
631 $w[$i - 15]->bitwise_rightRotate(8),
632 $w[$i - 15]->bitwise_rightShift(7)
634 $s0 = $temp[0]->bitwise_xor($temp[1]);
635 $s0 = $s0->bitwise_xor($temp[2]);
637 $w[$i - 2]->bitwise_rightRotate(19),
638 $w[$i - 2]->bitwise_rightRotate(61),
639 $w[$i - 2]->bitwise_rightShift(6)
641 $s1 = $temp[0]->bitwise_xor($temp[1]);
642 $s1 = $s1->bitwise_xor($temp[2]);
643 $w[$i] = $w[$i - 16]->copy();
644 $w[$i] = $w[$i]->add($s0);
645 $w[$i] = $w[$i]->add($w[$i - 7]);
646 $w[$i] = $w[$i]->add($s1);
649 // Initialize hash value for this chunk
650 $a = $hash[0]->copy();
651 $b = $hash[1]->copy();
652 $c = $hash[2]->copy();
653 $d = $hash[3]->copy();
654 $e = $hash[4]->copy();
655 $f = $hash[5]->copy();
656 $g = $hash[6]->copy();
657 $h = $hash[7]->copy();
660 for ($i = 0; $i < 80; $i++) {
662 $a->bitwise_rightRotate(28),
663 $a->bitwise_rightRotate(34),
664 $a->bitwise_rightRotate(39)
666 $s0 = $temp[0]->bitwise_xor($temp[1]);
667 $s0 = $s0->bitwise_xor($temp[2]);
673 $maj = $temp[0]->bitwise_xor($temp[1]);
674 $maj = $maj->bitwise_xor($temp[2]);
675 $t2 = $s0->add($maj);
678 $e->bitwise_rightRotate(14),
679 $e->bitwise_rightRotate(18),
680 $e->bitwise_rightRotate(41)
682 $s1 = $temp[0]->bitwise_xor($temp[1]);
683 $s1 = $s1->bitwise_xor($temp[2]);
686 $g->bitwise_and($e->bitwise_not())
688 $ch = $temp[0]->bitwise_xor($temp[1]);
691 $t1 = $t1->add($k[$i]);
692 $t1 = $t1->add($w[$i]);
704 // Add this chunk's hash to result so far
717 // Produce the final hash value (big-endian)
718 // (Crypt_Hash::hash() trims the output for hashes but not for HMACs. as such, we trim the output here)
719 $temp = $hash[0]->toBytes() . $hash[1]->toBytes() . $hash[2]->toBytes() . $hash[3]->toBytes() .
720 $hash[4]->toBytes() . $hash[5]->toBytes();
721 if ($this->l != 48) {
722 $temp.= $hash[6]->toBytes() . $hash[7]->toBytes();
732 * @param Integer $int
733 * @param Integer $amt
737 function _rightRotate($int, $amt)
740 $mask = (1 << $invamt) - 1;
741 return (($int << $invamt) & 0xFFFFFFFF) | (($int >> $amt) & $mask);
748 * @param Integer $int
749 * @param Integer $amt
753 function _rightShift($int, $amt)
755 $mask = (1 << (32 - $amt)) - 1;
756 return ($int >> $amt) & $mask;
763 * @param Integer $int
769 return ~$int & 0xFFFFFFFF;
775 * _sha256() adds multiple unsigned 32-bit integers. Since PHP doesn't support unsigned integers and since the
776 * possibility of overflow exists, care has to be taken. Math_BigInteger() could be used but this should be faster.
778 * @param String $string
779 * @param optional Integer $index
792 $arguments = func_get_args();
793 foreach ($arguments as $argument) {
794 $result+= $argument < 0 ? ($argument & 0x7FFFFFFF) + 0x80000000 : $argument;
797 return fmod($result, $mod);
803 * Inspired by array_shift
805 * @param String $string
806 * @param optional Integer $index
810 function _string_shift(&$string, $index = 1)
812 $substr = substr($string, 0, $index);
813 $string = substr($string, $index);