init(); } function init() { $this->h[0] = (int)0x67452301; $this->h[1] = (int)0xefcdab89; $this->h[2] = (int)0x98badcfe; $this->h[3] = (int)0x10325476; $this->h[4] = (int)0xc3d2e1f0; } # $str MUST be 512 bits function hash_chunk($str) { # Unpack chunk into 32-bit LITTLE-ENDIAN blocks, then # re-base them to 0. # NOTE: Blizzard interprets the data as little-endian words, # while proper SHA1 uses big-endian. $W = unpack("V*", $str); for ($x = 0; $x < 16; $x++) $W[$x] = $W[$x + 1]; # expand 512 input bits into an additional 2048 bits # NOTE: Blizzard has the operands of this rotate left operation # flipped vs. proper SHA1. for ($x = 16; $x < 80; $x++) $W[$x] = $this->rl(1, $W[$x - 3] ^ $W[$x - 8] ^ $W[$x - 14] ^ $W[$x - 16]); $a = $this->h[0]; $b = $this->h[1]; $c = $this->h[2]; $d = $this->h[3]; $e = $this->h[4]; for ($x = 0; $x < 80; $x++) { if ($x < 20) $T = (($b & $c) | (~$b & $d)) + 0x5a827999; else if ($x < 40) $T = ($b ^ $c ^ $d) + 0x6ed9eba1; else if ($x < 60) $T = (($b & $c) | ($b & $d) | ($c & $d)) + 0x8f1bbcdc; else if ($x < 80) $T = ($b ^ $c ^ $d) + 0xca62c1d6; $T += $this->rl($a, 5) + $e + $W[$x]; $e = $d; $d = $c; $c = $this->rl($b, 30); $b = $a; $a = $T & 0xffffffff; } $this->h[0] = ($this->h[0] + $a) & 0xffffffff; $this->h[1] = ($this->h[1] + $b) & 0xffffffff; $this->h[2] = ($this->h[2] + $c) & 0xffffffff; $this->h[3] = ($this->h[3] + $d) & 0xffffffff; $this->h[4] = ($this->h[4] + $e) & 0xffffffff; } function add($data) { $need = 64 - strlen($this->pending); do { if ($need == 0) { $this->hash_chunk($this->pending); $this->pending = ''; $need = 64; } $this->pending .= substr($data, 0, $need); $data = substr($data, $need); $need = 64 - strlen($this->pending); } while ($need == 0); } function finish() { # if we have pending data, pad out this chunk if (strlen($this->pending)) { $this->hash_chunk(str_pad($this->pending, 64, "\0")); $this->pending = ''; } return $this->hexdigest(); } function hexdigest() { return sprintf("%08x%08x%08x%08x%08x", $this->h[0], $this->h[1], $this->h[2], $this->h[3], $this->h[4]); } function rl($value, $bits) { $value &= 0xffffffff; # NOTE: this both depends on and works around sign extension. # We must truncate $bits because Blizzard's code has the # operands reversed. $left = $value << ($bits & 31); $right = $value >> ((-$bits) & 31); $right &= (1 << ($bits & 31)) - 1; return ($left | $right); } } $bah = new SHA1_blizzard; $bah->add($_REQUEST['in']); printf("%s\n", $bah->finish()); ?>