fkupper fkupper - 5 months ago 11
PHP Question

Translate CRC alrgorythm from C to PHP

SOLVED



I have the following code on C and I have to write it on PHP

const U16 crc_table[16] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef
};

U16 CalculateCrc(char *data, U32 len) {
U32 i;
U16 crc = 0;

while (len--) {
i = (crc >> 12) ^ (*data >> 4);
crc = crc_table[i & 0x0F] ^ (crc << 4);
i = (crc >> 12) ^ (*data >> 0);
crc = crc_table[i & 0x0F] ^ (crc << 4);
data++;
}
return (crc & 0xFFFF);
}


In a basic logic translation, I did this so far:

public function crc($data){

$i = 0;
$crc = 0;

/* @var $crc_table array */
$crc_table = array
(
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef
);

for($a = 0; $a < strlen($data); $a++){
$i = (($crc >> 12) ^ ($data[$a] >> 4));
$crc = ($crc_table[$i & 0x0F] ^ ($crc << 4));
$i = (($crc >> 12) ^ $data[$a]);
$crc = ($crc_table[$i & 0x0F] ^ ($crc << 4));
}



return ($crc & 0xFFFF);

}


The results are not matching by no means and I'm no expert on this kind of thing. Any suggestion?




EDIT

Thanks "squeamish ossifrage"!
Based on your help, I'm using to this function now:

private function crc($data){

$i = 0;
$crc = 0;

$crc_table = array
(
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef
);

$data = hex2bin($data);
$l = 0;
while($l < strlen($data)){

$byte = $data[$l];
$i = (($crc >> 12) ^ (ord($byte) >> 4));
$crc = ($crc_table[$i & 0x0F] ^ ($crc << 4));
$i = (($crc >> 12) ^ (ord($byte) >> 4));
$crc = ($crc_table[$i & 0x0F] ^ ($crc << 4));
$l++;
}

return ($crc & 0xFFFF);

}


I'm testing it with "Hello world" as hex "48656C6C6F20776F726C64".
On C I get 37278 and on php function above 56062.

Any clues now?




EDIT

Ok, my bad...the problem was already solved but I have confused myself after so many tests.

This is my first version of the code with the suggested correction by "squeamish ossifrage":

$byte = $data[$l];
$i = (($crc >> 12) ^ (ord($byte) >> 4));
$crc = ($crc_table[$i & 0x0F] ^ ($crc << 4));
$i = (($crc >> 12) ^ **ord($byte));**
$crc = ($crc_table[$i & 0x0F] ^ ($crc << 4));
$l++;


Thanks!

Answer

Your code isn't working because you're computing XOR products of integers and string variables:

$i = (($crc >> 12) ^ ($data[$a] >> 4));

Here $data[$a] is a substring of the input data. You should use ord() to convert this to an integer:

$i = (($crc >> 12) ^ (ord($data[$a]) >> 4));

(Edit: With this change to your PHP code, the string Hello, world! hashes to 31454 in both functions.)