Security: SHA256 Hashing Algorithm Updated v1.1.1

Small, short code snippets that other people may find useful. Do you have a good regex that you would like to share? Share it! Even better, the code can be commented on, and improved.

Moderator: General Moderators

User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Security: SHA256 Hashing Algorithm Updated v1.1.1

Post by feyd »

Edit:2006-01-23
v1.1.1 is now available for download from the newly finished (yeah, long time coming) demo page. Only a very minor tweak to a behaviour was made in the SHA256 algorithm file.

Note: the files below are v1.1.0, not v1.1.1.
----

I spent the last day or so updating the previous version. After I get back from my business trip, I'll put together a demo page, if someone hasn't already by then. The new version is broken into three scripts. One for the base class definitions, one for SHA256 itself, and one for testing the hashing algorithm.

Features updated or added in this release:
  • SHA256 can now hash local files and URLs (protocol support withstanding).
  • Reorganized object logic and a few other things. Appears to have increased performance dramatically.
    I was getting around a quarter of a second for processing a simple string previously. Now, it has been down around a tenth of a second.

Code: Select all

<?php


/*******************************************************************************
 *
 *	Hashing abstract base class definition file.
 *
 *	(C) Copyright 2005 Developer's Network. All rights reserved.
 *
 *	This library is free software; you can redistribute it and/or modify it
 *	under the terms of the GNU Lesser General Public License as published by the
 *	Free Software Foundation; either version 2.1 of the License, or (at your
 *	option) any later version.
 *
 *	This library is distributed in the hope that it will be useful, but WITHOUT
 *	ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 *	FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
 *	for more details.
 *
 *	You should have received a copy of the GNU Lesser General Public License
 *	along with this library; if not, write to the
 *		Free Software Foundation, Inc.
 *		59 Temple Place, Suite 330,
 *		Boston, MA 02111-1307 USA 
 *	
 *----- Version 1.1.0 ----------------------------------------------------------
 *
 *	These classes generate PHP level error when an error, warning, or notice of
 *	some kind happens during execution. This allows you to "hide" any of these
 *	like you would any other function's error output using error_reporting().
 *
 *----- History ----------------------------------------------------------------
 *
 *		1.1.0	Split from hash_sha256.php
 *
 *----- Source Control Information ---------------------------------------------
 *
 *	$Workfile: hash_base.php $
 *	$Author: Feyd $
 *	$JustDate: 05.04.06 $
 *	$Revision: 4 $
 *
 *	$Header: /inc/hash_base.php 4     05.04.06 2:57p Feyd $
 *
 ******************************************************************************/


//	hashing class state and register storage object. Abstract base class only.
class hashData
{
	//	final hash
	var $hash = null;
}


//	hashing class message object. Abstract base class only.
class hashMessage
{
	//	retrieve the next chunk
	function nextChunk()
	{
		trigger_error('hashMessage::nextChunk() NOT IMPLEMENTED', E_USER_WARNING);
		return false;
	}
	
	//	retrieve the current chunk
	function currentChunk()
	{
		trigger_error('hashMessage::currentChunk() NOT IMPLEMENTED', E_USER_WARNING);
		return false;
	}
}


//	hashing class message object for files. Abstract base class only.
class hashMessageFile extends hashMessage
{
	function hashMessageFile( $filename )
	{
		trigger_error('hashMessageFile::hashMessageFile() NOT IMPLEMENTED', E_USER_WARNING);
		return false;
	}
}


//	hashing class message object for URLs. Abstract base class only.
class hashMessageURL extends hashMessage
{
	function hashMessageURL( $url )
	{
		trigger_error('hashMessageURL::hashMessageURL() NOT IMPLEMENTED', E_USER_WARNING);
		return false;
	}
}


//	hashing class. Abstract base class only.
class hash
{
	//	The base modes are:
	//		'bin' - binary output (most compact)
	//		'bit' - bit output (largest)
	//		'hex' - hexidecimal (default, medium)
	//		'HEX' - hexidecimal (upper case)

	//	perform a hash on a string
	function hash($str, $mode = 'hex')
	{
		trigger_error('hash::hash() NOT IMPLEMENTED', E_USER_WARNING);
		return false;
	}

	//	chop the resultant hash into $length byte chunks
	function hashChunk($str, $length, $mode = 'hex')
	{
		trigger_error('hash::hashChunk() NOT IMPLEMENTED', E_USER_WARNING);
		return false;
	}
	
	//	perform a hash on a file.
	function hashFile($filename, $mode = 'hex')
	{
		trigger_error('hash::hashFile() NOT IMPLEMENTED', E_USER_WARNING);
		return false;
	}

	//	chop the resultant hash into $length byte chunks
	function hashChunkFile($filename, $length, $mode = 'hex')
	{
		trigger_error('hash::hashChunkFile() NOT IMPLEMENTED', E_USER_WARNING);
		return false;
	}
	
	//	perform a hash on a URL
	function hashURL($url, $timeout = null, $mode = 'hex')
	{
		trigger_error('hash::hashURL() NOT IMPLEMENTED', E_USER_WARNING);
		return false;
	}

	//	chop the resultant hash into $length byte chunks
	function hashChunkURL($url, $length, $timeout = null, $mode = 'hex')
	{
		trigger_error('hash::hashChunkURL() NOT IMPLEMENTED', E_USER_WARNING);
		return false;
	}
}

/*****************************************************************************
 *	$History: hash_base.php $
 * 
 * *****************  Version 4  *****************
 * User: Feyd         Date: 05.04.06   Time: 2:57p
 * Updated in $/inc
 * adjust/modify some documentation for release of 1.1.0
 * 
 * *****************  Version 3  *****************
 * User: Feyd         Date: 05.04.05   Time: 1:26a
 * Updated in $/inc
 * hashURL() finished.
 * 
 * *****************  Version 2  *****************
 * User: Feyd         Date: 05.04.04   Time: 12:40a
 * Updated in $/inc
 * Finished hashFile(). Next up, hashURL().
 * 
 * *****************  Version 1  *****************
 * User: Feyd         Date: 05.04.03   Time: 3:53a
 * Created in $/inc
 * Initial source control addition.
 *****************************************************************************/

/* EOF :: Document Settings: tab:4; */

?>
Last edited by feyd on Mon Jan 23, 2006 5:52 am, edited 2 times in total.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

Code: Select all

<?php


