PHP Developers Network

A community of PHP developers offering assistance, advice, discussion, and friendship.
 
Loading
It is currently Sun Dec 17, 2017 12:24 pm

All times are UTC - 5 hours




Post new topic Reply to topic  [ 12 posts ] 
Author Message
PostPosted: Tue Mar 01, 2005 3:55 am 
Offline
Neighborhood Spidermoddy
User avatar

Joined: Mon Mar 29, 2004 4:24 pm
Posts: 31559
Location: Bothell, Washington, USA
okay boys and girls.. here it is, the SHA256 hashing algorithm implemenation. Usage information and description are in the code. Please note: I have only been able to test this against relatively small messages. There are testing functions provided at the bottom of the code which is after a "REMOVAL ALL FUNCTIONS AFTER THIS WHEN NOT TESTING" comment. :)
Syntax: [ Download ] [ Hide ]
<?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
 *
 *  © Copyright 2005 Developer's Network. All rights reserved.
 *  This is licensed under the Lesser General Public License (LGPL)
 * 
 *  Thanks to CertainKey Inc. for providing some example outputs in Javascript
 *
 *----- Version 1.0.0 ----------------------------------------------------------
 *
 *  Syntax:
 *      string SHA256::hash( string message[, string format ])
 *
 *  Description:
 *      SHA256::hash() is a static function that must be called with `message`
 *      and optionally `format`. Possible values for `format` are:
 *      'bin'   binary string output
 *      'hex'   default; hexidecimal string output (lower case)
 *
 *      Failures return FALSE.
 *
 *  Usage:
 *      $hash = SHA256::hash('string to hash');
 *
 ******************************************************************************/

 
 
//  hashing class state and storage object. Abstract base class only.
class hashData
{
    //  final hash
    var $hash = null;
}
 
 
//  hashing class. Abstract base class only.
class hash
{
    //  The base modes are:
    //      'bin' - binary output (most compact)
    //      'bit' - bit output (largest)
    //      'oct' - octal output (medium-large)
    //      'hex' - hexidecimal (default, medium)
 
    //  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;
    }
}
 
 
//  ------------
 
 
class SHA256Data extends hashData
{
    //  buffer
    var $buf = array();
   
    //  padded data
    var $chunks = null;
   
    function SHA256Data($str)
    {
        $M = strlen($str);  //  number of bytes
        $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
       
        $str .= chr(0x80) . str_repeat(chr(0), $k) . $l;
       
        assert('strlen($str) % 64 == 0');
       
        //  break the binary string into 512-bit blocks
        preg_match_all( '#.{64}#', $str, $this->chunks );
        $this->chunks = $this->chunks[0];
       
        //  H(0)
        $this->hash = array
        (
            (int)0x6A09E667, (int)0xBB67AE85,
            (int)0x3C6EF372, (int)0xA54FF53A,
            (int)0x510E527F, (int)0x9B05688C,
            (int)0x1F83D9AB, (int)0x5BE0CD19,
        );
    }
}
 
 
//  static class. Access via SHA256::hash()
class SHA256 extends hash
{
    function hash($str, $mode = 'hex')
    {
        static $modes = array( 'hex', 'bin' );
        $ret = false;
       
        if(!in_array(strtolower($mode), $modes))
        {
            trigger_error('mode specified is unrecognized: ' . $mode, E_USER_WARNING);
        }
        else
        {
            $data =& new SHA256Data($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);
            }
            else
            {
                trigger_error('SHA256::hash' . $mode . '() NOT IMPLEMENTED.', E_USER_WARNING);
            }
        }
       
        return $ret;
    }
   
    //  ------------
    //  begin internal functions
   
    //  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
    function compute(&$hashData)
    {
        static $vars = 'abcdefgh';
        static $K = null;
       
        if($K === null)
        {
            $K = array(
                (int)0x428A2F98, (int)0x71374491, (int)0xB5C0FBCF, (int)0xE9B5DBA5,
                (int)0x3956C25B, (int)0x59F111F1, (int)0x923F82A4, (int)0xAB1C5ED5,
                (int)0xD807AA98, (int)0x12835B01, (int)0x243185BE, (int)0x550C7DC3,
                (int)0x72BE5D74, (int)0x80DEB1FE, (int)0x9BDC06A7, (int)0xC19BF174,
                (int)0xE49B69C1, (int)0xEFBE4786, (int)0x0FC19DC6, (int)0x240CA1CC,
                (int)0x2DE92C6F, (int)0x4A7484AA, (int)0x5CB0A9DC, (int)0x76F988DA,
                (int)0x983E5152, (int)0xA831C66D, (int)0xB00327C8, (int)0xBF597FC7,
                (int)0xC6E00BF3, (int)0xD5A79147, (int)0x06CA6351, (int)0x14292967,
                (int)0x27B70A85, (int)0x2E1B2138, (int)0x4D2C6DFC, (int)0x53380D13,
                (int)0x650A7354, (int)0x766A0ABB, (int)0x81C2C92E, (int)0x92722C85,
                (int)0xA2BFE8A1, (int)0xA81A664B, (int)0xC24B8B70, (int)0xC76C51A3,
                (int)0xD192E819, (int)0xD6990624, (int)0xF40E3585, (int)0x106AA070,
                (int)0x19A4C116, (int)0x1E376C08, (int)0x2748774C, (int)0x34B0BCB5,
                (int)0x391C0CB3, (int)0x4ED8AA4A, (int)0x5B9CCA4F, (int)0x682E6FF3,
                (int)0x748F82EE, (int)0x78A5636F, (int)0x84C87814, (int)0x8CC70208,
                (int)0x90BEFFFA, (int)0xA4506CEB, (int)0xBEF9A3F7, (int)0xC67178F2
                );
        }
       
        $W = array();
        for($i = 0, $numChunks = sizeof($hashData->chunks); $i < $numChunks; $i++)
        {
            //  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($hashData->chunks[$i]{$j*4  }) & 0xFF; $T1 <<= 8;
                    $T1 |= ord($hashData->chunks[$i]{$j*4+1}) & 0xFF; $T1 <<= 8;
                    $T1 |= ord($hashData->chunks[$i]{$j*4+2}) & 0xFF; $T1 <<= 8;
                    $T1 |= ord($hashData->chunks[$i]{$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;
    }
}
 
 
//--------------
//  REMOVAL ALL FUNCTIONS AFTER THIS WHEN NOT TESTING
//--------------
 
//  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";
}
 
 
//  testing functions
 
function test1()
{
    $it = 10000;
   
    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->chunks);
        echo hexerize($data->hash);
        echo 'processing took ' . (($e2 - $s2 + $e1 - $s1) / $it) . ' seconds.' . "\n\n\n";
    }
 
    echo '</pre>';
}
 
