CRC32 체크섬은 어떻게 계산됩니까?


103

어쩌면 나는 그것을 보지 못하고 있지만 CRC32는 불필요하게 복잡해 보이거나 웹에서 찾을 수있는 곳에서 충분히 설명하지 못하는 것 같습니다.

나는 그것이 (생성자) 다항식으로 나눈 메시지 값의 비 캐리 기반 산술 분할의 나머지라는 것을 이해하지만 실제 구현은 나를 피합니다.

A Painless Guide To CRC Error Detection Algorithms를 읽었 으며 고통스럽지 않았다고 말해야합니다. 그것은 이론을 다소 잘 다루지 만 저자는 결코 단순한 "이것이다"에 도달하지 않습니다. 그는 표준 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;
}

그러나 이것은 인터넷의 다른 곳에서 찾은 가치와 일치하지 않는 가치를 생성하는 것 같습니다. 내가 할 수 내가 온라인으로 발견 된 값을 사용하지만, 나는 그들이 만든 방법을 이해하고 싶다.

이 엄청나게 혼란스러운 숫자를 정리하는 데 도움을 주시면 대단히 감사하겠습니다.


9
CRC32 테이블을 생성하기위한 코드가 올바른 것 같습니다. lsbit-first ( reversed ) CRC32 다항식은 0xEDB88320msbit-first ( normal )로 쓸 수도 있습니다 0x04C11DB7. 다른 곳에서 찾은 테이블 값이 동일한 CRC 다항식을 사용하여 생성 되었습니까?
jschmier 2011 년

1
@jschmier 안녕하세요, 저는이 사람이 질문을하는 것보다 한 걸음 뒤처진 느낌이 듭니까? stackoverflow.com/questions/62168128/…
bluejayke

: 다른 사람이 원래의 URL이 묶였던되어 있지만 구글이 쉽게 일을 포함한 여러 사본, 발견, 위의 링크 "A 고통 안내하는 CRC 오류 검출 알고리즘"을 읽고 호기심 경우 zlib.net/crc_v3.txt
스테판

답변:


118

CRC32의 다항식은 다음과 같습니다.

x 32 + x 26 + x 23 + x 22 + x 16 + x 12 + x 11 + x 10 + x 8 + x 7 + x 5 + x 4 + x 2 + x + 1

또는 16 진수 및 2 진수 :

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

최고 용어 (x 32 )는 일반적으로 명시 적으로 작성되지 않으므로 대신 16 진수로 표현할 수 있습니다.

0x 04 C1 1D B7

1과 0을 자유롭게 셀 수 있지만 다항식과 일치하는 것을 알 수 있습니다. 여기서는 1비트 0 (또는 첫 번째 비트)이고 x비트 1 (또는 두 번째 비트)입니다.

왜이 다항식입니까? 주어진 다항식 표준이 필요하고 표준은 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가되도록했습니다. 따라서 기본적으로 모든 이진 다항식 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 스트림은 패딩되어야합니다. 또한 스트림의 끝에서 나누기가 중지됩니다.)


13
끝에있는 "Average Guy Review"에 +1-이 오른쪽을 맨 위로 이동하는 것이 좋습니다. 일종의 TL입니다. DR : P
aaronsnoswell 2013

4
@abstractnature 우리는 단지 이진수가 아니라 다항식을 나눈다는 것을 기억하십시오. 우리는 $ x ^ {n + 1} $에서 $ x ^ n $를 "빌릴"수 없기 때문에 "정상적인"빼기를 할 수 없습니다. 그들은 다른 종류의 것들입니다. 또한 비트가 0 또는 1이기 때문에 -1은 무엇일까요? 실제로, 우리는 $ Z / 2Z $ 필드에 계수가있는 다항식 링에서 작업하고 있습니다.이 필드에는 0과 1이라는 두 개의 요소 만 있고 $ 1 + 1 = 0 $이 있습니다. cofficients를 필드에 넣음으로써 다항식은 Euclidean Domain이라고 불리는 것을 형성합니다. 기본적으로 우리가하려는 것이 처음부터 잘 정의되도록 허용합니다.
calavicci

6
실제 다항식을 명확히하기 위해 100000100110000010001110110110111 = 0x104C11DB7입니다. MSB는 암시 적이지만 구현시 여전히 고려해야합니다. 다항식이 33 비트 길이 여야하기 때문에 항상 설정되기 때문에 (나머지 32 비트 길이가 될 수 있음) 일부 사람들은 MSB를 생략합니다.
Felipe T.

