web-dev-qa-db-ja.com

CRC32チェックサムはどのように計算されますか?

たぶん私はそれを見ないだけかもしれませんが、CRC32は不必要に複雑であるか、ウェブ上で見つけることができる場所で説明が不十分です。

私はそれがメッセージ値の非キャリーベースの算術除算の余りであり、(生成器)多項式で除算されていることを理解していますが、実際の実装は私を逃れます。

CRCエラー検出アルゴリズムの痛みのないガイド を読みましたが、痛みはなかったと言わざるを得ません。それは理論をかなり上回りますが、著者は決して単純な「これはそれです」に到達しません。彼は標準のCRC32アルゴリズムのパラメーターは何であるかを述べていますが、どのように到達するかを明確に説明することを怠っています。

私が得られるのは、彼が「これだ」と言ってから、「ああ、それは元に戻すか、異なる初期条件で開始することができます」と追加し、最終的な方法について明確な答えを与えないときです追加したすべての変更を考慮してCRC32チェックサムを計算します。

  • CRC32の計算方法の簡単な説明はありますか?

テーブルがどのように形成されるかをCでコーディングしようとしました:

for (i = 0; i < 256; i++)
{
    temp = i;

    for (j = 0; j < 8; j++)
    {
        if (temp & 1)
        {
            temp >>= 1;
            temp ^= 0xEDB88320;
        }
        else {temp >>= 1;}
    }
    testcrc[i] = temp;
}

しかし、これは私がインターネット上の他の場所で見つけた値と矛盾する値を生成するようです。 Icouldはオンラインで見つけた値を使用しますが、それらがどのように作成されたかを理解したいと思います。

これらの信じられないほど紛らわしい数字を片付ける助けは、veryありがたいです。

84
aquanar

CRC32の多項式は次のとおりです。

バツ32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1

または、16進数とバイナリで:

0x 01 04 C1 1D B7
1 0000 0100 1100 0001 0001 1101 1011 0111

最高の用語(x32)は通常、明示的に記述されていないため、代わりに16進数で表すことができます。

0x 04 C1 1D B7

1と0を自由に数えますが、それらは多項式と一致することがわかります。1はビット0(または最初のビット)であり、xはビット1(または2番目のビット)です。 )。

なぜこの多項式なのか?与えられた多項式には標準が必要であり、標準はIEEE 802.3によって設定されたためです。また、異なるビットエラーを効果的に検出する多項式を見つけることは非常に困難です。

CRC-32は、一連の「キャリーのないバイナリ演算」、または基本的に「XORおよびシフト演算」と考えることができます。これは技術的には多項式演算と呼ばれます。

理解を深めるために、次の乗算を考えてください。

(x^3 + x^2 + x^0)(x^3 + x^1 + x^0)
= (x^6 + x^4 + x^3
 + x^5 + x^3 + x^2
 + x^3 + x^1 + x^0)
= x^6 + x^5 + x^4 + 3*x^3 + x^2 + x^1 + x^0

Xが2を底とすると、次のようになります。

x^7 + x^3 + x^2 + x^1 + x^0

どうして? 3x ^ 3は11x ^ 11(ただし、必要なのは1桁または0桁のプレディジットのみ)であるため、引き継いでいます:

=1x^110 + 1x^101 + 1x^100          + 11x^11 + 1x^10 + 1x^1 + x^0
=1x^110 + 1x^101 + 1x^100 + 1x^100 + 1x^11 + 1x^10 + 1x^1 + x^0
=1x^110 + 1x^101 + 1x^101          + 1x^11 + 1x^10 + 1x^1 + x^0
=1x^110 + 1x^110                   + 1x^11 + 1x^10 + 1x^1 + x^0
=1x^111                            + 1x^11 + 1x^10 + 1x^1 + x^0

しかし、数学者はmod 2になるようにルールを変更しました。したがって、基本的に、2進多項式mod 2はキャリーまたはXORなしの単なる加算です。したがって、元の方程式は次のようになります。

=( 1x^110 + 1x^101 + 1x^100 + 11x^11 + 1x^10 + 1x^1 + x^0 ) MOD 2
=( 1x^110 + 1x^101 + 1x^100 +  1x^11 + 1x^10 + 1x^1 + x^0 )
= x^6 + x^5 + x^4 + 3*x^3 + x^2 + x^1 + x^0 (or that original number we had)

私はこれが信仰の飛躍であることを知っていますが、これはラインプログラマーとしての私の能力を超えています。あなたがハードコアのCS学生またはエンジニアである場合、私はこれを打破することに挑戦します。誰もがこの分析の恩恵を受けるでしょう。

したがって、完全な例を理解するには:

   Original message                : 1101011011
   Polynomial of (W)idth 4         :      10011
   Message after appending W zeros : 11010110110000

ここで、CRC演算を使用して、拡張されたメッセージをPolyで除算します。これは以前と同じ区分です:

            1100001010 = Quotient (nobody cares about the quotient)
       _______________
10011 ) 11010110110000 = Augmented message (1101011011 + 0000)
=Poly   10011,,.,,....
        -----,,.,,....
         10011,.,,....
         10011,.,,....
         -----,.,,....
          00001.,,....
          00000.,,....
          -----.,,....
           00010,,....
           00000,,....
           -----,,....
            00101,....
            00000,....
            -----,....
             01011....
             00000....
             -----....
              10110...
              10011...
              -----...
               01010..
               00000..
               -----..
                10100.
                10011.
                -----.
                 01110
                 00000
                 -----
                  1110 = Remainder = THE CHECKSUM!!!!

除算により、商が捨てられ、残りが計算されたチェックサムになります。これで計算が終了します。通常、チェックサムはメッセージに追加され、結果が送信されます。この場合、送信は11010110111110になります。

