PHP Doku:: Berechnet den polynomischen CRC32-Wert eines Strings - function.crc32.html

Verlauf / Chronik / History: (1) anzeigen

Sie sind hier:
Doku-StartseitePHP-HandbuchFunktionsreferenzTextverarbeitungZeichenkettenString-Funktionencrc32

Ein Service von Reinhard Neidl - Webprogrammierung.

String-Funktionen

<<count_chars

crypt>>

crc32

(PHP 4 >= 4.0.1, PHP 5)

crc32Berechnet den polynomischen CRC32-Wert eines Strings

Beschreibung

int crc32 ( string $str )

Berechnet die zyklisch redundante polynomische Prüfsumme mit einer Länge von 32-Bit für str. Dies wird gewöhnlich für die Integritätsprüfung übermittelter Daten verwendet.

Da der Datentyp Integer von PHP vorzeichenbehaftet ("signed") ist und viele Prüfsummen negative Integer-Werte ergeben, müssen Sie die Formatierungsanweisung "%u" von sprintf() oder printf() verwenden, um die String-Repräsentation der nicht vorzeichenbehafteten ("unsigned") CRC32-Prüfsumme zu erhalten.

Parameter-Liste

str

Die Daten.

Rückgabewerte

Gibt die CRC32-Prüfsumme von str als Integer zurück.

Beispiele

Beispiel #1 Anzeigen einer CRC32-Prüfsumme

Das folgende Beispiel zeigt, wie eine konvertierte Prüfsumme mittels der Funktion printf() ausgegeben wird:

<?php
$pruefsumme 
crc32("Der schnelle braune Fuchs sprang über den trägen Hund.");
printf("%u\n"$pruefsumme);
?>

Siehe auch

  • md5() - Errechnet den MD5-Hash eines Strings
  • sha1() - Berechnet den SHA1-Hash eines Strings


31 BenutzerBeiträge:
- Beiträge aktualisieren...
chernyshevsky at hotmail dot com
23.09.2010 1:36
Here's how you can compute the CRC32 of a stream as it's being read using a stream filter with the help of the crc32_combine() function provided by petteri at qred dot fi:

// registering filter
class crc32_filter extends php_user_filter {
    public $params;

    public function filter($in, $out, &$consumed, $closing) {
        while($bucket = stream_bucket_make_writeable($in)) {
            $consumed += $bucket->datalen;
            $this->params->crc32 = crc32_combine($this->params->crc32, crc32($bucket->data), $bucket->datalen);
            stream_bucket_append($out, $bucket);
            }
        return PSFS_PASS_ON;
    }   
}

stream_filter_register('crc32', 'crc32_filter');

// usage
$params->crc32 = 0;
stream_filter_append($file, 'crc32', STREAM_FILTER_READ, $params);
while($stuff = fread($file, 10)) {
}
echo $params->crc32;

This technique is useful if you want to use the zlib.deflate filter to compress incoming data, but also need the CRC32 signature of the original file. In this case, you append the crc32 filter first, then append zlib.deflate. When all the data from the stream is read, the crc32 member in the params object is the value you want.
chernyshevsky at hotmail dot com
23.09.2010 0:54
The crc32_combine() function provided by petteri at qred dot fi has a bug that causes an infinite loop, a shift operation on a 32-bit signed int might never reach zero. Replacing the function gf2_matrix_times() with the following seems to fix it:

function gf2_matrix_times($mat, $vec)
{
    $sum=0;
    $i=0;

    while ($vec) {
        if ($vec & 1) {
            $sum ^= $mat[$i];
        }
        $vec = ($vec >> 1) & 0x7FFFFFFF;
        $i++;      
    }
    return $sum;
}

Otherwise, it's probably the best solution if you can't use hash_file(). Using a 1meg read buffer, the function only takes twice as long to process a 300meg files than hash_file() in my test.
gabri dot ns at gmail dot com
16.09.2010 7:05
if you are looking for a fast function to hash a file, take a look at
http://www.php.net/manual/en/function.hash-file.php
this is crc32 file checker based on a CRC32 guide
it have performance at ~ 625 KB/s on my 2.2GHz Turion
far slower than hash_file('crc32b','filename.ext')
<?php
function crc32_file ($filename)
{
  
$f = @fopen($filename,'rb');
   if (!
$f) return false;
  
   static
$CRC32Table, $Reflect8Table;
   if (!isset(
$CRC32Table))
   {
     
$Polynomial = 0x04c11db7;
     
$topBit = 1 << 31;
      
      for(
$i = 0; $i < 256; $i++)
      {
        
$remainder = $i << 24;
         for (
$j = 0; $j < 8; $j++)
         {
            if (
$remainder & $topBit)
              
$remainder = ($remainder << 1) ^ $Polynomial;
            else
$remainder = $remainder << 1;
         }
        
        
$CRC32Table[$i] = $remainder;
        
         if (isset(
$Reflect8Table[$i])) continue;
        
$str = str_pad(decbin($i), 8, '0', STR_PAD_LEFT);
        
$num = bindec(strrev($str));
        
$Reflect8Table[$i] = $num;
        
$Reflect8Table[$num] = $i;
      }
   }
  
  
$remainder = 0xffffffff;
   while (
$data = fread($f,1024))
   {
     
$len = strlen($data);
      for (
$i = 0; $i < $len; $i++)
      {
        
$byte = $Reflect8Table[ord($data[$i])];
        
$index = (($remainder >> 24) & 0xff) ^ $byte;
        
$crc = $CRC32Table[$index];
        
$remainder = ($remainder << 8) ^ $crc;
      }
   }
  
  
$str = decbin($remainder);
  
$str = str_pad($str, 32, '0', STR_PAD_LEFT);
  
$remainder = bindec(strrev($str));
   return
$remainder ^ 0xffffffff;
}
?>

<?php
$a
= microtime();
echo
dechex(crc32_file('filename.ext'))."\n";
$b = microtime();
echo
array_sum(explode(' ',$b)) - array_sum(explode(' ',$a))."\n";
?>
Output:
ec7369fe
2.384134054184 (or similiar)
carlos at dimension-e dot net
27.08.2010 4:36
This crc32 issue on 64 bits servers may not be a bug, but for sure it wracks many applications when the server migrates to a linux 64 bit machine.

For example, many database fields are set to accept signed 32 bits integers. This odd behavior makes those fields to be filled with the 2147483647 value, which es the higest possible number to be saved in this type of field.

It seems the PHP team regards this as a operative system issue, rather than a language issue, but the result is just the same: You just can not rely on this for data comparison between machines.
jian at theorchard dot com
17.02.2010 19:13
This function returns an unsigned integer from a 64-bit Linux platform.  It does return the signed integer from other 32-bit platforms even a 64-bit Windows one.

The reason is because the two constants PHP_INT_SIZE and PHP_INT_MAX have different values on the 64-bit Linux platform.

I've created a work-around function to handle this situation.

<?php
function get_signed_int($in) {
   
$int_max = pow(2, 31)-1;
    if (
$in > $int_max){
       
$out = $in - $int_max * 2 - 2;
    }
    else {
       
$out = $in;
    }
    return
$out;
}
?>

Hope this helps.
berna (at) gensis (dot) com (dot) br
30.09.2009 5:16
For those who want a more familiar return value for the function:

<?php
function strcrc32($text) {
 
$crc = crc32($text);
  if (
$crc & 0x80000000) {
   
$crc ^= 0xffffffff;
   
$crc += 1;
   
$crc = -$crc;
  }
  return
$crc;
}
?>

And to show the result in Hex string:

<?php
function int32_to_hex($value) {
 
$value &= 0xffffffff;
  return
str_pad(strtoupper(dechex($value)), 8, "0", STR_PAD_LEFT);
}
?>
Anonymous
16.07.2009 10:26
<?php
 
