C语言 - 读取二进制文件,验证校验和

3

如何在 C 语言中读取二进制文件并验证校验和?

以下是我处理的数据示例:

0A 01 17 D8 04 00 07 9A 1F 10 FF CF 7F FF FF FF
FF 7F 7F 7F FF 7F FF FF FF FF 7F 81 01 01 03 01
01 01 01 81 00 73 67 68 66 97 6C 76 64 64 6A 6B
6E 64 66 67 44 41 [17 7A]

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 44 41 [00 85]

方括号内的校验和为前面 54 个字节的和,以两个字节(大端序)表示。

这是我一直在使用的代码:

#include <stdio.h>
int main(int argc, char **argv)
{
    FILE *f = fopen(argv[1], "rb");

    unsigned char data[512];
    fread(data, 1, 512, f);

    int i;
    int sum = 0;
    for (i = 0; i < 54; i++)
    {
        sum += data[i];
    }

    if ((sum >> 8)   == data[54] &&
        (sum & 0xFF) == data[55])
    {
        printf("Checksum is valid.\n");
    }
    else
    {
        printf("Checksum is invalid.\n");
    }
    system("pause");
}

我已经使用字符数组来存储字节,使用索引在循环中重新计算校验和。为了验证,我使用了一些位移和掩码操作。是否有更好的解决方案呢?
谢谢!
1个回答

3
您所写的内容很合理,但是如果只有56个字节,尝试读取512个字节是没有意义的。此外,第二次出现时,可以使用sizeof(data)而不是重复512。您可以将代码打包为一个函数,并在校验和不匹配时打印实际和期望的检验和。校验和算法并不是非常敏感,因此它会轻易地忽略一些错误,比如置换错误,但也会捕获大量的错误。
嗯...再看一遍...您写道:
if ((sum >> 8)   == data[54] &&
    (sum & 0xFF) == data[55])

由于sum是一个(有符号的)int,因此您可能应该编写:

if ((sum >> 8) & 0xFF == data[54] &&
    (sum & 0xFF)      == data[55])

否则,您可能会发生溢出。也许仅使用54字节的数据不会出现问题,但如果要校验和的数据足够长(肯定超过256字节),您可能会得到一个大于65535的总和,并且当它不应该失败时比较会失败。我假设sizeof(int) == 4,而不是sizeof(int) == 2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接