32ビットの数値のみを除数として使用し、ストリーム全体を配当として使用します。商を捨て、残りを保持します。メッセージの最後に残りをタックすると、CRC32があります。

平均的な男のレビュー:

         QUOTIENT
        ----------
DIVISOR ) DIVIDEND
                 = REMAINDER
  1. 最初の32ビットを取得します。
  2. シフトビット
  3. 32ビットがDIVISORより小さい場合は、手順2に進みます。
  4. DIVISORによるXOR 32ビット。ステップ2に進みます。

(ストリームは32ビットで分割可能であるか、パディングする必要があることに注意してください。たとえば、8ビットANSIストリームはパディングする必要があります。また、ストリームの最後で分割が停止します。)

93
user295190

CRCは非常に簡単です。ビットとデータとして表される多項式を取り、多項式をデータに分割します(またはデータを多項式として表して同じことを行います)。 0と多項式の間の剰余はCRCです。あなたのコードは不完全であるため、理解するのが少し難しいです:tempとtestcrcは宣言されていないので、何がインデックス付けされているか、そしてアルゴリズムを通してどのくらいのデータが実行されているかは不明です。

CRCを理解する方法は、短いデータ(16ビット程度)と短い多項式(おそらく4ビット)を使用していくつかを計算することです。この方法を実践すれば、コーディングの方法を実際に理解できます。

頻繁に行う場合、CRCの計算はソフトウェアで非常に遅くなります。ハードウェアの計算ははるかに効率的であり、必要なゲートはわずかです。

8
WhirlWind

IEEE802.3の場合、CRC-32。メッセージ全体をシリアルビットストリームと考え、メッセージの末尾に32個のゼロを追加します。次に、メッセージのすべてのバイトのビットを反転し、最初の32ビットを1で補う必要があります。ここで、CRC-32多項式0x104C11DB7で除算します。最後に、この除算の32ビットの剰余を1の補数で補う必要があります。剰余の4バイトをそれぞれビット反転します。これは、メッセージの末尾に追加される32ビットCRCになります。

この奇妙な手順の理由は、最初のイーサネット実装が一度に1バイトずつメッセージをシリアル化し、各バイトの最下位ビットを最初に送信するためです。次に、シリアルビットストリームは、シリアルCRC-32シフトレジスタの計算を通過しました。これは、単純に補完され、メッセージの完了後に有線で送信されました。メッセージの最初の32ビットを補完する理由は、メッセージがすべてゼロであっても、すべてゼロのCRCを取得しないようにするためです。

7
Pavlo Bobrek

ウィキペディアに加えて Cyclic redundancy check および CRCの計算 記事、私は Reverseing CRC-Theory and Practice というタイトルの論文を見つけました* 良い参考になります。

CRCの計算には、本質的に3つのアプローチがあります。代数的アプローチ、ビット指向アプローチ、およびテーブル駆動アプローチです。 In CRCの逆転-理論と実践*、これらの3つのアルゴリズム/アプローチのそれぞれは、Cプログラミング言語でのCRC32の実装により、付録に理論的に説明されています。

PDFリンク
CRCの逆転–理論と実践。
HU Berlin Public Report
SAR-PR-2006-05
2006年5月
著者:
Martin Stigge、HenrykPlötz、WolfMüller、Jens-Peter Redlich

6
jschmier

私はこの質問の答えを明らかにしようとしてしばらく費やし、今日CRC-32に関するチュートリアルをようやく公開しました: CRC-32 hash tutorial-AutoHotkey Community

この例では、ASCII文字列 'abc'のCRC-32ハッシュを計算する方法を示します。

calculate the CRC-32 hash for the ASCII string 'abc':

inputs:
dividend: binary for 'abc': 0b011000010110001001100011 = 0x616263
polynomial: 0b100000100110000010001110110110111 = 0x104C11DB7

011000010110001001100011
reverse bits in each byte:
100001100100011011000110
append 32 0 bits:
10000110010001101100011000000000000000000000000000000000
XOR the first 4 bytes with 0xFFFFFFFF:
01111001101110010011100111111111000000000000000000000000

'CRC division':
01111001101110010011100111111111000000000000000000000000
 100000100110000010001110110110111
 ---------------------------------
  111000100010010111111010010010110
  100000100110000010001110110110111
  ---------------------------------
   110000001000101011101001001000010
   100000100110000010001110110110111
   ---------------------------------
    100001011101010011001111111101010
    100000100110000010001110110110111
    ---------------------------------
         111101101000100000100101110100000
         100000100110000010001110110110111
         ---------------------------------
          111010011101000101010110000101110
          100000100110000010001110110110111
          ---------------------------------
           110101110110001110110001100110010
           100000100110000010001110110110111
           ---------------------------------
            101010100000011001111110100001010
            100000100110000010001110110110111
            ---------------------------------
              101000011001101111000001011110100
              100000100110000010001110110110111
              ---------------------------------
                100011111110110100111110100001100
                100000100110000010001110110110111
                ---------------------------------
                    110110001101101100000101110110000
                    100000100110000010001110110110111
                    ---------------------------------
                     101101010111011100010110000001110
                     100000100110000010001110110110111
                     ---------------------------------
                       110111000101111001100011011100100
                       100000100110000010001110110110111
                       ---------------------------------
                        10111100011111011101101101010011

remainder: 0b10111100011111011101101101010011 = 0xBC7DDB53
XOR the remainder with 0xFFFFFFFF:
0b01000011100000100010010010101100 = 0x438224AC
reverse bits:
0b00110101001001000100000111000010 = 0x352441C2

thus the CRC-32 hash for the ASCII string 'abc' is 0x352441C2
4
vafylec