2
x^6 + x^5 + x^4 + 3*x^3 + x^2 + x^1 + x^0 ... If we assume x is base 2 then we get: x^7 + x^3 + x^2 + x^1 + x^0. 이것은 수학이 작동하는 방식이 아닙니다. 다항식에 대한 계수는 mod (2) 또는 GF (2)이고 x는 그대로 두어 x ^ 6 + x ^ 5 + x ^ 4 + x ^ 3 + x ^ 2 + x ^ 1 + x ^ 0 (3 mod (2) = 1 이후). Tack the remainder on the end of your message-기술적으로 나머지는 메시지에 추가 된 0 비트에서 빼지 만 이것은 mod (2) 수학이므로 더하기와 빼기는 모두 XOR과 같고 나머지와 함께 XOR 된 0 비트는 동일합니다. 나머지로.
rcgldr

2
@MarcusJ-- Why did you append four 0s though?crc를 계산하는 소프트웨어 알고리즘은 명확하지 않지만 효과적으로 0을 추가합니다. 긴 손 나누기를 사용하여 CRC 계산을 표시하는 경우 나누기 예제가 올바르게 나타나도록 0을 추가해야합니다.
rcgldr

11

IEEE802.3, CRC-32의 경우. 전체 메시지를 직렬 비트 스트림으로 생각하고 메시지 끝에 32 개의 0을 추가합니다. 다음으로, 메시지의 모든 바이트의 비트를 반전하고 처음 32 비트를 1로 보완해야합니다. 이제 CRC-32 다항식 0x104C11DB7로 나눕니다. 마지막으로,이 분할의 32 비트 나머지를 1로 보완해야합니다. 나머지 4 바이트를 각각 역으로 바꿉니다. 이것은 메시지 끝에 추가되는 32 비트 CRC가됩니다.

이 이상한 절차의 이유는 첫 번째 이더넷 구현이 메시지를 한 번에 한 바이트 씩 직렬화하고 모든 바이트의 최하위 비트를 먼저 전송하기 때문입니다. 그런 다음 직렬 비트 스트림은 직렬 CRC-32 시프트 레지스터 계산을 거쳤으며, 이는 메시지가 완료된 후 간단히 보완되어 유선으로 전송되었습니다. 메시지의 처음 32 비트를 보완하는 이유는 메시지가 모두 0이더라도 모두 0 CRC를 얻지 못하기 때문입니다.


2
이것이 지금까지 가장 좋은 대답이지만, '4 바이트 각각을 비트 반전'으로 바꾸고 '4 바이트를 비트 반전, 하나의 엔티티로 취급'예를 들어 'abcdefgh ijklmnop qrstuvwx yzABCDEF'를 'FEDCBAzy xwvutsrq ponmlkji hgfedcba '. 참조 : CRC-32 해시 자습서-AutoHotkey 커뮤니티 .
vafylec

1
안녕하세요, 정확한 "메시지"는 무엇입니까? stackoverflow.com/questions/62168128/…
bluejayke

10

CRC는 매우 간단합니다. 비트와 데이터로 표현 된 다항식을 취하고 다항식을 데이터로 나눕니다 (또는 데이터를 다항식으로 표현하고 동일한 작업을 수행합니다). 0과 다항식 사이에있는 나머지는 CRC입니다. 부분적으로 불완전하기 때문에 코드를 이해하기가 약간 어렵습니다. temp 및 testcrc가 선언되지 않았기 때문에 인덱싱되는 항목과 알고리즘을 통해 실행되는 데이터의 양이 명확하지 않습니다.

CRC를 이해하는 방법은 짧은 다항식 (아마도 4 비트)이있는 짧은 데이터 (16 비트 정도)를 사용하여 몇 가지를 계산하는 것입니다. 이런 식으로 연습하면 코딩 방법을 이해하게 될 것입니다.

자주 수행하는 경우 CRC는 소프트웨어에서 계산하는 데 상당히 느립니다. 하드웨어 계산은 훨씬 더 효율적이며 몇 개의 게이트 만 필요합니다.


1
CRC32 또는 CRC32b의 경우 두 개의 다른 문자열에 대해 해시 충돌 의미를 얻
습니까?

1
안녕하세요, "다항식을 데이터로 나누기"란 무슨 뜻인지 약간 혼란 스럽습니까? stackoverflow.com/questions/62168128/… 다항식에서 X는 무엇으로 표현됩니까? 청크의 다른 바이트를 사용합니까?
bluejayke

7

Wikipedia Cyclic redundancy checkComputation of CRC 기사 외에도 Reversing CRC-Theory and Practice * 라는 제목의 논문 이 좋은 참고 자료가되었습니다.

CRC를 계산하는 데는 기본적으로 대수적 접근 방식, 비트 지향 접근 방식 및 테이블 기반 접근 방식의 세 가지 접근 방식이 있습니다. 에서 CRC 반전 - 이론 및 실습 * ,이 세 가지 각각의 알고리즘을 / C 프로그래밍 언어의 CRC32의 구현하여 부록에 동반 이론적으로 설명 접근한다.

* PDF 링크
반전 CRC – 이론 및 실습.
HU 베를린 공개 보고서
SAR-PR-2006-05
2006 년 5 월
저자 :
Martin Stigge, Henryk Plötz, Wolf Müller, Jens-Peter Redlich


