도구스개발

Adler-32·플레처 체크섬 계산기

글자나 16진수를 넣으면 Adler-32와 플레처(16·32·64) 체크섬을 계산하고, 두 누적합 A·B가 어떻게 만들어지는지 보여 줍니다. 65521이라는 법이 왜 소수인지, 짧은 데이터에서 왜 약한지, 플레처가 왜 0과 「전부 1」을 구별하지 못하는지도 함께 다룹니다.

UTF-8 바이트로 계산합니다. 한글 한 글자는 3바이트입니다.

Adler-32

0x11E60398

RFC 1950 해설에 실린 검산값과 같습니다 — "Wikipedia"의 Adler-32는 0x11E60398입니다.

입력 길이9바이트
A = 1 + 바이트 합920 (0x0398)
B = A의 누적합4,582 (0x11E6)
법(modulus)65,521 (소수)
10진수 값300,286,872

바이트

57 69 6B 69 70 65 64 69 61

플레처 체크섬도 같은 방식입니다

덩어리
Fletcher-161바이트2550xEE9A
Fletcher-322바이트65,5350xB7DDA1F8
Fletcher-644바이트4,294,967,2950x0F0B0748D2CFCF28

플레처는 법으로 소수 대신 덩어리가 담을 수 있는 최댓값(255 · 65535 · 2³²−1)을 씁니다. 나눗셈을 시프트와 덧셈만으로 할 수 있어 Adler-32보다도 빠릅니다. 폭이 2배가 될 때마다 한 번에 읽는 덩어리도 2배가 되고, 덩어리는 리틀엔디언으로 읽으며 마지막이 모자라면 0으로 채웁니다 (지금 입력은 Fletcher-32에서 1바이트를 채웠습니다).

왜 하필 65521인가. 2¹⁶ 아래에서 가장 큰 소수이기 때문입니다. 소수를 법으로 쓰면 나머지가 고르게 흩어져 충돌이 줄어듭니다 — 65536처럼 2의 거듭제곱을 쓰면 하위 비트만 남아 상위 비트의 차이를 통째로 놓칩니다. A와 B가 각각 16비트에 담기므로 결과는 32비트가 되고, zlib(RFC 1950)이 압축 스트림 끝에 붙이는 값이 이것입니다.
짧은 데이터에서는 약합니다. A는 1 + 바이트 합이라 아무리 커도 1 + 255n을 넘지 못합니다. 지금 입력(9바이트)이라면 A가 닿을 수 있는 값이 2,296가지로 65,521가지 중 3.5%뿐입니다. A가 한 바퀴를 채우려면 257바이트는 있어야 합니다. RFC 1950 자신이 Adler-32가 CRC-32보다 약하다고 적어 두었고, 대신 곱셈 없이 덧셈만 해서 훨씬 빠르다는 것이 맞바꾼 값입니다.
왜 누적합이 두 개인가. A만 있으면 바이트 순서를 바꿔도 값이 같습니다. B는 A를 다시 누적한 것이라 앞에 있는 바이트에 더 큰 가중치가 붙고, 그래서 순서가 바뀌면 값이 달라집니다. 다만 A와 B가 함께 같아지는 짝은 세 바이트만으로도 만들 수 있습니다 — 01 02 03과 00 04 02는 Adler-32가 똑같습니다. 오류 검출용이지 위변조를 막는 값이 아니라는 뜻이므로, 일부러 바꾼 데이터를 걸러야 한다면 해시나 서명을 써야 합니다.

사용 방법

  1. 1입력 형식을 글자와 16진수 중에 고릅니다.
  2. 2체크섬을 구할 데이터를 넣습니다.
  3. 3Adler-32 값과 그것을 이루는 A·B를 확인합니다.
  4. 4플레처 표에서 폭마다 덩어리 크기와 법이 어떻게 달라지는지 봅니다.
  5. 50x00이나 0xFF가 들어간 데이터를 넣어 플레처의 사각을 직접 확인합니다.

자주 묻는 질문

누적합 두 개로 만듭니다. A는 1에서 시작해 바이트를 더해 나간 값이고, B는 그 A를 매 걸음 다시 더한 값입니다. 둘 다 65521로 나눈 나머지를 쓰고, B를 위 16비트, A를 아래 16비트에 두어 32비트로 이어 붙입니다. 예를 들어 "Wikipedia"는 A = 920(0x398), B = 4582(0x11E6)이라 0x11E60398이 됩니다.

2¹⁶ 아래에서 가장 큰 소수이기 때문입니다. 소수를 법으로 쓰면 나머지가 고르게 흩어져 충돌이 줄어듭니다. 65536처럼 2의 거듭제곱을 쓰면 하위 비트만 남아 상위 비트의 차이를 통째로 놓치게 됩니다. A와 B가 각각 16비트에 담기므로 결과는 32비트가 됩니다.