echo crc32('example')+4294967296;
?>

gives you the same result as the CRC32() function in MySQL (>=4.1)

"SELECT CRC32('example')"

vice versa

"SELECT CRC32('example')-4294967296"

in MySQL gives you the same result as:

<?php
 
echo  crc32('example');
?>
lenar at city dot ee
27.10.2008 9:25
Simplest/fastest crc16 (CRC-CCITT-16 0x1021) implementation I could find:
(and credit goes to http://www.ccsinfo.com/forum/viewtopic.php?t=24977)

<?php
function crc16($data)
{
 
$crc = 0xFFFF;
  for (
$i = 0; $i < strlen($data); $i++)
  {
   
$x = (($crc >> 8) ^ ord($data[$i])) & 0xFF;
   
$x ^= $x >> 4;
   
$crc = (($crc << 8) ^ ($x << 12) ^ ($x << 5) ^ $x) & 0xFFFF;
  }
  return
$crc;
}
kobuki
8.06.2008 1:14
I tried to use this function to calculate CRC32 values that are compatible with the CRCs in the well known SFV files. Apparently, this doesn't work out of the box, since the crc32 hash algo calculates a different value than found in SFV files (probably a different poly is used). There is another hash algo supported by PHP though, crc32b, which is almost right, but needs some transformation. The transformation involves a signed-unsigned conversion and a byte order (or endian) swap. Below is my simple function for the task.

<?
 
function crc32_file($fileName)
  {
   
$crc = hash_file("crc32b", $fileName);
   
$crc = sprintf("%08x", 0x100000000 + hexdec($crc));
    return
substr($crc, 6, 2) . substr($crc, 4, 2) . substr($crc, 2, 2) . substr($crc, 0, 2);
  }
?>

As a side note:

<?
  crc32
(file_get_contents("some_filename.dat"));
?>

produces correct output without additional transformation. I wonder if this is a bug of PHP5 i should try to report.
bbo
6.05.2008 14:20
unsigned 32 .. correct gf2_matrix_times is:
function gf2_matrix_times($mat, $vec)
{
    $sum=0;
    $i=0;
    while ($vec) {
        if ($vec & 1) {
            $sum ^= $mat[$i];
        }
        $vec>>= 1;
        $vec &= 0x7fffffff;
        $i++;
    }
    return $sum;
}
Guilherme
8.04.2008 23:02
On response to slimshady451:

hash_file( 'crc32', $file )

will not have the same return of

crc32( file_get_contents( $file ) )
angelo (at) mandato (period) com
18.01.2008 15:54
From my tests noted below, md5_file() function is the best function for performing file verification. This will remain the case until a native crc32_file() function is added to PHP.

file_crc() function that Bulk at bulksplace dot com posted is the most efficient solution on Windows for small and medium size files.  It is most likely because file_get_contents() uses memory mapping techniques.  Unfortunately on Linux (Fedora), the results were slightly better for md5_file().

sha1_file() on large files is slower than md5_file().  The time it takes for the __crc32_file() function found below is linear to the size of the file.  I would avoid using __crc32_file().  The file_crc() function will fail when using the file_get_contents() if the file is larger than the PHP.ini memory_limit setting.  Windows does not seem to use the memory_limit for file_get_contents(), but I did run into an error 'FATAL: emalloc(): Unable to allocate x bytes' when testing iso files.

I ran the following tests on both WindowsXP and Fedora 4 machines.

<?php
  
// File verification tests by Angelo Mandato (angelo [at] mandato {period} com)
 
   // __crc32_file() is very slow, you can uncomment to test for yourself.
   //require_once('crc32_file.php');
   // Copy and paste the contents of the crc32_file() code found on
   // the php.net crc32 PHP manual page in a new file and save
   // as crc32_file.php in the same directory as this script.
 
   // Get microseconds
  
function GetMicrotime()
   {
       list(
$usec, $sec) = explode(" ", microtime());
       return ((float)
$usec + (float)$sec);
   }
 
  
// file_crc() - function to test
  
function file_crc($file)
   {
      
$file_string = file_get_contents($file);
      
$crc = crc32($file_string);
       return
sprintf("%u", $crc);
   }

  
$Methods = array('sha1_file()', 'md5_file()', 'file_crc()');
   if(
function_exists('__crc32_file') )
      
$Methods[] = '__crc32_file()';
  
$directory = '/path/to/directory/'; // Don't forget trailing backslash.
  
$files = scandir($directory);
 
   for(
$method_index = 0; $method_index < count($Methods); $method_index++ )
   {
      
$start_time = GetMicrotime();
       while( list(
$index,$file) = each($files) )
       {
           if(
$file != '.' && $file != '..' && is_file($directory.$file) )
           {
               switch(
$method_index )
               {
                   case
0: { // sha1_file()
                      
$value = sha1_file($directory.$file);
                   }; break;
                   case
1: { // md5_file()
                      
$value = md5_file($directory.$file);
                   }; break;
                   case
2: { // file_crc()
                      
$value = file_crc($directory.$file);
                   }; break;
                   case
3: { // __crc32_file()
                      
$value = __crc32_file($directory.$file);
                   }; break;
               }
           }
           else
// It is not part of our test results, lets remove it from the array
          
{
               unset(
$files[$index]);
           }
       }
      
$end_time = GetMicrotime();
       echo
sprintf("%s took %.03f seconds to calculate %d files.\n", $Methods[$method_index], $end_time-$start_time, count($files) );
      
reset($files); // Reset pointer in array
  
}
   echo
"file verification tests completed.\n";
?>

It would be nice if a crc32_file() function was added to PHP natively.

I am not sure why anyone removed this post from this thread, but this is very useful information. and I believe it should remain.  If you're the moderator and deleted this before, please contact me and explain why it was removed. This is not a question, a report of a bug nor a feature request.  This is factual information that is useful to all.
daniele_dll at yahoo dot it
17.12.2007 17:44
In response to manuel at sadism-softworks dot de ( http://it2.php.net/manual/en/function.crc32.php#75061 )

You should never buffer all this stuff because you will need a lot of I/O without any really benefit! In a normal case (7.200rpm disk with ide/sata 8/16mb of cache) you should not read more that 8kb, or, at least, not more of 16kb.

The reason is simple: if you read, for example, of 128kb the system will do 16 i/o reads each of 8kb!

So the performance will be the same (or really near) but you will use really few memory for the script ... in that way you let to the server to have more memory for other scripts and stuffs
dave at jufer dot info
3.12.2007 23:15
// This function returns the same int value on a 64 bit mc. like the crc32() function on a 32 bit mc.

function crcKw($num){
    $crc = crc32($num);
    if($crc & 0x80000000){
        $crc ^= 0xffffffff;
        $crc += 1;
        $crc = -$crc;
    }
    return $crc;
}
Ren
3.10.2007 20:53
Dealing with 32 bit unsigned values overflowing 32 bit php signed values can be done by adding 0x10000000 to any unexpected negative result, rather than using sprintf.

$i = crc32('1');
printf("%u\n", $i);
if (0 > $i)
{
    // Implicitly casts i as float, and corrects this sign.
    $i += 0x100000000;
}
var_dump($i);

Outputs:

2212294583
float(2212294583)
petteri at qred dot fi
29.06.2007 8:03
If you have php version<5.1.2 you might use this.
It's a little bit faster than __crc32_file() :)

Ps. crc32_combine() is ported directly from zlib.

<?php
function crc32_file($filename)
{
   
$fp=fopen($filename, "rb");
   
$old_crc=false;

    if (
$fp != false) {
       
$buffer = '';
       
        while (!
feof($fp)) {
           
$buffer=fread($fp, 10485760);
           
$len=strlen($buffer);      
           
$t=crc32($buffer);   
       
            if (
$old_crc) {
               
$crc32=crc32_combine($old_crc, $t, $len);
               
$old_crc=$crc32;
            } else {
               
$crc32=$old_crc=$t;
            }
        }
       
fclose($fp);
    } else {
        print
"Cannot open file\n";
    }

    return
$crc32;
}

function
crc32_combine($crc1, $crc2, $len2)
{
   
$odd[0]=0xedb88320;
   
$row=1;

    for(
$n=1;$n<32;$n++) {
       
$odd[$n]=$row;
       
$row<<=1;
    }

   
gf2_matrix_square($even,$odd);
   
gf2_matrix_square($odd,$even);

    do {
       
/* apply zeros operator for this bit of len2 */
       
gf2_matrix_square($even, $odd);

        if (
$len2 & 1)
           
$crc1=gf2_matrix_times($even, $crc1);

       
$len2>>=1;
   
       
/* if no more bits set, then done */
       
if ($len2==0)
            break;
   
       
/* another iteration of the loop with odd and even swapped */
       
gf2_matrix_square($odd, $even);
        if (
$len2 & 1)
           
$crc1=gf2_matrix_times($odd, $crc1);
       
$len2>>= 1;
   
    } while (
$len2 != 0);

   
$crc1 ^= $crc2;
    return
$crc1;
}

function
gf2_matrix_square(&$square, &$mat)
{
    for (
$n=0;$n<32;$n++) {
       
$square[$n]=gf2_matrix_times($mat, $mat[$n]);
    }
}

function
gf2_matrix_times($mat, $vec)
{
   
$sum=0;
   
$i=0;
    while (
$vec) {
        if (
$vec & 1) {
           
$sum ^= $mat[$i];
        }
       
$vec>>= 1;
       
$i++;
    }
    return
$sum;
}
?>
slimshady451
20.06.2007 11:14
I see a lot of function for crc32_file, but for php version >= 5.1.2 don't forget you can use this :

function crc32_file($filename)
{
    return hash_file ('CRC32', $filename , FALSE );
}

Using crc32(file_get_contents($filename)) will use too many memory on big file so don't use it.
mail at tristansmis dot nl
30.05.2007 10:36
I used the abs value of this function on a 32-bit system. When porting the code to a 64-bit system I’ve found that the value is different. The following code has the same outcome on both systems.
<?php

   $crc
= abs(crc32($string));
   if(
$crc & 0x80000000){
     
$crc ^= 0xffffffff;
     
$crc += 1;
   }

  
/* Old solution
    * $crc = abs(crc32($string))
    */

?>
manuel at sadism-softworks dot de
10.05.2007 15:35
In response to quix at free dot fr (http://www.php.net/manual/de/function.crc32.php#31832):

Through buffering his CRC32 calculation is about 2-4 times faster:

<?php
 
function __crc32_file($name)
  {
   
// Creates a CRC from a file
    // Info: look at __crc32_string
   
   
global $__crc32_table;

   
// Start out with all bits set high.
   
$crc = 0xffffffff;

   
// Open the file
   
$fp = fopen($name, "rb");
   
   
// Read the file using a 1MB buffer
    // This will speed up CRC calculation at least 2-4x!
    // (5MB file: 15sec instead of 50sec)
   
if ($fp != false)
    {
     
$buffer = '';
     
      while (!
feof($fp))
      {
       
$buffer = fread($fp, 1048576); // Buffer 1MByte of file into memory
       
$len = strlen($buffer);        // Cache buffer length (just this saves about 10sec on a 5MB file!)
       
for ($i = 0; $i < $len; $i++)
        {
         
$crc = (($crc >> 8) & 0x00ffffff) ^ $__crc32_table[($crc & 0xFF) ^ ord($buffer[$i])];
        }
      }

     
fclose($fp);
    }

   
// Exclusive OR the result with the beginning value.
   
return $crc ^ 0xffffffff;
  }
?>
adam dot chout at gmail dot com
5.03.2007 22:25
it should be poitned out that this function does not operate the same on 32-bit systems and 64-bit systems. so any php code written for one is not portable on the other. more information can be found here:

http://bugs.php.net/bug.php?id=39062
roberto at spadim dot com dot br
8.04.2006 6:52
MODBUS RTU, CRC16,
input-> modbus rtu string
output -> 2bytes string, in correct modbus order

function crc16($string,$length=0){

    $auchCRCHi=array(    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
                0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
                0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
                0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
                0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
                0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
                0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
                0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
                0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
                0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
                0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
                0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
                0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
                0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
                0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
                0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
                0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
                0x40);
    $auchCRCLo=array(    0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,
                0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
                0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,
                0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
                0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,
                0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
                0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
                0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
                0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,
                0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
                0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,
                0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
                0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,
                0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
                0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,
                0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
                0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
                0x40);
    $length        =($length<=0?strlen($string):$length);
    $uchCRCHi    =0xFF;
    $uchCRCLo    =0xFF;
    $uIndex        =0;
    for ($i=0;$i<$length;$i++){
        $uIndex        =$uchCRCLo ^ ord(substr($string,$i,1));
        $uchCRCLo    =$uchCRCHi ^ $auchCRCHi[$uIndex];
        $uchCRCHi    =$auchCRCLo[$uIndex] ;
    }
    return(chr($uchCRCLo).chr($uchCRCHi));
}
Bulk at bulksplace dot com
27.08.2005 14:46
A faster way I've found to return CRC values of larger files, is instead of using the file()/implode() method used below, is to us file_get_contents() (PHP 4 >= 4.3.0) which uses memory mapping techniques if supported by your OS to enhance performance. Here's my example function:

<?
// $file is the path to the file you want to check.
function file_crc($file)
{
   
$file_string = file_get_contents($file);

   
$crc = crc32($file_string);
   
    return
sprintf("%u", $crc);
}

$file_to_crc = /home/path/to/file.jpg;

echo
file_crc($file_to_crc); // Outputs CRC value for given file.
?>

I've found in testing this method is MUCH faster for larger binary files.
schmeic-php at lovo dot org
7.07.2005 22:26
I think that Mario's (spectrumizer at cycos dot net) CRC16 algorithm might be wrong.  At least according to these two online calculators:

http://www.zorc.breitbandkatze.de/crc.html
http://www.lammertbies.nl/comm/info/crc-calculation.html

  However, it seems that there can be some confusion concerning "official" CRC16 algorithms.  See this article for two possible CRC16-CCITT algorithms:

http://www.joegeluso.com/software/articles/ccitt.htm

  Here is a php implementation of the "bad" CRC16-CCITT algorithm from the article.  The "bad" implementation might not match the "official" algorithm, but is widely used, including by the two crc calculators mentioned above.

  Note that crc16-CCITT is also referred to as crc16c.

<?php

// this function is used to calculate the (common) crc16c for an entire buffer
function calculate_common_crc16c($buffer)
{
   
$crc16c = 0xffff// the crc initial value

   
$buffer_length = strlen($buffer);

    for (
$i = 0; $i < $buffer_length; $i++)
    {
       
$ch = ord($buffer[$i]);

       
$crc16c = update_common_crc16c($ch, $crc16c);
    }

    return
$crc16c;
}

// this function is used to calculate the (common) crc16c byte by byte
// $ch is the next byte and $crc16c is the result from the last call, or 0xffff initially
function update_common_crc16c($ch, $crc16c)
{
    global
$crc16c_polynomial;

   
// This comment was in the code from
    // http://www.joegeluso.com/software/articles/ccitt.htm

    // Why are they shifting this byte left by 8 bits??
    // How do the low bits of the poly ever see it?
   
$ch <<= 8;

    for(
$i = 0; $i < 8; $i++)
    {
        if ((
$crc16c ^ $ch) & 0x8000)
        {
           
$xor_flag = true;
        }
        else
        {
           
$xor_flag = false;
        }

       
$crc16c = $crc16c << 1;

        if (
$xor_flag)
        {
           
$crc16c = $crc16c ^ $crc16c_polynomial;
        }

       
$ch = $ch << 1;
    }

   
// mask off (zero out) the upper two bytes
   
$crc16c = $crc16c & 0x0000ffff;

    return
$crc16c;
}

?>
gribber (_at) hellburner (dot_) net
18.05.2004 23:41
A little correction to the sfv checksum code above, this was confuseing me for a while, heading zeros was striped away.

<?php
function sfv_checksum ($filename) {
    return
str_pad (strtoupper (dechex (crc32 (file_get_contents ($filename)))), 8, '0', STR_PAD_LEFT);
}
?>
waldomonster at netjukebox dot demon dot nl
23.04.2004 17:48
<?php
$data
= 'dot';
echo
dechex(crc32($data));
?>

Returns 59278a3
Witch is missing a leading zero.

<?php
$data
= 'dot';
echo
str_pad(dechex(crc32($data)), 8, '0', STR_PAD_LEFT);
?>

Returns the correct string: 059278a3
arachnid at notdot dot net
14.04.2004 5:44
Note that the CRC32 algorithm should NOT be used for cryptographic purposes, or in situations where a hostile/untrusted user is involved, as it is far too easy to generate a hash collision for CRC32 (two different binary strings that have the same CRC32 hash). Instead consider SHA-1 or MD5.
same
2.02.2004 2:27
bit by bit crc32 computation

<?php

function bitbybit_crc32($str,$first_call=false){

   
//reflection in 32 bits of crc32 polynomial 0x04C11DB7
   
$poly_reflected=0xEDB88320;

   
//=0xFFFFFFFF; //keep track of register value after each call
   
static $reg=0xFFFFFFFF;

   
//initialize register on first call
   
if($first_call) $reg=0xFFFFFFFF;
   
   
$n=strlen($str);
   
$zeros=$n<4 ? $n : 4;

   
//xor first $zeros=min(4,strlen($str)) bytes into the register
   
for($i=0;$i<$zeros;$i++)
       
$reg^=ord($str{$i})<<$i*8;

   
//now for the rest of the string
   
for($i=4;$i<$n;$i++){
       
$next_char=ord($str{$i});
        for(
$j=0;$j<8;$j++)
           
$reg=(($reg>>1&0x7FFFFFFF)|($next_char>>$j&1)<<0x1F)
                ^(
$reg&1)*$poly_reflected;
    }

   
//put in enough zeros at the end
   
for($i=0;$i<$zeros*8;$i++)
       
$reg=($reg>>1&0x7FFFFFFF)^($reg&1)*$poly_reflected;

   
//xor the register with 0xFFFFFFFF
   
return ~$reg;
}

$str="123456789"; //whatever
$blocksize=4; //whatever

for($i=0;$i<strlen($str);$i+=$blocksize) $crc=bitbybit_crc32(substr($str,$i,$blocksize),!$i);

?>
xethmir at yournextclient dot com
17.07.2003 4:12
This is a really simple way of displaying the crc-32 hexadecimal code/checksum for a file... (absolute paths are more reliable)

<?
$file
= "http://foo.net/bar.jpg";

// Read the file into an array
$data = file($file);

// Join the array into a string
$data = implode('', $data);

// Calculate the crc
$crc = crc32($data);

//convert from decimal to hexadecimal
$crchex=DecHex($crc*1);

//echo the result
echo "$crchex";
?>
quix at free dot fr
5.05.2003 22:19
I needed the crc32 of a file that was pretty large, so I didn't want to read it into memory.
So I made this:

<?php
    $GLOBALS
['__crc32_table']=array();        // Lookup table array
   
__crc32_init_table();

    function
__crc32_init_table() {            // Builds lookup table array
        // This is the official polynomial used by
        // CRC-32 in PKZip, WinZip and Ethernet.
       
$polynomial = 0x04c11db7;

       
// 256 values representing ASCII character codes.
       
for($i=0;$i <= 0xFF;++$i) {
           
$GLOBALS['__crc32_table'][$i]=(__crc32_reflect($i,8) << 24);
            for(
$j=0;$j < 8;++$j) {
               
$GLOBALS['__crc32_table'][$i]=(($GLOBALS['__crc32_table'][$i] << 1) ^
                    ((
$GLOBALS['__crc32_table'][$i] & (1 << 31))?$polynomial:0));
            }
           
$GLOBALS['__crc32_table'][$i] = __crc32_reflect($GLOBALS['__crc32_table'][$i], 32);
        }
    }

    function
__crc32_reflect($ref, $ch) {        // Reflects CRC bits in the lookup table
       
$value=0;
       
       
// Swap bit 0 for bit 7, bit 1 for bit 6, etc.
       
for($i=1;$i<($ch+1);++$i) {
            if(
$ref & 1) $value |= (1 << ($ch-$i));
           
$ref = (($ref >> 1) & 0x7fffffff);
        }
        return
$value;
    }

    function
__crc32_string($text) {        // Creates a CRC from a text string
        // Once the lookup table has been filled in by the two functions above,
        // this function creates all CRCs using only the lookup table.

        // You need unsigned variables because negative values
        // introduce high bits where zero bits are required.
        // PHP doesn't have unsigned integers:
        // I've solved this problem by doing a '&' after a '>>'.

        // Start out with all bits set high.
       
$crc=0xffffffff;
       
$len=strlen($text);

       
// Perform the algorithm on each character in the string,
        // using the lookup table values.
       
for($i=0;$i < $len;++$i) {
           
$crc=(($crc >> 8) & 0x00ffffff) ^ $GLOBALS['__crc32_table'][($crc & 0xFF) ^ ord($text{$i})];
        }
       
       
// Exclusive OR the result with the beginning value.
       
return $crc ^ 0xffffffff;
    }
   
    function
__crc32_file($name) {            // Creates a CRC from a file
        // Info: look at __crc32_string

        // Start out with all bits set high.
       
$crc=0xffffffff;

        if((
$fp=fopen($name,'rb'))===false) return false;

       
// Perform the algorithm on each character in file
       
for(;;) {
           
$i=@fread($fp,1);
            if(
strlen($i)==0) break;
           
$crc=(($crc >> 8) & 0x00ffffff) ^ $GLOBALS['__crc32_table'][($crc & 0xFF) ^ ord($i)];
        }
       
        @
fclose($fp);
       
       
// Exclusive OR the result with the beginning value.
       
return $crc ^ 0xffffffff;
    }
?>
lander at liebe dot nu
21.04.2003 4:22
A simple and quite fast (10ms/Mb) way to generate checksums used with the popular SFV (Simple File Verification) format. strtoupper() isn't really needed, but the output looks better this way ;)

<?php
function generate_sfv_checksum($filename) {
$sfv_checksum = strtoupper(dechex(crc32(file_get_contents($filename))));
return $sfv_checksum;
}
?>
spectrumizer at cycos dot net
30.12.2002 0:30
Here is a tested and working CRC16-Algorithm:

<?php
function crc16($string) {
 
$crc = 0xFFFF;
  for (
$x = 0; $x < strlen ($string); $x++) {
   
$crc = $crc ^ ord($string[$x]);
    for (
$y = 0; $y < 8; $y++) {
      if ((
$crc & 0x0001) == 0x0001) {
       
$crc = (($crc >> 1) ^ 0xA001);
      } else {
$crc = $crc >> 1; }
    }
  }
  return
$crc;
}
?>

Regards,
Mario



PHP Powered Diese Seite bei php.net
The PHP manual text and comments are covered by the Creative Commons Attribution 3.0 License © the PHP Documentation Group - Impressum - mail("TO:Reinhard Neidl",...)