function test2()
{
    $it = 10000;
   
    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;
        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>';
}
 
testSpeedHash(1);
 
//--------------
//  END REMOVAL HERE
//--------------
 
/* EOF :: Document Settings: tab:4; */
 
?>


Top
 Profile  
 
PostPosted: Thu Mar 10, 2005 5:15 pm 
Offline
Neighborhood Spidermoddy
User avatar

Joined: Mon Mar 29, 2004 4:24 pm
Posts: 31559
Location: Bothell, Washington, USA
This version of my class implements a full debugging help output data set. A post of an example output will follow.
Syntax: [ Download ] [ Hide ]
 
<?php
/*******************************************************************************
 *
 *  SHA256 static class for PHP4, debug output version
 *  implemented by feyd _at_ devnetwork .dot. net
 *  specification from http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf
 *
 *  © Copyright 2005 Developer's Network. All rights reserved.
 *  This is licensed under the Lesser General Public License (LGPL)
 * 
 *  Thanks to CertainKey Inc. for providing some example outputs in Javascript
 *
 *----- Version 1.0.0 ----------------------------------------------------------
 *
 *  Syntax:
 *      string SHA256::hash( string message[, string format ])
 *
 *  Description:
 *      SHA256::hash() is a static function that must be called with `message`
 *      and optionally `format`. Possible values for `format` are:
 *      'bin'   binary string output
 *      'hex'   default; hexidecimal string output (lower case)
 *
 *      Failures return FALSE.
 *
 *  Usage:
 *      $hash = SHA256::hash('string to hash');
 *
 ******************************************************************************/

 
 
//  hashing class state and storage object. Abstract base class only.
class hashData
{
    //  final hash
    var $hash = null;
}
 
 
//  hashing class. Abstract base class only.
class hash
{
    //  The base modes are:
    //      'bin' - binary output (most compact)
    //      'bit' - bit output (largest)
    //      'oct' - octal output (medium-large)
    //      'hex' - hexidecimal (default, medium)
 
    //  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;
    }
}
 
 
//  ------------
 
 
class SHA256Data extends hashData
{
    //  buffer
    var $buf = array();
   
    //  padded data
    var $chunks = null;
   
