<?php
/*
* A PHP implementation of the Secure Hash Algorithm, SHA-1, as defined
* in FIPS PUB 180-1
* Adjusted from the Javascript implementation by Joror (hide@address.com).
*
* Javascript Version 2.1 Copyright Paul Johnston 2000 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for details.
*/
class Sha1Lib
{
/*
* Configurable variables. You may need to tweak these to be compatible with
* the server-side, but the defaults work in most cases.
*/
var $hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
var $b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
var $chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
/*
* These are the functions you'll usually want to call
* They take string arguments and return either hex or base-64 encoded strings
*/
function hex_sha1($s){return $this->binb2hex($this->core_sha1($this->str2binb($s),strlen($s) * $this->chrsz));}
function b64_sha1($s){return $this->binb2b64($this->core_sha1($this->str2binb($s),strlen($s) * $this->chrsz));}
function str_sha1($s){return $this->binb2str($this->core_sha1($this->str2binb($s),strlen($s) * $this->chrsz));}
function hex_hmac_sha1($key, $data){ return $this->binb2hex($this->core_hmac_sha1($key, $data));}
function b64_hmac_sha1($key, $data){ return $this->binb2b64($this->core_hmac_sha1($key, $data));}
function str_hmac_sha1($key, $data){ return $this->binb2str($this->core_hmac_sha1($key, $data));}
/*
* Perform a simple self-test to see if the VM is working
*/
function sha1_vm_test()
{
return $this->hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
}
/*
* Calculate the SHA-1 of an array of big-endian words, and a bit $length
*/
function core_sha1($x, $len)
{
/* append padding */
$x[$len >> 5] |= 0x80 << (24 - $len % 32);
$x[(($len + 64 >> 9) << 4) + 15] = $len;
$w = Array();
$a = 1732584193;
$b = -271733879;
$c = -1732584194;
$d = 271733878;
$e = -1009589776;
for($i = 0; $i < sizeof($x); $i += 16)
{
$olda = $a;
$oldb = $b;
$oldc = $c;
$oldd = $d;
$olde = $e;
for($j = 0; $j < 80; $j++)
{
if ($j < 16)
$w[$j] = $x[$i + $j];
else
$w[$j] = $this->rol($w[$j-3] ^ $w[$j-8] ^ $w[$j-14] ^ $w[$j-16], 1);
$t = $this->safe_add( $this->safe_add($this->rol($a, 5), $this->sha1_ft($j, $b, $c, $d)),
$this->safe_add($this->safe_add($e, $w[$j]), $this->sha1_kt($j)));
$e = $d;
$d = $c;
$c = $this->rol($b, 30);
$b = $a;
$a = $t;
}
$a = $this->safe_add($a, $olda);
$b = $this->safe_add($b, $oldb);
$c = $this->safe_add($c, $oldc);
$d = $this->safe_add($d, $oldd);
$e = $this->safe_add($e, $olde);
}
return Array($a, $b, $c, $d, $e);
}
/*
* Joror: PHP does not have the java(script) >>> operator, so this is a
* replacement function. Credits to Terium.
*/
function zerofill_rightshift($a, $b)
{
$z = hexdec(80000000);
if ($z & $a)
{
$a >>= 1;
$a &= (~ $z);
$a |= 0x40000000;
$a >>= ($b-1);
}
else
{
$a >>= $b;
}
return $a;
}
/*
* Perform the appropriate triplet combination function for the current
* iteration
*/
function sha1_ft($t, $b, $c, $d)
{
if($t < 20) return ($b & $c) | ((~$b) & $d);
if($t < 40) return $b ^ $c ^ $d;
if($t < 60) return ($b & $c) | ($b & $d) | ($c & $d);
return $b ^ $c ^ $d;
}
/*
* Determine the appropriate additive constant for the current iteration
* Silly php does not understand the inline-if operator well when nested,
* so that's why it's ()ed now.
*/
function sha1_kt($t)
{
return ($t < 20) ? 1518500249 : (($t < 40) ? 1859775393 :
(($t < 60) ? -1894007588 : -899497514));
}
/*
* Calculate the HMAC-SHA1 of a key and some data
*/
function core_hmac_sha1($key, $data)
{
$bkey = $this->str2binb($key);
if(sizeof($bkey) > 16) $bkey = $this->core_sha1($bkey, sizeof($key) * $this->chrsz);
$ipad = Array();
$opad = Array();
for($i = 0; $i < 16; $i++)
{
$ipad[$i] = $bkey[$i] ^ 0x36363636;
$opad[$i] = $bkey[$i] ^ 0x5C5C5C5C;
}
$hash = $this->core_sha1(array_merge($ipad,$this->str2binb($data)), 512 + sizeof($data) * $this->chrsz);
return $this->core_sha1(array_merge($opad,$hash), 512 + 160);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add($x, $y)
{
$lsw = ($x & 0xFFFF) + ($y & 0xFFFF);
$msw = ($x >> 16) + ($y >> 16) + ($lsw >> 16);
return ($msw << 16) | ($lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function rol($num, $cnt)
{
return ($num << $cnt) | $this->zerofill_rightshift($num, (32 - $cnt));
}
/*
* Convert an 8-bit or 16-bit string to an array of big-endian words
* In 8-bit function, characters >255 have their hi-byte silently ignored.
*/
function str2binb($str)
{
$bin = Array();
$mask = (1 << $this->chrsz) - 1;
for($i = 0; $i < strlen($str) * $this->chrsz; $i += $this->chrsz)
$bin[$i >> 5] |= (ord($str{$i / $this->chrsz}) & $mask) << (24 - $i%32);
return $bin;
}
/*
* Convert an array of big-endian words to a string
*/
function binb2str($bin)
{
$str = "";
$mask = (1 << $this->chrsz) - 1;
for($i = 0; $i < sizeof($bin) * 32; $i += $this->chrsz)
$str .= chr($this->zerofill_rightshift($bin[$i>>5], 24 - $i%32) & $mask);
return $str;
}
/*
* Convert an array of big-endian words to a hex string.
*/
function binb2hex($binarray)
{
$hex_tab = $this->hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
$str = "";
for($i = 0; $i < sizeof($binarray) * 4; $i++)
{
$str .= $hex_tab{($binarray[$i>>2] >> ((3 - $i%4)*8+4)) & 0xF} .
$hex_tab{($binarray[$i>>2] >> ((3 - $i%4)*8 )) & 0xF};
}
return $str;
}
/*
* Convert an array of big-endian words to a base-64 string
*/
function binb2b64($binarray)
{
$tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
$str = "";
for($i = 0; i < sizeof($binarray) * 4; $i += 3)
{
$triplet = ((($binarray[$i >> 2] >> 8 * (3 - $i %4)) & 0xFF) << 16)
| ((($binarray[$i+1 >> 2] >> 8 * (3 - ($i+1)%4)) & 0xFF) << 8 )
| (($binarray[$i+2 >> 2] >> 8 * (3 - ($i+2)%4)) & 0xFF);
for($j = 0; $j < 4; $j++)
{
if($i * 8 + $j * 6 > sizeof($binarray) * 32) $str .= $this->b64pad;
else $str .= $tab{($triplet >> 6*(3-j)) & 0x3F};
}
}
return $str;
}
}
if ( !function_exists('sha1') )
{
function sha1( $string, $raw_output = false )
{
$library = new Sha1Lib();
return $raw_output ? $library->str_sha1($string) : $library->hex_sha1($string);
}
}
?>