안녕하세요, 좀 자세히 설명해 주 시겠어요?
bluejayke

7

이 질문에 대한 답을 찾기 위해 잠시 시간을 보냈고 마침내 오늘 CRC-32에 대한 자습서를 게시했습니다. CRC-32 해시 자습서-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

1
더 빠른 속도를 원하면 2006 년경 Intel의 일부 엔지니어가 일반적으로 4 바이트 또는 8 바이트의 시스템 데이터 버스 폭을 동시에 사용하는 방법을 사용했습니다. 학술 논문 : static.aminer.org/pdf/PDF/000/432/446/… Sourceforge 프로젝트 : sourceforge.net/projects/slicing-by-8 일반 crc 페이지 : create.stephan-brumme.com/crc32
Alan Corey

1
감사합니다. 멋지지만 다항식 값을 정확히 어떻게 얻습니까? X는 정확히 무엇을 나타 냅니까? 그리고 그것이 x ^ 32라고 말할 때, x의 32 제곱 또는 비트 연산자 ^입니까? stackoverflow.com/questions/62168128/…
bluejayke


1

crc32를 미리 알림으로 줄이려면 다음을 수행해야합니다.

  1. 각 바이트에서 비트 반전
  2. xor 0xFF를 사용하는 처음 4 바이트 (이는 선행 0에서 오류를 방지하기위한 것입니다)
  3. 끝에 패딩 추가 (마지막 4 바이트가 해시에 포함되도록 함)
  4. 알림 계산
  5. 비트를 다시 반전
  6. xor 결과를 다시.

코드에서 이것은 다음과 같습니다.


func CRC32 (file []byte) uint32 {
    for i , v := range(file) {
        file[i] = bits.Reverse8(v)
    }
    for i := 0; i < 4; i++ {
        file[i] ^= 0xFF
    }

    // Add padding
    file = append(file, []byte{0, 0, 0, 0}...)
    newReminder := bits.Reverse32(reminderIEEE(file))

    return newReminder ^ 0xFFFFFFFF
}

여기서 alertIEEE는 GF (2) [x]에 대한 순수한 알림입니다.


1
나는 이것을 이해하는 데 약간의 (의도 된 말장난) 문제가 있습니까? stackoverflow.com/questions/62168128/…
bluejayke

1
안녕하세요 @bluejayke,이 라이브러리를 확인하십시오. github.com/furstenheim/sparse_crc32/blob/master/main.go 스파 스 파일에 대한 crc32를 구현합니다. 계산에 대한 핵심적인 세부 정보를 볼 수 있습니다. 최적화되지 않았으므로 일반 구현보다 따르기가 쉽습니다. 이해하지 못하는 것은 GF (2) [x] 부분 일 수 있습니다. 기본적으로 x ^ 3 + x는 1010을 의미하고 x ^ 4 + x + 1은 10011을 의미합니다. 그런 다음 나누기를 수행해야합니다 (예 : x). ^ 3 + x는 x * (x ^ 2 + 1)입니다. 따라서 x에 대한 x ^ 3 + x의 알림은 0이지만 x ^ 2에 대한 알림은 x ^ 2 * x + x가됩니다. 즉, 알림은 x가됩니다.
Gabriel Furstenheim

1
@bluejayke 및 알림 IEEE는 잘 알려진 다항식 IEEE 다항식에 대한 알림을 의미합니다.
Gabriel Furstenheim

안녕하세요. 답변 해 주셔서 감사합니다. 다항식에서 "x"가 무엇을 나타내는 지 (자바 스크립트 목적으로) 이해하려고합니다. "x"는 내가 여기서 놓치고있는 것에 대한 일종의 코드 워드인가? 여기에 저를 혼란스럽게하는 많은 용어가 있습니다. 저는 CRC32에 대해 들어 본 적이 없으며 검색 후에도 실제로 설명 된 것을 찾을 수 없었습니다. 예를 들어 PNG의 경우 "각 청크에 대한 CRC"를 가져와야한다고 말합니다. "청크의 모든 데이터에 대해"를 의미합니까? 그러나 어떻게 다항식에 "연결"합니까? "x"는 무엇을 의미합니까? 또한 x ^ 32라고 말할 때 Math.pow (x, 32) 또는 비트 ^
bluejayke

1
안녕하세요 @bluejayke, x는 계산을 쉽게하기위한 추상화입니다. 어떤 것으로도 대체 될 것으로 예상되지 않습니다. x ^ 2 공식적인 곱셈으로 x * x를 의미합니다. 여기서 chrisballance.com/wp-content/uploads/2015/10/CRC-Primer.html 해당 부서에 대한 멋진 설명을 찾을 수 있습니다. 내가 내 대답에 노력하는 (즉, 링크) 부문 사이의 간격과 실제 계산을 작성하는 것이 었습니다
가브리엘 Furstenheim
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.