    function SHA256Data($str)
    {
        $M = strlen($str);  //  number of bytes
        $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
       
        $str .= chr(0x80) . str_repeat(chr(0), $k) . $l;
       
        assert('strlen($str) % 64 == 0');
       
        //  break the binary string into 512-bit blocks
        preg_match_all( '#.{64}#', $str, $this->chunks );
        $this->chunks = $this->chunks[0];
       
        //  H(0)
        $this->hash = array
        (
            (int)0x6A09E667, (int)0xBB67AE85,
            (int)0x3C6EF372, (int)0xA54FF53A,
            (int)0x510E527F, (int)0x9B05688C,
            (int)0x1F83D9AB, (int)0x5BE0CD19,
        );
    }
}
 
 
//  static class. Access via SHA256::hash()
class SHA256 extends hash
{
    function hash($str, $mode = 'hex')
    {
        static $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($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);
            }
            else
            {
                trigger_error('SHA256::hash' . $mode . '() NOT IMPLEMENTED.', E_USER_WARNING);
            }
        }
       
        return $ret;
    }
   
    //  ------------
    //  begin internal functions
   
    //  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
    function compute(&$hashData)
    {
        static $vars = 'abcdefgh';
        static $K = null;
       
        if($K === null)
        {
            $K = array(
                (int)0x428A2F98, (int)0x71374491, (int)0xB5C0FBCF, (int)0xE9B5DBA5,
                (int)0x3956C25B, (int)0x59F111F1, (int)0x923F82A4, (int)0xAB1C5ED5,
                (int)0xD807AA98, (int)0x12835B01, (int)0x243185BE, (int)0x550C7DC3,
                (int)0x72BE5D74, (int)0x80DEB1FE, (int)0x9BDC06A7, (int)0xC19BF174,
                (int)0xE49B69C1, (int)0xEFBE4786, (int)0x0FC19DC6, (int)0x240CA1CC,
                (int)0x2DE92C6F, (int)0x4A7484AA, (int)0x5CB0A9DC, (int)0x76F988DA,
                (int)0x983E5152, (int)0xA831C66D, (int)0xB00327C8, (int)0xBF597FC7,
                (int)0xC6E00BF3, (int)0xD5A79147, (int)0x06CA6351, (int)0x14292967,
                (int)0x27B70A85, (int)0x2E1B2138, (int)0x4D2C6DFC, (int)0x53380D13,
                (int)0x650A7354, (int)0x766A0ABB, (int)0x81C2C92E, (int)0x92722C85,
                (int)0xA2BFE8A1, (int)0xA81A664B, (int)0xC24B8B70, (int)0xC76C51A3,
                (int)0xD192E819, (int)0xD6990624, (int)0xF40E3585, (int)0x106AA070,
                (int)0x19A4C116, (int)0x1E376C08, (int)0x2748774C, (int)0x34B0BCB5,
                (int)0x391C0CB3, (int)0x4ED8AA4A, (int)0x5B9CCA4F, (int)0x682E6FF3,
                (int)0x748F82EE, (int)0x78A5636F, (int)0x84C87814, (int)0x8CC70208,
                (int)0x90BEFFFA, (int)0xA4506CEB, (int)0xBEF9A3F7, (int)0xC67178F2
                );
        }
       
        echo "\nPadded Message::\n";
        for($i = 0, $numChunks = sizeof($hashData->chunks); $i < $numChunks; $i++)
        {
            echo memdump($hashData->chunks[$i]) . "\n";
        }
       
        $W = array();
        for($i = 0, $numChunks = sizeof($hashData->chunks); $i < $numChunks; $i++)
        {
            //  initialize the registers
            for($j = 0; $j < 8; $j++)
                ${$vars{$j}} = $hashData->hash[$j];
           
            echo "\n\nChunk " . ($i + 1) . ' of ' . $numChunks . " ::\nhash " . memdump($hashData->hash);
           
            //  the SHA-256 compression function
            for($j = 0; $j < 64; $j++)
            {
                if($j < 16)
                {
                    $T1  = ord($hashData->chunks[$i]{$j*4  }) & 0xFF; $T1 <<= 8;
                    $T1 |= ord($hashData->chunks[$i]{$j*4+1}) & 0xFF; $T1 <<= 8;
                    $T1 |= ord($hashData->chunks[$i]{$j*4+2}) & 0xFF; $T1 <<= 8;
                    $T1 |= ord($hashData->chunks[$i]{$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);
               
                echo ' t' . sprintf('%02d',$j+1) . ' ' . memdump(array($a, $b, $c, $d, $e, $f, $g, $h));
            }
           
            //  compute the next hash set
            for($j = 0; $j < 8; $j++)
                $hashData->hash[$j] = SHA256::sum(${$vars{$j}}, $hashData->hash[$j]);
           
            echo 'DONE ' . memdump($hashData->hash);
            echo "\n\nW::\n" . memdump($W, 4) . "\n";
        }
    }
   
   
    //  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;
    }
}
 
 
//  dump passed memory
function memdump($data, $brk = 0)
{
    if(is_array($data))
    {
        $n = 0;
        $b = -1;
        $brk_step = $brk - 1;
       
        $o = '';
        for($n = 0, $y = sizeof($data); $n < $y; $n++, $b %= $brk)
        {
            if($n != 0)
            {
                if($brk > 0)
                {
                    $o .= ($b == $brk_step ? "\n" : ' ');
                }
                else
                {
                    $o .= ' ';
                }
            }
           
            $o .= memdump($data[$n]);
           
            ++$b;
        }
       
        $o .= "\n";
    }
    else
    {
        $n = 0;
        $b = 0;
        if(is_integer($data) || is_float($data))
            $data = pack('N',$data);
        $o = '';
        for($i = 0, $j = strlen($data); $i < $j; $i++, $b = $i % 4)
        {
            $o .= sprintf('%02x', ord($data{$i}));
            //  only process when 32-bits have passed through
            if($i != 0 && $b == 3)
            {
                //  process new line points
                if($n == 3)
                    $o .= "\n";
                elseif($j > 4)
                    $o .= ' ';
                ++$n;
                $n %= 4;
            }
        }
    }
   
    return $o;
}
 
 
//--------------
//  REMOVAL ALL FUNCTIONS AFTER THIS WHEN NOT TESTING
//--------------
 
//  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";
}
 
 
//  testing functions
 
function test1($it = 10000)
{
    $it = intval($it);
    if($it === 0)
        $it = 10000;
   
    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->chunks);
        echo hexerize($data->hash);
        echo 'processing took ' . (($e2 - $s2 + $e1 - $s1) / $it) . ' seconds.' . "\n\n\n";
    }
 
    echo '</pre>';
}
 
function test2($it = 10000)
{
    $it = intval($it);
    if($it === 0)
        $it = 10000;
   
    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>';
}
 
testSpeedHash(1);
 
//--------------
//  END REMOVAL HERE
//--------------
 
/* EOF :: Document Settings: tab:4; */
 
?>
 


Top
 Profile  
 
PostPosted: Thu Mar 10, 2005 5:27 pm 
Offline
Neighborhood Spidermoddy
User avatar

Joined: Mon Mar 29, 2004 4:24 pm
Posts: 31559
Location: Bothell, Washington, USA
The following shows the output for a test against the string 'abc' using the above debugging version of the SHA256 class.

  1. The first piece you will see is the results of the padding against a message block (512 bits - 64 bytes). an example of what this should be is provided in the specification linked to in the code above.
  2. The next section is the compression algrorithm output registers, starting with the initial data of the starting constants. an example of what this should be is provided in the specification linked to in the code above.
  3. The section after that is the W temporary storage variable's contents.
  4. repeat from number 2 for each chunk in the message.

Notice that the 'DONE' line in the final compression algorithm output is the final hash broken into 32-bit chunks.
Syntax: [ Download ] [ Hide ]
Testing 'abc'
Start time: 2005-03-10 16:23:37

Padded Message::
61626380 00000000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000018



