CRC

CRC-32-Prüfsumme

Fehlererkennung per Polynomdivision — in PNG-Chunks & ZIP-Einträgen

CRC-32 (Cyclic Redundancy Check, 32 Bit) ist eine Prüfsumme, mit der sich Übertragungs- und Speicherfehler erkennen lassen. Sie steckt in jedem PNG-Chunk, in jedem ZIP-Eintrag, in gzip und in Ethernet-Frames.

Die Idee stammt aus der Polynomdivision: Die Daten werden als ein riesiges Polynom über GF(2) (Rechnen modulo 2, also XOR) aufgefasst und durch ein festes Generatorpolynom geteilt. Der Rest dieser Division ist die CRC.

In der Praxis rechnet man nicht bitweise, sondern mit einer vorberechneten 256-Einträge-Tabelle byteweise — das ist deutlich schneller und liefert exakt dasselbe Ergebnis.

Reflektiertes Polynom: 0xEDB88320 · Init 0xFFFFFFFF · End-XOR 0xFFFFFFFF

⚙️ So funktioniert der Algorithmus

Startwert, byteweise Tabellen-Verknüpfung, abschließendes XOR.

Tabellengesteuerter CRC-32 (wie in PNG/ZIP):

   crc = 0xFFFFFFFF                      ← Startwert
        │
        ▼   für jedes Byte b:
   ┌─────────────────────────────────────────────┐
   │ idx = (crc XOR b) AND 0xFF                    │
   │ crc = table[idx] XOR (crc >> 8)               │
   └─────────────────────────────────────────────┘
        │
        ▼
   crc = crc XOR 0xFFFFFFFF              ← End-XOR = Ergebnis

Tabellenaufbau (einmalig, pro Eintrag n):
   c = n
   8×:  c = (c & 1) ? (0xEDB88320 ^ (c>>1)) : (c>>1)
   table[n] = c

🎬 Visuelles Beispiel

CRC-32 von "IEND" — Schritt für Schritt bis zum bekannten Wert AE426082:

I
49
E
45
N
4E
D
44
0
Initialisierung: crc = FFFFFFFF
1
Byte I (49)tab[B6]crc = 22FDE946
2
Byte E (45)tab[03]crc = 992BAC53
3
Byte N (4E)tab[1D]crc = 639F4775
4
Byte D (44)tab[31]crc = 51BD9F7D
Final-XOR mit FFFFFFFF → Ergebnis: AE426082
Bit-Sicht des ersten Bytes „I“:
01001001

CRC-32 verarbeitet die Bits LSB-first und verknüpft sie über die Lookup-Tabelle (vorberechnete Polynomdivision).

Kontrolle: crc32("IEND") = AE426082

Zweites Beispiel

Der Klassiker "123456789"CBF43926:

1
31
2
32
3
33
4
34
5
35
6
36
7
37
8
38
9
39
0
Initialisierung: crc = FFFFFFFF
1
Byte 1 (31)tab[CE]crc = 7C231048
2
Byte 2 (32)tab[7A]crc = B0ACBB32
3
Byte 3 (33)tab[01]crc = 77B79C2D
4
Byte 4 (34)tab[19]crc = 641C1F5C
5
Byte 5 (35)tab[69]crc = 340AC5E3
6
Byte 6 (36)tab[D5]crc = F68D2C9E
7
Byte 7 (37)tab[A9]crc = AFFC9660
8
Byte 8 (38)tab[58]crc = 651F2550
9
Byte 9 (39)tab[69]crc = 340BC6D9
Final-XOR mit FFFFFFFF → Ergebnis: CBF43926
Bit-Sicht des ersten Bytes „1“:
00110001

CRC-32 verarbeitet die Bits LSB-first und verknüpft sie über die Lookup-Tabelle (vorberechnete Polynomdivision).

Kontrolle: crc32("123456789") = CBF43926

🧮 Woher kommt 0xEDB88320?

Der Wert 0xEDB88320 ist NICHT willkürlich: Er ist die bit-reflektierte Schreibweise des standardisierten CRC-32-Generatorpolynoms 0x04C11DB7. Dieses Polynom wurde 1975 für das ARPANET gewählt und später in IEEE 802.3 (Ethernet) festgeschrieben.

Als Polynom geschrieben lautet 0x04C11DB7: x³² + x²⁶ + x²³ + x²² + x¹⁶ + x¹² + x¹¹ + x¹⁰ + x⁸ + x⁷ + x⁵ + x⁴ + x² + x + 1. Es wurde so gewählt, dass es möglichst viele Fehlerarten (Einzelbit-, Doppelbit-, Bündelfehler) zuverlässig erkennt.

Weil PNG, ZIP & gzip die Bits LSB-first (reflektiert) verarbeiten, dreht man die Bitreihenfolge des Polynoms um — aus 0x04C11DB7 wird 0xEDB88320. Beide beschreiben dasselbe mathematische Polynom, nur in unterschiedlicher Leserichtung. (0x82608EDB ist die dritte gängige, „reversed reciprocal“ Schreibweise.)