/*******************************************************************************
 *
 *	SHA256 static class for PHP4
 *	implemented by feyd _at_ devnetwork .dot. net
 *	specification from http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf
 *
 *	(C) Copyright 2005 Developer's Network. All rights reserved.
 *
 *	This library is free software; you can redistribute it and/or modify it
 *	under the terms of the GNU Lesser General Public License as published by the
 *	Free Software Foundation; either version 2.1 of the License, or (at your
 *	option) any later version.
 *
 *	This library is distributed in the hope that it will be useful, but WITHOUT
 *	ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 *	FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
 *	for more details.
 *
 *	You should have received a copy of the GNU Lesser General Public License
 *	along with this library; if not, write to the
 *		Free Software Foundation, Inc.
 *		59 Temple Place, Suite 330,
 *		Boston, MA 02111-1307 USA 
 *	
 *	Thanks to CertainKey Inc. for providing some example outputs in Javascript
 *
 *----- Version 1.1.0 ----------------------------------------------------------
 *
 *	These classes generate PHP level error when an error, warning, or notice of
 *	some kind happens during execution. This allows you to "hide" any of these
 *	like you would any other function's error output using error_reporting().
 *
 *  ---------------------------------
 *
 *	Function:
 *		SHA256::hash()
 *
 *	Syntax:
 *		string SHA256::hash( string message[, string format ])
 *
 *	Description:
 *		SHA256::hash() is intended to hash a single string, of nominal length
 *		(memory permitting.) The entire string is loaded into memory, broken
 *		into chunks and appended with the hashing fill algorithm.
 *
 *		SHA256::hash() is a static function that must be called with `message`
 *		and optionally `format`. Possible values for `format` are:
 *		'hex'	default; hexidecimal string output (lower case)
 *		'HEX'	hexidecimal string output (upper case)
 *		'bin'	binary string output
 *		'bit'	bit level output (256 character '1' & '0' string)
 *
 *		Failures return FALSE.
 *
 *	Usage:
 *		$hash = SHA256::hash('string to hash');
 *
 *  ---------------------------------
 *
 *	Function:
 *		SHA256::hashFile()
 *
 *	Syntax:
 *		string SHA256::hashFile( string filename[, string format ])
 *
 *	Description:
 *		SHA256::hashFile() is intended to hash a local file _only_. STDIN is
 *		not supported at this time, nor is any other protocol other than 'file.'
 *
 *		SHA256::hashFile() is a static function that must be called with a
 *		`filename` and optionally `format`. Possible values for `format` are:
 *		'hex'	default; hexidecimal string output (lower case)
 *		'HEX'	hexidecimal string output (upper case)
 *		'bin'	binary string output
 *		'bit'	bit level output (256 character '1' & '0' string)
 *
 *		Failures return FALSE.
 *
 *	Usage:
 *		$hash = SHA256::hashFile('/path/to/file.ext');
 *
 *	Note:
 *		This function will not accept any other protocols other than 'file'.
 *		This is due to the use of fstat(), among other reasons.
 *
 *  ---------------------------------
 *
 *	Function:
 *		SHA256::hashURL()
 *
 *	Syntax:
 *		string SHA256::hashURL( string url[, string format ])
 *
 *	Description:
 *		SHA256::hashURL() is intended to hash a url. 'http://' is optional, if
 *		you want to use it. The function checks if allow_url_fopen is enabled.
 *		If it is, the url is passed through fopen(), so all protocols supported
 *		your installation of PHP are supported automatically. If allow_url_fopen
 *		is off, fsockopen is attempted to be used. This version only supports
 *		http requests through fsockopen. So beware.
 *
 *		SHA256::hashURL() is a static function that must be called with a `url`
 *		and optionally `format`. Possible values for `format` are:
 *		'hex'	default; hexidecimal string output (lower case)
 *		'HEX'	hexidecimal string output (upper case)
 *		'bin'	binary string output
 *		'bit'	bit level output (256 character '1' & '0' string)
 *
 *		Failures return FALSE.
 *
 *		If a protocol is not specified, 'http' is assumed.
 *
 *	Usage:
 *		$hash = SHA256::hashURL('http://www.site.com');
 *
 *	Note:
 *		The protocol used _must_ be registered with your PHP with
 *		allow_url_fopen enabled, or must be 'http'.
 *
 *----- History ----------------------------------------------------------------
 *
 *		1.1.0	Split out generic 'hash' class to a seperate include, for future
 *					hashes to use.
 *				Changed handling around to allow for very large message chunks
 *					for files and URL handling (does not affect string hashes).
 *				Added file hashing support. see notes above for details.
 *				Added url hashing support. see notes above for details.
 *				Split testing to a seperate file.
 *				Initial check-in to source control
 *				Removed octal output as a future option, due to incomplete usage
 *				Added bit and upper case hex output
 *
 *		1.0.1	Potential integer truncation bug fix for various operating
 *					systems and processor combinations.
 *
 *		1.0.0	First version made available.
 *
 *----- Source Control Information ---------------------------------------------
 *
 *	$Workfile: hash_sha256.php $
 *	$Author: Feyd $
 *	$JustDate: 05.04.06 $
 *	$Revision: 4 $
 *
 *	$Header: /inc/hash_sha256.php 4     05.04.06 2:46p Feyd $
 *
 ******************************************************************************/


//	hash base class definition file
require_once('hash_base.php');


/*==============================================================================
 *	SHA256 Main Class
 *============================================================================*/


class SHA256 extends hash
{
	// hash a known string of data
	function hash($str, $mode = 'hex')
	{
		return SHA256::_hash( '', $str, $mode );
	}
	
	//	hash a file
	function hashFile($filename, $mode = 'hex')
	{
		return SHA256::_hash( 'File', $filename, $mode );
	}
	
	//	hash a URL
	function hashURL($url, $mode = 'hex')
	{
		return SHA256::_hash( 'URL', $url, $mode );
	}

	
	//	-------------------------------
	//	BEGIN INTERNAL FUNCTIONS
	//	-------------------------------
	
