如何在 PHP 中实现纵向冗余校验 (LRC/CRC8/XOR8) 校验和?
根据此处提供的算法,我在尝试在 PHP 中实现 XOR8/LRC 校验和时遇到了真正的问题: http://en.wikipedia.org/wiki/Longitudinal_redundancy_check
我想做的是,给定任何字符串计算其 LRC 校验和。
例如,我确定这个字符串:
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 的二进制字符串。从那里,我尝试创建一个字节数组并将算法应用于字节数组,但它不起作用,我不明白为什么。
我用于将字符串转换为二进制字符串的函数是:
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;
}
我用于从二进制字符串转换为二进制数组的函数是:
function byteStr2byteArray($s) {
return array_slice(unpack("C*", "\0".$s), 1);
}
最后,我使用的带有按位运算符的 LRC 实现是:
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;
}
然后,我们用 dechex($checksum + 0) 转换 LRC 校验和的最终十进制结果,这样我们就得到了最终的十六进制校验和。
经过所有这些操作后,我没有得到预期的结果,因此任何帮助将不胜感激。
提前致谢。
另外,我无法按照 CRC8-Check in PHP 答案使其工作。
I'm having real problems trying to implement a XOR8/LRC checksum in PHP, according to the algorithm present here: http://en.wikipedia.org/wiki/Longitudinal_redundancy_check
What I'm trying to do is, given any string calculate its LRC checksum.
For example, I know for sure this string:
D$1I 11/14/2006 18:15:00 1634146 3772376 3772344 3772312 3772294 1*
Has a hexadecimal checksum of 39 (including the last *
char).
For anyone interested what is the meaning of the string, it's is a DART (Deep-ocean Assesment and Reporting of Tsunamis) message - http://nctr.pmel.noaa.gov/Dart/Pdf/dartMsgManual3.01.pdf.
I convert the string to a binary string with 1's and 0's. From there, I try to create a byte array and apply the algorithm to the byte array, but it's not working and I can't figure out why.
The function I'm using for converting to String to Binary String is:
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;
}
The function I'm using for converting from Binary String to Binary Array is:
function byteStr2byteArray($s) {
return array_slice(unpack("C*", "\0".$s), 1);
}
Finally, the LRC implementation I'm using, with bitwise operators, is:
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;
}
Then, we convert the final decimal result of the LRC checksum with dechex($checksum + 0), so we have the final hexadecimal checksum.
After all these operations, I'm not getting the expected result, so any help will be highly appreciated.
Thanks in advance.
Also, I can't make it work following the CRC8-Check in PHP answer.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
恐怕 StackOverflow 上没有人可以帮助您,原因如下。这个问题困扰着我,所以我去了你提到的 DART 网站查看他们的规格。两个问题变得显而易见:
第一个问题是您误解了他们的部分规格。消息以回车符(
\r
或\0x0D
)开头,星号*
不是消息的一部分。 checksum第二个更大的问题是他们的规格包含多个错误。其中一些可能源于错误的复制/粘贴和/或从 Microsoft .doc 到 PDF 的错误转换。
我花时间检查了其中一些,如果您可以联系规范作者或维护者,以便他们可以修复或澄清它们,那就太好了。这是我发现的。
2.1.2 消息细分提及
C/I
作为消息状态,即使它没有出现在示例消息中。2.1.3 校验和错误,由对应于字符
1
的0x31
关闭。2.2.3 六个校验和都是错误的,由对应于字符
-
的0x2D
引起。2.3.1.2 我认为
dev3
和tries
之间缺少2.3.1.3 校验和由
0x0D
关闭,并且dev3
和tries
之间没有分隔符。如果dev3
值和tries
值之间有回车符,则校验和将是正确的。2.3.2.2-3 与2.3.1.2-3相同。
2.3.3.3 校验和再次错误,并且
tries
之前没有分隔符。2.4.2 消息细分提到
D$2 = 消息 ID
,应为D$3 = 消息 ID
。这是我用来验证其校验和的代码:
I'm afraid that nobody on StackOverflow can help you, and here's why. This question was bugging me so I went to the DART website you mentionned to take a look at their specs. Two problems became apparent:
The first one is you have misunderstood part of their specs. Messages start with a Carriage Return (
\r
or\0x0D
) and the asterisk*
is not part of the checksumThe second, bigger problem is that their specs contain several errors. Some of them may originate from bad copy/paste and/or an incorrect transformation from Microsoft .doc to PDF.
I have taken the time to inspect some of them so that would be nice if you could contact the specs authors or maintainers so they can fix them or clarify them. Here is what I've found.
2.1.2 The message breakdown mentions
C/I
as message status even though it doesn't appear in the example message.2.1.3 The checksum is wrong, off by
0x31
which corresponds to the character1
.2.2.3 The six checksums are wrong, off by
0x2D
which corresponds to the character-
.2.3.1.2 I think there's a
<cr>
missing betweendev3
andtries
2.3.1.3 The checksum is off by
0x0D
and there's no delimiter betweendev3
andtries
. The checksum would be correct if there was a carriage return between thedev3
value and thetries
value.2.3.2.2-3 Same as 2.3.1.2-3.
2.3.3.3 Wrong checksum again, and there's no delimiter before
tries
.2.4.2 The message breakdown mentions
D$2 = message ID
which should beD$3 = message ID
.Here's the code I used to verify their checksums:
就其价值而言,这是来自维基百科的算法的完全未优化的直接实现:
它会导致示例中的字符串为
0x0E
,因此我要么设法伪造实现,要么产生 0x39 的算法不一样。For what it's worth, here's a completely unoptimized, straight-up implementation of the algorithm from Wikipedia:
It results in
0x0E
for the string from your example, so either I've managed to fudge the implementation or the algorithm that produced 0x39 is not the same.我意识到这个问题很老了,但我很难弄清楚如何做到这一点。它现在可以工作了,所以我想我应该粘贴代码。就我而言,校验和需要以 ASCII 字符串形式返回。
I realize that this question pretty old, but I had trouble figuring out how to do this. It's working now, so I figured I should paste the code. In my case, the checksum needs to return as an ASCII string.