首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在PHP中实现纵向冗余校验(LRC/LRC 8/XOR8)?

如何在PHP中实现纵向冗余校验(LRC/LRC 8/XOR8)?
EN

Stack Overflow用户
提问于 2011-06-09 09:34:06
回答 3查看 6.6K关注 0票数 2

我在用PHP实现XOR8 8/LRC校验和时遇到实际问题,根据这里给出的算法:http://en.wikipedia.org/wiki/Longitudinal_redundancy_check

我想做的是,给定任何字符串计算它的LRC校验和。

例如,我肯定知道这个字符串:

代码语言:javascript
运行
复制
D$1I 11/14/2006 18:15:00 1634146 3772376 3772344 3772312 3772294 1*

其十六进制校验和为39 (包括最后一个*字符)。

对于任何感兴趣的人来说,这是一条DART (深海海啸评估和报告)消息-- http://nctr.pmel.noaa.gov/Dart/Pdf/dartMsgManual3.01.pdf

我把字符串转换成具有1和0的二进制字符串。然后,我尝试创建一个字节数组,并将算法应用到字节数组中,但是它不起作用,我也不知道为什么。

用于将字符串转换为二进制字符串的函数是:

代码语言:javascript
运行
复制
        function str2binStr($str) { 
         $ret = '';
         for ($i = 0, $n = strlen($str); $i < $n; ++$i) 
           $ret .= str_pad(decbin(ord($str[$i])), 8, 0, STR_PAD_LEFT); 
         return $ret; 
        }

我用来将二进制字符串转换为二进制数组的函数是:

代码语言:javascript
运行
复制
        function byteStr2byteArray($s) {
          return array_slice(unpack("C*", "\0".$s), 1);
        }

最后,我使用的按位运算符使用的LRC实现是:

代码语言:javascript
运行
复制
        function lrc($byteArr) {
           $lrc = 0;
           $byteArrLen = count($byteArr);
           for ($i = 0; $i < $byteArrLen; $i++) {
             $lrc = ($lrc + $byteArr[$i]) & 0xFF;
           }
           $lrc = (($lrc ^ 0xFF) + 1) & 0xFF;
           return $lrc;
        }

然后,我们用十进制($checksum+ 0)转换LRC校验和的最后十进制结果,从而得到最后的十六进制校验和。

在所有这些操作之后,我没有得到预期的结果,所以任何帮助都会非常感谢

提前谢谢。

而且,我不能让它按照CRC8-Check in PHP的答案工作。

EN

回答 3

Stack Overflow用户

发布于 2011-06-09 15:42:33

恐怕StackOverflow上没有人能帮你,原因如下。这个问题困扰着我,所以我去了你提到的DART网站,看看他们的规格。有两个问题变得很明显:

  • ,第一个是,你误解了他们的规范的一部分。消息以传输返回(\r\0x0D)开始,星号*不是校验和
  • 的一部分。第二个更大的问题是,它们的规范包含几个错误。其中一些可能源于错误的复制/粘贴和/或从Microsoft .doc到PDF.

的不正确转换。

我已经花了时间检查其中的一些,如果您能够联系规范的作者或维护人员,以便他们能够修复它们或澄清它们,那就太好了。这是我发现的。

2.1.2消息分解提到了C/I作为消息状态,即使它没有出现在示例消息中。

2.1.3校验和是错误的,由与字符1对应的0x31关闭。

2.2.3 6校验和错误,由与字符-对应的0x2D关闭。

2.3.1.2我认为dev3tries之间缺少一个<cr>

2.3.1.3校验和由0x0D关闭,dev3和和与tries之间没有分隔符。如果在dev3值和tries值之间有回车,校验和将是正确的。

2.3.2.2-32.3.1.2-3相同.

2.3.3.3又错了校验和,在tries之前没有分隔符。

2.4.2消息分解提到了D$2 = message ID,应该是D$3 = message ID

下面是我用来验证校验和的代码:

代码语言:javascript
运行
复制
$messages = array(
    "\rD\$0 11/15/2006 13:05:28 3214.2972 N 12041.3991 W* 46",
    "\rD\$1I 11/14/2006 18:15:00 1634146 3772376 3772344 3772313 3772294 1* 39",
    "\rD\$1I 11/14/2006 19:15:00 1634146 3772275 3772262 3772251 3772249 1* 38",
    "\rD\$1I 11/14/2006 20:15:00 1634146 3772249 3772257 3772271 3772293 1* 3E",
    "\rD\$1I 11/14/2006 21:15:00 1634146 3772315 3772341 3772373 3772407 1* 39",
    "\rD\$1I 11/14/2006 22:15:00 1634146 3772440 3772472 3772506 3772540 1* 3C",
    "\rD\$1I 11/14/2006 23:15:00 1634146 3772572 3772603 3772631 3772657 1* 3B",
    "\rD\$2I 00 tt 18:32:45 ts 18:32:00 3772311\r00000063006201* 22",
    "\rD\$2I 01 tt 18:32:45 ts 18:32:00 3772311\r000000630062706900600061005f005ffffafff9fff8fff8fff7fff6fff401* 21",
    "\rD\$2I 02 tt 18:32:45 ts 18:32:00 3772335\rfffdfffafff7fff5fff1ffeeffea00190048ffe1ffddffdaffd8ffd5ffd101* 21"
);

foreach ($messages as $k => $message)
{
    $pos = strpos($message, '*');

    $payload = substr($message, 0, $pos);
    $crc = trim(substr($message, $pos + 1));

    $checksum = 0;

    foreach (str_split($payload, 1) as $c)
    {
        $checksum ^= ord($c);
    }

    $crc = hexdec($crc);

    printf(
        "Expected: %02X - Computed: %02X - Difference: %02X - Possibly missing: %s\n",
        $crc, $checksum, $crc ^ $checksum, addcslashes(chr($crc ^ $checksum), "\r")
    );
}
票数 1
EN

Stack Overflow用户

发布于 2011-06-09 11:00:20

值得注意的是,这里是维基百科算法的一个完全未优化的、直接的实现:

代码语言:javascript
运行
复制
$buffer = 'D$1I 11/14/2006 18:15:00 1634146 3772376 3772344 3772312 3772294 1*';

$LRC = 0;
foreach (str_split($buffer, 1) as $b)
{
    $LRC = ($LRC + ord($b)) & 0xFF;
}
$LRC = (($LRC ^ 0xFF) + 1) & 0xFF;

echo dechex($LRC);

它会为示例中的字符串生成0x0E,所以要么我设法伪造实现,要么生成0x39的算法不一样。

票数 0
EN

Stack Overflow用户

发布于 2013-05-08 15:36:05

我意识到这个问题很老,但我想不出该怎么做。它现在起作用了,所以我想我应该粘贴代码。在我的例子中,校验和需要作为ASCII字符串返回。

代码语言:javascript
运行
复制
public function getLrc($string)
{
    $LRC = 0;
    // Get hex checksum.
    foreach (str_split($string, 1) as $char) {
        $LRC ^= ord($char);
    }
    $hex = dechex($LRC);
    // convert hex to string
    $str = '';
    for($i=0;$i<strlen($hex);$i+=2) $str .= chr(hexdec(substr($hex,$i,2)));
    return $str;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6290781

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档