我正在尝试计算某些数据的校验和。这是代码:
#include <stdio.h>
#include <string.h>
int main()
{
char MyArray[] = "my secret data";
char checksum = 0;
int SizeOfArray = strlen(MyArray);
for(int x = 0; x < SizeOfArray; x++)
{
checksum += MyArray[x];
}
printf("Sum of the bytes for MyArray is: %d\n", checksum);
printf("The checksum: \n");
checksum = (checksum ^ 0xFF);
printf("%d\n",checksum);
}
输出:
Sum of the bytes for MyArray is: 70
The checksum:
-71
代码中的修改:
#include <stdio.h>
#include <string.h>
int main()
{
char MyArray[] = "my secret data";
char checksum = 0; // could be an int if preferred
int SizeOfArray = strlen(MyArray);
for(int x = 0; x < SizeOfArray; x++)
{
checksum += MyArray[x];
}
printf("Sum of the bytes for MyArray is: %d\n", checksum);
//Perform bitwise inversion
checksum=~checksum;
//Increment
checksum++;
printf("Checksum for MyArray is: %d\n", checksum);
}
输出:
Sum of the bytes for MyArray is: 70
Checksum for MyArray is: -70
为什么修改校验和值?不同的算法会提供不同的校验和吗?
最终价值如何有用?实际上,我不清楚校验和及其在数据验证中的用途。我在网上搜索,发现了很多文章,但仍然不清楚。希望我今天能在这里了解校验和。
答案 0 :(得分:7)
在考虑如何生成校验和之前,您需要了解它是什么。假设通过不可靠的通信信道(例如网络连接)发送数据的问题。您需要确保没有干扰影响您的消息。
执行此操作的一种方法是将消息发送两次,并检查差异(实际上,在传输两个消息期间发生完全相同的错误的可能性非常小)。但是,这需要使用相当多的带宽(发送消息两次)。
更有效的方法是根据消息计算值并将其附加到消息中。接收者然后应用相同的函数并检查值是否相同。
为了获得更直观的示例,书的校验和可以是页数。您从图书馆购买书籍并计算其页数。如果页数不符合您的预期,则会出现问题。
你实现了一个特定的校验和函数(总和的LSB),这很好。所有校验和函数都有一些您应该注意的属性,但重点是没有正确的方法来计算校验和。有许多功能可用于此目的。
答案 1 :(得分:4)
这是校验和算法的美丽:你产生校验和的方式以及你检查它的方式是某种方式对称!
校验和通常用于验证数据的完整性,尤其是在嘈杂/不可实现的通信信道上。因此,它主要用于错误检测。也就是说,如果收到的数据正确,知道。
这与纠错有很大不同。由于不仅在检查时出现错误,而且更正。
错误检测和错误纠正都有开销(或自动调整)数据。也就是说,数据不是原始数据的一部分,而是被添加到原始数据中,以便检查原始数据是否被更改(例如在案例或错误检测中)或纠正它(例如在案件或纠错)。
与错误检测算法不同,错误纠正算法的开销数据大小倾向于与原始数据成比例(因为您拥有的数据越多,恢复它所需的开销就越大)。
我们通常不希望开销数据量大,因为大数据意味着我们需要处理更多资源(即处理时间,传输时间等)。因此,在这种意义上,良好校验和算法通常是使用最小数量的开销数据来检测错误但是具有很强的稳健性(极少产生错误结果)。
根据这种理解,问题在于,因为校验和的稳健性实际上不仅取决于算法,还取决于通道特征。某些频道可能会出现某些错误,而其他频道则会出现不同的错误
然而,一般而言,有些校验和已知比其他校验和更受欢迎且更强大。在后者中,部分原因是它具有固有属性,以确保它在大多数,如果或所有通道中都是健壮的(我最喜欢的错误检测算法之一是 CRC - 循环冗余检查,因为它有固有的财产)。 但是每个场景都没有完美的校验和,它实际上取决于使用和场景。
但是,您仍然可以衡量校验和算法的 robustness 。有一种数学方法可以做到这一点,我认为这超出了本讨论的范围。因此,在某些意义上,某些校验和可以说比其他校验和更弱。您在问题中显示的校验和也是弱的,因为它们可能比强校友(例如CRC)更容易产生错误的结果。
对于8位的XOR和0xFF完全等效于二进制反转一个值,并且不难看出它。
XOR with 0xFF
1110 0010
1111 1111
--------- XOR
0001 1101 //notice that this is exactly the same as binary inverting!
因此,当您使用0xFF和~checksum
执行XOR时,您会得到相同的结果-71(并且由于您的数据类型为char
,因此它具有负数)。然后你将它增加1,这样你得到-70。
二进制补码是对二进制数的数学运算,以及基于此运算的二进制有符号数表示。它在计算中的广泛应用使其成为基数补充的最重要的例子。 (wikipedia)
换句话说,2&#39;补码是找到一个值的负表示(在计算机二进制文件中),正如你所正确的那样,它的方法是通过反转所有的位然后加一个位来实现。这就是你得到-70 by 2&#39;补充70 。但这确实不意味着2&#39;补码和XOR由0xFF 相同,正如您通过示例所看到的,它实际上是不一样的。
在8位数据中,0xFF对XOR的影响只是等于反转所有位。它不会添加一个。
由于校验和用于了解数据的完整性(无论是否更改),人们会尝试找到最佳实践。你做的实际上是通过2&#39;来获得校验和。补码或XOR与0xFF。
这些就是他们所做的:
因此,在这两种情况下,您只需检查消息是否包含错误,方法是检查最终结果是否为0(无错误)!! 这通常适用于校验和算法!
这是校验和算法的美丽:你产生校验和的方式以及你检查的方式是对称!
答案 2 :(得分:3)
校验和通常用于检测数据的变化。通信,加密/签名等......校验和随处可见。
校验和如何有用?
这可能看似矛盾,但只有1位更改时,您的校验和才会起作用。但是,请
(A) checksum += 0x11 instead of 0x10
以后
(B) checksum += 0x30 instead of 0x31
在(A)中,校验和为-1 ......而在(B)中,校验和为+1。正负1 == 0。校验和会检测到 这两个错误。
基本上校验和的质量取决于
关于校验和的长度(校验和越大,它就越接受更大的数据,没有&#34;循环&#34;(一个字节只有256个校验和,2个字节有65536;注意在上面的情况下,你的算法不会改变结果)
校验和计算的质量,以尽可能地防止两个差异相互抵消。
有许多算法可用。 This answer on SO是一个好的开始。