我需要在Perl中实现CRC-32(带有自定义多项式)。我已经看到有一个名为Digest::CRC的模块可以做到这一点。但是,当我将结果与在线计算器进行比较时,我得不到相同的CRC代码。
我的多项式是“101101”(bin)或“2d”(hex)
我的数据是“1e5”
在线计算器为https://ghsi.de/CRC/index.php?Polynom=101101&Message=1e5。我从计算器得到的结果是“1010”(bin)或“A”(hex)。
这是我使用过的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代码出了什么问题?
答案 0 :(得分:4)
正如所说,您的程序计算字符串485
的CRC(字节34 38 35
),这是数字0x1E5
的十进制字符串表示形式。同时,网站正在计算字节01 e5
的CRC。我不知道你想要哪一个,如果有的话。
绝对正确的是,网站不计算任何类型的CRC32,因为它的结果不是32位长,似乎取决于您指定的多项式的大小。
此外,如果您使用Digest::CRC
指定type => 'crc32'
,它将忽略所有其他参数,只需计算标准CRC32。
如果你想要一个多项式为0x2D的32位CRC,你可以尝试
my $ctx = Digest::CRC->new(width => 32, poly => 0x2D);
但是还需要定义一些其他的东西来指定CRC,包括(但不限于)位和字节顺序,初始值和结束xor值,并且没有办法告诉它是否会给你正确的校验和,没有看到完整的规范。
当然你有一个文件说的不仅仅是“CRC32,多项式0x2d”?
<强>更新强>
如何使用
Digest::CRC
将数据视为十六进制字节而不是字符串?
Digest::CRC
只处理字符串,您需要以这种方式打包数据。在这种情况下,您可能需要my $string = "\x01\xe5"
另外,什么是“结束xor值”?
end xor
值只是一个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=
你能告诉我我的错误在哪里吗?
my $ctx = Digest::CRC->new(width => 32, poly => 0x04c11db7, init => 0xFFFFFFFF, xorout => 0xFFFFFFFF, refin => 1, refout => 1);
这会应用0xFFFFFFFF
的初始值和最终值,并将refin
和refout
设置为true。这会在处理之前和之后反转位顺序( ref 是 reflect 的缩写),并且是MSB优先和LSB优先之间的差异。