2

Possible Duplicate:
CRC8-Check in PHP

Is there any good PHP 8bit CRC generation? I searched and I couldn't find any good source. I've found a 16bit though:

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; 
} 
Community
  • 1
  • 1
HabibS
  • 382
  • 6
  • 14
  • Why do you need an 8 bit one? I can't imagine it would be awfully useful for error detection (Probability of a false negative is too high) or for bucketing (Probability of collisions is too high) – GordonM Dec 29 '12 at 07:16
  • need this for small packet crc. – HabibS Dec 29 '12 at 07:22
  • Note that a single TCP segment already has a header of 20 bytes. With a single byte checksum, you only have 256 different values. That means that having as little 257 different packets will produce at least one crc that is the same for at least two packets. – GolezTrol Dec 29 '12 at 08:07
  • GolezTrol; that script have problem, and wont generate right CRC. it is in comments too. – HabibS Dec 29 '12 at 08:19

2 Answers2

7

I've made a simple code based on Mark's code in c, and will put it here for anyone to use:

global $crc8_table;
$crc8_table = array(
    0x00, 0x3e, 0x7c, 0x42, 0xf8, 0xc6, 0x84, 0xba, 0x95, 0xab, 0xe9, 0xd7,
    0x6d, 0x53, 0x11, 0x2f, 0x4f, 0x71, 0x33, 0x0d, 0xb7, 0x89, 0xcb, 0xf5,
    0xda, 0xe4, 0xa6, 0x98, 0x22, 0x1c, 0x5e, 0x60, 0x9e, 0xa0, 0xe2, 0xdc,
    0x66, 0x58, 0x1a, 0x24, 0x0b, 0x35, 0x77, 0x49, 0xf3, 0xcd, 0x8f, 0xb1,
    0xd1, 0xef, 0xad, 0x93, 0x29, 0x17, 0x55, 0x6b, 0x44, 0x7a, 0x38, 0x06,
    0xbc, 0x82, 0xc0, 0xfe, 0x59, 0x67, 0x25, 0x1b, 0xa1, 0x9f, 0xdd, 0xe3,
    0xcc, 0xf2, 0xb0, 0x8e, 0x34, 0x0a, 0x48, 0x76, 0x16, 0x28, 0x6a, 0x54,
    0xee, 0xd0, 0x92, 0xac, 0x83, 0xbd, 0xff, 0xc1, 0x7b, 0x45, 0x07, 0x39,
    0xc7, 0xf9, 0xbb, 0x85, 0x3f, 0x01, 0x43, 0x7d, 0x52, 0x6c, 0x2e, 0x10,
    0xaa, 0x94, 0xd6, 0xe8, 0x88, 0xb6, 0xf4, 0xca, 0x70, 0x4e, 0x0c, 0x32,
    0x1d, 0x23, 0x61, 0x5f, 0xe5, 0xdb, 0x99, 0xa7, 0xb2, 0x8c, 0xce, 0xf0,
    0x4a, 0x74, 0x36, 0x08, 0x27, 0x19, 0x5b, 0x65, 0xdf, 0xe1, 0xa3, 0x9d,
    0xfd, 0xc3, 0x81, 0xbf, 0x05, 0x3b, 0x79, 0x47, 0x68, 0x56, 0x14, 0x2a,
    0x90, 0xae, 0xec, 0xd2, 0x2c, 0x12, 0x50, 0x6e, 0xd4, 0xea, 0xa8, 0x96,
    0xb9, 0x87, 0xc5, 0xfb, 0x41, 0x7f, 0x3d, 0x03, 0x63, 0x5d, 0x1f, 0x21,
    0x9b, 0xa5, 0xe7, 0xd9, 0xf6, 0xc8, 0x8a, 0xb4, 0x0e, 0x30, 0x72, 0x4c,
    0xeb, 0xd5, 0x97, 0xa9, 0x13, 0x2d, 0x6f, 0x51, 0x7e, 0x40, 0x02, 0x3c,
    0x86, 0xb8, 0xfa, 0xc4, 0xa4, 0x9a, 0xd8, 0xe6, 0x5c, 0x62, 0x20, 0x1e,
    0x31, 0x0f, 0x4d, 0x73, 0xc9, 0xf7, 0xb5, 0x8b, 0x75, 0x4b, 0x09, 0x37,
    0x8d, 0xb3, 0xf1, 0xcf, 0xe0, 0xde, 0x9c, 0xa2, 0x18, 0x26, 0x64, 0x5a,
    0x3a, 0x04, 0x46, 0x78, 0xc2, 0xfc, 0xbe, 0x80, 0xaf, 0x91, 0xd3, 0xed,
    0x57, 0x69, 0x2b, 0x15);