A만 있으면 바이트 순서를 바꿔도 값이 같아지기 때문입니다. B는 A를 다시 누적한 것이라 앞쪽 바이트에 더 큰 가중치가 붙고, 그래서 순서가 바뀌면 값이 달라집니다. 실제로 01 02와 02 01은 A가 같지만 B가 다릅니다.

짧은 데이터에서 약합니다. A는 1 + 바이트 합이라 n바이트면 아무리 커도 1 + 255n을 넘지 못하는데, 10바이트라면 65,521가지 중 2,551가지(3.9%)만 쓰게 됩니다. A가 값의 범위를 한 바퀴 채우려면 257바이트는 있어야 합니다. RFC 1950 자신이 이 점을 적어 두었고, 대신 곱셈 없이 덧셈만 해서 훨씬 빠르다는 것이 맞바꾼 값입니다.

법으로 소수 대신 덩어리가 담을 수 있는 최댓값(255·65535·2³²−1)을 씁니다. 나눗셈을 시프트와 덧셈만으로 할 수 있어 더 빠릅니다. 폭이 2배가 될 때마다 한 번에 읽는 덩어리도 2배가 되어 Fletcher-16은 1바이트, Fletcher-32는 2바이트, Fletcher-64는 4바이트씩 읽습니다.

법이 곧 덩어리의 최댓값이라 「전부 0」인 덩어리와 「전부 1」인 덩어리의 나머지가 같다는 뜻입니다. Fletcher-16이라면 데이터의 0x00을 0xFF로 바꿔도 체크섬이 한 비트도 달라지지 않습니다. 다만 이 사각은 바이트가 아니라 덩어리 단위여서, Fletcher-32에서는 2바이트가 통째로 0x0000이거나 0xFFFF일 때만 나타납니다. Adler-32는 법이 65521이고 바이트 값이 255를 넘지 않아 이 문제가 없습니다.

안 됩니다. Adler-32는 세 바이트만으로도 충돌하는 짝을 만들 수 있습니다 — 01 02 03과 00 04 02가 같은 값입니다. 전송·저장 중에 우연히 생기는 오류를 잡는 것이 목적이지 일부러 바꾼 데이터를 막는 값이 아니므로, 위변조를 걸러야 한다면 해시나 서명을 써야 합니다.

전송되지 않습니다. 모든 계산은 브라우저 안에서 이뤄지고, 입력값은 이 기기에만 남습니다.

알아두면 좋은 점

  • Adler-32는 RFC 1950 해설에 실린 검산값 "Wikipedia" → 0x11E60398과 대조해 고정했습니다. 아홉 바이트뿐이라 A = 920, B = 4582를 종이에서 한 걸음씩 따라가 확인할 수 있는 값입니다.
  • 플레처는 널리 쓰이는 검산값 세 가지로 고정했습니다. Fletcher-16("abcde") = 0xC8F0, Fletcher-32("abcde") = 0xF04FC729, Fletcher-64("abcde") = 0xC8C6C527646362C6이며, 리틀엔디언으로 읽고 모자란 덩어리를 0으로 채우는 규칙까지 이 값들로 확인됩니다.
  • B를 「누적합의 누적합」이 아니라 가중합 Σ(n−i+1)·dᵢ의 닫힌 식으로 다시 세는 두 번째 구현을 만들어 대조했습니다. 원리가 겹치지 않는 두 방법이라 서로를 검산해 줍니다.
  • 플레처의 사각이 바이트가 아니라 덩어리 단위라는 것을 테스트가 먼저 잡았습니다. 0x00 한 바이트만 0xFF로 바꾸면 Fletcher-16에서는 값이 같지만 Fletcher-32·64에서는 달라집니다. 이 도구의 사각 데모는 Fletcher-16 기준입니다.
  • 세 바이트짜리 Adler-32 충돌(01 02 03과 00 04 02)은 A와 B가 함께 같아지는 조건을 풀어 만든 것이고 테스트로 고정해 두었습니다. 체크섬이 무엇을 보증하지 않는지 보이는 자리입니다.
  • Adler-32는 zlib(RFC 1950)이 압축 스트림 끝에 붙이는 값입니다. gzip은 대신 CRC-32를 씁니다 — 같은 압축 알고리즘을 쓰면서도 컨테이너에 따라 붙는 체크섬이 다릅니다.

함께 보면 좋은 도구

마지막 검증: 2026년 9월 1일 · 결과는 참고용 추정치입니다.