	//	the actual hash interface function, which ~dynamically switches types.
	function _hash( $type, $str, $mode )
	{
		$modes = array( 'hex', 'bin', 'bit' );
		$ret = false;
		
		if(!in_array(strtolower($mode), $modes))
		{
			trigger_error('mode specified is unrecognized: ' . $mode, E_USER_WARNING);
		}
		else
		{
			$data =& new SHA256Data( $type, $str );

			SHA256::compute($data);

			$func = array('SHA256', 'hash' . $mode);
			if(is_callable($func))
			{
				$func = 'hash' . $mode;
				$ret = SHA256::$func($data);
				//$ret = call_user_func($func, $data);
				
				if( $mode === 'HEX' )
				{
					$ret = strtoupper( $ret );
				}
			}
			else
			{
				trigger_error('SHA256::hash' . $mode . '() NOT IMPLEMENTED.', E_USER_WARNING);
			}
		}
		
		return $ret;
	}
		
	
	//	32-bit summation
	function sum()
	{
		$T = 0;
		for($x = 0, $y = func_num_args(); $x < $y; $x++)
		{
			//	argument
			$a = func_get_arg($x);
			
			//	carry storage
			$c = 0;
			
			for($i = 0; $i < 32; $i++)
			{
				//	sum of the bits at $i
				$j = (($T >> $i) & 1) + (($a >> $i) & 1) + $c;
				//	carry of the bits at $i
				$c = ($j >> 1) & 1;
				//	strip the carry
				$j &= 1;
				//	clear the bit
				$T &= ~(1 << $i);
				//	set the bit
				$T |= $j << $i;
			}
		}
		
		return $T;
	}
	
	
	//	compute the hash. This is the real hashing function.
	function compute(&$hashData)
	{
		static $vars = 'abcdefgh';
		static $K = null;
		
		if($K === null)
		{
			$K = array (
				 1116352408,	 1899447441,	-1245643825,	 -373957723,
				  961987163,	 1508970993,	-1841331548,	-1424204075,
				 -670586216,	  310598401,	  607225278,	 1426881987,
				 1925078388,	-2132889090,	-1680079193,	-1046744716,
				 -459576895,	 -272742522,	  264347078,	  604807628,
				  770255983,	 1249150122,	 1555081692,	 1996064986,
				-1740746414,	-1473132947,	-1341970488,	-1084653625,
				 -958395405,	 -710438585,	  113926993,	  338241895,
				  666307205,	  773529912,	 1294757372,	 1396182291,
				 1695183700,	 1986661051,	-2117940946,	-1838011259,
				-1564481375,	-1474664885,	-1035236496,	 -949202525,
				 -778901479,	 -694614492,	 -200395387,	  275423344,
				  430227734,	  506948616,	  659060556,	  883997877,
				  958139571,	 1322822218,	 1537002063,	 1747873779,
				 1955562222,	 2024104815,	-2067236844,	-1933114872,
				-1866530822,	-1538233109,	-1090935817,	 -965641998,
				);
		}
		
		$W = array();
		while(($chunk = $hashData->message->nextChunk()) !== false)
		{
			//	initialize the registers
			for($j = 0; $j < 8; $j++)
				${$vars{$j}} = $hashData->hash[$j];
			
			//	the SHA-256 compression function
			for($j = 0; $j < 64; $j++)
			{
				if($j < 16)
				{
					$T1  = ord($chunk{$j*4  }) & 0xFF; $T1 <<= 8;
					$T1 |= ord($chunk{$j*4+1}) & 0xFF; $T1 <<= 8;
					$T1 |= ord($chunk{$j*4+2}) & 0xFF; $T1 <<= 8;
					$T1 |= ord($chunk{$j*4+3}) & 0xFF;
					$W[$j] = $T1;
				}
				else
				{
					$W[$j] = SHA256::sum(((($W[$j-2] >> 17) & 0x00007FFF) | ($W[$j-2] << 15)) ^ ((($W[$j-2] >> 19) & 0x00001FFF) | ($W[$j-2] << 13)) ^ (($W[$j-2] >> 10) & 0x003FFFFF), $W[$j-7], ((($W[$j-15] >> 7) & 0x01FFFFFF) | ($W[$j-15] << 25)) ^ ((($W[$j-15] >> 18) & 0x00003FFF) | ($W[$j-15] << 14)) ^ (($W[$j-15] >> 3) & 0x1FFFFFFF), $W[$j-16]);
				}

				$T1 = SHA256::sum($h, ((($e >> 6) & 0x03FFFFFF) | ($e << 26)) ^ ((($e >> 11) & 0x001FFFFF) | ($e << 21)) ^ ((($e >> 25) & 0x0000007F) | ($e << 7)), ($e & $f) ^ (~$e & $g), $K[$j], $W[$j]);
				$T2 = SHA256::sum(((($a >> 2) & 0x3FFFFFFF) | ($a << 30)) ^ ((($a >> 13) & 0x0007FFFF) | ($a << 19)) ^ ((($a >> 22) & 0x000003FF) | ($a << 10)), ($a & $b) ^ ($a & $c) ^ ($b & $c));
				$h = $g;
				$g = $f;
				$f = $e;
				$e = SHA256::sum($d, $T1);
				$d = $c;
				$c = $b;
				$b = $a;
				$a = SHA256::sum($T1, $T2);
			}
			
			//	compute the next hash set
			for($j = 0; $j < 8; $j++)
				$hashData->hash[$j] = SHA256::sum(${$vars{$j}}, $hashData->hash[$j]);
		}
	}
	
	
	//	set up the display of the hash in hex.
	function hashHex(&$hashData)
	{
		$str = '';
		
		reset($hashData->hash);
		do
		{
			$str .= sprintf('%08x', current($hashData->hash));
		}
		while(next($hashData->hash));
		
		return $str;
	}
	
	
	//	set up the output of the hash in binary
	function hashBin(&$hashData)
	{
		$str = '';
		
		reset($hashData->hash);
		do
		{
			$str .= pack('N', current($hashData->hash));
		}
		while(next($hashData->hash));
		
		return $str;
	}
	
	
	//	set up the output of the hash in bits
	function hashBit(&$hashData)
	{
		$str = '';
		
		reset($hashData->hash);
		do
		{
			$t = current($hashData->hash);
			for($i = 31; $i >= 0; $i--)
			{
				$str .= ($t & (1 << $i) ? '1' : '0');
			}
		}
		while(next($hashData->hash));
		
		return $str;
	}
}


/*==============================================================================
 *	SHA256 Data Class
 *============================================================================*/


class SHA256Data extends hashData
{
	function SHA256Data( $type, $str )
	{
		$type = 'SHA256Message' . $type;
		$this->message =& new $type( $str );
		
		//	H(0)
		$this->hash = array
		(
			 1779033703,	-1150833019,
			 1013904242,	-1521486534,
			 1359893119,	-1694144372,
			  528734635,	 1541459225,
		);
	}
}


/*==============================================================================
 *	SHA256 Message Classes
 *============================================================================*/


class SHA256Message extends hashMessage
{
	function SHA256Message( $str )
	{
		$str .= $this->calculateFooter( strlen( $str ) );
		
		//	break the binary string into 512-bit blocks
		preg_match_all( '#.{64}#s', $str, $this->chunk );
		$this->chunk = $this->chunk[0];
		
		$this->curChunk = -1;
	}
	
	//	retrieve the next chunk of the message
	function nextChunk()
	{
		if( is_array($this->chunk) && ($this->curChunk >= -1) && isset($this->chunk[$this->curChunk + 1]) )
		{
			$this->curChunk++;
			$ret =& $this->chunk[$this->curChunk];
		}
		else
		{
			$this->chunk = null;
			$this->curChunk = -1;
			$ret = false;
		}
		
		return $ret;
	}
	
	//	retrieve the current chunk of the message
	function currentChunk()
	{
		if( is_array($this->chunk) )
		{
			if( $this->curChunk == -1 )
			{
				$this->curChunk = 0;
			}
			if( ($this->curChunk >= 0) && isset($this->chunk[$this->curChunk]) )
			{
				$ret =& $this->chunk[$this->curChunk];
			}
		}
		else
		{
			$ret = false;
		}
		
		return $ret;
	}
	
	
	//	internal static function calculateFooter() which, calculates the footer appended to all messages
	function calculateFooter( $numbytes )
	{
		$M =& $numbytes;
		$L1 = ($M >> 28) & 0x0000000F;	//	top order bits
		$L2 = $M << 3;	//	number of bits
		$l = pack('N*', $L1, $L2);

		//	64 = 64 bits needed for the size mark. 1 = the 1 bit added to the
		//	end. 511 = 511 bits to get the number to be at least large enough
		//	to require one block. 512 is the block size.
		$k = $L2 + 64 + 1 + 511;
		$k -= $k % 512 + $L2 + 64 + 1;
		$k >>= 3;	//	convert to byte count
		
		$footer = chr(128) . str_repeat(chr(0), $k) . $l;
		
		assert('($M + strlen($footer)) % 64 == 0');
		
		return $footer;
	}
}