Chunk 1 of 1 ::
hash 6a09e667 bb67ae85 3c6ef372 a54ff53a 510e527f 9b05688c 1f83d9ab 5be0cd19
 t01 5d6aebcd 6a09e667 bb67ae85 3c6ef372 fa2a4622 510e527f 9b05688c 1f83d9ab
 t02 5a6ad9ad 5d6aebcd 6a09e667 bb67ae85 78ce7989 fa2a4622 510e527f 9b05688c
 t03 c8c347a7 5a6ad9ad 5d6aebcd 6a09e667 f92939eb 78ce7989 fa2a4622 510e527f
 t04 d550f666 c8c347a7 5a6ad9ad 5d6aebcd 24e00850 f92939eb 78ce7989 fa2a4622
 t05 04409a6a d550f666 c8c347a7 5a6ad9ad 43ada245 24e00850 f92939eb 78ce7989
 t06 2b4209f5 04409a6a d550f666 c8c347a7 714260ad 43ada245 24e00850 f92939eb
 t07 e5030380 2b4209f5 04409a6a d550f666 9b27a401 714260ad 43ada245 24e00850
 t08 85a07b5f e5030380 2b4209f5 04409a6a 0c657a79 9b27a401 714260ad 43ada245
 t09 8e04ecb9 85a07b5f e5030380 2b4209f5 32ca2d8c 0c657a79 9b27a401 714260ad
 t10 8c87346b 8e04ecb9 85a07b5f e5030380 1cc92596 32ca2d8c 0c657a79 9b27a401
 t11 4798a3f4 8c87346b 8e04ecb9 85a07b5f 436b23e8 1cc92596 32ca2d8c 0c657a79
 t12 f71fc5a9 4798a3f4 8c87346b 8e04ecb9 816fd6e9 436b23e8 1cc92596 32ca2d8c
 t13 87912990 f71fc5a9 4798a3f4 8c87346b 1e578218 816fd6e9 436b23e8 1cc92596
 t14 d932eb16 87912990 f71fc5a9 4798a3f4 745a48de 1e578218 816fd6e9 436b23e8
 t15 c0645fde d932eb16 87912990 f71fc5a9 0b92f20c 745a48de 1e578218 816fd6e9
 t16 b0fa238e c0645fde d932eb16 87912990 07590dcd 0b92f20c 745a48de 1e578218
 t17 21da9a9b b0fa238e c0645fde d932eb16 8034229c 07590dcd 0b92f20c 745a48de
 t18 c2fbd9d1 21da9a9b b0fa238e c0645fde 846ee454 8034229c 07590dcd 0b92f20c
 t19 fe777bbf c2fbd9d1 21da9a9b b0fa238e cc899961 846ee454 8034229c 07590dcd
 t20 e1f20c33 fe777bbf c2fbd9d1 21da9a9b b0638179 cc899961 846ee454 8034229c
 t21 9dc68b63 e1f20c33 fe777bbf c2fbd9d1 8ada8930 b0638179 cc899961 846ee454
 t22 c2606d6d 9dc68b63 e1f20c33 fe777bbf e1257970 8ada8930 b0638179 cc899961
 t23 a7a3623f c2606d6d 9dc68b63 e1f20c33 49f5114a e1257970 8ada8930 b0638179
 t24 c5d53d8d a7a3623f c2606d6d 9dc68b63 aa47c347 49f5114a e1257970 8ada8930
 t25 1c2c2838 c5d53d8d a7a3623f c2606d6d 2823ef91 aa47c347 49f5114a e1257970
 t26 cde8037d 1c2c2838 c5d53d8d a7a3623f 14383d8e 2823ef91 aa47c347 49f5114a
 t27 b62ec4bc cde8037d 1c2c2838 c5d53d8d c74c6516 14383d8e 2823ef91 aa47c347
 t28 77d37528 b62ec4bc cde8037d 1c2c2838 edffbff8 c74c6516 14383d8e 2823ef91
 t29 363482c9 77d37528 b62ec4bc cde8037d 6112a3b7 edffbff8 c74c6516 14383d8e
 t30 a0060b30 363482c9 77d37528 b62ec4bc ade79437 6112a3b7 edffbff8 c74c6516
 t31 ea992a22 a0060b30 363482c9 77d37528 0109ab3a ade79437 6112a3b7 edffbff8
 t32 73b33bf5 ea992a22 a0060b30 363482c9 ba591112 0109ab3a ade79437 6112a3b7
 t33 98e12507 73b33bf5 ea992a22 a0060b30 9cd9f5f6 ba591112 0109ab3a ade79437
 t34 fe604df5 98e12507 73b33bf5 ea992a22 59249dd3 9cd9f5f6 ba591112 0109ab3a
 t35 a9a7738c fe604df5 98e12507 73b33bf5 085f3833 59249dd3 9cd9f5f6 ba591112
 t36 65a0cfe4 a9a7738c fe604df5 98e12507 f4b002d6 085f3833 59249dd3 9cd9f5f6
 t37 41a65cb1 65a0cfe4 a9a7738c fe604df5 0772a26b f4b002d6 085f3833 59249dd3
 t38 34df1604 41a65cb1 65a0cfe4 a9a7738c a507a53d 0772a26b f4b002d6 085f3833
 t39 6dc57a8a 34df1604 41a65cb1 65a0cfe4 f0781bc8 a507a53d 0772a26b f4b002d6
 t40 79ea687a 6dc57a8a 34df1604 41a65cb1 1efbc0a0 f0781bc8 a507a53d 0772a26b
 t41 d6670766 79ea687a 6dc57a8a 34df1604 26352d63 1efbc0a0 f0781bc8 a507a53d
 t42 df46652f d6670766 79ea687a 6dc57a8a 838b2711 26352d63 1efbc0a0 f0781bc8
 t43 17aa0dfe df46652f d6670766 79ea687a decd4715 838b2711 26352d63 1efbc0a0
 t44 9d4baf93 17aa0dfe df46652f d6670766 fda24c2e decd4715 838b2711 26352d63
 t45 26628815 9d4baf93 17aa0dfe df46652f a80f11f0 fda24c2e decd4715 838b2711
 t46 72ab4b91 26628815 9d4baf93 17aa0dfe b7755da1 a80f11f0 fda24c2e decd4715
 t47 a14c14b0 72ab4b91 26628815 9d4baf93 d57b94a9 b7755da1 a80f11f0 fda24c2e
 t48 4172328d a14c14b0 72ab4b91 26628815 fecf0bc6 d57b94a9 b7755da1 a80f11f0
 t49 05757ceb 4172328d a14c14b0 72ab4b91 bd714038 fecf0bc6 d57b94a9 b7755da1
 t50 f11bfaa8 05757ceb 4172328d a14c14b0 6e5c390c bd714038 fecf0bc6 d57b94a9
 t51 7a0508a1 f11bfaa8 05757ceb 4172328d 52f1ccf7 6e5c390c bd714038 fecf0bc6
 t52 886e7a22 7a0508a1 f11bfaa8 05757ceb 49231c1e 52f1ccf7 6e5c390c bd714038
 t53 101fd28f 886e7a22 7a0508a1 f11bfaa8 529e7d00 49231c1e 52f1ccf7 6e5c390c
 t54 f5702fdb 101fd28f 886e7a22 7a0508a1 9f4787c3 529e7d00 49231c1e 52f1ccf7
 t55 3ec45cdb f5702fdb 101fd28f 886e7a22 e50e1b4f 9f4787c3 529e7d00 49231c1e
 t56 38cc9913 3ec45cdb f5702fdb 101fd28f 54cb266b e50e1b4f 9f4787c3 529e7d00
 t57 fcd1887b 38cc9913 3ec45cdb f5702fdb 9b5e906c 54cb266b e50e1b4f 9f4787c3
 t58 c062d46f fcd1887b 38cc9913 3ec45cdb 7e44008e 9b5e906c 54cb266b e50e1b4f
 t59 ffb70472 c062d46f fcd1887b 38cc9913 6d83bfc6 7e44008e 9b5e906c 54cb266b
 t60 b6ae8fff ffb70472 c062d46f fcd1887b b21bad3d 6d83bfc6 7e44008e 9b5e906c
 t61 b85e2ce9 b6ae8fff ffb70472 c062d46f 961f4894 b21bad3d 6d83bfc6 7e44008e
 t62 04d24d6c b85e2ce9 b6ae8fff ffb70472 948d25b6 961f4894 b21bad3d 6d83bfc6
 t63 d39a2165 04d24d6c b85e2ce9 b6ae8fff fb121210 948d25b6 961f4894 b21bad3d
 t64 506e3058 d39a2165 04d24d6c b85e2ce9 5ef50f24 fb121210 948d25b6 961f4894