In der Praxis gibt es viele CRC-32-Varianten mit ANDEREN Polynomen — sie sind nicht kompatibel zueinander:

Verbreitete CRC-32-Varianten (unterschiedliche Polynome!)

VariantePolynom (reflektiert)Verwendung
CRC-32 (IEEE)0xEDB88320PNG, ZIP, gzip, Ethernet
CRC-32C (Castagnoli)0x82F63B78iSCSI, ext4, SSE4.2-Befehl
CRC-32K (Koopman)0xEB31D82Efehlertolerante Systeme
CRC-32Q0xD5828281Luftfahrt (AIXM)
Kurz: 0xEDB88320 ist standardisiert (IEEE 802.3) und für PNG/ZIP verbindlich. Andere Anwendungen nutzen aber bewusst andere Polynome (z. B. CRC-32C) — dann kommen andere, untereinander inkompatible Prüfsummen heraus.

📊 Referenzwerte & Parameter

Bekannte CRC-32-Werte (IEEE 802.3)

EingabeCRC-32 (hex)
"" (leer)00000000
"123456789"CBF43926
"IEND"AE426082
"The quick brown fox…lazy dog"414FA339

Parameter dieser CRC-Variante

ParameterWert
Breite32 Bit
Polynom (normal)0x04C11DB7
Polynom (reflektiert)0xEDB88320
Init0xFFFFFFFF
Reflect In/Outja / ja
End-XOR0xFFFFFFFF

⌨️ Implementierung in C

CRC-32-Tabelle erzeugen · c
#include <stdint.h>

uint32_t crc_table[256];

void make_crc_table(void) {
    for (uint32_t n = 0; n < 256; n++) {
        uint32_t c = n;
        for (int k = 0; k < 8; k++) {
            /* bei gesetztem LSB mit dem Polynom XOR-en, dann schieben */
            c = (c & 1) ? (0xEDB88320u ^ (c >> 1)) : (c >> 1);
        }
        crc_table[n] = c;
    }
}

ℹ️ Achtung auf das Polynom: 0xEDB88320 (reflektiert). Ein Tippfehler hier liefert falsche, aber plausibel aussehende Prüfsummen.

CRC-32 berechnen (byteweise) · c
uint32_t crc32(const uint8_t *data, size_t len) {
    uint32_t crc = 0xFFFFFFFFu;              /* Init */
    for (size_t i = 0; i < len; i++) {
        uint8_t idx = (crc ^ data[i]) & 0xFF;
        crc = crc_table[idx] ^ (crc >> 8);
    }
    return crc ^ 0xFFFFFFFFu;                 /* End-XOR */
}

/* Beispiel: crc32((const uint8_t*)"IEND", 4) == 0xAE426082 */

ℹ️ Exakt dieser Algorithmus prüft die Integrität jedes PNG-Chunks und ZIP-Eintrags.

Anwendung in PNG: Chunk prüfen · c
/* Prüft die CRC eines PNG-Chunks (Typ[4] + Daten[len]) */
int png_chunk_ok(const char type[4], const uint8_t *data,
                 size_t len, uint32_t stored_crc) {
    uint32_t crc = 0xFFFFFFFFu;
    for (int i = 0; i < 4; i++)             /* zuerst der Typ */
        crc = crc_table[(crc ^ type[i]) & 0xFF] ^ (crc >> 8);
    for (size_t i = 0; i < len; i++)        /* dann die Daten */
        crc = crc_table[(crc ^ data[i]) & 0xFF] ^ (crc >> 8);
    crc ^= 0xFFFFFFFFu;
    return crc == stored_crc;               /* gültig? */
}

ℹ️ Die CRC läuft über Typ + Daten — NICHT über das Längenfeld.

🔗 Wo CRC-32 auftaucht

Jeder PNG-Chunk endet mit einer CRC-32 über Typ + Daten. Auch jeder ZIP-Eintrag speichert die CRC-32 seiner unkomprimierten Daten, um Beschädigungen zu erkennen.

💡 Wissenswert

CRC erkennt zuverlässig Bitfehler, ist aber KEINE kryptografische Prüfsumme — man kann Daten gezielt so verändern, dass die CRC gleich bleibt.
Die leere PNG-IEND-Datenmenge ergibt die berühmte konstante CRC 0xAE426082 für den IEND-Chunk.
Es gibt viele CRC-32-Varianten (CRC-32/BZIP2, CRC-32C/Castagnoli …) — sie unterscheiden sich in Polynom, Init und Reflektion.
Der häufigste Bug ist ein vertauschtes Polynom (0xEDB88320 ↔ 0xEDB88820): Das Ergebnis sieht zufällig aus, ist aber falsch.
← Zurück zur Übersicht