home *** CD-ROM | disk | FTP | other *** search
/ H4CK3R 4 / hacker04 / 04_HACK04.ISO / src / PHP / sha.php3.txt < prev    next >
Encoding:
Text File  |  2002-05-06  |  11.4 KB  |  347 lines

  1. <?php 
  2. //////////////////////////////////////////////////////////////////////////// 
  3. // SHA implementation  v1.0 
  4. // Based on the SHA algorithm as given in "Applied Cryptography" 
  5. // Code written by Chris Monson (chris@bouncingchairs.net) 
  6. // Most recent version available on http://bouncingchairs.net 
  7. // Licensed under the GPL (http://www.gnu.org/copyleft/gpl.html) 
  8. // April 11, 2000 
  9. //////////////////////////////////////////////////////////////////////////// 
  10.  
  11. //////////////////////////////////////////////////////////////////////////// 
  12. // USAGE: 
  13. //------------------------------------------------------------------------ 
  14. //       
  15. //      Simple text hash: 
  16. //       
  17. //      sha = new SHA; 
  18. //      hasharray = sha.hash_text( 'hash me!' ); 
  19. // 
  20. //      This returns an array of 5 32-bit integers. 
  21. //      The SHA.hash_bytes function does the same thing, but requires 
  22. //      an array of bytes as input.  Note that the input values will be 
  23. //      truncated if they are larger than 8 bits. 
  24. // 
  25. //------------------------------------------------------------------------ 
  26. // 
  27. //      There are also some hash to string conversion functions.  The 
  28. //      naming convention admittedly could be better, but it works :). 
  29. // 
  30. //      sha.hash_to_string( hasharray ) 
  31. //       
  32. //      Converts the hash array to an uppercase hex string. 
  33. // 
  34. //------------------------------------------------------------------------ 
  35. // 
  36. //      Hashing very large blocks a piece at a time: 
  37. // 
  38. //      sha = new SHA; 
  39. //      sha.init(); 
  40. //      while (blocks_to_process) { 
  41. //          sha.update( next_byte_array ) 
  42. //      } 
  43. //      hasharray = sha.finalize() 
  44. //       
  45. //////////////////////////////////////////////////////////////////////////// 
  46.  
  47. //////////////////////////////////////////////////////////////////////////// 
  48. // NOTES: 
  49. //      This is basically a rip off of SHAPerl.pm, which I also wrote. 
  50. //      I discovered, much to my chagrin, that PHP does not have even 
  51. //      the crappy 32-bit int support that Perl has, so I had to employ 
  52. //      some funny tricks in the code to get it to use all 32 bits. 
  53. //      One of the most obvious of these is using an 'add' method instead 
  54. //      of just adding numbers together.  Any numbers over 32 bits don't get 
  55. //      bit-truncated.  They get corralled, which is not what I wanted. 
  56. //      Another trick I had to employ was splitting large numeric constants 
  57. //      into two pieces.  Apparently, you can't specify 0xffffffff.  It gets 
  58. //      set to 0.  Everything up to 0x7fffffff works fine.  So, I used 
  59. //      some shifting and bitwise operators to get the needed constants. 
  60. // 
  61. //      A word on optimization: it isn't optimized.  My chief concern was 
  62. //      to get it working, and it is fast enough for my needs.  If, however, 
  63. //      you intend to try to brute force some hash values with this, either 
  64. //      it will need some serious optimizations done, or you should be 
  65. //      using one of the freely available C implementations. 
  66. // 
  67. //////////////////////////////////////////////////////////////////////////// 
  68. class SHA { 
  69.     var $A, $B, $C, $D, $E;  // result variables 
  70.     var $ta, $tb, $tc, $td, $te;  // temp variables 
  71.     var $K0_19, $K20_39, $K40_59, $K60_79; 
  72.  
  73.     var $buffer; 
  74.     var $buffsize; 
  75.     var $totalsize; 
  76.  
  77.     function SHA () { 
  78.         $this->init(); 
  79.     } 
  80.  
  81.     function init () { 
  82.          // The long constants can't be used for some dumb reason. 
  83.     $this->A = 0x6745 << 16 | 0x2301; 
  84.     $this->B = 0xefcd << 16 | 0xab89; 
  85.     $this->C = 0x98ba << 16 | 0xdcfe; 
  86.     $this->D = 0x1032 << 16 | 0x5476; 
  87.     $this->E = 0xc3d2 << 16 | 0xe1f0; 
  88.     $this->ta = $this->A; 
  89.     $this->tb = $this->B; 
  90.     $this->tc = $this->C; 
  91.     $this->td = $this->D; 
  92.     $this->te = $this->E; 
  93.     $this->K0_19 = 0x5a82 << 16 | 0x7999; 
  94.     $this->K20_39 = 0x6ed9 << 16 | 0xeba1; 
  95.     $this->K40_59 = 0x8f1b << 16 | 0xbcdc; 
  96.     $this->K60_79 = 0xca62 << 16 | 0xc1d6; 
  97.  
  98.         $this->buffer = array(); 
  99.         $this->buffsize = 0; 
  100.         $this->totalsize = 0; 
  101.     } 
  102.  
  103.     function bytes_to_words( $block ) { 
  104.         $nblk = array(); 
  105.         for( $i=0; $i<16; ++$i) { 
  106.             $index = $i * 4; 
  107.             $nblk[$i] = 0; 
  108.             $nblk[$i] |= ($block[$index] & 0xff) << 24; 
  109.             $nblk[$i] |= ($block[$index+1] & 0xff) << 16; 
  110.             $nblk[$i] |= ($block[$index+2] & 0xff) << 8; 
  111.             $nblk[$i] |= ($block[$index+3] & 0xff); 
  112.         } 
  113.         return $nblk; 
  114.     } 
  115.  
  116.     function pad_block( $block, $size ) { 
  117.          // Returns a block that is a multiple of 512 bits long 
  118.         $blksize = sizeof( $block ); 
  119.         $bits = $size * 8; 
  120.  
  121.          // Always pad with 0x80, then add as many zeros as necessary to 
  122.          // make the message 64 bits short of 512.  Then add the 64-bit size. 
  123.         $newblock = $block; 
  124.         $newblock[] = 0x80;  // push 0x80 onto the end 
  125.          // Add the zeros 
  126.         while((sizeof($newblock) % 64) != 56) { 
  127.             $newblock[] = 0; 
  128.         } 
  129.          // Add the size 
  130.         for ($i=0; $i<8; ++$i) { 
  131.             $newblock[] = ($i<4) ? 0 : ($bits >> ((7-$i)*8)) & 0xff; 
  132.         } 
  133.  
  134.         return $newblock; 
  135.     } 
  136.  
  137.     function circ_shl( $num, $amt ) { 
  138.         $leftmask = 0xffff | (0xffff << 16); 
  139.         $leftmask <<= 32 - $amt; 
  140.         $rightmask = 0xffff | (0xffff << 16); 
  141.         $rightmask <<= $amt; 
  142.         $rightmask = ~$rightmask; 
  143.  
  144.         $remains = $num & $leftmask; 
  145.         $remains >>= 32 - $amt; 
  146.         $remains &= $rightmask; 
  147.  
  148.         $res = ($num << $amt) | $remains; 
  149.  
  150.         return $res; 
  151.     } 
  152.  
  153.     function f0_19( $x, $y, $z ) { 
  154.         return ($x & $y) | (~$x & $z); 
  155.     } 
  156.  
  157.     function f20_39( $x, $y, $z ) { 
  158.         return ($x ^ $y ^ $z); 
  159.     } 
  160.  
  161.     function f40_59( $x, $y, $z ) { 
  162.         return ($x & $y) | ($x & $z) | ($y & $z); 
  163.     } 
  164.  
  165.     function f60_79( $x, $y, $z ) { 
  166.         return $this->f20_39( $x, $y, $z ); 
  167.     } 
  168.  
  169.     function expand_block( $block ) { 
  170.         $nblk = $block; 
  171.         for( $i=16; $i<80; ++$i ) { 
  172.             $nblk[$i] = $this->circ_shl( 
  173.                     $nblk[$i-3] ^ $nblk[$i-8] ^ $nblk[$i-14] ^ $nblk[$i-16], 1 
  174.                 ); 
  175.         } 
  176.  
  177.         return $nblk; 
  178.     } 
  179.  
  180.     function print_bytes( $bytes ) { 
  181.         $len = sizeof( $bytes ); 
  182.         for( $i=0; $i<$len; ++$i) { 
  183.             $str[] = sprintf(  "%02x", $bytes[$i] ); 
  184.         } 
  185.  
  186.         print( join(  ", ", $str ) .  "\n" ); 
  187.     } 
  188.  
  189.     function wordstr( $word ) { 
  190.         return sprintf(  
  191.              "%04x%04x", ($word >> 16) & 0xffff, $word & 0xffff 
  192.             ); 
  193.     } 
  194.  
  195.     function print_words( $words ) { 
  196.         $len = sizeof( $words ); 
  197.         for( $i=0; $i<$len; ++$i) { 
  198.             $str[] = $this->wordstr( $words[$i] ); 
  199.         } 
  200.          
  201.         print( join(  ", ", $str ) .  "\n" ); 
  202.     } 
  203.  
  204.     function hash_to_string( $hash ) { 
  205.         $len = sizeof( $hash ); 
  206.         for ($i=0; $i<$len; ++$i) { 
  207.             $astr[] = $this->wordstr( $hash[$i] ); 
  208.         } 
  209.         return join(  "", $astr ); 
  210.     } 
  211.  
  212.      // Add simply adds two numbers.  It is provided for compatibility on 
  213.      // platforms that only support a 31 bit add (there are a few, apparently) 
  214.     function add( $a, $b ) { 
  215.         $ma = ($a >> 16) & 0xffff; 
  216.         $la = ($a) & 0xffff; 
  217.         $mb = ($b >> 16) & 0xffff; 
  218.         $lb = ($b) & 0xffff; 
  219.  
  220.         $ls = $la + $lb; 
  221.          // Carry 
  222.         if ($ls > 0xffff) { 
  223.             $ma += 1; 
  224.             $ls &= 0xffff; 
  225.         } 
  226.  
  227.          // MS add 
  228.         $ms = $ma + $mb; 
  229.         $ms &= 0xffff; 
  230.  
  231.          // Works because the bitwise operators are 32 bit 
  232.         $result = ($ms << 16) | $ls; 
  233.         return $result; 
  234.     } 
  235.  
  236.     function process_block( $blk ) { 
  237.         $blk = $this->expand_block( $blk ); 
  238.  
  239.         for( $i=0; $i<80; ++$i ) { 
  240.             $temp = $this->circ_shl( $this->ta, 5 ); 
  241.             if ($i<20) { 
  242.                 $f = $this->f0_19( $this->tb, $this->tc, $this->td ); 
  243.                 $k = $this->K0_19; 
  244.             } 
  245.             elseif ($i<40) { 
  246.                 $f = $this->f20_39( $this->tb, $this->tc, $this->td ); 
  247.                 $k = $this->K20_39; 
  248.             } 
  249.             elseif ($i<60) { 
  250.                 $f = $this->f40_59( $this->tb, $this->tc, $this->td ); 
  251.                 $k = $this->K40_59; 
  252.             } 
  253.             else { 
  254.                 $f = $this->f60_79( $this->tb, $this->tc, $this->td ); 
  255.                 $k = $this->K60_79; 
  256.             } 
  257.  
  258.             $temp = $this->add( $temp, $f ); 
  259.             $temp = $this->add( $temp, $this->te ); 
  260.             $temp = $this->add( $temp, $blk[$i] ); 
  261.             $temp = $this->add( $temp, $k ); 
  262.  
  263.             $this->te = $this->td; 
  264.             $this->td = $this->tc; 
  265.             $this->tc = $this->circ_shl( $this->tb, 30 ); 
  266.             $this->tb = $this->ta; 
  267.             $this->ta = $temp; 
  268.         } 
  269.  
  270.         $this->A = $this->add( $this->A, $this->ta ); 
  271.         $this->B = $this->add( $this->B, $this->tb ); 
  272.         $this->C = $this->add( $this->C, $this->tc ); 
  273.         $this->D = $this->add( $this->D, $this->td ); 
  274.         $this->E = $this->add( $this->E, $this->te ); 
  275.     } 
  276.  
  277.     function update ( $bytes ) { 
  278.         $length = sizeof( $bytes ); 
  279.         $index = 0; 
  280.  
  281.          // Process each full block 
  282.         while (($length - $index) + $this->buffsize >= 64) { 
  283.             for( $i=$this->buffsize; $i<64; ++$i) { 
  284.                 $this->buffer[$i] = $bytes[$index + $i - $this->buffsize]; 
  285.             } 
  286.             $this->process_block( $this->bytes_to_words( $this->buffer ) ); 
  287.             $index += 64; 
  288.             $this->buffsize = 0; 
  289.         } 
  290.  
  291.          // Any remaining bytes that do not make up a full block need to be' 
  292.          // added into the buffer for the next update (or final) 
  293.         $remaining = $length - $index; 
  294.         for( $i=0; $i<$remaining; ++$i) { 
  295.             $this->buffer[$this->buffisze + $i] = $bytes[$index + $i]; 
  296.         } 
  297.         $this->buffsize += $remaining; 
  298.         $this->totalsize += $length; 
  299.     } 
  300.  
  301.     function final() { 
  302.          // Pad and process the buffer 
  303.         for( $i=0; $i<$this->buffsize; ++$i) { 
  304.             $last_block[$i] = $this->buffer[$i]; 
  305.         } 
  306.         $this->buffsize = 0; 
  307.          // Pad the block 
  308.         $last_block = $this->pad_block( $last_block, $this->totalsize ); 
  309.          // Process the last one (or two) block(s) 
  310.         $index = 0; 
  311.         $length = sizeof( $last_block ); 
  312.         while( $index < $length ) 
  313.         { 
  314.             $block = array(); 
  315.             for( $i=0; $i<64; ++$i) { 
  316.                 $block[$i] = $last_block[$i + $index]; 
  317.             } 
  318.             $this->process_block( $this->bytes_to_words( $block ) ); 
  319.             $index += 64; 
  320.         } 
  321.  
  322.         $result[0] = $this->A; 
  323.         $result[1] = $this->B; 
  324.         $result[2] = $this->C; 
  325.         $result[3] = $this->D; 
  326.         $result[4] = $this->E; 
  327.  
  328.         return $result; 
  329.     } 
  330.  
  331.     function hash_bytes( $bytes ) { 
  332.         $this->init(); 
  333.         $this->update( $bytes ); 
  334.         return $this->final(); 
  335.     } 
  336.  
  337.     function hash_string( $str ) { 
  338.         $len = strlen( $str ); 
  339.         for($i=0; $i<$len; ++$i) { 
  340.             $bytes[] = ord( $str[$i] ) & 0xff; 
  341.         } 
  342.         return $this->hash_bytes( $bytes ); 
  343.     } 
  344. ?> 
  345.  
  346.