DONE ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad


W::
61626380 00000000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000018
61626380 000f0000 7da86405 600003c6
3e9d7b78 0183fc00 12dcbfdb e2e2c38e
c8215c1a b73679a2 e5bc3909 32663c5b
9d209d67 ec8726cb 702138a4 d3b7973b
93f5997f 3b68ba73 aff4ffc1 f10a5c62
0a8b3996 72af830a 9409e33e 24641522
9f47bf94 f0a64f5a 3e246a79 27333ba3
0c4763f2 840abf27 7a290d5d 065c43da
fb3e89cb cc7617db b9e66c34 a9993667
84badedd c21462bc 1487472c b20f7a99
ef57b9cd ebe6b238 9fe3095e 78bc8d4b
a43fcf15 668b2ff8 eeaba2cc 12b1edeb

'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad' == 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad' PASSED
processing took 0.300431 seconds.


Top
 Profile  
 
PostPosted: Fri Mar 11, 2005 7:50 pm 
Offline
Neighborhood Spidermoddy
User avatar

Joined: Mon Mar 29, 2004 4:24 pm
Posts: 31559
Location: Bothell, Washington, USA
This is for all users who may be having 'FAILED' on tests.. It resolves an issue on some machines that would truncate some of the initial constants to 0x7fffffff instead of their proper value.

Syntax: [ Download ] [ Hide ]
<?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
 *
 *  © Copyright 2005 Developer's Network. All rights reserved.
 *  This is licensed under the Lesser General Public License (LGPL)
 * 
 *  Thanks to CertainKey Inc. for providing some example outputs in Javascript
 *
 *----- Version 1.0.1 ----------------------------------------------------------
 *
 *  Syntax:
 *      string SHA256::hash( string message[, string format ])
 *
 *  Description:
 *      SHA256::hash() is a static function that must be called with `message`
 *      and optionally `format`. Possible values for `format` are:
 *      'bin'   binary string output
 *      'hex'   default; hexidecimal string output (lower case)
 *
 *      Failures return FALSE.
 *
 *  Usage:
 *      $hash = SHA256::hash('string to hash');
 *
 ******************************************************************************/

 
 
//  hashing class state and storage object. Abstract base class only.
class hashData
{
    //  final hash
    var $hash = null;
}
 
 
//  hashing class. Abstract base class only.
class hash
{
    //  The base modes are:
    //      'bin' - binary output (most compact)
    //      'bit' - bit output (largest)
    //      'oct' - octal output (medium-large)
    //      'hex' - hexidecimal (default, medium)
 
    //  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;
    }
}
 
 
//  ------------
 
 
class SHA256Data extends hashData
{
    //  buffer
    var $buf = array();
   
    //  padded data
    var $chunks = null;
   
