简体   繁体   English

使用Pycrc和PHP代码进行CRC32计算与预期结果不匹配

[英]CRC32 Calculation With Pycrc and PHP code Doesn't Match Expected Result

I was trying to convert a CRC32 algorithm defined as a C/C++ macro 我试图转换定义为C / C ++宏的CRC32算法

unsigned long sctp_crc_c[256] = {
0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L,
};

#define SCTP_CRC32C(c, d) (c = ((c) >> 8) ^ sctp_crc_c[((c) ^ (d)) & 0xFF])

UINT32 CRC32_F_calc(UINT32 crc32, unsigned char *buffer, unsigned int length)
{
    unsigned int i;

    for (i = 0; i < length; i++)
    {
       SCTP_CRC32C(crc32, buffer[i]);
    }

    return (crc32);
}

into a PHP code ( already asked once for that ) and I couldn't get the result output the same as the C++ one. 进入PHP代码( 已经问过一次 ),我无法得到与C ++相同的结果输出。 The input is (128 bytes binary) displayed as hex string: 输入为(128字节二进制)显示为十六进制字符串:

CC9F786E57B408F83EE907D32D1D7FA6F180632E1CBE97AE717B2CD964EBB5E71E97B49619E8CD7A94DA0CDD06083D169618017FB8A1722F21FFD609EA655665F8881B05AFE0B282B186E0B8A4A5C26727778EC6639592776E392996430D47143F740E541E3755B1627ECD31C1B98A7C3D010AE273D6900263F6A49600000000 CC9F786E57B408F83EE907D32D1D7FA6F180632E1CBE97AE717B2CD964EBB5E71E97B49619E8CD7A94DA0CDD06083D169618017FB8A1722F21FFD609EA655665F8881B05AFE0B282B186E0B8A4A5C26727778EC6639592776E392996430D47143F740E541E3755B1627ECD31C1B98A7C3D010AE273D6900263F6A49600000000

and the expected CRC32 in hex is 956E04C6 . 并且预期的十六进制CRC32是956E04C6 It's OK even if it's in reverse order, but I MUST produce that exact value. 即使它是相反的顺序也没关系,但我必须产生那个确切的值。

The algorithm calculates the code in chunks and the only other MUST is a starting crc32 = 7 ie the initial CRC value for the function CRC32_F_calc , and the bytes (displayed as hex string) for the buffer are actually 128 in length. 该算法以块为单位计算代码,唯一的另一个必须是起始crc32 = 7,即函数CRC32_F_calc的初始CRC值, 缓冲区的字节(显示为十六进制字符串)实际上是128个长度。

What I could get wasn't even close, so I checked the pycrc program, but also couldn't get it to work. 我能得到的甚至不是很接近,所以我检查了pycrc程序,但也无法让它工作。 Here is what happened: 这是发生了什么:

the command (with parameters for crc-32c and xor-in changed to 0x7) 命令( crc-32c和xor-in的参数更改为0x7)

 ./pycrc.py --check-hexstring CC...<same string as above>...9600000000 --verbose --width 32 --poly 0x1edc6f41 --reflect-in True --xor-in 0x7 --reflect-out True --xor-out 0xffffffff --algorithm table-driven

the output 输出

Width        = 32
Poly         = 0x1edc6f41
ReflectIn    = True
XorIn        = 0x00000007
ReflectOut   = True
XorOut       = 0xffffffff
Algorithm    = table-driven

0xab2c9624

I don't know what I'm missing. 我不知道我错过了什么。 I have very little time to make it happen (few hours), so even the python program (with correct parameters) is good if I can call it from the PHP application. 我没有多少时间来实现它(几个小时),所以即使是python程序(具有正确的参数)也是好的,如果我可以从PHP应用程序调用它。

The PHP code I got so far is: 到目前为止我得到的PHP代码是:

function hex2str($hex)
{
    $string = '';
    $length = strlen($hex);
    for ($i = 0; $i < $length - 1; $i += 2)
    {
        $string .= chr(hexdec($hex[$i] . $hex[$i + 1]));
    }
    return $string;
}

function str2hex($string)
{
    $hex = '';
    $length = strlen($string);
    for ($i = 0; $i < $length; $i++)
    {
        $hex .= dechex(ord($string[$i]));
    }
    return strtoupper($hex);
}

function crc32c($string = '', $hex = false)
{

    $crc_array = array(0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351, );
    $crc_array_hex = array_map('dechex', $crc_array);
    echo "\ncrc_array: " . implode(', ', $crc_array_hex) . "\n";

    if ($hex)
    {
        $string = hex2str($string);
    }

    $length = strlen($string);
    $crc32 = 7;
    echo "\nlength of string: $length, starting crc32: $crc32\n\n";
    echo "step\tdata\tindex\tcrc32\n";

    for ($i = 0; $i < $length; $i++)
    {
        $data = (int)ord($string[$i]);
        $index = 0xFF & (int)($crc32 ^ $data);
        $crc32 = (int)($crc32>>8) ^ $crc_array[$index];
        echo "$i\t$data\t$index\t" . dechex($crc32) . "\n";
    }

    return $crc32;

}

echo "<pre>\n";
$hex_string = 'CC9F786E57B408F83EE907D32D1D7FA6F180632E1CBE97AE717B2CD964EBB5E71E97B49619E8CD7A94DA0CDD06083D169618017FB8A1722F21FFD609EA655665F8881B05AFE0B282B186E0B8A4A5C26727778EC6639592776E392996430D47143F740E541E3755B1627ECD31C1B98A7C3D010AE273D6900263F6A49600000000';
echo "\nresult: " . dechex(crc32c($hex_string, true));
echo "\nexpected: 956E04C6 or C6046E95\n\n";

The provided C code produces the answer you expect, which is 0xc6046e95. 提供的C代码会产生您期望的答案,即0xc6046e95。 When written out in little-endian order, which is probably what you were seeing, the result is 95 6e 04 c6. 当以小端顺序写出时,这可能就是你所看到的,结果是95 6e 04 c6。

Simply translate that code from C to php, and it will produce the same answer. 只需将代码从C转换为php,它就会产生相同的答案。 php has 32-bit integers and bitwise operators that do the same thing. php有32位整数和按位运算符,可以做同样的事情。

You need to be careful with the difference between signed and unsigned integers. 您需要注意有符号和无符号整数之间的区别。 When shifting down an unsigned integer, as in the C code, it will be filled in at the top with zeros. 当向下移位无符号整数时,如在C代码中那样,它将在顶部用零填充。 When shifting down a signed integer, which is all that php has, the top will be filled in with the sign bit, ie the very top bit of what was there at the start. 当向下移动一个有符号整数(这就是php所拥有的整数)时,顶部将填充符号位,即开头时的最高位。 So to emulate the unsigned behavior, you need to "and"-out those bits: 因此,要模拟未签名的行为,您需要“和” - 那些位:

unsigned int c;
(c) >> 8

becomes: 变为:

int c;
((c) >> 8) & 0xffffff

to do the same thing. 做同样的事情。 So your php code needs to read: 所以你的PHP代码需要阅读:

$crc32 = ((int)($crc32>>8) & 0xffffff) ^ $crc_array[$index];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM