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バイトの合計を2バイト(ビッグエンディアン)の数値として格納します。

これは私が使用しているものです:

#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");
}

ループ内のチェックサムを再計算するためにインデックスを使用して、バイトを格納するためにchar配列を使用しました。検証するために、ビット単位のシフトとマスキングを使用しました。より良い解決策はありますか?

ありがとう!

4

1 に答える 1

3

あなたが書いたものは合理的ですが、56バイトしかない場合、512バイトを読み取ろうとしても意味がありません。また、512を繰り返すのではなくsizeof(data)、2回目の出現に使用します。コードを関数としてパッケージ化し、不一致がある場合に実際のチェックサムと予想されるチェックサムを出力する場合があります。チェックサムアルゴリズムはあまり敏感ではないため、かなりの数をキャッチしますが、転置エラーなどのいくつかの間違いを簡単に見逃します。


うーん...もう一度見て...あなたは書いた:

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ます。

于 2012-04-14T03:25:51.287 に答える