class SHA256MessageFile extends hashMessageFile
{
	function SHA256MessageFile( $filename )
	{
		$this->filename = $filename;
		$this->fp = false;
		$this->size = false;
		$this->append = '';
		$this->chunk = '';
		$this->more = true;
		
		$info = parse_url( $filename );
		if( isset( $info['scheme'] ) && !in_array(strtolower( $info['scheme'] ), array('php','file')) )
		{
			trigger_error('SHA256MessageFile(' . var_export($filename,true) . ' does not handle the ' . var_export( $info['scheme'], true ) . ' protocol.', E_USER_ERROR);
			return;
		}
		
		$this->fp = (is_readable( $filename ) ? @fopen( $filename, 'rb' ) : false);
		
		if( $this->fp === false )
		{
			trigger_error('SHA256MessageFile(' . var_export($filename,true) . '): unable to open file for SHA256 hashing.', E_USER_ERROR);
		}

		$stat = @fstat( $this->fp );
		
		if( $stat === false )
		{
			trigger_error('SHA256MessageFile(' . var_export($filename,true) . '): unable to pull file status information.', E_USER_ERROR);
			return;
		}
		
		$this->append = SHA256Message::calculateFooter($this->size = intval($stat['size']));
	}
	
	//	load the next chunk from the file.
	function nextChunk()
	{
		$ret = false;
		
		if( $this->fp !== false )
		{
			$ret = @fread( $this->fp, 64 );
			if( ($l = strlen($ret)) != 64 )
			{
				if(strlen($ret . $this->append) > 64)
				{
					$ret = substr( $ret . $this->append, 0, 64 );
					$this->append = substr( $this->append, 64 - $l );
				}
				else
				{
					$ret .= $this->append;
					$this->more = false;
					
					assert('strlen($ret) % 64 == 0');
				}
			}
			
			if(!$this->more)
			{
				@fclose( $this->fp );
				$this->fp = false;
				$this->size = false;
				$this->append = '';
			}
		}
		
		$this->chunk = (string)$ret;
		
		return $ret;
	}
	
	//	return the current chunk that was previously loaded
	function currentChunk()
	{
		if( $this->chunk === '' && $this->fp !== false )
		{
			return $this->nextChunk();
		}
		else
		{
			return ($this->chunk === '' ? false : $this->chunk);
		}
	}
}


class SHA256MessageURL extends hashMessageURL
{
	//	timeout for a socket resource open request
	var $socket_timeout = 5;
	function SHA256MessageURL( $url )
	{
		$this->fp = false;
		$this->more = true;
		$this->first = true;
		$this->headers = false;
		$this->append = '';
		$this->chunk = '';
		$this->curChunk = 0;
		$this->size = 0;
		
		if( ini_get( 'allow_url_fopen' ) == false )
		{	//	allow_url_fopen is off, check if protocol is http or not
			$info = parse_url($url);
			if( !isset($info['scheme']) || (strcasecmp(trim($info['scheme']), 'http') == 0) )
			{	//	http mode, use fsockopen
				
				if( !isset($info['scheme']) )
				{
					$url = 'http://' . $url;
					$info = parse_url($url);
				}
				
				if( function_exists( 'fsockopen' ) == false )
				{
					trigger_error('SHA256MessageURL(): allow_url_fopen is off, fsockopen is disabled or not available.', E_USER_WARNING);
					return;
				}
				elseif(empty($info['host']))
				{	//	fsockopen is on, but there's no known host in the url
					trigger_error('SHA256MessageURL(' . var_export($url,true) .') does not appear to be a url.', E_USER_NOTICE);
					return;
				}
				
				//	protocol has been determined to be 'http', use fsockopen
				
				$this->fp = @fsockopen( $info['host'], (isset($info['port']) ? $info['port'] : 80), $errno, $errstr, $this->socket_timeout );
				
				if(!$this->fp)
				{	//	fsockopen failed
					trigger_error('SHA256MessageURL(): fsockopen failure ' . $errno . ' - ' . $errstr, E_USER_WARNING);
					return;
				}
				
				//	send the request for the page
				@fwrite($this->fp, 'GET ' . (empty($info['path']) ? '/' : $info['path']) . " HTTP/1.0\r\nHost: " . strtolower($info['host']) . "\r\n\r\n");
				$this->headers = true;
			}
			else
			{
				trigger_error('SHA256MessageURL(' . var_export($url,true) . ') is using an unsupported protocol: ' . var_export($info['scheme']), E_USER_WARNING);
			}
		}
		else
		{	//	allow_url_fopen is enabled, lets see if we can open the url
			$info = parse_url( $url );
			
			if( !isset($info['scheme']) )
			{
				$url = 'http://' . $url;
			}
			
			$this->fp = fopen( $url, 'rb' );
			
			if( $this->fp === false )
			{	//	we cannot open the url
				trigger_error('SHA256MessageURL(' . var_export($url,true) . '): unable to open the url supplied.', E_USER_WARNING);
			}
		}
	}
	
	
	//	retrieve the next message chunk
	function nextChunk()
	{
		$this->tossHeader();
		
		$ret = false;
		
		if( is_array($this->chunk) )
		{
			//	first pass?
			if( $this->first === true )
			{
				$this->first = false;
			}
			else
			{
				$this->curChunk++;
			}
			
			$ret = (isset($this->chunk[$this->curChunk]) ? $this->chunk[$this->curChunk] : false);
		}
		elseif( $this->fp !== false )
		{
			if( $this->first == true )
			{
				if( ($l = strlen($this->append)) > 64 )
				{
					$ret = substr($this->append, 0, 64);
					$this->append = substr($this->append, 64);
				}
				else
				{
					$ret = $this->append . fread( $this->fp, 64 - $l );
					$this->append = '';
					$this->first = false;
				}
			}
			else
			{
				$ret = @fread( $this->fp, 64 );
			}
			
			$l = strlen($ret);
			$this->size += $l;

			if( $l != 64 )
			{
				if(empty($this->append))
				{
					$this->append = SHA256Message::calculateFooter( $this->size );
				}
				
				if(strlen($ret . $this->append) > 64)
				{
					$ret = substr( $ret . $this->append, 0, 64 );
					$this->append = substr( $this->append, 64 - $l );
				}
				else
				{
					$ret .= $this->append;
					$this->more = false;
					
					assert('strlen($ret) % 64 == 0');
				}
			}
			
			if(!$this->more)
			{
				@fclose( $this->fp );
				$this->fp = false;
				$this->size = false;
				$this->append = '';
			}
			
			$this->chunk = (string)$ret;
		}
		
		return $ret;
	}
	
	
	//	return the current chunk that was previously loaded
	function currentChunk()
	{
		if( $this->chunk === '' && $this->fp !== false )
		{
			return $this->nextChunk();
		}
		else
		{
			return ($this->chunk === '' ? false : $this->chunk);
		}
	}


