3

我需要在 Perl 中实现 CRC-32(带有自定义多项式)。我已经看到有一个名为Digest::CRC的模块可以做到这一点。但是,当我将结果与在线计算器进行比较时,我没有得到相同的 CRC 码。


我的多项式是“101101”(bin)或“2d”(hex)

我的数据是“1e5”


在线计算器是https://ghsi.de/CRC/index.php?Polynom=101101&Message=1e5。我从计算器得到的结果是“1010”(二进制)或“A”(十六进制)。


这是我使用的 Perl 代码(在线某处找到)


use strict;

use warnings;

use Digest::CRC;

my $string = 0x01e5;

my $ctx = Digest::CRC->new(type => "crc32", poly => 0x2D);

$ctx->add($string);

print "CRC for '$string' is 0x" . $ctx->hexdigest . "\n";

这是此 Perl 代码的输出:

“485”的 CRC 为 0x9d0fec86


我很确定在线计算器是正确的。

我的 Perl 代码有什么问题?

4

1 回答 1

4

正如它所说,您的程序正在计算字符串485(bytes 34 38 35) 的 CRC,这是 number 的十进制字符串表示形式0x1E5。同时,网站正在计算字节的 CRC 01 e5。我不知道你想要哪一个,如果有的话。

绝对正确的是,该网站没有计算任何类型的 CRC32,因为它的结果不是 32 位长,而且似乎取决于您指定的多项式的大小。

此外,如果您使用Digest::CRC指定type => 'crc32',它将忽略所有其他参数并简单地计算标准 CRC32。

如果您想要一个多项式为 0x2D 的 32 位 CRC,那么您可以尝试

my $ctx = Digest::CRC->new(width => 32, poly => 0x2D);

但是您还需要定义其他几项来指定 CRC,包括(但不限于)位和字节顺序、初始值和结束异或值,并且没有办法判断这是否会给您正确的校验和看到完整的规范。

当然,您有一份文件说的不仅仅是“CRC32,多项式0x2d”吗?


更新

如何使用 将Digest::CRC数据视为十六进制字节而不是字符串?

  • Digest::CRC只处理字符串,您需要以这种方式打包数据。在这种情况下,您可能想要my $string = "\x01\xe5"

另外,什么是“结束异或值”?

  • end xor值只是一个与结果进行异或的位模式,作为获得最终 CRC 的最后一步。

另外,如果我理解正确,以下两种方法应该给出相同的结果:

my $ctx1 = Digest::CRC->new(type => "crc32");
my $rr1 = $ctx1->add(pack 'H*', '1e5')->hexdigest;
print "a1=$rr1=\n";

my $ctx2 = Digest::CRC->new(width => 32, poly => 0x04c11db7);
my $rr2 = $ctx2->add(pack 'H*', '1e5')->hexdigest;
print "a2=$rr2=\n";

但是我得到不同的结果:

a1=fef37cd4= a2=758cce0=

你能告诉我我的错误在哪里吗?

  • 正如我所说,CRC 有很多说明符。这就是为什么您必须建立所需的 CRC 的完整规范,不仅包括宽度和多项式。要显式生成 CRC32 校验和,您需要这个
my $ctx = Digest::CRC->new(width => 32, poly => 0x04c11db7, init => 0xFFFFFFFF, xorout => 0xFFFFFFFF, refin => 1, refout => 1);

这将0xFFFFFFFF和集合的初始值refin和最终值应用refout到真。这反转了处理前后的位顺序( refreflect的缩写),并且是 MSB first 和 LSB first 之间的区别。

于 2013-03-20T15:30:58.300 回答