    function SHA256Data($str)
    {
        $M = strlen($str);  //  number of bytes
        $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
       
        $str .= chr(0x80) . str_repeat(chr(0), $k) . $l;
       
        assert('strlen($str) % 64 == 0');
       
        //  break the binary string into 512-bit blocks
        preg_match_all( '#.{64}#', $str, $this->chunks );
        $this->chunks = $this->chunks[0];
       
        //  H(0)
        /*
        $this->hash = array
        (
            (int)0x6A09E667, (int)0xBB67AE85,
            (int)0x3C6EF372, (int)0xA54FF53A,
            (int)0x510E527F, (int)0x9B05688C,
            (int)0x1F83D9AB, (int)0x5BE0CD19,
        );
        */

       
        $this->hash = array
        (
            1779033703,     -1150833019,
            1013904242,     -1521486534,
            1359893119,     -1694144372,
            528734635,       1541459225,
        );
    }
}
 
 
//  static class. Access via SHA256::hash()
class SHA256 extends hash
{
    function hash($str, $mode = 'hex')
    {
        static $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($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);
            }
            else
            {
                trigger_error('SHA256::hash' . $mode . '() NOT IMPLEMENTED.', E_USER_WARNING);
            }
        }
       
        return $ret;
    }
   
    //  ------------
    //  begin internal functions
   
    //  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
    function compute(&$hashData)
    {
        static $vars = 'abcdefgh';
        static $K = null;
       
        if($K === null)
        {
            /*
            $K = array(
                (int)0x428A2F98, (int)0x71374491, (int)0xB5C0FBCF, (int)0xE9B5DBA5,
                (int)0x3956C25B, (int)0x59F111F1, (int)0x923F82A4, (int)0xAB1C5ED5,
                (int)0xD807AA98, (int)0x12835B01, (int)0x243185BE, (int)0x550C7DC3,
                (int)0x72BE5D74, (int)0x80DEB1FE, (int)0x9BDC06A7, (int)0xC19BF174,
                (int)0xE49B69C1, (int)0xEFBE4786, (int)0x0FC19DC6, (int)0x240CA1CC,
                (int)0x2DE92C6F, (int)0x4A7484AA, (int)0x5CB0A9DC, (int)0x76F988DA,
                (int)0x983E5152, (int)0xA831C66D, (int)0xB00327C8, (int)0xBF597FC7,
                (int)0xC6E00BF3, (int)0xD5A79147, (int)0x06CA6351, (int)0x14292967,
                (int)0x27B70A85, (int)0x2E1B2138, (int)0x4D2C6DFC, (int)0x53380D13,
                (int)0x650A7354, (int)0x766A0ABB, (int)0x81C2C92E, (int)0x92722C85,
                (int)0xA2BFE8A1, (int)0xA81A664B, (int)0xC24B8B70, (int)0xC76C51A3,
                (int)0xD192E819, (int)0xD6990624, (int)0xF40E3585, (int)0x106AA070,
                (int)0x19A4C116, (int)0x1E376C08, (int)0x2748774C, (int)0x34B0BCB5,
                (int)0x391C0CB3, (int)0x4ED8AA4A, (int)0x5B9CCA4F, (int)0x682E6FF3,
                (int)0x748F82EE, (int)0x78A5636F, (int)0x84C87814, (int)0x8CC70208,
                (int)0x90BEFFFA, (int)0xA4506CEB, (int)0xBEF9A3F7, (int)0xC67178F2
                );
            */

            $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();
        for($i = 0, $numChunks = sizeof($hashData->chunks); $i < $numChunks; $i++)
        {
            //  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($hashData->chunks[$i]{$j*4  }) & 0xFF; $T1 <<= 8;
                    $T1 |= ord($hashData->chunks[$i]{$j*4+1}) & 0xFF; $T1 <<= 8;
                    $T1 |= ord($hashData->chunks[$i]{$j*4+2}) & 0xFF; $T1 <<= 8;
                    $T1 |= ord($hashData->chunks[$i]{$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;
    }
}
 
 
//--------------
//  REMOVAL ALL FUNCTIONS AFTER THIS WHEN NOT TESTING
//--------------
 
//  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";
}
 
 
//  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->chunks);
        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;
        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>';
}
 
testSpeedHash(1);
 
//--------------
//  END REMOVAL HERE
//--------------
 
/* EOF :: Document Settings: tab:4; */
 
?>


Last edited by Weirdan on Sun Feb 22, 2009 10:43 am, edited 1 time in total.
removed syntax highlighting so parser won't eat entire code block


Top
 Profile  
 
PostPosted: Fri Mar 11, 2005 7:52 pm 
Offline
Neighborhood Spidermoddy
User avatar

Joined: Mon Mar 29, 2004 4:24 pm
Posts: 31559
Location: Bothell, Washington, USA
New debug version of the previous update. Just in case people want to see what happens internally. The example output still performs the same way with the new code.
Syntax: [ Download ] [ Hide ]
<?php
 
 
/*******************************************************************************
 *
 *  SHA256 static class for PHP4, debug output version
 *  implemented by feyd _at_ devnetwork .dot. net
 *  specification from http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf
 *
 *  © Copyright 2005 Developer's Network. All rights reserved.
 *  This is licensed under the Lesser General Public License (LGPL)
 * 
 *  Thanks to CertainKey Inc. for providing some example outputs in Javascript
 *
 *----- Version 1.0.1 ----------------------------------------------------------
 *
 *  Syntax:
 *      string SHA256::hash( string message[, string format ])
 *
 *  Description:
 *      SHA256::hash() is a static function that must be called with `message`
 *      and optionally `format`. Possible values for `format` are:
 *      'bin'   binary string output
 *      'hex'   default; hexidecimal string output (lower case)
 *
 *      Failures return FALSE.
 *
 *  Usage:
 *      $hash = SHA256::hash('string to hash');
 *
 ******************************************************************************/

 
 
//  hashing class state and storage object. Abstract base class only.
class hashData
{
    //  final hash
    var $hash = null;
}
 
 
//  hashing class. Abstract base class only.
class hash
{
    //  The base modes are:
    //      'bin' - binary output (most compact)
    //      'bit' - bit output (largest)
    //      'oct' - octal output (medium-large)
    //      'hex' - hexidecimal (default, medium)
 
    //  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;
    }
}
 
 
//  ------------
 
 
class SHA256Data extends hashData
{
    //  buffer
    var $buf = array();
   
    //  padded data
    var $chunks = null;
   
    function SHA256Data($str)
    {
        $M = strlen($str);  //  number of bytes
        $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
       
        $str .= chr(0x80) . str_repeat(chr(0), $k) . $l;
       
        assert('strlen($str) % 64 == 0');
       
        //  break the binary string into 512-bit blocks
        preg_match_all( '#.{64}#', $str, $this->chunks );
        $this->chunks = $this->chunks[0];
       
        //  H(0)
        /*
        $this->hash = array
        (
            (int)0x6A09E667, (int)0xBB67AE85,
            (int)0x3C6EF372, (int)0xA54FF53A,
            (int)0x510E527F, (int)0x9B05688C,
            (int)0x1F83D9AB, (int)0x5BE0CD19,
        );
        */

       
        $this->hash = array
        (
            1779033703,     -1150833019,
            1013904242,     -1521486534,
            1359893119,     -1694144372,
            528734635,       1541459225,
        );
    }
}
 
 
//  static class. Access via SHA256::hash()
class SHA256 extends hash
{
    function hash($str, $mode = 'hex')
    {
        static $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($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);
            }
            else
            {
                trigger_error('SHA256::hash' . $mode . '() NOT IMPLEMENTED.', E_USER_WARNING);
            }
        }
       
        return $ret;
    }
   
    //  ------------
    //  begin internal functions
   
    //  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
    function compute(&$hashData)
    {
        static $vars = 'abcdefgh';
        static $K = null;
       
        if($K === null)
        {
            /*
            $K = array(
                (int)0x428A2F98, (int)0x71374491, (int)0xB5C0FBCF, (int)0xE9B5DBA5,
                (int)0x3956C25B, (int)0x59F111F1, (int)0x923F82A4, (int)0xAB1C5ED5,
                (int)0xD807AA98, (int)0x12835B01, (int)0x243185BE, (int)0x550C7DC3,
                (int)0x72BE5D74, (int)0x80DEB1FE, (int)0x9BDC06A7, (int)0xC19BF174,
                (int)0xE49B69C1, (int)0xEFBE4786, (int)0x0FC19DC6, (int)0x240CA1CC,
                (int)0x2DE92C6F, (int)0x4A7484AA, (int)0x5CB0A9DC, (int)0x76F988DA,
                (int)0x983E5152, (int)0xA831C66D, (int)0xB00327C8, (int)0xBF597FC7,
                (int)0xC6E00BF3, (int)0xD5A79147, (int)0x06CA6351, (int)0x14292967,
                (int)0x27B70A85, (int)0x2E1B2138, (int)0x4D2C6DFC, (int)0x53380D13,
                (int)0x650A7354, (int)0x766A0ABB, (int)0x81C2C92E, (int)0x92722C85,
                (int)0xA2BFE8A1, (int)0xA81A664B, (int)0xC24B8B70, (int)0xC76C51A3,
                (int)0xD192E819, (int)0xD6990624, (int)0xF40E3585, (int)0x106AA070,
                (int)0x19A4C116, (int)0x1E376C08, (int)0x2748774C, (int)0x34B0BCB5,
                (int)0x391C0CB3, (int)0x4ED8AA4A, (int)0x5B9CCA4F, (int)0x682E6FF3,
                (int)0x748F82EE, (int)0x78A5636F, (int)0x84C87814, (int)0x8CC70208,
                (int)0x90BEFFFA, (int)0xA4506CEB, (int)0xBEF9A3F7, (int)0xC67178F2
                );
            */

            $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,
                );
        }
       
        echo "\nPadded Message::\n";
        for($i = 0, $numChunks = sizeof($hashData->chunks); $i < $numChunks; $i++)
        {
            echo memdump($hashData->chunks[$i]) . "\n";
        }
       
        $W = array();
        for($i = 0, $numChunks = sizeof($hashData->chunks); $i < $numChunks; $i++)
        {
            //  initialize the registers
            for($j = 0; $j < 8; $j++)
                ${$vars{$j}} = $hashData->hash[$j];
           
            echo "\n\nChunk " . ($i + 1) . ' of ' . $numChunks . " ::\nhash " . memdump($hashData->hash);
           
            //  the SHA-256 compression function
            for($j = 0; $j < 64; $j++)
            {
                if($j < 16)
                {
                    $T1  = ord($hashData->chunks[$i]{$j*4  }) & 0xFF; $T1 <<= 8;
                    $T1 |= ord($hashData->chunks[$i]{$j*4+1}) & 0xFF; $T1 <<= 8;
                    $T1 |= ord($hashData->chunks[$i]{$j*4+2}) & 0xFF; $T1 <<= 8;
                    $T1 |= ord($hashData->chunks[$i]{$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);
               
                echo ' t' . sprintf('%02d',$j+1) . ' ' . memdump(array($a, $b, $c, $d, $e, $f, $g, $h));
            }
           
            //  compute the next hash set
            for($j = 0; $j < 8; $j++)
                $hashData->hash[$j] = SHA256::sum(${$vars{$j}}, $hashData->hash[$j]);
           
            echo 'DONE ' . memdump($hashData->hash);
            echo "\n\nW::\n" . memdump($W, 4) . "\n";
        }
    }
   
   
    //  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;
    }
}
 
 
//  dump passed memory
function memdump($data, $brk = 0)
{
    if(is_array($data))
    {
        $n = 0;
        $b = -1;
        $brk_step = $brk - 1;
       
        $o = '';
        for($n = 0, $y = sizeof($data); $n < $y; $n++, $b %= $brk)
        {
            if($n != 0)
            {
                if($brk > 0)
                {
                    $o .= ($b == $brk_step ? "\n" : ' ');
                }
                else
                {
                    $o .= ' ';
                }
            }
           
            $o .= memdump($data[$n]);
           
            ++$b;
        }
       
        $o .= "\n";
    }
    else
    {
        $n = 0;
        $b = 0;
        if(is_integer($data) || is_float($data))
            $data = pack('N',$data);
        $o = '';
        for($i = 0, $j = strlen($data); $i < $j; $i++, $b = $i % 4)
        {
            $o .= sprintf('%02x', ord($data{$i}));
            //  only process when 32-bits have passed through
            if($i != 0 && $b == 3)
            {
                //  process new line points
                if($n == 3)
                    $o .= "\n";
                elseif($j > 4)
                    $o .= ' ';
                ++$n;
                $n %= 4;
            }
        }
    }
   
    return $o;
}
 
 
//--------------
//  REMOVAL ALL FUNCTIONS AFTER THIS WHEN NOT TESTING
//--------------
 
