【问题标题】:How to use Perl's 'Digest' module to calculate CRC?如何使用 Perl 的“摘要”模块计算 CRC?
【发布时间】:2013-03-09 15:10:26
【问题描述】:

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


我的多项式是“101101”(二进制)或“2d”(十六进制)

我的数据是“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 代码有什么问题?

【问题讨论】:

    标签: perl crc digest


    【解决方案1】:

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

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

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

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

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

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

    您肯定有一个文档比“CRC32, polynomial 0x2d” 有更多内容吗?


    更新

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

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

    另外,什么是“end xor value”?

    • 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 的初始值和最终值,并将refinrefout 设置为true。这反转了处理前后的位顺序(refreflect 的缩写),是 MSB first 和 LSB first 之间的区别。

    【讨论】:

    • Thx Borodin,如何使用 digest::crc 将数据视为十六进制字节而不是字符串?另外,什么是“结束异或值”?谢谢!
    • 此外,如果我理解正确,以下 2 种方法应该给出相同的结果: my $ctx1 = Digest::CRC->new(type=>"crc32");我的 $ctx2 = 摘要::CRC->new(width=>32, poly=>0x04c11db7);我的 $rr1 = $ctx1->add(pack 'H*', '1e5')->hexdigest;我的 $rr2 = $ctx2->add(pack 'H*', '1e5')->hexdigest;打印“a1=$rr1=\n”;打印“a2=$rr2=\n”; 但是我得到不同的结果: a1=fef37cd4= a2=758cce0= 你能告诉我我的错误在哪里吗?谢谢你
    • @user2190993:我已更新我的答案以回答您的其他问题。
    • 谢谢,它成功了。没有更好的digest::CRC手册来完全理解所有参数的含义吗?如果您能回答如何使用 HEX 而不是 ASCII 的数据。这是我运行 CRC 所需的数据。谢谢(顺便说一句,我是新来的,无法找到很好地格式化 cmets 的方法。
      对我不起作用...)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 2021-03-22
    • 2014-10-26
    • 1970-01-01
    • 2019-09-27
    • 1970-01-01
    相关资源
    最近更新 更多