	//	-------------------------------
	//	BEGIN INTERNAL FUNCTIONS
	//	-------------------------------
	
	//	
	function tossHeader()
	{
		if( $this->headers === true )
		{
			$buf = '';
			while(!feof($this->fp))
			{
				$buf .= fread($this->fp, 4);
				
				if( preg_match("#(\r\n|\n\r|\r|\n)\\1#s", $buf, $match, PREG_OFFSET_CAPTURE ) )
				{
					$this->append = substr( $buf, $match[0][1] + strlen($match[0][0]) );
					$this->headers = false;
					break;
				}
			}
			
			if( $this->headers === true )
			{	//	the header/content divide was not found, End of file reached.
				trigger_error('SHA256MessageURL::tossHeader(): no headers were sent. Falling back to string hashing', E_USER_NOTICE);
				//	prevent this from showing again.
				$this->headers = false;
				
				// fall back to breaking the whole thing apart into an array of chunks, just like SHA256Message
				$this->chunk = $buf . SHA256Message::calculateFooter( $this->size = strlen( $buf ) );
				preg_match_all( '#.{64}#s', $str, $this->chunk );
				$this->chunk = $this->chunk[0];
			}
		}
	}
}


/*****************************************************************************
 *	$History: hash_sha256.php $
 * 
 * *****************  Version 4  *****************
 * User: Feyd         Date: 05.04.06   Time: 2:46p
 * Updated in $/inc
 * add some bits to the documentation
 * 
 * *****************  Version 3  *****************
 * User: Feyd         Date: 05.04.05   Time: 1:26a
 * Updated in $/inc
 * hashURL() finished.
 * 
 * *****************  Version 2  *****************
 * User: Feyd         Date: 05.04.04   Time: 12:40a
 * Updated in $/inc
 * Finished hashFile(). Next up, hashURL().
 * 
 * *****************  Version 1  *****************
 * User: Feyd         Date: 05.04.03   Time: 3:53a
 * Created in $/inc
 * Initial source control addition.
 *****************************************************************************/

/* EOF :: Document Settings: tab:4; */

?>
Last edited by feyd on Thu Sep 29, 2005 9:16 am, edited 1 time in total.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

Code: Select all

<?php

/*******************************************************************************
 *
 *	SHA256 static class for PHP4
 *	implemented by feyd _at_ devnetwork .dot. net
 *	specification from http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf
 *
 *	(C) Copyright 2005 Developer's Network. All rights reserved.
 *
 *	This library is free software; you can redistribute it and/or modify it
 *	under the terms of the GNU Lesser General Public License as published by the
 *	Free Software Foundation; either version 2.1 of the License, or (at your
 *	option) any later version.
 *
 *	This library is distributed in the hope that it will be useful, but WITHOUT
 *	ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 *	FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
 *	for more details.
 *
 *	You should have received a copy of the GNU Lesser General Public License
 *	along with this library; if not, write to the
 *		Free Software Foundation, Inc.
 *		59 Temple Place, Suite 330,
 *		Boston, MA 02111-1307 USA 
 *
 *----- Source Control Information ---------------------------------------------
 *
 *	$Workfile: test_sha256.php $
 *	$Author: Feyd $
 *	$JustDate: 05.04.06 $
 *	$Revision: 3 $
 *
 *	$Header: /inc/test_sha256.php 3     05.04.06 2:57p Feyd $
 *
 ******************************************************************************/

require_once( 'hash_sha256.php' );

//	format a string into 4 byte hex chunks
function hexerize($str)
{
	$n = 0;
	$b = 0;
	if(is_array($str))
	{
		reset($str);
		$o = 'array(' . sizeof($str) . ')::' . "\n\n";
		while($s = current($str))
		{
			$o .= hexerize($s);
			next($str);
		}
		$o .= 'end array;'."\n";
	}
	else
	{
		if(is_integer($str) || is_float($str))
			$str = pack('N',$str);
		$o = 'string(' . strlen($str) . ')' . "::\n";
		for($i = 0, $j = strlen($str); $i < $j; $i++, $b = $i % 4)
		{
			$o .= sprintf('%02X', ord($str{$i}));
			//	only process when 32-bits have passed through
			if($i != 0 && $b == 3)
			{
				//	process new line points
				if($n == 3)
					$o .= "\n";
				else
					$o .= ' ';
				++$n;
				$n %= 4;
			}
		}
	}
	
	return $o . "\n";
}


class testSHA256
{
	function runTests( $run = null )
	{
		if( $run === null )
		{
			$run = array
			(
				'test1',
				'test2',
				'testSum',
				array('testSpeedHash', 10),
				
				array('testOutput', 'hex', 10),
				array('testOutput', 'HEX', 10),
				array('testOutput', 'bin', 10),
				array('testOutput', 'bit', 10),
				
				array('testFiles', 'hex', 10),
				array('testFiles', 'HEX', 10),
				array('testFiles', 'bin', 10),
				array('testFiles', 'bit', 10),
				
				array('testURLs', 'hex', 1),
				array('testURLs', 'HEX', 1),
				array('testURLs', 'bin', 1),
				array('testURLs', 'bit', 1),
			);
		}
		
		echo '<html><body color="#000000" bgcolor="#FFFFFF">';
		
		foreach( $run as $k => $v )
		{
			if( is_string( $v ) )
			{
				if( is_callable( array('testSHA256', $v) ) )
				{
					echo 'running testSHA256::' . $v . '()' . "\n\n";

					testSHA256::$v();
				}
				else
				{
					trigger_error('testSHA256::' . $v . '() is an unknown function.', E_USER_NOTICE);
				}
			}
			elseif( is_array( $v ) )
			{
				if( is_callable( array('testSHA256', $v[0]) ) )
				{
					$f = $v[0];
					array_shift($v);

					echo 'running testSHA256::' . $f . '(' . var_export($v,true) . ')' . "\n\n";

					call_user_func_array( array('testSHA256', $f), $v );
				}
				else
				{
					trigger_error('testSHA256::' . $v[0] . '() is an unknown function.', E_USER_NOTICE);
				}
			}
			else
			{
				trigger_error('testSHA256(): unknown data at key ' . $k, E_USER_NOTICE);
			}
		}
		
		echo '</body></html>';
	}


	//	testing functions

	function test1()
	{
		$it = 1;

		echo '<pre>';

		$test = array('abc','abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq');

		foreach($test as $str)
		{
			echo 'Testing ' . var_export($str,true) . "\n";
			list($s1,$s2) = explode(' ', microtime());
			for($x = 0; $x < $it; $x++)
				$data =& new SHA256Data('', $str);
			list($e1,$e2) = explode(' ', microtime());
			echo hexerize($data->message->chunk);
			echo hexerize($data->hash);
			echo 'processing took ' . (($e2 - $s2 + $e1 - $s1) / $it) . ' seconds.' . "\n\n\n";
		}

		echo '</pre>';
	}

