본문 바로가기
임베디드 개발/펌웨어

데이터 무결성 검사, 체크섬과 CRC

by eteo 2023. 2. 11.

데이터 또는 파일의 무결성 검사를 위해 체크썸이나 CRC를 사용할 수 있다.

 

 

 

체크섬

 

체크섬(Checksum)은 중복 검사의 한 형태로, 오류 정정을 통해, 데이터의 무결성을 보호하는 단순한 방법이다.
통신에서 순환 중복 검사(CRC)를 체크섬이라고 말하기도 하지만, 엄밀히 말하면 체크섬은 나열된 데이터를 단순 더하여 체크섬 숫자를 얻고, 정해진 비트수의 모듈러로 정해진 비트수로 재구성 한다. 

대중적인 방식이기 때문에 누구나 데이터에 같은 작업을 수행할 수 있고, 무결성 검사에 대한 결과를 비교할 수 있으며, 메시지의 손상여부를 판단할 수 있다.

 

체크섬 사용 사례

 

임베디드 시스템에서 C 언어로 작성된 소스 코드를 컴파일러와 링커에 의해 최종 결합하면 기계어 코드의 묶음인 바이너리 파일이 나온다. 이 바이너리 정보를 ASCII 텍스트 형태로 전달하여 해당 이진 데이터를 메모리에 써서 CPU가 동작할 수 있게 하는 파일이 hex 파일인데, 인텔과 모토로라에서는 이 hex 파일에 체크섬을 적용하였다. 정해진 형식에 따라 바이트 단위로 단순 덧셈을 하여, 1바이트 모듈로를 취해 최종 값을 만들고, 이것을 해당라인의 끝에 오류 체크용으로 붙인다.



체크섬의 예시


다음과 같이 4 바이트의 데이터가 있다고 치자: 0x25, 0x62, 0x3F, 0x52


1. 모든 바이트를 덧셈하면 0x118이 된다.

2. 캐리를 버림으로써 0x18을 만든다.

3. 0x18의 2의 보수를 취해서 0xE8을 얻는다. 이것이 체크섬 바이트이다.

 

데이터에 체크섬을 붙여 송신하고 수신자는 받아서 체크한다.

 

1. 데이터의 모든 바이트를 덧셈하고 거기에 체크섬 바이트까지 더하면 0x200이 된다.

2. 캐리를 버리면 0x00이 된다. 이처럼 오류가 없으면 0x00이 나오고, 다른 값이 나오면 데이터가 깨졌다고 판별한다. (하지만 오류가 있어도 우연히 0x00이 될 수 있다.)

 

uint8_t CalcChecksum(const uint8_t *p_data, uint32_t size) {
  uint8_t sum = 0;
  for (uint32_t i = 0; i < size; i++) {
    sum += p_data[i];
  }
  return ~sum + 1;
}

 

 

 

 

또 다른 방식은 단순히 모든 바이트를 더한 뒤 & 0xFF로 모듈로 연산을 하는 방식도 있다.

 

uint8_t CalcChecksum(const uint8_t *p_data, uint32_t size)
{
  uint32_t sum = 0;
  const uint8_t *p_data_end = p_data + size;

  while (p_data < p_data_end )
  {
    sum += *p_data++;
  }

  return (sum & 0xffu);
}

 

 

 

 

 

 

 

 

 

 

CRC (Cyclic Redundancy Check)

 

CRC는 네트워크 등을 통하여 데이터를 전송할 때 전송된 데이터에 오류가 있는지를 확인하기 위한 체크값을 결정하는 방식을 말한다. 

데이터를 전송하기 전에 주어진 데이터의 값에 따라 CRC 값을 계산하여 데이터에 붙여 전송하고, 데이터 전송이 끝난 후 받은 데이터의 값으로 다시 CRC 값을 계산하게 된다. 이어서 두 값을 비교하고, 이 두 값이 다르면 데이터 전송 과정에서 잡음 등에 의해 오류가 덧붙여 전송된 것임을 알 수 있다.

CRC는 이진법 기반의 하드웨어에서 구현하기 쉽고, 데이터 전송 과정에서 발생하는 흔한 오류들을 검출하는 데 탁월하다. 하지만 CRC의 구조 때문에 의도적으로 주어진 CRC 값을 갖는 다른 데이터를 만들기가 쉽고, 따라서 데이터 무결성을 검사하는 데 부족한 점이 있어 MD5 등의 함수들이 대안으로 사용된다.

CRC 생성을 위해서 사용되는 사전에 약속된 다양한 다항식들이 존재하며, 가장 널리 사용되는 표준 다항식에는 CRC-8, CRC-16, CRC-32, CRC-64 등 이 있다.

 

 

 

CRC 계산 방식 : 하드웨어 vs 소프트웨어

 

CRC를 계산하는 과정은 하드웨어적 방식과 소프트웨어적 방식을 생각할 수 있다. 보통 통신시스템에서 프로토콜 계층이 물리층에 가까울수록 하드웨어 방식을 그리고 상위계층에 가까울수록 소프트웨어적인 방식을 적용된다. 물리계층에 가까울수록 전송라인은 거의 직렬 데이터인데 직렬 데이터는 비트단위의 논리 회로를 만들면 간단하기 때문에 하드웨어적 계산방식을 선호한다.

그러나 높은 계층으로 갈수록 병렬데이터(8비트)를 사용하며, 이런 경우는 소프트웨어적 접근으로 주로 바이트 단위로 계산한다. CRC는 결국 비트단위 입력에 대한 각 비트별 XOR 연산이므로 바이트 단위로 소프트웨어적 고속계산을 하기에는 한계가 있기 때문에 주로 미리 계산을 한 테이블 형태를 사용한다.

 

 

 

 

온라인 CRC Check 사이트 :

2023.05.07 - [DSP, MCU/펌웨어공부] - Online CRC 계산 사이트

 

Online CRC 계산 사이트

CRC 계산 사이트 https://crccalc.com/?crc=01020304&method=crc32&datatype=hex http://www.sunshine2k.de/coding/javascript/crc/crc_js.html https://www.lammertbies.nl/comm/info/crc-calculation 파일 CRC 계산 사이트 https://emn178.github.io/online-too

eteo.tistory.com

 

 

 

CRC-32, CRC-16 관련글 :

2023.05.07 - [DSP, MCU/펌웨어공부] - CRC-32

 

CRC-32

CRC (Cyclic Redundancy Check) 는 데이터 전송 과정에서 오류를 검출하거나 파일의 무결성을 검증하기 위한 방법으로, 그 과정에서 여러 종류의 다항식이 쓰일 수 있는 데 가장 널리 사용되는 CRC 다항식

eteo.tistory.com

2023.05.07 - [DSP, MCU/펌웨어공부] - CRC-16-CCITT

 

CRC-16-CCITT

CRC-16-CCITT의 다항식(Polynomial)은 아래와 같다. XMODEM, YMODEM 등에 쓰이는 방식이다. 이 다항식의 16진수 표현 CRC-16-CCITT 함수 uint16_t UpdateCRC16(uint16_t crc_in, uint8_t byte) { uint32_t crc = crc_in; uint32_t in = byte |

eteo.tistory.com

 

 

 

 

 

 

 

 

 

 

참고 :

https://ko.wikipedia.org/wiki/%EC%88%9C%ED%99%98_%EC%A4%91%EB%B3%B5_%EA%B2%80%EC%82%AC#%EA%B0%81%EC%A3%BC

https://ko.wikipedia.org/wiki/%EC%B2%B4%ED%81%AC%EC%84%AC