//  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";
}
 
 
//  testing functions
 
function test1($it = 10000)
{
    $it = intval($it);
    if($it === 0)
        $it = 10000;
   
    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->chunks);
        echo hexerize($data->hash);
        echo 'processing took ' . (($e2 - $s2 + $e1 - $s1) / $it) . ' seconds.' . "\n\n\n";
    }
 
    echo '</pre>';
}
 
function test2($it = 10000)
{
    $it = intval($it);
    if($it === 0)
        $it = 10000;
   
    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>';
}
 
testSpeedHash(1);
 
//--------------
//  END REMOVAL HERE
//--------------
 
/* EOF :: Document Settings: tab:4; */
 
?>


Last edited by Weirdan on Sun Feb 22, 2009 10:42 am, edited 1 time in total.
removed syntax highlighting so parser won't eat entire code block


Top
 Profile  
 
 Post subject:
PostPosted: Sat Mar 12, 2005 5:10 pm 
Offline
Forum Newbie

Joined: Sat Mar 12, 2005 4:57 pm
Posts: 1
I've put up a quick interface to your class at: http://balbinus.net/2005/03/sha256/. I hope you don't mind ;) Thanks for this wonderful job :)


Top
 Profile  
 
 Post subject:
PostPosted: Sat Mar 12, 2005 9:39 pm 
Offline
Breakbeat Nuttzer
User avatar

Joined: Wed Mar 24, 2004 8:57 am
Posts: 13098
Location: Melbourne, Australia
Very nice :D


Top
 Profile  
 
PostPosted: Sat Jan 19, 2008 3:46 am 
Offline
Forum Newbie

Joined: Sat Jan 19, 2008 3:41 am
Posts: 0
Cool code,thanks for sharing.


Top
 Profile  
 
PostPosted: Thu Jan 24, 2008 4:41 am 
Offline
Forum Contributor
User avatar

Joined: Tue Jul 04, 2006 3:59 am
Posts: 147
Location: San Francisco, CA
This code has become "classic" for me. I've been using it for around 2 years. Works great! +10 for feyd.

Wish there are more "original" code like this in the php community. They are the "core of the core".


Top
 Profile  
 
PostPosted: Tue Aug 05, 2008 10:46 am 
Offline
Forum Contributor
User avatar

Joined: Sun Oct 14, 2007 4:36 am
Posts: 305
Location: Hoče, Slovenia
just to know: php has native hash implementation since 5.1.2

benchmark (100 hashes):
php: 0.00043797492981
feyd's class: 13.5305600166


Top
 Profile  
 
PostPosted: Sun Jul 05, 2009 9:37 am 
Offline
Forum Commoner
User avatar

Joined: Sun Jul 05, 2009 9:27 am
Posts: 34
Quote:
php has native hash implementation


Generate a hash value of a string:
Syntax: [ Download ] [ Hide ]
hash('sha256', $string);


Generate a hash value using the contents of a given file
Syntax: [ Download ] [ Hide ]
hash_file('sha256', 'example.txt');


Top
 Profile  
 
PostPosted: Sun Jul 05, 2009 9:47 am 
Offline
Forum Commoner
User avatar

Joined: Sun Jul 05, 2009 9:27 am
Posts: 34
Of course hash() and hash_file() functions can use many other hash algorithms such as:
md2
md4
md5
sha1
sha256
sha384
sha512
ripemd128
ripemd160
ripemd256
ripemd320
whirlpool
tiger128,3
tiger160,3
tiger192,3
tiger128,4
tiger160,4
tiger192,4
snefru
gost
adler32
crc32
crc32b
haval128,3
haval160,3
haval192,3
haval224,3
haval256,3
haval128,4
haval160,4
haval192,4
haval224,4
haval256,4
haval128,5
haval160,5
haval192,5
haval224,5
haval256,5

You can get this list by using hash_algos() function:
Syntax: [ Download ] [ Hide ]
echo '<pre>';
print_r(hash_algos());
echo '</pre>';


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 12 posts ] 

All times are UTC - 5 hours


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group