	function test2()
	{
		$it = 1;

		echo '<pre>';

		$test = array('abc','abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq');

		foreach($test as $str)
		{
			echo 'Testing ' . var_export($str,true) . "\n";
			list($s1,$s2) = explode(' ', microtime());
			for($x = 0; $x < $it; $x++)
				$o = SHA256::hash($str);
			list($e1,$e2) = explode(' ', microtime());
			echo $o . "\n";
			echo 'processing took ' . (($e2 - $s2 + $e1 - $s1) / $it) . ' seconds.' . "\n\n\n";
		}

		echo '</pre>';
	}

	function testSum()
	{
		echo '<pre>';

		echo SHA256::sum(1,2,3,4,5,6,7,8,9,10);

		echo '</pre>';
	}

	function testSpeedHash($it = 10)
	{
		$it = intval($it);
		if($it === 0)
			$it = 10;

		set_time_limit(-1);

		echo '<pre>' . "\n";

		$test = array(
			''=>'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',
			'abc'=>'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad',
			'message digest'=>'f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650',
			'secure hash algorithm'=>'f30ceb2bb2829e79e4ca9753d35a8ecc00262d164cc077080295381cbd643f0d',
			'SHA256 is considered to be safe'=>'6819d915c73f4d1e77e4e1b52d1fa0f9cf9beaead3939f15874bd988e2a23630',
			'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'=>'248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1',
			'For this sample, this 63-byte string will be used as input data'=>'f08a78cbbaee082b052ae0708f32fa1e50c5c421aa772ba5dbb406a2ea6be342',
			'This is exactly 64 bytes long, not counting the terminating byte'=>'ab64eff7e88e2e46165e29f2bce41826bd4c7b3552f6b382a9e7d3af47c245f8',
			);

		foreach($test as $str => $hash)
		{
			echo 'Testing ' . var_export($str,true) . "\n";
			echo 'Start time: ' . date('Y-m-d H:i:s') . "\n";
			if($it > 1)
			{
				list($s1,$s2) = explode(' ', microtime());
				$o = SHA256::hash($str);
				list($e1,$e2) = explode(' ', microtime());
				echo 'estimated time to perform test: ' . (($e2 - $s2 + $e1 - $s1) * $it) . ' seconds for ' . $it . ' iterations.' . "\n";
			}

			$t = 0;
			for($x = 0; $x < $it; $x++)
			{
				list($s1,$s2) = explode(' ', microtime());
				$o = SHA256::hash($str);
				list($e1,$e2) = explode(' ', microtime());
				$t += $e2 - $s2 + $e1 - $s1;
			}
			echo var_export($o,true) . ' == ' . var_export($hash,true) . ' ' . (strcasecmp($o,$hash)==0 ? 'PASSED' : 'FAILED') . "\n";
			echo 'processing took ' . ($t / $it) . ' seconds.' . "\n\n\n";
		}

		echo '</pre>';
	}

	function testOutput($mode = 'hex', $it = 10)
	{
		$modes = array( 'hex' => 16, 'HEX' => 16, 'bin' => 10, 'bit' => 2 );
		static $hex = '0123456789abcdef';
		static $bit = array(
			'0' => '0000',
			'1' => '0001',
			'2' => '0010',
			'3' => '0011',
			'4' => '0100',
			'5' => '0101',
			'6' => '0110',
			'7' => '0111',
			'8' => '1000',
			'9' => '1001',
			'a' => '1010',
			'b' => '1011',
			'c' => '1100',
			'd' => '1101',
			'e' => '1110',
			'f' => '1111',
			);
		$it = intval($it);
		if($it == 0)
			$it = 10;

		set_time_limit(-1);

		echo '<pre>' . "\n";

		$test = array(
			''=>'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',
			'abc'=>'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad',
			'message digest'=>'f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650',
			'secure hash algorithm'=>'f30ceb2bb2829e79e4ca9753d35a8ecc00262d164cc077080295381cbd643f0d',
			'SHA256 is considered to be safe'=>'6819d915c73f4d1e77e4e1b52d1fa0f9cf9beaead3939f15874bd988e2a23630',
			'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'=>'248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1',
			'For this sample, this 63-byte string will be used as input data'=>'f08a78cbbaee082b052ae0708f32fa1e50c5c421aa772ba5dbb406a2ea6be342',
			'This is exactly 64 bytes long, not counting the terminating byte'=>'ab64eff7e88e2e46165e29f2bce41826bd4c7b3552f6b382a9e7d3af47c245f8',
			);

		if( isset($modes[$mode]) )
		{
			foreach($test as $k => $v)
			{
				switch( $mode )
				{
					case 'HEX':
						$test[$k] = strtoupper($v);
						break;

					case 'bin':
						$test[$k] = '';
						for($i = 0, $j = strlen($v); $i < $j; $i += 2)
						{
							$test[$k] .= chr( (strpos($hex,$v{$i}) << 4) | (strpos($hex,$v{$i + 1})) );
						}
						break;

					case 'bit':
						$test[$k] = '';
						for($i = 0, $j = strlen($v); $i < $j; $i++)
						{
							$test[$k] .= $bit[$v{$i}];
						}
						break;

					case 'hex':
					default:
						break;
				}
			}
		}
		else
		{
			$mode = 'hex';
		}

		foreach($test as $str => $hash)
		{
			echo 'Testing ' . var_export($str,true) . "\n";
			echo 'Start time: ' . date('Y-m-d H:i:s') . "\n";
			if($it > 1)
			{
				list($s1,$s2) = explode(' ', microtime());
				$o = SHA256::hash($str, $mode);
				list($e1,$e2) = explode(' ', microtime());
				echo 'estimated time to perform test: ' . (($e2 - $s2 + $e1 - $s1) * $it) . ' seconds for ' . $it . ' iterations.' . "\n";
			}

			$t = 0;
			for($x = 0; $x < $it; $x++)
			{
				list($s1,$s2) = explode(' ', microtime());
				$o = SHA256::hash($str, $mode);
				list($e1,$e2) = explode(' ', microtime());
				$t += $e2 - $s2 + $e1 - $s1;
			}
			echo var_export($o,true) . ' ==
' . var_export($hash,true) . ' ' . ($o === $hash ? 'PASSED' : 'FAILED') . "\n";
			echo 'processing took ' . ($t / $it) . ' seconds.' . "\n\n\n";
		}

		echo '</pre>';
	}