function crc8($data1)
{
    global $crc8_table;

    $crc = 0xff;
    for ($ii1=0;$ii1<strlen($data1);$ii1++){
        $crc = $crc8_table[($crc ^ ($data1[$ii1]))];
    }
    return $crc ^ 0xff;
}

//samples here:
echo "CRC1:".crc8("JDoas OIJE #@)( DPOASDjPOIow)")."<br />\n";
echo "CRC2:".crc8("29890sskd-2109-129us")."<br />\n";
echo "CRC3:".crc8("0917380982748097218082188217897266661091263")."<br />\n";

<!--BUT TRY THESE TOO before you place too much reliance on this coding -->
echo "CRC4a:".crc8("spookily, the same text gives the same results, in lower or upper case")."<br />\n";
echo "CRC4b:".crc8("SPOOKILY, THE SAME TEXT GIVES THE SAME RESULTS, IN LOWER OR UPPER CASE")."<br />\n";
echo "CRC4c:".crc8("And different text of the same length also gives the same check result")."<br />\n";
echo "CRC4d:".crc8("And the text can have special characters too!!!!!!!!!!!!!!!!!!!!!!!!!!")."<br /><br />\n";
HabibS
  • 382
  • 6
  • 14
1

CRC-8 in C. The commented out crc8_slow() could be readily adapted to php like your 16-bit example. Or you could use the version with the table, crc8().

#include <stddef.h>

/* 8-bit CRC with polynomial x^8+x^6+x^3+x^2+1, 0x14D.
   Chosen based on Koopman, et al. (0xA6 in his notation = 0x14D >> 1):
   http://www.ece.cmu.edu/~koopman/roses/dsn04/koopman04_crc_poly_embedded.pdf
 */

