https://ko.wikipedia.org/wiki/%EC%88%9C%ED%99%98_%EC%A4%91%EB%B3%B5_%EA%B2%80%EC%82%AC
위키 백과 참고하여 정리한 글입니다.
CRC (Cyclic Redundancy Check) 순환 중복 검사.
: 네트워크 등을 통하여 데이터 전송 시 데이터에 오류가 있는지를 확인하기 위한 체크값을 결정하는 방식. 데이터를 전송하기 전에 주어진 데이터 값에 따라 CRC 값을 계산하여 데이터에 붙여 전송하고, 받은 데이터의 CRC 값을 계산하여 Error Check가 가능하다.
개요.
CRC는 Commutative ring(가환환)의 나눗셈(mod-2의 덧셈-XOR-)에 기반한다.
(참고) Mod-2 연산 : 기본적으로 나눗셈 연산(mod)에 기초. 2로 나눈 나머지를 염두에 두고 계산하면 됨.
쉽게 말하면, 이는 한 비트의 계수를 갖는 다항식(Polynomial)의 집합이고, 이 다항식들 간의 사칙연산은 다시 계수들을 가장 아래 비트만 따도록 정의하여 한 비트 계수의 다항식으로 표현하도록 정의된다.
(예시)
위 식에서 2는 이진수로 10이고, 따라서 정의에 의해서 가장 아래비트인 0을 취하고 그 이상의 자리수는 버려 위와 같은 결과가 나온다.
위 식에서는 나눗셈의 몫은 X^2 + 1이고 나머지는 -1이고, -1은 홀수이기 때문에 1이 된다.
모든 데이터 비트 스트림은 이러한 다항식의 계수로 상상할 수 있다.
즉, 101은 0번자리가 1, 1번 자리가 0, 2번 자리가 1이므로, 다항식 x^2 + 1에 해당한다고 볼 수 있다.
CRC 값은 정해진 특정 다항식으로 데이터 스트링으로 주어진 다항식을 나누어 그 나머지를 나타내는 특정 길이의 비트 스트링이 된다. 특정한 CRC는 사용되는 다항식으로 정의하며, n비트 CRC를 만드는 데는 x^n+...+1 꼴의 1차 다항식이 필요한다. 이를 기본적으로 (n+1) 비트 문자열로 나타낼 수 있지만, 차수가 가장 높은 x^n 항의 계수는 항상 1이기 때문에 이 항을 빼고 n비트 문자열로 나타낼 수 있다.
(예시)
CRC-16 표준에 사용되는 다항식인 x^15 + x^2 + 1은 비트 순서에 따라 0x8005나 0xa001로 나타낼 수 있다.
CRC 다항식들과 종류들.
CRC에는 비트수에 따라 CRC-8, CRC-16, CRC-32 등이 존재한다.
CRC 값을 계산하려면 비트수와 다항식을 결정해야 하며, 정해진 값을 토대로 계산하면 입력된 메시지는 오류가 없는 경우 항상 같은 CRC 값이 나온다.
이름 | 사용 | 다항식 | ||
정상 | 역방향 | 역방향의 역수 | ||
CRC-8-CCITT | I.432.1; ATM HEC, ISDN HEC and cell delineation | 0x07 | 0xE0 | 0x83 |
CRC-8-Dallas/Maxim | 1-Wire bus | 0x31 | 0x8C | 0x98 |
CRC-8 | 0xD5 | 0xAB | 0xEA | |
CRC-8-SAE J1850 | AES3 | 0x1D | 0xB8 | 0x8E |
CRC-8-WCDMA | 0x9B | 0xD9 | 0xCD | |
CRC-16-IBM | Bisync(Binary Synchronous Communications), Modbus, USB, ANSI X3.28, SIA DC-07, 기타. CRC-16 또는 CRC-16-ANSI로 알려짐. | 0x8005 | 0xA001 | 0xC002 |
CRC-16-CCITT | X.25, V.41, HDLC FCS, XMODEM, Bluetooth, PACTOR, SD 카드,기타. CRC-CCITT라고도 함. | 0x1021 | 0x8408 | 0x8810 |
CRC-16-T10-DIF | SCSI DIF | 0x8BB7 | 0xEDD1 | 0xC5DB |
CRC-16-DNP | DNP, IEC 870, M-Bus | 0x3D65 | 0xA6BC | 0x9EB2 |
CRC-16-DECT | 무선전화 | 0x0589 | 0x91A0 | 0x82C4 |
CRC-16-ARINC | ACARS 응용 | 0xA02B | 0xD405 | 0xD015 |
CRC-32 | HDLC, ANSI X3.66, ITU-T V.42, 이더넷, Serial ATA, MPEG-2, PKZIP, Gzip, Bzip2, PNG, many others | 0x04C11DB7 | 0xEDB88320 | 0x82608EDB |
CRC-32C (Castagnoli) | iSCSI, SCTP, G.hn payload, SSE4.2, Btrfs, ext4 | 0x1EDC6F41 | 0x82F63B78 | 0x8F6E37A0 |
CRC-32K (Koopman) | 0x741B8CD7 | 0xEB31D82E | 0xBA0DC66B | |
CRC-32Q | aviation; AIXM | 0x814141AB | 0xD5828281 | 0xC0A0A0D5 |
소프트웨어 구현.
소프트웨어에서 보통 CRC를 적용할 때 바이트 단위로 구현하지만, 비트단위로 계산해야 하는 경우에는 속도등의 문제로 오히려 CRC 테이블 기법을 많이 사용한다.
실제 소프트웨어 코드 방식으로 사용되는 방법.
1. CRC 테이블을 만들어 변수화 하고,
2. 데이터를 바이트단위로 테이블 탐색을 통해 CRC 값을 결정한다.
(CRC-16/ARC C# 코드 예시)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
private static ushort[] CRCtable = {
0X0000, 0XC0C1, 0XC181, 0X0140, 0XC301, 0X03C0, 0X0280, 0XC241,
0XC601, 0X06C0, 0X0780, 0XC741, 0X0500, 0XC5C1, 0XC481, 0X0440,
0XCC01, 0X0CC0, 0X0D80, 0XCD41, 0X0F00, 0XCFC1, 0XCE81, 0X0E40,
0X0A00, 0XCAC1, 0XCB81, 0X0B40, 0XC901, 0X09C0, 0X0880, 0XC841,
0XD801, 0X18C0, 0X1980, 0XD941, 0X1B00, 0XDBC1, 0XDA81, 0X1A40,
0X1E00, 0XDEC1, 0XDF81, 0X1F40, 0XDD01, 0X1DC0, 0X1C80, 0XDC41,
0X1400, 0XD4C1, 0XD581, 0X1540, 0XD701, 0X17C0, 0X1680, 0XD641,
0XD201, 0X12C0, 0X1380, 0XD341, 0X1100, 0XD1C1, 0XD081, 0X1040,
0XF001, 0X30C0, 0X3180, 0XF141, 0X3300, 0XF3C1, 0XF281, 0X3240,
0X3600, 0XF6C1, 0XF781, 0X3740, 0XF501, 0X35C0, 0X3480, 0XF441,
0X3C00, 0XFCC1, 0XFD81, 0X3D40, 0XFF01, 0X3FC0, 0X3E80, 0XFE41,
0XFA01, 0X3AC0, 0X3B80, 0XFB41, 0X3900, 0XF9C1, 0XF881, 0X3840,
0X2800, 0XE8C1, 0XE981, 0X2940, 0XEB01, 0X2BC0, 0X2A80, 0XEA41,
0XEE01, 0X2EC0, 0X2F80, 0XEF41, 0X2D00, 0XEDC1, 0XEC81, 0X2C40,
0XE401, 0X24C0, 0X2580, 0XE541, 0X2700, 0XE7C1, 0XE681, 0X2640,
0X2200, 0XE2C1, 0XE381, 0X2340, 0XE101, 0X21C0, 0X2080, 0XE041,
0XA001, 0X60C0, 0X6180, 0XA141, 0X6300, 0XA3C1, 0XA281, 0X6240,
0X6600, 0XA6C1, 0XA781, 0X6740, 0XA501, 0X65C0, 0X6480, 0XA441,
0X6C00, 0XACC1, 0XAD81, 0X6D40, 0XAF01, 0X6FC0, 0X6E80, 0XAE41,
0XAA01, 0X6AC0, 0X6B80, 0XAB41, 0X6900, 0XA9C1, 0XA881, 0X6840,
0X7800, 0XB8C1, 0XB981, 0X7940, 0XBB01, 0X7BC0, 0X7A80, 0XBA41,
0XBE01, 0X7EC0, 0X7F80, 0XBF41, 0X7D00, 0XBDC1, 0XBC81, 0X7C40,
0XB401, 0X74C0, 0X7580, 0XB541, 0X7700, 0XB7C1, 0XB681, 0X7640,
0X7200, 0XB2C1, 0XB381, 0X7340, 0XB101, 0X71C0, 0X7080, 0XB041,
0X5000, 0X90C1, 0X9181, 0X5140, 0X9301, 0X53C0, 0X5280, 0X9241,
0X9601, 0X56C0, 0X5780, 0X9741, 0X5500, 0X95C1, 0X9481, 0X5440,
0X9C01, 0X5CC0, 0X5D80, 0X9D41, 0X5F00, 0X9FC1, 0X9E81, 0X5E40,
0X5A00, 0X9AC1, 0X9B81, 0X5B40, 0X9901, 0X59C0, 0X5880, 0X9841,
0X8801, 0X48C0, 0X4980, 0X8941, 0X4B00, 0X8BC1, 0X8A81, 0X4A40,
0X4E00, 0X8EC1, 0X8F81, 0X4F40, 0X8D01, 0X4DC0, 0X4C80, 0X8C41,
0X4400, 0X84C1, 0X8581, 0X4540, 0X8701, 0X47C0, 0X4680, 0X8641,
0X8201, 0X42C0, 0X4380, 0X8341, 0X4100, 0X81C1, 0X8081, 0X4040
};
public static UInt16 CalculateCRC(byte[] data)
{
ushort crc = 0xFFFF;
foreach (byte datum in data)
{
crc = (ushort)((crc >> 8) ^ CRCtable[(crc ^ datum) & 0xFF]);
}
return crc;
}
|
cs |
(CRC-16/ARC VisualBasic 코드 예시)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
Private CRCtable As UShort() = {
&H0, &HC0C1, &HC181, &H140, &HC301, &H3C0, &H280, &HC241,
&HC601, &H6C0, &H780, &HC741, &H500, &HC5C1, &HC481, &H440,
&HCC01, &HCC0, &HD80, &HCD41, &HF00, &HCFC1, &HCE81, &HE40,
&HA00, &HCAC1, &HCB81, &HB40, &HC901, &H9C0, &H880, &HC841,
&HD801, &H18C0, &H1980, &HD941, &H1B00, &HDBC1, &HDA81, &H1A40,
&H1E00, &HDEC1, &HDF81, &H1F40, &HDD01, &H1DC0, &H1C80, &HDC41,
&H1400, &HD4C1, &HD581, &H1540, &HD701, &H17C0, &H1680, &HD641,
&HD201, &H12C0, &H1380, &HD341, &H1100, &HD1C1, &HD081, &H1040,
&HF001, &H30C0, &H3180, &HF141, &H3300, &HF3C1, &HF281, &H3240,
&H3600, &HF6C1, &HF781, &H3740, &HF501, &H35C0, &H3480, &HF441,
&H3C00, &HFCC1, &HFD81, &H3D40, &HFF01, &H3FC0, &H3E80, &HFE41,
&HFA01, &H3AC0, &H3B80, &HFB41, &H3900, &HF9C1, &HF881, &H3840,
&H2800, &HE8C1, &HE981, &H2940, &HEB01, &H2BC0, &H2A80, &HEA41,
&HEE01, &H2EC0, &H2F80, &HEF41, &H2D00, &HEDC1, &HEC81, &H2C40,
&HE401, &H24C0, &H2580, &HE541, &H2700, &HE7C1, &HE681, &H2640,
&H2200, &HE2C1, &HE381, &H2340, &HE101, &H21C0, &H2080, &HE041,
&HA001, &H60C0, &H6180, &HA141, &H6300, &HA3C1, &HA281, &H6240,
&H6600, &HA6C1, &HA781, &H6740, &HA501, &H65C0, &H6480, &HA441,
&H6C00, &HACC1, &HAD81, &H6D40, &HAF01, &H6FC0, &H6E80, &HAE41,
&HAA01, &H6AC0, &H6B80, &HAB41, &H6900, &HA9C1, &HA881, &H6840,
&H7800, &HB8C1, &HB981, &H7940, &HBB01, &H7BC0, &H7A80, &HBA41,
&HBE01, &H7EC0, &H7F80, &HBF41, &H7D00, &HBDC1, &HBC81, &H7C40,
&HB401, &H74C0, &H7580, &HB541, &H7700, &HB7C1, &HB681, &H7640,
&H7200, &HB2C1, &HB381, &H7340, &HB101, &H71C0, &H7080, &HB041,
&H5000, &H90C1, &H9181, &H5140, &H9301, &H53C0, &H5280, &H9241,
&H9601, &H56C0, &H5780, &H9741, &H5500, &H95C1, &H9481, &H5440,
&H9C01, &H5CC0, &H5D80, &H9D41, &H5F00, &H9FC1, &H9E81, &H5E40,
&H5A00, &H9AC1, &H9B81, &H5B40, &H9901, &H59C0, &H5880, &H9841,
&H8801, &H48C0, &H4980, &H8941, &H4B00, &H8BC1, &H8A81, &H4A40,
&H4E00, &H8EC1, &H8F81, &H4F40, &H8D01, &H4DC0, &H4C80, &H8C41,
&H4400, &H84C1, &H8581, &H4540, &H8701, &H47C0, &H4680, &H8641,
&H8201, &H42C0, &H4380, &H8341, &H4100, &H81C1, &H8081, &H4040
}
Public Function CalculateCRC(ByVal data As Byte()) As UInt16
Dim crc As UShort = &HFFFF
For i = 0 To data.Length - 1
crc = CUShort((crc >> 8) Xor CRCtable((crc Xor data(i)) And &HFF))
Next
Return crc
End Function
|
cs |
온라인 CRC 변환기.
위 링크에서 데이터를 입력하면 CRC로 변환할 수 있으며, 각 CRC 알고리즘의 테이블 값도 확인할 수 있다.
'IT > DEV Study' 카테고리의 다른 글
Android Studio 안드로이드 스튜디오 설치 방법 (2023.08) (56) | 2023.08.29 |
---|---|
[ML/Python] Keras를 이용한 Model 생성 및 학습 간단 정리 (2) | 2023.06.08 |
[VB] Dictionary Add & Remove Test (feat. LINQ 람다식) (0) | 2022.09.13 |
[Nomad Corders] NestJS로 API 만들기 #4 정리 (완강) (1) | 2022.07.27 |
[Nomad Corders] NestJS로 API 만들기 #3 정리 (358) | 2022.07.26 |