	function testFiles( $mode = 'hex', $it = 10 )
	{
		$modes = array( 'hex' => 16, 'HEX' => 16, 'bin' => 10, 'bit' => 2 );
		static $hex = '0123456789abcdef';
		static $bit = array(
			'0' => '0000',
			'1' => '0001',
			'2' => '0010',
			'3' => '0011',
			'4' => '0100',
			'5' => '0101',
			'6' => '0110',
			'7' => '0111',
			'8' => '1000',
			'9' => '1001',
			'a' => '1010',
			'b' => '1011',
			'c' => '1100',
			'd' => '1101',
			'e' => '1110',
			'f' => '1111',
			);
		$it = intval($it);
		if($it == 0)
			$it = 10;

		//set_time_limit(-1);

		echo '<pre>' . "\n";

		$test = array(
			''=>'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',
			'abc'=>'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad',
			'message digest'=>'f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650',
			'secure hash algorithm'=>'f30ceb2bb2829e79e4ca9753d35a8ecc00262d164cc077080295381cbd643f0d',
			'SHA256 is considered to be safe'=>'6819d915c73f4d1e77e4e1b52d1fa0f9cf9beaead3939f15874bd988e2a23630',
			'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'=>'248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1',
			'For this sample, this 63-byte string will be used as input data'=>'f08a78cbbaee082b052ae0708f32fa1e50c5c421aa772ba5dbb406a2ea6be342',
			'This is exactly 64 bytes long, not counting the terminating byte'=>'ab64eff7e88e2e46165e29f2bce41826bd4c7b3552f6b382a9e7d3af47c245f8',
			);

		if( isset($modes[$mode]) )
		{
			foreach($test as $k => $v)
			{
				switch( $mode )
				{
					case 'HEX':
						$test[$k] = strtoupper($v);
						break;

					case 'bin':
						$test[$k] = '';
						for($i = 0, $j = strlen($v); $i < $j; $i += 2)
						{
							$test[$k] .= chr( (strpos($hex,$v{$i}) << 4) | (strpos($hex,$v{$i + 1})) );
						}
						break;

					case 'bit':
						$test[$k] = '';
						for($i = 0, $j = strlen($v); $i < $j; $i++)
						{
							$test[$k] .= $bit[$v{$i}];
						}
						break;

					case 'hex':
					default:
						break;
				}
			}
		}
		else
		{
			$mode = 'hex';
		}

		foreach($test as $str => $hash)
		{
			$fn = tempnam('.','SHA_tmp');
			$fp = fopen( $fn, 'w' );
			fwrite( $fp, $str );
			echo 'Temp filename: ' .$fn . ' (' . __LINE__ . ")\n";
			fclose($fp);

			echo 'Testing ' . var_export($str,true) . "\n";
			echo 'Start time: ' . date('Y-m-d H:i:s') . "\n";

			if($it > 1)
			{
				list($s1,$s2) = explode(' ', microtime());
				$o = SHA256::hashFile($fn, $mode);
				list($e1,$e2) = explode(' ', microtime());
				echo 'estimated time to perform test: ' . (($e2 - $s2 + $e1 - $s1) * $it) . ' seconds for ' . $it . ' iterations.' . "\n";
			}

			$t = 0;
			for($x = 0; $x < $it; $x++)
			{
				list($s1,$s2) = explode(' ', microtime());
				$o = SHA256::hashFile($fn, $mode);
				list($e1,$e2) = explode(' ', microtime());
				$t += $e2 - $s2 + $e1 - $s1;
			}

			echo var_export($o,true) . ' ==
' . var_export($hash,true) . ' ' . ($o === $hash ? 'PASSED' : 'FAILED') . "\n";
			echo 'processing took ' . ($t / $it) . ' seconds.' . "\n\n\n";

			unlink($fn);
		}

		echo '</pre>';
	}


	function testURLs( $mode = 'hex', $it = 1 )
	{
		$modes = array( 'hex' => 16, 'HEX' => 16, 'bin' => 10, 'bit' => 2 );
		static $hex = '0123456789abcdef';
		static $bit = array(
			'0' => '0000',
			'1' => '0001',
			'2' => '0010',
			'3' => '0011',
			'4' => '0100',
			'5' => '0101',
			'6' => '0110',
			'7' => '0111',
			'8' => '1000',
			'9' => '1001',
			'a' => '1010',
			'b' => '1011',
			'c' => '1100',
			'd' => '1101',
			'e' => '1110',
			'f' => '1111',
			);
		$it = intval($it);
		if($it == 0)
			$it = 10;

		set_time_limit(60);

		echo '<pre>' . "\n";

		$test = array(
			''=>array('http://www.tatzu.net/test/blank.txt','e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'),
			'abc'=>array('http://tatzu.net/test/abc.php','ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad'),
			'message digest'=>array('test.tatzu.net/3.html','f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650'),
			'secure hash algorithm'=>array('http://test.tatzu.com/secure.js','f30ceb2bb2829e79e4ca9753d35a8ecc00262d164cc077080295381cbd643f0d'),
			'SHA256 is considered to be safe'=>array('http://www.TATZU.NeT/test/','6819d915c73f4d1e77e4e1b52d1fa0f9cf9beaead3939f15874bd988e2a23630'),
			'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'=>array('wWw.tAtZu.nEt/test/asDF.php','248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1'),
			'For this sample, this 63-byte string will be used as input data'=>array('http://www.tatzu.net/test/far.txt','f08a78cbbaee082b052ae0708f32fa1e50c5c421aa772ba5dbb406a2ea6be342'),
			'This is exactly 64 bytes long, not counting the terminating byte'=>array('www.tatzu.net/test/fir.html','ab64eff7e88e2e46165e29f2bce41826bd4c7b3552f6b382a9e7d3af47c245f8'),
			);

		if( isset($modes[$mode]) )
		{
			foreach($test as $k => $v)
			{
				switch( $mode )
				{
					case 'HEX':
						$test[$k][1] = strtoupper($v[1]);
						break;

					case 'bin':
						$test[$k][1] = '';
						for($i = 0, $j = strlen($v[1]); $i < $j; $i += 2)
						{
							$test[$k][1] .= chr( (strpos($hex,$v[1]{$i}) << 4) | (strpos($hex,$v[1]{$i + 1})) );
						}
						break;

					case 'bit':
						$test[$k][1] = '';
						for($i = 0, $j = strlen($v[1]); $i < $j; $i++)
						{
							$test[$k][1] .= $bit[$v[1]{$i}];
						}
						break;

					case 'hex':
					default:
						break;
				}
			}
		}
		else
		{
			$mode = 'hex';
		}

		foreach($test as $str => $arr)
		{
			list($url,$hash) = $arr;

			echo 'Testing ' . var_export($str,true) . "\n";
			echo 'URL: ' . $url . "\n";
			echo 'Start time: ' . date('Y-m-d H:i:s') . "\n";

			if($it > 1)
			{
				list($s1,$s2) = explode(' ', microtime());
				$o = SHA256::hashURL($url, $mode);
				list($e1,$e2) = explode(' ', microtime());
				echo 'estimated time to perform test: ' . (($e2 - $s2 + $e1 - $s1) * $it) . ' seconds for ' . $it . ' iterations.' . "\n";
			}

			$t = 0;
			for($x = 0; $x < $it; $x++)
			{
				list($s1,$s2) = explode(' ', microtime());
				$o = SHA256::hashURL($url, $mode);
				list($e1,$e2) = explode(' ', microtime());
				$t += $e2 - $s2 + $e1 - $s1;
			}

			echo var_export($o,true) . ' ==
' . var_export($hash,true) . ' ' . ($o === $hash ? 'PASSED' : 'FAILED') . "\n";
			echo 'processing took ' . ($t / $it) . ' seconds.' . "\n\n\n";
		}

		echo '</pre>';
	}

}