static unsigned char crc8_table[] = {
    0x00, 0x3e, 0x7c, 0x42, 0xf8, 0xc6, 0x84, 0xba, 0x95, 0xab, 0xe9, 0xd7,
    0x6d, 0x53, 0x11, 0x2f, 0x4f, 0x71, 0x33, 0x0d, 0xb7, 0x89, 0xcb, 0xf5,
    0xda, 0xe4, 0xa6, 0x98, 0x22, 0x1c, 0x5e, 0x60, 0x9e, 0xa0, 0xe2, 0xdc,
    0x66, 0x58, 0x1a, 0x24, 0x0b, 0x35, 0x77, 0x49, 0xf3, 0xcd, 0x8f, 0xb1,
    0xd1, 0xef, 0xad, 0x93, 0x29, 0x17, 0x55, 0x6b, 0x44, 0x7a, 0x38, 0x06,
    0xbc, 0x82, 0xc0, 0xfe, 0x59, 0x67, 0x25, 0x1b, 0xa1, 0x9f, 0xdd, 0xe3,
    0xcc, 0xf2, 0xb0, 0x8e, 0x34, 0x0a, 0x48, 0x76, 0x16, 0x28, 0x6a, 0x54,
    0xee, 0xd0, 0x92, 0xac, 0x83, 0xbd, 0xff, 0xc1, 0x7b, 0x45, 0x07, 0x39,
    0xc7, 0xf9, 0xbb, 0x85, 0x3f, 0x01, 0x43, 0x7d, 0x52, 0x6c, 0x2e, 0x10,
    0xaa, 0x94, 0xd6, 0xe8, 0x88, 0xb6, 0xf4, 0xca, 0x70, 0x4e, 0x0c, 0x32,
    0x1d, 0x23, 0x61, 0x5f, 0xe5, 0xdb, 0x99, 0xa7, 0xb2, 0x8c, 0xce, 0xf0,
    0x4a, 0x74, 0x36, 0x08, 0x27, 0x19, 0x5b, 0x65, 0xdf, 0xe1, 0xa3, 0x9d,
    0xfd, 0xc3, 0x81, 0xbf, 0x05, 0x3b, 0x79, 0x47, 0x68, 0x56, 0x14, 0x2a,
    0x90, 0xae, 0xec, 0xd2, 0x2c, 0x12, 0x50, 0x6e, 0xd4, 0xea, 0xa8, 0x96,
    0xb9, 0x87, 0xc5, 0xfb, 0x41, 0x7f, 0x3d, 0x03, 0x63, 0x5d, 0x1f, 0x21,
    0x9b, 0xa5, 0xe7, 0xd9, 0xf6, 0xc8, 0x8a, 0xb4, 0x0e, 0x30, 0x72, 0x4c,
    0xeb, 0xd5, 0x97, 0xa9, 0x13, 0x2d, 0x6f, 0x51, 0x7e, 0x40, 0x02, 0x3c,
    0x86, 0xb8, 0xfa, 0xc4, 0xa4, 0x9a, 0xd8, 0xe6, 0x5c, 0x62, 0x20, 0x1e,
    0x31, 0x0f, 0x4d, 0x73, 0xc9, 0xf7, 0xb5, 0x8b, 0x75, 0x4b, 0x09, 0x37,
    0x8d, 0xb3, 0xf1, 0xcf, 0xe0, 0xde, 0x9c, 0xa2, 0x18, 0x26, 0x64, 0x5a,
    0x3a, 0x04, 0x46, 0x78, 0xc2, 0xfc, 0xbe, 0x80, 0xaf, 0x91, 0xd3, 0xed,
    0x57, 0x69, 0x2b, 0x15};

unsigned crc8(unsigned crc, unsigned char *data, size_t len)
{
    unsigned char *end;

    if (len == 0)
        return crc;
    crc ^= 0xff;
    end = data + len;
    do {
        crc = crc8_table[crc ^ *data++];
    } while (data < end);
    return crc ^ 0xff;
}

/* this was used to generate the table and to test the table-version

#define POLY 0xB2

unsigned crc8_slow(unsigned crc, unsigned char *data, size_t len)
{
    unsigned char *end;

    if (len == 0)
        return crc;
    crc ^= 0xff;
    end = data + len;
    do {
        crc ^= *data++;
        crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
        crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
        crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
        crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
        crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
        crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
        crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
        crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
    } while (data < end);
    return crc ^ 0xff;
}
*/

#include <stdio.h>

#define SIZE 16384

int main(void)
{
    unsigned char data[SIZE];
    size_t got;
    unsigned crc;

    crc = 0;
    do {
        got = fread(data, 1, SIZE, stdin);
        crc = crc8(crc, data, got);
    } while (got == SIZE);
    printf("%02x\n", crc);
    return 0;
}
Mark Adler
  • 101,978
  • 13
  • 118
  • 158
  • I'm not familiar with c, but is crc8 function's data a multibyte data? – HabibS Dec 29 '12 at 09:02
  • @HabibS: data is a [pointer](http://en.wikipedia.org/wiki/Pointer_%28computer_programming%29). *data++ initially refers to the first byte of data and then to each subsequent byte. – PleaseStand Dec 29 '12 at 09:48
  • I have created a more detailed implementation of your suggestion for CRC8 in Java [here](http://stackoverflow.com/a/28937333/2773737) and would very much like for you to comment, since I cannot fully understand the CRC math, especially the polynomial variations. – fubar Mar 09 '15 at 08:01