두 CRC 도구가 다른 값을 내는 이유
같은 다항식을 쓰는 CRC-16 셋이 서로 다른 값을 냅니다. 초기값·반전·최종 XOR이 무엇을 하는지 정리했습니다.
장비 문서에 "CRC-16을 붙여 보내라"고 적혀 있습니다. 계산해서 보냈는데 거부됩니다.
같은 다항식, 다른 값
규격의 표준 검사 문자열 "123456789"로 여러 변종을 계산해 봤습니다.
이름 다항식 초기값 반전 결과
CRC-16/ARC 0x8005 0x0000 예 0xBB3D
CRC-16/MODBUS 0x8005 0xFFFF 예 0x4B37
CRC-16/CCITT-FALSE 0x1021 0xFFFF 아니오 0x29B1
CRC-16/XMODEM 0x1021 0x0000 아니오 0x31C3
CRC-16/KERMIT 0x1021 0x0000 예 0x2189
CRC-32 (zlib) 0x04C11DB7 0xFFFFFFFF 예 0xCBF43926
CRC-32/BZIP2 0x04C11DB7 0xFFFFFFFF 아니오 0xFC891918
다항식 0x1021을 쓰는 셋이 전부 다른 값을 냅니다. CRC-32도 반전 여부만으로 갈립니다.
"CRC-16"이라는 이름만으로는 값이 정해지지 않습니다.
파라미터 다섯 개
CRC 하나를 특정하려면 다섯 가지가 필요합니다.
| 파라미터 | 하는 일 |
|---|---|
| 폭 | 결과 비트 수 (16, 32 …) |
| 다항식 | 나눗셈에 쓰는 값 |
| 초기값 | 레지스터 시작값 |
| 입출력 반전 | 비트 순서를 뒤집는지 |
| 최종 XOR | 결과에 XOR할 값 |
초기값이 0이 아닌 이유가 있습니다. 초기값 0이면 앞에 붙은 0x00 바이트가 값을 바꾸지 않습니다. [0x00, 0x00, 0x41]과 [0x41]이 같은 CRC를 냅니다. 초기값을 0xFFFF로 두면 선행 0이 구분됩니다.
반전은 하드웨어 구현에서 왔습니다. 직렬 통신은 최하위 비트부터 보내는 경우가 많아서, 시프트 레지스터가 자연스럽게 반전된 순서로 동작합니다. 소프트웨어로 옮기면서 그 순서를 재현한 것이 반전 플래그입니다.
검사 문자열이 있는 이유
CRC 규격들은 "123456789"(ASCII 9바이트)에 대한 값을 함께 적어 둡니다. 구현이 맞는지 확인하는 기준값입니다.
위 표의 값들은 전부 규격에 적힌 값과 일치합니다. 새 구현을 붙일 때 이 문자열부터 넣어 보면 파라미터가 맞는지 바로 나옵니다.
CRC는 무결성 검사이지 서명이 아니다
CRC는 선형입니다. 이 성질이 오류 검출에는 유리하고 위조 방지에는 치명적입니다.
CRC32("PAY 100") = 33BA647C
CRC32("PAY 900") = 3DA935C4
두 값을 XOR = 0E1351B8
이 XOR 값은 두 평문의 차이만으로 계산됩니다. 키가 개입하지 않습니다.
그래서 메시지를 바꾸면서 CRC를 원하는 값으로 맞추는 것이 쉽습니다. 메시지 어딘가에 4바이트 여유만 있으면 CRC를 임의의 값으로 조정할 수 있습니다.
CRC가 잡는 것은 전송 중 발생한 잡음입니다. 연속된 비트 오류를 다항식 차수까지 확실히 검출합니다. 악의적인 변조는 잡지 못합니다. 그 자리에는 HMAC이 갑니다.
어디서 마주치나
| 곳 | 변종 |
|---|---|
| zlib·PNG·gzip·Ethernet | CRC-32 |
| Modbus RTU | CRC-16/MODBUS |
| XMODEM 프로토콜 | CRC-16/XMODEM |
| 옛 아카이브(ARC) | CRC-16/ARC |
| USB 패킷 | CRC-5, CRC-16 |
임베디드 장비 문서에서 "CCITT"라고만 적혀 있으면 조심해야 합니다. CCITT-FALSE(초기값 0xFFFF, 반전 없음)와 KERMIT(초기값 0x0000, 반전)이 둘 다 CCITT 계열로 불리는데 값이 다릅니다.
확인 순서
- 상대 장비의 CRC 파라미터 다섯 개를 문서에서 확인합니다. 이름만으로는 부족합니다
"123456789"를 넣어 기대값이 나오는지 먼저 봅니다- 값이 안 맞으면 반전부터 의심합니다. 바이트 순서를 뒤집은 값이 나오는 경우가 흔합니다
- 결과를 전송할 때 바이트 순서(빅엔디언·리틀엔디언)를 확인합니다. 계산이 맞아도 여기서 갈립니다
- 변조 방지가 목적이면 CRC가 아니라 HMAC을 씁니다
tools.onuel.dev의 CRC 계산기는 다항식·초기값·반전·최종 XOR을 직접 지정할 수 있어서, 장비 문서의 파라미터를 그대로 넣어 대조할 수 있습니다. CRC-16은 Modbus 등에서 쓰는 ARC 변종을 바로 계산하고, CRC-32는 zlib 계열입니다. 변조 방지가 필요하면 HMAC 쪽이고, 바이트를 직접 확인할 때는 Hex 덤프를 씁니다.
- #CRC
- #체크섬
- #프로토콜