/*****************************************************************************
 *	How the syntax of this test works:
 *	Each element of the array (optionally) passed to testSHA256::runTests()
 *	is static method call information for methods within testSHA256.
 *
 *	A simple string is used for method calls that will use no arguments, or
 *	all default arguments of the method specified. An array is used for those
 *	methods that need some arguments passed to them. The first element is the
 *	method to call. All other elements are passed directly to the method.
 *	Methods are called in order of how they are stored in this array.
 ****************************************************************************/

$tests = array
(
	'test1',
	'test2',
	'testSum',
	array('testSpeedHash', 10),

	array('testOutput', 'hex', 1),
	array('testOutput', 'HEX', 1),
	array('testOutput', 'bin', 1),
	array('testOutput', 'bit', 1),

	array('testFiles', 'hex', 1),
	array('testFiles', 'HEX', 1),
	array('testFiles', 'bin', 1),
	array('testFiles', 'bit', 1),

	array('testURLs', 'hex', 1),
	array('testURLs', 'HEX', 1),
	array('testURLs', 'bin', 1),
	array('testURLs', 'bit', 1),
);
testSHA256::runTests( $tests );


/*****************************************************************************
 *	$History: test_sha256.php $
 * 
 * *****************  Version 3  *****************
 * User: Feyd         Date: 05.04.06   Time: 2:57p
 * Updated in $/inc
 * adjust/modify some documentation for release of 1.1.0
 * 
 * *****************  Version 2  *****************
 * User: Feyd         Date: 05.04.05   Time: 1:26a
 * Updated in $/inc
 * hashURL() finished.
 * 
 * *****************  Version 1  *****************
 * User: Feyd         Date: 05.04.04   Time: 12:40a
 * Created in $/inc
 * initial add
 *****************************************************************************/

/* EOF :: Document Settings: tab:4; */

?>
User avatar
fresh
Forum Contributor
Posts: 259
Joined: Mon Jun 14, 2004 10:39 am
Location: Amerika

Post by fresh »

good job with the code, it is very detailed, you even time the function, nice :)
User avatar
Ambush Commander
DevNet Master
Posts: 3698
Joined: Mon Oct 25, 2004 9:29 pm
Location: New Jersey, US

Post by Ambush Commander »

Since this script is still referenced, I'd like to make a note of warning: for big files, the programmed sha256 is no match for the faster, built-in but less secure md5 or sha1 functions. My script timed out when I tried using SHA256 for a 3.6mb file.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

considering the raw computations required for a block with 256, they are extremely different beasts. Yes, it would be faster as a compiled function, as would anything else.. however, a lot of php'ers don't have the liberties to install/load our own extensions on hosts.. or are allowed access to the system functions that provide this service either.

I wrote this as a software based solution to allow someone to use the added security and protection of a 256-bit hashing without needing anything else but basic PHP4 level support which is provided by most hosts. I even had to write a lot of flexibility into the URL and file handling sides just to support the various securities that some hosts use.
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

I posted the original post wondering is such a version existed - :) EndOfBragging...

I required such a solution for these exact reasons. I work on a few projects, and the lack of a non-mcrypt (library) version was a bit of a wonder in light of MD5/SHA1 research. Some of those projects are hosted on servers with mcrypt not enabled, and the users unable to do anything about it. Why should they do without the little extra security because of stubborn hosts? ;)

Much appreciated.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

I've got a few plans to implement a SHA512 and SHA1024 system at some point in the (near?) future... but that will be after the whirlwind of coding I have to do for our first client demo ;)
User avatar
n00b Saibot
DevNet Resident
Posts: 1452
Joined: Fri Dec 24, 2004 2:59 am
Location: Lucknow, UP, India
Contact:

Post by n00b Saibot »

Maugrim_The_Reaper wrote:I work on a few projects, and the lack of a non-mcrypt (library) version was a bit of a wonder in light of MD5/SHA1 research. Some of those projects are hosted on servers with mcrypt not enabled, and the users unable to do anything about it.
If you really need the mhash lib functionality on servers without mhash lib, read the lance_rushing's post in user_contributed_notes section on mhash page. he provides a php implementation of the mhash function which i have used each time mhash lib wasn't available and i guarantee it works perfectly well. :)
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Post by Jenk »

Will you be implementing for PHP5 aswell?
Roja
Tutorials Group
Posts: 2692
Joined: Sun Jan 04, 2004 10:30 pm

Post by Roja »

Jenk wrote:Will you be implementing for PHP5 aswell?
The sha256 library posted works fine on PHP5.
Roja
Tutorials Group
Posts: 2692
Joined: Sun Jan 04, 2004 10:30 pm

Post by Roja »

Ambush Commander wrote:Since this script is still referenced, I'd like to make a note of warning: for big files, the programmed sha256 is no match for the faster, built-in but less secure md5 or sha1 functions. My script timed out when I tried using SHA256 for a 3.6mb file.
You are comparing the wrong things. You meant to say, its not a match for the built-in md5_file/sha1_file functions.

For hashing strings, feyd's sha256 is extremely competitive in my timing tests with md5 and sha1.

Of course, hashing a file is a slow process. Even doing so on the commandline is rather slow.
n00b Saibot wrote:
Maugrim_The_Reaper wrote:I work on a few projects, and the lack of a non-mcrypt (library) version was a bit of a wonder in light of MD5/SHA1 research. Some of those projects are hosted on servers with mcrypt not enabled, and the users unable to do anything about it.
If you really need the mhash lib functionality on servers without mhash lib, read the lance_rushing's post in user_contributed_notes section on mhash page. he provides a php implementation of the mhash function which i have used each time mhash lib wasn't available and i guarantee it works perfectly well. :)
mhash != mcrypt.

Lance's implementation is just a hash version of md5/sha1. Maugrim was (I think) pointing at the fact that one of the more secure hash choices in mhash was sha256, and that there was no implementation of it except in mcrypt - until feyd made it.
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Post by Jenk »

Roja wrote:
Jenk wrote:Will you be implementing for PHP5 aswell?
The sha256 library posted works fine on PHP5.
But using PHP5's syntax?

What about public, private etc?
Roja
Tutorials Group
Posts: 2692
Joined: Sun Jan 04, 2004 10:30 pm

Post by Roja »

Jenk wrote:
Roja wrote:
Jenk wrote:Will you be implementing for PHP5 aswell?
The sha256 library posted works fine on PHP5.
But using PHP5's syntax?

What about public, private etc?
OH, you mean "Will you make a version that won't work on php4, just to avoid E_STRICT warnings".

Because thats what using public/private accomplishes, and little else.
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

that there was no implementation of it except in mcrypt - until feyd made it.

Yep, that was my meaning...works fine in PHP5 like Roja stated. If you need all the PHP5 specific changes, it's a simple editing matter I would think.
Post Reply