Zum Inhalt springen

„Zyklische Redundanzprüfung“ – Versionsunterschied

aus Wikipedia, der freien Enzyklopädie
[ungesichtete Version][gesichtete Version]
Inhalt gelöscht Inhalt hinzugefügt
Keine Bearbeitungszusammenfassung
 
(528 dazwischenliegende Versionen von mehr als 100 Benutzern, die nicht angezeigt werden)
Zeile 1: Zeile 1:
Die '''zyklische Redundanzprüfung''' ('''ZRP''') (englisch ''Cyclic redundancy check'', daher häufig '''CRC''') ist ein Verfahren (bzw. eine bestimmte Klasse von Verfahren) aus der Informationstechnik zur Bestimmung eines [[Prüfsumme|Prüfwerts]] für Daten (z. B. [[Rechnernetz|Netzwerkverkehr]] oder eine [[Datei]]), um Fehler bei der Übertragung oder Duplizierung von Daten erkennen zu können.
Die '''zyklische Redundanzprüfung''' ('''ZRP''', englisch ''cyclic redundancy check'', daher meist '''CRC''') ist ein Verfahren zur Bestimmung eines [[Prüfsumme|Prüfwerts]] für Daten, um Fehler bei der Übertragung oder Speicherung erkennen zu können. Im Idealfall kann das Verfahren sogar die empfangenen Daten selbständig korrigieren, um eine erneute Übertragung zu vermeiden.


Es wurde 1961 von [[W. Wesley Peterson]] entwickelt.<ref>W. W. Peterson: ''Cyclic Codes for Error Detection''. In: ''Proceedings of the IRE'', Vol. 49, No. 1, 1961, S. 228–235</ref>
Vor Beginn der Übertragung bzw. Kopie eines Blocks der Daten wird ein ZRP-Wert berechnet. Nach Abschluss der Transaktion wird der ZRP-Wert erneut berechnet. Anschließend werden diese beiden Prüfwerte verglichen. ZRP sind so ausgelegt, dass Fehler bei der Übertragung der Daten, wie sie beispielsweise durch Rauschen auf der Leitung verursacht werden könnten, fast immer entdeckt werden.


== Allgemeines ==
ZRPs können jedoch nicht die Integrität der Daten bestätigen. D. h., es ist verhältnismäßig leicht, durch beabsichtigte Modifikation einen Datenstrom zu erzeugen, der den gleichen ZRP-Wert wie eine gegebene Nachricht hat. Wenn eine solche Sicherheit gefordert ist, müssen kryptografische [[Hash-Funktion|Hash-Funktionen]] wie z. B. [[MD5]] zum Einsatz kommen.
Vor der [[Datenspeicher]]ung oder [[Datenübertragung|Übertragung]] wird für jeden Datenblock der [[Nutzdaten]] zusätzliche [[Redundanz (Informationstheorie)|Redundanz]] in Form eines sogenannten CRC-Werts angefügt. Dieser ist ein nach einem bestimmten Verfahren berechneter Prüfwert, mit dessen Hilfe man während der Speicherung bzw. Übertragung eventuell aufgetretene Fehler erkennen kann. Zur Überprüfung der Daten wird dasselbe Berechnungsverfahren auf den Datenblock einschließlich des angefügten CRC-Werts angewandt. Ist das Ergebnis dann null, kann angenommen werden, dass der Datenblock unverfälscht ist. Verschiedene technische Anwendungen weichen allerdings von diesem Schema ab, indem sie beispielsweise die Berechnung mit einem bestimmten Wert initialisieren oder den CRC-Wert vor der Übermittlung invertieren.

CRC ist so ausgelegt, dass Fehler bei der Übertragung der Daten, wie sie beispielsweise durch [[Rauschen (Physik)|Rauschen]] auf der Leitung verursacht werden könnten, mit hoher Wahrscheinlichkeit entdeckt werden. CRCs von seriellen Datenübertragungen können sehr einfach in Hardware realisiert werden. Zum Beispiel werden Datenübertragungen über Ethernet sowie die meisten Festplatten-Übertragungen mit CRC-Verfahren geprüft.

Das CRC-Verfahren ist nur für die Erkennung von zufälligen Fehlern ausgelegt. Es ist nicht geeignet, die [[Integrität (Informationssicherheit)|Integrität]] der Daten zu bestätigen. Das heißt, es ist verhältnismäßig leicht, durch beabsichtigte Modifikation einen Datenstrom zu erzeugen, der den gleichen CRC-Wert wie eine gegebene Nachricht hat. Wenn eine solche Sicherheit gefordert ist, müssen kryptografische [[Hash-Funktion]]en wie beispielsweise [[Secure Hash Algorithm|SHA]] oder Signatur-Funktionen wie beispielsweise [[RSA-Kryptosystem|RSA]] zum Einsatz kommen.

Der Name des Verfahrens beruht darauf, dass der angefügte Wert keinen Informationsgehalt besitzt, der nicht bereits in dem zugrunde liegenden Datenblock enthalten ist. Er ist deshalb redundant. CRCs beruhen auf [[Zyklischer Code|zyklischen Codes]]. Das sind Block-Codes, die die Eigenschaft haben, dass jede zyklische Verschiebung der Bits eines gültigen Code-Worts ebenfalls ein gültiges Code-Wort ist.


== Verfahren ==
== Verfahren ==
Die Berechnung des CRC-Werts beruht auf dem Prinzip der [[Polynomdivision]]. Die zu übertragenden Bits werden als Faktoren eines [[Polynom]]s interpretiert, mit welchen Berechnungen angestellt werden können, die das nachfolgende Verfahren ermöglichen. Insbesondere entspricht die Polynomdivision einem bitweisen [[XOR]] (exklusiv-oder bzw. entweder-oder). Sind die Bits gleich, ist das Ergebnis 0. Sind sie verschieden, ist das Ergebnis 1.


Es wird ein Prüfwert der Länge ''n'' bestimmt (das CRC-Polynom) und die zu übertragende Bitfolge mit ''n-1'' 0en verlängert. Dies ergibt den sogenannte Rahmen. Anschließend wird der Rahmen wiederholt durch den Prüfwert geteilt, wobei die beiden Bitfolgen jeweils an der ersten Ziffer ausgerichtet werden, die 1 ist. Dieses Verfahren ist nicht mit normaler Division von Binärzahlen zu verwechseln, welche andere Ergebnisse liefert. Für den Rahmen bzw. das Zwischenergebnis 000110101 und den Prüfwert 01011, würden die Werte wie folgend ausgerichtet und verrechnet werden:
ZRP beruht auf [[Polynomdivision]]: Die Folge der zu übertragenden Bits wird als dyadisches Polynom betrachtet. Beispiel: Die Bitfolge 10011101 entspricht dem Polynom
<syntaxhighlight lang="text">
Zwischenergebnis 000110100
Prüfwert 01011
Division /
Ergebnis 000011000
</syntaxhighlight>Das Ergebnis dieser Berechnung wird mit jedem Schritt kleiner. Hat das Ergebnis weniger relevante Stellen als der Prüfwert, werden die letzten ''n-1'' Stellen als Rest übernommen, der sogenannte CRC-Wert. Dieser Rest wird an die zu übertragende Bitfolge angehängt und gemeinsam übertragen.


Um zu verifizieren, dass die Daten fehlerfrei übertragen wurden, wiederholt der Empfänger die Berechnung mit der übertragenen Bitfolge und dem CRC-Polynom. Da die Bitfolge um den ermittelten Rest ergänzt wurde, bleibt dieses Mal kein Rest übrig, wenn die Daten fehlerfrei übertragen wurden (oder wenn ein sehr seltener Fehler auftrat, der einem Vielfachen des CRC-Polynoms entsprach).
<math>1x^7 + 0x^6 + 0x^5 + 1x^4 + 1x^3 + 1x^2 + 0x^1 + 1x^0 = x^7 + x^4 + x^3 + x^2 + 1</math>


Das Verfahren setzt voraus, dass Sender und Empfänger wissen, dass gesicherte Daten übertragen werden und wie das CRC-Polynom lautet. Den Daten selbst ist beides nicht zu entnehmen.
Die [[Bit]]folge der [[Code]]repräsentation der Daten wird durch ein vorher festzulegendes Generatorpolynom (das ''ZRP-Polynom'') mod 2 dividiert, wobei ein Rest bleibt. Dieser Rest ist der ZRP-Wert. Bei der Übertragung des Datenblocks hängt man den ZRP-Wert an den originalen Datenblock an und überträgt ihn mit.


=== Beispiel ===
Um zu verifizieren, dass die Daten keinen Fehler beinhalten, wird der empfangene Datenblock mit angehängtem ZRP-Wert als Binärfolge interpretiert, erneut durch das ZRP-Polynom mod 2 geteilt und der Rest ermittelt. Wenn kein Rest bleibt, ist entweder kein Fehler aufgetreten oder es ist ein Fehler aufgetreten, der in Polynomdarstellung das ZRP-Polynom als Faktor hat.
Für die Bitfolge 11011 und dem Prüfwert 110101 (Länge n = 6), ergibt sich der Rahmen 1101100000 (Bitfolge um ''n-1'' = 5 0en verlängert). Anschließend wird der Rahmen durch das Generatorpolynom dividiert. Die beiden Zahlen werden jeweils an der ersten Ziffer ausgerichtet, da diese beide eine 1 sind.<syntaxhighlight lang="text">
Rahmen 1101100000
Prüfwert 110101
Division /
Zwischenergebnis 0000110000
</syntaxhighlight>Das Zwischenergebnis hat sechs relevante Stellen (110000), der Prüfwert ebenfalls. Also wird erneut dividiert. Dieses Mal wird der Prüfwert an der fünften Stelle des Zwischenergebnisses ausgerichtet.<syntaxhighlight lang="text">
Zwischenergebnis 0000110000
Prüfwert 110101
Division /
Ergebnis 0000000101
</syntaxhighlight>
Das Ergebnis hat nun nur noch drei relevante Stellen, also werden die letzten ''n-1'' (=5) Stellen als CRC-Wert übernommen, in diesem Fall also 00101. Die Bitfolge 11011 und der Rest 00101 ergeben die zu übertragenden Daten 1101100101. Möchte der Empfänger die Korrektheit der Daten verifizieren, führt er die Polynomdivision mit dem Rahmen 1101100101 und dem Prüfwert 110101 durch:<syntaxhighlight lang="text">
Rahmen 1101100101
Prüfwert 110101
Division /
Zwischenergebnis 0000110101
Prüfwert 110101
Division /
Ergebnis 0
</syntaxhighlight>Das Ergebnis ist 0, also trat wahrscheinlich kein Fehler auf. Wurde stattdessen der fehlerhafte Rahmen 1'''0'''01100101 empfangen, ergibt sich folgende Berechnung:<syntaxhighlight lang="text">
Rahmen 1001100101
Prüfwert 110101
Division /
Zwischenergebnis 0100110101
Prüfwert 110101
Division /
Zwischenergebnis 10011101
Prüfwert 110101
Division /
Zwischenergebnis 1001001
Prüfwert 110101
Division /
Zwischenergebnis 100011
Prüfwert 110101
Division /
Zwischenergebnis 10110
</syntaxhighlight>Der Rest der Division (<code>10110</code>) ist ungleich null. Also ist ein Fehler aufgetreten.


Bei der Überprüfung auf Richtigkeit können folgende vier Fälle auftreten:
Die Datenübertragung erfordert bestimmte unerlässliche Übereinkommen. Zum einen muss dem Empfänger bewusst sein, daß überhaupt eine gesicherte Übertragung der Ursprungsdaten stattfinden soll. An der Art des eintreffenden Datenstromes allein ist dies nicht zu erkennen. Des weiteren muss der Empfänger das selbe ZRP-Polynom und Rechenverfahren benutzen wie der Sender. Und schliesslich muss der Empfänger die Information besitzen, wo sich die zusätzlich zu den Daten übertragene Prüfsumme befindet.
# Der Rest der Division ist null und die Nachricht ist richtig
# Der Rest der Division ist null und die Nachricht ist fehlerhaft (dieser Fall ist unwahrscheinlich, kann aber vorkommen, wenn das Fehlerpolynom ein Vielfaches des Generatorpolynoms ist oder wenn sich zwei Fehler in der gleichen Übertragung gegenseitig aufheben)
# Der Rest der Division ist ungleich null und die Nachricht ist fehlerhaft
# Der Rest der Division ist ungleich null und die Nachricht ist richtig (dieser Fall tritt ein, wenn lediglich der angehängte Rest fehlerhaft übertragen wird; dies ist jedoch ebenfalls unwahrscheinlich, da der übertragene Rest im Vergleich zur Gesamtlänge des Pakets kurz ist)

=== Umsetzung ===
Das CRC-Verfahren lässt sich sowohl in einfachen [[Hardware]]-Bausteinen als auch in [[Software]] realisieren. Verwendet werden
* ein [[Schieberegister]] mit ''n''&nbsp;Bits, dabei ist ''n'' die Länge des Prüfwerts (etwa ein 32-Bit-Schieberegister bei CRC-32) und
* ein Bit-Datenstrom beliebiger Länge gefolgt von ''n''&nbsp;Null-Bits.

[[Pseudocode]] des [[Algorithmus]], [[Bitwertigkeit|höchstwertiges Bit]] ganz links, Multiplikation mit 2 bedeutet ein Schieben um eine Stelle nach links:
<poem style="margin-left: 2em; white-space: nowrap;">
<em>crc</em><span style="font-family:monospace;"> := </span>''0000…'' (Startwert)
<span style="font-family:monospace;">für alle </span>Bits <em>b</em> im Datenstrom<span style="font-family:monospace;">:</span>
<span style="font-family:monospace;">&nbsp;&nbsp;wenn&nbsp;</span> das am weitesten links stehende Bit von <em>crc</em> 1 ist<span style="font-family:monospace;">:</span>
<span style="font-family:monospace;">&nbsp;&nbsp;&nbsp;&nbsp;</span><em>crc</em><span style="font-family:monospace;"> := (</span><em>crc</em><span style="font-family:monospace;"> * 2 + </span><em>b</em><span style="font-family:monospace;">) [[XOR|xor]] </span>CRC-Polynom
<span style="font-family:monospace;">&nbsp;&nbsp;sonst:</span>
<span style="font-family:monospace;">&nbsp;&nbsp;&nbsp;&nbsp;</span><em>crc</em><span style="font-family:monospace;"> := </span><em>crc</em><span style="font-family:monospace;"> * 2 + </span><em>b</em>
<em>crc</em> enthält das Ergebnis.

</poem>

Durch Verwendung einer Tabelle, die beim Verfahren CRC-8 beispielsweise für jedes der 256 möglichen Bytes den zugehörigen CRC-Wert enthält, lässt sich obiger Algorithmus um den Faktor&nbsp;8 beschleunigen. Das resultiert daraus, dass ein Tabelleneintrag 8&nbsp;Bits = 1&nbsp;Byte enthält und <math>\mathrm{Basis}^\mathrm{Stellen} = 2^8 = 256</math> verschiedene Tabelleneinträge existieren. Die Geschwindigkeitssteigerung wird durch den direkten Zugriff auf die Tabelle mithilfe der zu berechnenden Bitfolge realisiert, indem die gesuchte CRC-8-Berechnung an der Stelle in der Tabelle steht, welche den binären Wert der zu berechnenden Bitfolge als Index hat.

Die Operationen Linksschieben und Exklusiv-Oder machen die CRC hervorragend geeignet zur Verwendung in [[Digitaltechnik|Logikschaltungen]]. Die CRC eines Datenstroms kann bitweise (oder auch Byte-weise usf.) berechnet und vom Sender an die Daten angehängt werden. Der Empfänger des Datenstroms kann den CRC genauso wie der Sender berechnen, jedoch unter Einbeziehung des CRC. Das Ergebnis inklusive des CRC muss dann gleich null sein, sonst enthält der Strom [[Bitfehler]].

CRC-Typen werden oft anhand des als Divisor verwendeten Polynoms unterschieden (im [[Hexadezimal]]-Format). Eines der meistverwendeten CRCs (u.&nbsp;a. von [[Ethernet]], [[FDDI]], [[ZIP (Dateiformat)|ZIP]] und [[Portable Network Graphics|PNG]] benutzt) ist das Polynom 0x04C11DB7, <!-- sic! 33 Bits --> bekannt als CRC-32. Es stellte sich heraus, dass einige Polynome besser „schützen“ als andere. Für CRC häufig verwendete Polynome sind das Ergebnis umfangreicher mathematischer und [[Empirie|empirischer]] Analysen und keine Zufallszahlen, auch wenn sie so aussehen.

=== Andere Startwerte ===
Die Implementierung führt eine Polynomdivision aus, wenn als Startwert ''0000…'' verwendet wird. Oft findet man andere Startwerte, etwa ''1111…''. Dies entspricht einer Polynomdivision, wenn die ersten ''n'' Bits des Datenstroms invertiert werden.

Ein Startwert ungleich ''0000…'' ist vorzuziehen, da fehlende Bits innerhalb führender Nullen im Datenstrom sonst nicht erkannt werden (ebenso wie bei einer gewöhnlichen Division zählen bei einer Polynomdivision führende Nullen nicht).

=== Nullproblem und Nachbearbeitung ===
Eine weitere Problematik stellt das Nullproblem dar, das in zweierlei Form auftritt:

# Produziert ein [[Datenstrom]] zufällig einen CRC gleich null, so ist der CRC auch dann null, wenn dem Datenstrom zusätzliche Nullen angehängt werden, oder –&nbsp;falls der Datenstrom mit einer oder mehreren Nullen endet&nbsp;– einige dieser letzten Nullen entfernt werden.
# Ist dem Ende des Datenstroms der CRC angehängt (so wie es ein Sender eben verschickt) und bei der Übertragung werden (nach dem gesendeten CRC) noch zusätzliche Nullen angefügt, so können diese zusätzlichen Nullen am Ende nicht erkannt werden.

Das Nullproblem in beiden Ausführungen ist unabhängig davon, ob Startwerte gleich null oder ungleich null verwendet werden.

Das Nullproblem in beiden Ausführungen wird vermieden, indem die Bits des CRC-Ergebnisses invertiert werden. Erfolgt im Empfänger die CRC-Prüfung derart, dass der Empfänger einen CRC aus dem empfangenen Datenpaket berechnet, wobei das Datenpaket aus Datenstrom und angehängtem CRC besteht, so ist im Falle eines unveränderten (nichtinvertierten) CRC des Senders der berechnete CRC im Empfänger stets null. Im Falle eines invertierten CRC des Senders ist der berechnete CRC im Empfänger immer der gleiche Wert, dieser wird auch als Magic Number bezeichnet.

Das Nullproblem der zweiten Ausführung kann auch vermieden werden, indem die Reihenfolge der CRC-Bits umgekehrt wird. Unerkannt bleibt jedoch der Fall, wo der CRC gleich null ist, was das Nullproblem der ersten Art darstellt.

Das bisher beschriebene Nullproblem bezieht sich also auf die Problematik, am Ende des Datenstroms zusätzlich hinzugefügte oder verlorengegangene Nullen zu erkennen. Dies ist jedoch nur dann nötig, wenn aufgrund vorherrschender Randbedingungen nicht sichergestellt werden kann, dass die Größe der Daten unverändert bleibt.

Von einem Nullproblem spricht man jedoch bisweilen auch dann, wenn es problematisch ist, wenn ein Datenstrom aus lauter Nullen auch einen CRC gleich Null erzeugt. Ein CRC gleich null aus Null-Daten entsteht unabhängig vom Generatorpolynom grundsätzlich, wenn der CRC-Startwert gleich null ist und die Bits des resultierenden CRC nicht invertiert werden. Dieses Problem kann somit vermieden werden, indem ein Startwert ungleich null festgelegt wird oder aber auch die resultierenden CRC-Bits invertiert werden.

Der bekannte CRC-32 verwendet sowohl ''1111...'' als Startwert als auch ein inverses Ergebnis. Bei CRC-16 wird ebenfalls meist ''1111..'' verwendet, das Ergebnis jedoch nicht invertiert. In beiden Fällen bleibt die Reihenfolge der CRC-Bits unverändert.


== Erkannte Fehler ==
== Erkannte Fehler ==
Ist das CRC-Polynom gut gewählt, können mit dem oben beschriebenen Verfahren alle Einbitfehler, jede ungerade Anzahl von verfälschten Bits, sowie alle [[Bündelfehler]] der Länge <math>\leq r</math> erkannt werden, wobei <math>r</math> der Grad des CRC-Polynoms ist. Zusätzlich werden alle Fehler (also auch unabhängige Vierbit-, Sechsbit-, Achtbitfehler usw.) erkannt, deren Polynomdarstellung einen kleineren Grad als das CRC-Polynom hat. Zweibitfehler werden entgegen der landläufigen Meinung nicht grundsätzlich erkannt. Warum das so ist bzw. wie das CRC-Polynom zu wählen ist, folgt aus den kommenden Überlegungen.


Sei <math>G(x)</math> das CRC-Polynom (Generatorpolynom) und <math>T(x)</math> die Polynomdarstellung der um den CRC-Wert erweiterten zu übertragenden Bitfolge. Wenn ein Fehler bei der Übertragung auftritt, kommt (in Polynomdarstellung) beim Empfänger nicht <math>T(x)</math>, sondern <math>T(x)+E(x)</math> an. Die zu <math>E(x)</math> gehörende Bitfolge hat an jeder Bitposition, die bei der zu übertragenden Bitfolge invertiert bzw. verfälscht wurde, eine 1.
Ist das ZRP-Polynom gut gewählt, können mit dem oben beschriebenen Verfahren alle Einbit- und Zweibitfehler, jede ungerade Anzahl von verfälschten Bits sowie alle Bündelfehler der Länge <math>\leq r</math> erkannt werden, wobei <math>r</math> der Grad des ZRP-Polynoms ist. Warum dass so ist bzw. wie das ZRP-Polynom zu wählen ist, folgt aus den kommenden Überlegungen.
Wenn der Empfänger die um den CRC-Wert erweiterte Bitfolge erhält, berechnet er <math>(T(x)+E(x))/G(x)</math>. Da <math>T(x)/G(x)=0</math> (per Definition von <math>T(x)</math>), ist das Ergebnis <math>E(x)/G(x)</math>.


=== Ein-Bit-Fehler ===
Sei <math>G(x)</math> das ZRP-Polynom (Generatorpolynom) und <math>T(x)</math> die Polynomdarstellung der um den ZRP-Wert erweiterten zu übertragenden Bitfolge. Wenn ein Fehler bei der Übertragung auftritt, kommt (in Polynomdarstellung) beim Empfänger nicht <math>T(x)</math>, sondern <math>T(x)+E(x)</math> an. Die zu <math>E(x)</math> gehörende Bitfolge hat an jeder Bitposition, die bei der zu übertragenden Bitfolge invertiert bzw. verfälscht wurde, eine 1.
Wenn der Empfänger die um den ZRP-Wert erweiterten Bitfolge erhält, berechnet er <math>(T(x)+E(x))/G(x)</math>. Da <math>T(x)/G(x)=0</math> (per Definition von <math>T(x)</math>), ist das Ergebnis <math>E(x)/G(x)</math>.
Wenn ein Ein-Bit-Fehler aufgetreten ist, gilt <math>E(x)=x^i</math>, wobei <math>i</math> bestimmt, welches Bit invertiert ist. Wenn nun <math>G(x)</math> zwei oder mehr Terme enthält, wird <math>G(x)</math> niemals <math>E(x)</math> teilen.


=== Zwei isolierte Ein-Bit-Fehler ===
----
Sind zwei isolierte Ein-Bit-Fehler aufgetreten, gilt <math>E(x)=x^i+x^j</math>, wobei <math>i>j</math>. Klammert man <math>x^j</math> aus, lässt sich dies auch als <math>E(x)=x^j(x^{i-j}+1)</math> schreiben. Da <math>G(x)</math> nicht durch <math>x</math> teilbar sein kann, reicht es zu fordern, dass <math>G(x)</math> nicht <math>x^k+1</math> teilt (für alle <math>k</math> bis zum maximalen Wert von <math>(i-j)</math>, das heißt der maximalen Rahmenlänge). Einfache Polynome geringen Grades, die eine sichere Übertragung für lange Rahmen ermöglichen, sind bekannt. Zum Beispiel teilt <math>x^{15}+x^{14}+1</math> den Term <math>x^k+1</math> nicht für jedes <math>k</math> kleiner 32767.


=== Ungerade Anzahl von Fehlern ===
Wenn ein Einbitfehler aufgetreten ist, gilt <math>E(x)=x^i</math>, wobei <math>i</math> bestimmt welches Bit invertiert ist. Wenn nun <math>G(x)</math> zwei oder mehr Terme enthält, wird <math>G(x)</math> niemals <math>E(x)</math> teilen.
Ist eine ungerade Anzahl von Bits verfälscht, enthält <math>E(x)</math> eine ungerade Anzahl von Termen (z.&nbsp;B. <math>x^7+x^2+1</math>, aber nicht z.&nbsp;B. <math>x^2+1</math>). Wählt man das CRC-Polynom so, dass es <math>(x+1)</math> als Faktor hat, werden alle Fehler mit einer ungeraden Anzahl von verfälschten Bits erkannt.


Beweis: Bei der Division durch ein Polynom mit gerader Parität (= Anzahl der Terme in dem Polynom, also Anzahl der Einsen in der Bitfolge) ist die Geradheit oder Ungeradheit der Parität im Divisions-Rest gleich der des Dividenden, denn aus 00 wird 11 (und umgekehrt) und aus 01 wird 10 (und umgekehrt).
----


<math>(x+1)</math> ist das kleinste Polynom mit gerader Parität. Bei <math>E(x) / G(x)</math> wird also stets <math>x</math> oder <math>1</math> als Rest bleiben, wenn <math>E(x)</math> ungerade Parität hat. Damit ist <math>E(x)</math> nicht durch <math>G(x)</math> teilbar.
Sind zwei isolierte Zweibitfehler aufgetreten, gilt <math>E(x)=x^i+x^j</math>, wobei <math>i>j</math>. Klammert man <math>x^j</math> aus, lässt sich dies auch als <math>E(x)=x^j(x^{i-j}+1)</math> schreiben. Angenommen, <math>G(x)</math> ist nicht durch <math>x</math> teilbar (z.B. wenn <math>G(x)</math> <math>x^0</math> enthält), reicht es zu fordern, dass <math>G(x)</math> nicht <math>x^k+1</math> teilt (für alle <math>k</math> bis zum maximalen Wert von <math>(j-i)</math>, i.e. der maximalen Rahmenlänge). Einfache Polynome geringen Grades, die eine sichere Übertragung für lange Rahmen ermöglichen, sind bekannt. Zum Beispiel teilt <math>x^15+x^14+1</math> <math>x^k+1</math> nicht für jedes <math>k</math> kleiner 32768.


=== Bündelfehler ===
----
Alle [[Bündelfehler]] (eng. Burst) der Länge <math>k \leq r</math>, wobei <math>r</math> der Grad des CRC-Polynoms ist, werden erkannt. Ein Bündelfehler der Länge <math>k</math> lässt sich schreiben als <math>x^i(x^{k-1}+\cdots+1)=x^ib(x)</math>, wobei <math>i</math> bestimmt, wie viele Bitpositionen von der rechten Seite der empfangenen Bitfolge (bzw. des empfangenen Rahmens) der Bündelfehler entfernt ist. Wenn der Fehler erkannt werden soll, muss die Division von <math>E(x)=x^ib(x)</math> durch <math>G(x)</math> einen Rest ergeben.


Ist eine ungerade Anzahl von Bits verfälscht, enthät <math>E(x)</math> eine ungerade Anzahl von Termen (z.B. <math>x^7+x^2+1</math>, aber nicht <math>x^2+1</math>). Wählt man das ZRP-Polynom so, dass es <math>(x+1)</math> als Faktor hat, werden alle Fehler mit einer ungeraden Anzahl von verfälschten Bits erkannt.
Da <math>G(x)</math> immer den Term <math>x^0</math> enthält, sind <math>G(x)</math> und <math>x</math> teilerfremd. Das heißt, wenn <math>G(x)|x^ib(x)</math>, dann muss <math>G(x)|b(x)</math>. Dies ist jedoch nicht möglich, da per Annahme der Grad von <math>b(x)</math> kleiner ist (<math>\mathrm{deg}( b(x) )=k-1</math>) als der Grad von <math>G(x)</math>. Der Rest kann niemals 0 sein und der Bündelfehler wird erkannt.
Um zu sehen, warum das so ist, führen wir einen kurzen und einfachen Widerspruchsbeweis. Angenommen <math>E(x)</math> hat eine ungerade Anzahl von Termen und ist durch <math>(x+1)</math> teilbar. Dann lässt sich <math>E(x)</math> nach einer Faktorisierung auch darstellen durch <math>E(x)=(x+1) Q(x)</math>. Wenn jetzt für <math>x</math> die Zahl <math>1</math> eingesetzt wird, gilt <math>E(1)=(1+1)Q(1)=0*Q(1)=0</math>, da in der Polynomarithmetik modulo 2 <math>1+1=0</math>. Wenn nun aber <math>E(x)</math> eine ungerade Anzahl von Termen hat, so müsste bei dem Einsetzen von <math>1</math> für <math>x</math> als Ergebnis die Zahl <math>1</math> herauskommen. Widerspruch!
Folglich ist kein Polynom mit einer ungeraden Anzahl von Termen durch <math>(x+1)</math> teilbar.


=== Beispiel ===
----
Das Generatorpolynom <math>G(x) = x^{16} + x^{15} + x^2 + 1</math> (IBM-CRC-16) lässt sich als <math>G(x) = (x^{15} + x + 1)(x + 1)</math> faktorisieren. Wegen des Faktors <math>(x + 1)</math> ist dieser CRC in der Lage, alle Fehler ungerader Anzahl erkennen zu können. Weiterhin ist die kleinste positive ganze Zahl ''k'', bei welcher das Generatorpolynom <math>G(x)</math> das Polynom <math>x^k+1</math> teilt, ''k''=32767. Dies bedeutet, dass alle beliebig angeordneten, zweifachen Bitfehler sicher erkannt werden, wenn die Blocklänge kleiner als 32768 ist. Weiter werden alle Bündelfehler der Länge 16 oder kleiner sicher erkannt. Bündelfehler mit einer Länge von 17 sind mit einer Wahrscheinlichkeit von 0,99997 erkennbar. Alle Bündelfehler mit einer Länge von 18 und mehr sind mit einer Wahrscheinlichkeit von 0,99998 erkennbar.<ref>{{Literatur|Autor=Todd K. Moon|Titel=Error Correction Coding|Verlag=John Wiley & Sons|Jahr=2005|ISBN=0-471-64800-0| Seiten=149}}</ref>


=== Erkannte Fehler (nach der Bitfiltertheorie) ===
Alle [[Bündelfehler]] der länge <math>\leq r</math>, wobei <math>r</math> der Grad des ZRP-Polynoms ist, werden erkannt. Ein Bündelfehler der Länge <math>k</math> lässt sich schreiben als <math>x^i(x^{k-1}+\cdots+1)</math>, wobei <math>i</math> bestimmt, wieviele Bitpositionen von der rechten Seite der empfangenen Bitfolge (bzw. des empfangenen Rahmens) der Bündelfehler entfernt ist. Wenn <math>G(x)</math> einen <math>x^0</math> Term enthält, so hat <math>G(x)</math> <math>x^i</math> sicher nicht als Faktor. Wenn zusätzlich der Grad von <math>(x^{k-1}+\cdots+1)</math> kleiner ist als der Grad von <math>G(x)</math>, kann der Rest niemals 0 sein.
Der Vollständigkeit halber sei hier folgendes ergänzt:
# Ein beliebiges Generatorpolynom erkennt sämtliche Bündelfehler, die nicht länger als das Generatorpolynom sind – bis auf eines, nämlich jenes, welches das gleiche Bitmuster hat wie das Generatorpolynom. Das beinhaltet natürlich auch Ein-Bit-Fehler als Bündelfehler der Länge&nbsp;1.
# Ein Generatorpolynom mit gerader Anzahl von Termen erkennt jede ungerade Anzahl von Bitfehlern.
# Mit der Bitfiltertheorie lässt sich zeigen, dass nur solche Zweibitfehler nicht erkannt werden, deren Abstand ein Vielfaches des Zyklus der Periode des längsten Bitfilters ist. Bei optimal gewählten Generatorpolynomen vom Grad <math>n</math> mit gerader Anzahl von Termen ist dieser Abstand <math>2^{n-1}-1</math>, also beispielsweise bei <math>n=16</math> beträgt diese Periode immerhin 32767, also mehr als 4000 Bytes!
# Es lässt sich ähnlich zeigen, dass alle Ein-Bit-Fehler korrigiert werden können, wenn der Datenblock nicht länger als die eben erwähnte Periode ist. Das folgt daraus, dass die Reste nach Division durch das Generatorpolynom alle verschieden sind – so weit man verschiedene Reste, von denen es höchstens <math>2^{n}</math> gibt, haben kann. Allerdings lassen unter Umständen Drei-Bit-Fehler die gleichen Reste, so dass in diesem Fall eine Korrektur das Ergebnis noch mehr verfälschen kann. Allerdings sind Ein- und Zwei-Bit-Fehler immer mit Sicherheit zu unterscheiden.


Genaueres entnehme man der Referenz ''Analyse des CRC-Verfahrens mit Bitfiltern''. Dort findet sich auch eine Liste optimaler Generatorpolynome verschiedener Grade.
== Beispiel ==


== Berechnung einer CRC-Prüfsumme in C und Pascal bzw. Delphi ==
Es folgt ein Beispiel mit einem Code n-ten Grades, wobei n=9. Das Generatorpolynom lautet 10011 (<math>1x^4 + 0x^3 + 0x^2 + 1x^1 + 1x^0</math>) und ist somit 4-ten Grades. Der zu übertragenden Bitfolge, Rahmen (engl. Frame) genannt, wird eine Kette aus Nullen entsprechend des Grades des Generatorpolynoms angehängt (siehe Rahmen mit Anhang).
'''CRC-32-Implementierung in der Programmiersprache C'''


Das folgende [[C (Programmiersprache)|C-Programm]] berechnet die CRC-32 des 8 Bit langen Datenstroms ''10001100'':
{|
| Generatorpolynom:
| 10011
|-
| Rahmen:
| 1101011011
|-
| Rahmen mit Anhang:
| 11010110110000 (das Generatorpolynom hat r-Stellen, also werden r-1 Nullen ergänzt; hier ist r=5)
|}


<syntaxhighlight lang="c">
Nun wird der Rahmen mit Anhang von links her durch das Generatorpolynom dividiert. Dabei wird ausschließlich das exklusive OR ([[XOR]]) verwendet. Wenn man stellenweise dividiert wird also aus 11010 durch 10011: 01001 (0 xor 0 = 0; 0 xor 1 = 1; 1 xor 0 = 1; 1 xor 1 = 0). Es folgt das vollständiges Beispiel
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
/* typedef unsigned __int32 uint32_t; => für MS-VS */


#define CRC32POLY 0x04C11DB7 /* CRC-32 Polynom */


const uint8_t bitstream[] = { 1,0,0,0,1,1,0,0 };
11010110110000
const int bitcount = 8;
10011
uint32_t crc32 = 0; /* Schieberegister */
-----
10011
10011
-----
000010110
10011 <- bei der ersten 1 wieder anfangen!
-----
010100
10011
-----
01110 (Rest)


int main ()
{
Die früher angehängte Null-kette wird nun durch den Rest ersetzt:
for (int i = 0; i < bitcount; i++)
{
if ( ((crc32 >> 31) & 1) != bitstream[i])
crc32 = (crc32 << 1) ^ CRC32POLY;
else
crc32 = (crc32 << 1);
}
printf ("0x%08X\n", crc32);
}
</syntaxhighlight>


'''Modifizierte CRC32: Startwert 111..., invertiertes Ergebnis mit umgekehrter Bitfolge'''
übertragener Rahmen: 11010110111110


Standards wie [[Ethernet]] modifizieren den Algorithmus:
Diese Nachricht kann jetzt z.B. über ein Netzwerk übertragen werden. Wenn die Nachricht beim Empfänger ankommt, kann dieser überprüfen, ob die Nachricht korrekt bei ihm angekommen ist.
* Als Startwert wird ''111....111'' verwendet (dies entspricht einer Invertierung der ersten 32 Bits im Datenstrom).
* Besteht der Datenstrom aus Bytes, wird das niedrigstwertige Bit zuerst verwendet.
* Alle Bits im Ergebnis werden invertiert und die Bitreihenfolge wird gedreht, das heißt, das höchstwertige Bit erscheint zuerst.


Das folgende Programm berechnet einen solchen modifizierten CRC-Wert:
Durch Division durch das Generatorpolynom kann jetzt die fehlerhafte Übertragung erkannt werden:


<syntaxhighlight lang="c">
{|
#include <stdio.h>
| Ein Beispiel für eine fehlerhafte Nachricht:
#include <stdlib.h>
| 11110110111110
#include <stdint.h>
|-
| Das Generatorpolynom (wie oben):
| 10011
|}


#define CRC32MASKREV 0xEDB88320 /* CRC-32 Bitmaske, umgekehrte Bitfolge */
11110110111110
10011
-----
11011
10011
-----
10001
10011
-----
0010011
10011
-----
00001110


const uint8_t bitstream[] = { 1,0,0,0,1,1,0,0 }; /* ASCII-"1", LSB zuerst */
Der Rest der Division (1110) ist ungleich Null. Also ist ein Fehler aufgetreten. Bei der Überprüfung auf Richtigkeit können folgende Fälle auftreten:
const int bitcount = 8;
uint32_t crc32_rev = ~0; /* Schieberegister, Startwert (111...) */


int main ()
1. Der Rest der Division ist Null und die Nachricht ist richtig.
{
2. Der Rest der Division ist Null und die Nachricht ist fehlerhaft (dieser Fall kann durchaus
for (int i = 0; i < bitcount; i++)
vorkommen, wenn die Nachricht an mehreren Stellen verfälscht wird).
{
3. Der Rest der Division ist ungleich Null und die Nachricht ist fehlerhaft.
if ((crc32_rev & 1) != bitstream[i])
crc32_rev = (crc32_rev >> 1) ^ CRC32MASKREV;
else
crc32_rev = (crc32_rev >> 1);
}
printf("0x%08X\n", ~crc32_rev); /* inverses Ergebnis, MSB zuerst */
}
</syntaxhighlight>


== Implementierung ==
'''IBM-CRC-16 Implementierung in der Programmiersprache Pascal/Delphi'''


Das folgende [[Pascal (Programmiersprache)|Pascal]] Programm berechnet einen IBM-CRC-16-Wert mit Startwert 111... und umgekehrter Bitfolge über ein [[Feld (Datentyp)|Array]] of [[Byte]]
Das ZRP-Verfahren lässt sich in einfachen [[Hardware]]-Bausteinen realisieren. Aber auch in [[Software]] ist ZRP leicht zu implementieren. Pseudo-Code des wesentlichen Teils des [[Algorithmus]], [[Bitwertigkeit|höchstwertiges Bit]] ganz links:
und gibt diese aus:


<syntaxhighlight lang="pascal">
Schieberegister := Startwert ''(meist 0000... oder 1111...)''
const
solange Bits im String verbleiben:
Polynom: Word = $A001;
falls das am weitesten links stehende Bit vom Schieberegister
Initial: Word = $FFFF;
ungleich zum nächsten Bit aus dem String ist:
var
Schieberegister := (Schieberegister linksschieben um 1, rechtes Bit 0)
CRC: Word;
[[XOR|xor]] CRC-Polynom
N, I: Integer;
andernfalls:
B: Byte;
Schieberegister := Schieberegister linksschieben um 1, rechtes Bit 0
Schieberegister enthält das Ergebnis


begin
Durch Verwendung einer Tabelle, die für jedes der 256 möglichen Bytes den zugehörigen ZRP-Wert enthält, lässt sich obiger Algorithmus auf das achtfache beschleunigen.
CRC := Initial;
for I := Low(Buffer) to High(Buffer) do
begin
B := Buffer[I];
CRC := CRC xor B;
for N := 1 to 8 do
if (CRC and 1) > 0 then
CRC := (CRC shr 1) xor Polynom
else
CRC := (CRC shr 1);
end;
Showmessage(IntToHex(CRC, 4)); (* Ausgabe *)
end;
</syntaxhighlight>


'''CRC-CCITT Implementierung in der Programmiersprache Pascal/Delphi'''
Die Operationen Linksschieben und Exklusiv-Oder machen die ZRP hervorragend geeignet zur Verwendung in [[Digitaltechnik|Logikschaltung]]en. Die ZRP eines Datenstroms kann bitweise (oder auch Byte-weise usf.) berechnet und vom Sender an die Daten angehängt werden. Der Empfänger des Datenstroms kann die ZRP genauso wie der Sender berechnen, jedoch unter Einbeziehung der ZRP. Das Ergebnis inclusive der ZRP muss dann gleich Null sein, sonst enthält der Strom Bitfehler.


Das folgende [[Pascal (Programmiersprache)|Pascal]] Programm berechnet einen CRC-CITT-Wert mit Startwert 0 über ein [[Feld (Datentyp)|Array]] of [[Byte]]
ZRP-Typen werden oft anhand des als Divisor verwendeten Polynoms unterschieden (im [[Hexadezimal]]-Format). Eines der meistverwendeten ZRPs (u. a. von [[Ethernet]], [[FDDI]], [[ZIP (Dateiformat)|ZIP]] und [[Portable Network Graphics|PNG]] benutzt) ist das Polynom ''0x04C11DB7'', bekannt als ''CRC-32''. Es stellte sich heraus, daß einige Polynome "besser" schützen als andere. Für ZRP häufig verwendete Polynome sind das Ergebnis umfangreicher mathematischer und empirischer Analysen und keine Zufallszahlen, auch wenn sie so aussehen.
und gibt diese aus:

<syntaxhighlight lang="pascal">
const
Polynom: Word = $1021;
Initial: Word = 0;
var
CRC: Word;
N, I: Integer;
B: Word;

begin
CRC := Initial;
for I := Low(Buffer) to High(Buffer) do
begin
B := Buffer[I];
CRC := CRC xor (B shl 8);
for N := 1 to 8 do
if (CRC and $8000) <> 0 then
CRC := (CRC shl 1) xor Polynom
else
CRC := CRC shl 1;
end;
CRC := CRC and $FFFF;
Showmessage(IntToHex(CRC, 4)); (* Ausgabe *)
end;
</syntaxhighlight>


== Polynome und Typen ==
== Polynome und Typen ==

{|
Die Faktorisierungen der nachfolgenden binären Generatorpolynome sind modulo 2 zu betrachten.
|CRC-CCITT (CRC-4)|| <math>x^{4} + x + 1</math>

{| class="wikitable" style="font-size:90%"
!Name ||Polynom ||Länge ||MHD ||Anmerkungen
|-
|-
|CRC-CCITT (CRC-16)|| <math>x^{16} + x^{12} + x^5 + 1</math>
|CRC-CCITT (CRC-4)|| <math>x^{4} + x + 1</math>||15||3||Identisch mit dem [[Hamming-Code#Zyklischer Hamming-Code|(15,11)-Hamming-Code]]
|-
|-
|IBM-CRC-16 || <math>x^{16} + x^{15} + x^2 + 1</math>
|USB (CRC-5)|| <math>x^5 + x^2 + 1</math> ||31||3|| Identisch mit dem [[Hamming-Code#Zyklischer Hamming-Code|(31,26)-Hamming-Code]]
|-
|-
|[[CRC-32]] || <math>x^{32} + x^{26} + x^{23} + x^{22} + x^{16} + x^{12} + x^{11} + x^{10} + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1</math>
|Bluetooth || <math>x^5 + x^4 + x^2 + 1 = (x + 1) (x^4 + x + 1)</math>||15|| || Verkürzter (15,10)-Hamming-Code.
|-
|-
|SD/MMC-Card (CRC-7)|| <math>x^7 + x^3 + 1</math>||127||3|| Identisch mit dem [[Hamming-Code#Zyklischer Hamming-Code|(127,120)-Hamming-Code]]
|CAN-CRC|| <math>x^{15} + x^{14} + x^{10} + x^8 + x^7 + x^4 + x^3 + 1</math>
|-
|-
|CRC-8 (Dallas/Maxim 1-Wire Bus)|| <math>x^8 + x^5 + x^4 + 1 = (x + 1) (x^7 + x^6 + x^5 + x^3 + x^2 + x + 1)</math>||127||4||Beschrieben bei Dallas/Maxim<ref>{{Webarchiv | url=http://datasheets.maxim-ic.com/en/ds/DS18S20-PAR.pdf | wayback=20100401003244 | text=Dallas/Maxim DS18S20, S. 6}} (PDF; 250&nbsp;kB) auf datasheets.maxim-ic.com</ref>
|Bluetooth || <math>x^5 + x^4 + x^2 + 1</math>
|-
|CRC-8 (ITU-T)|| <math>x^8+x^2+x+1=(x+1)(x^7+x^6+x^5+x^4+x^3+x^2+1)</math>||127||4||ISDN Header Error Control<ref>{{cite web |title=ITU-T Recommendation I432.1 |language=en |date=1999-02 |publisher=International Telecommunication Union |url=http://www.itu.int/rec/T-REC-I.432.1-199902-I/en |accessdate=2011-03-09 |pages=5–6}}</ref> (Kap. 7.3.2.2)
|-
|CRC-8 (SAE-J1850) || <math>x^8+x^4+x^3+x^2+1</math>||255||3||Verwendet bei [[AES/EBU]]
|-
|CRC-12 || <math>x^{12}+x^{11}+x^3+x^2+x+1=(x+1)(x^{11}+x^2+1)</math>|| || ||
|-
|CAN-CRC||<math>x^{15}+x^{14}+x^{10}+x^8+x^7+x^4+x^3+1=(x+1)(x^7+x^3+1)(x^7+x^3+x^2+x+1)</math>||127||6||
|-
|CRC-CCITT (CRC-16)|| <math>x^{16}+x^{12}+x^5+1=(x+1)(x^{15}+x^{14}+x^{13}+x^{12}+x^4+x^3+x^2+x+1)</math>||32767||4||Verwendet bei [[XMODEM]]&nbsp;CRC, [[High-Level Data Link Control|HDLC]], X.25<ref>{{cite web |title=ITU-T Recommendation X.25 |language=en |date=1996-10 |publisher=International Telecommunication Union |url=http://www.itu.int/rec/T-REC-X.25-199610-I/en |accessdate=2011-03-09 |pages=9, 145}}</ref> (Kap. 2.2.7.4, Anhang I)

|-
|IBM-CRC-16 || <math>x^{16}+x^{15}+x^2+1=(x+1)(x^{15}+x+1)</math>||32767||4||
|-
|CRC-DNP (CRC-16)|| <math>x^{16}+x^{13}+x^{12}+x^{11}+x^{10}+x^8+x^6+x^5+x^2+1 =</math> <math>(x+1)(x^{15}+x^{14}+x^{13}+x^{11}+x^8+x^5+x+1)</math>|| || ||
|-
|CRC-16 VÖV 04.05.1|| <math>x^{16}+x^{14}+x^{13}+x^{11}+x^{10}+x^9+x^8+x^6+x^5+x+1 =</math> <math>(x^8+x^4+x^3+x^2+x+1)(x^8+x^6+x^5+x^4+x^2+1)</math>|| || ||
|-
|CRC-24 (IETF RFC2440)|| <math>x^{24}+x^{23}+x^{18}+x^{17}+x^{14}+x^{11}+x^{10}+x^7+x^6+x^5+x^4+x^3+x+1 =</math> <math>(x+1)(x^{23}+x^{17}+x^{13}+x^{12}+x^{11}+x^9+x^8+x^7+x^5+x^3+1)</math>|| || ||
|-
|CRC-24 (Mode-S)|| <math>x^{24}+x^{23}+x^{22}+x^{21}+x^{20}+x^{19}+x^{18}+x^{17}+x^{16}+x^{15}+x^{14}+x^{13}+x^{12}+x^{10}+x^3+1 =</math> <math>(x+1)(x^6+x^5+x^4+x^2+1)(x^{17}+x^{16}+x^{15}+x^{13}+x^{10}+x^8+x^7+x^5+x^4+x^3+x+1)</math>|| || || Bei Framelänge bis 112 Bits fehlerkorrigierend bis 5 Bit
|-
|CRC-32 ([[IEEE 802.3]])|| <math>x^{32} + x^{26} + x^{23} + x^{22} + x^{16} + x^{12} + x^{11} + x^{10} + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1</math>||<math>2^{32}-1</math>||3||Verwendet bei Ethernet<ref>{{cite web|url=http://www.3utelecom.de/wp-content/uploads/2016/10/802.3-2015_SECTION1.pdf|title=IEEE Std 802.3-2015 Section 1|date=2015-09-09|accessdate=2018-05-04|last=|first=|publisher=IEEE Computer Society|pages=112|archiveurl=https://web.archive.org/web/20180504155849/http://www.3utelecom.de/wp-content/uploads/2016/10/802.3-2015_SECTION1.pdf|archivedate=2018-05-04|offline=0}}</ref>
|-
|CRC-64 (ISO 3309)|| <math>x^{64} + x^{4} + x^{3} + x + 1</math>|| || ||
|-
|CRC-64 ([[Ecma International|ECMA-182]]<ref>[http://www.ecma-international.org/publications/standards/Ecma-182.htm ECMA-182]</ref>) || <math>x^{64}+x^{62}+x^{57}+x^{55}+x^{54}+x^{53}+x^{52}+x^{47}+x^{46}+x^{45}+x^{40}+x^{39}+x^{38}+x^{37}+x^{35}+x^{33}+</math> <math>x^{32}+x^{31}+x^{29}+x^{27}+x^{24}+x^{23}+x^{22}+x^{21}+x^{19}+x^{17}+x^{13}+x^{12}+x^{10}+x^9+x^7+x^4+x+1=</math> <math>(x+1)^2(x^{15}+x+1)(x^{15}+x^{10}+x^5+x+1)(x^{15}+x^{12}+x^3+x+1)(x^{17}+x^{14}+x^{12}+x^{11}+x^{10}+x^9+x^8+x^5+x^4+x^3+1)</math>|| || || Verwendet bei [[XZ Utils]]
|}
|}


Die Spalte ''MHD'' gibt die minimale [[Hamming-Distanz]] an, die zwei Bitfolgen mit gültigem CRC-Wert unterscheidet. Ein CRC-Algorithmus kann also jeden Fehler erkennen, der innerhalb der angegebenen maximalen Länge weniger als ''MHD'' Bit-Positionen betrifft. Wird die maximale Länge überschritten, gibt es bei ''jedem'' CRC-Algorithmus Zwei-Bit-Fehler, die nicht erkannt werden (z.&nbsp;B. zwei Fehler, die genau ''Länge'' Positionen auseinanderliegen).
ZRPs werden häufig als [[Prüfsumme]]n bezeichnet, obwohl die Berechnung der Kontrollbits nicht nur durch (gewöhnliche) Addition geschieht. Der Begriff ''Prüfsumme'' wurde zuerst im Zusammenhang mit [[Paritätsbit]]s benutzt, welche sich als eine echte Summe über <math>\mathbb{Z}_2</math> berechnen lassen. Dabei hat sich der Begriff so sehr eingebürgert, dass er als Bezeichnung für die Berechnung von allgemeinen Kontrollbits übernommen wurde.

CRC-Werte werden häufig als [[Prüfsumme]]n bezeichnet, obwohl die Berechnung der Kontrollbits nicht nur durch (gewöhnliche) Addition geschieht. Der Begriff „Prüfsumme“ wurde zuerst im Zusammenhang mit [[Paritätsbit]]s benutzt, die sich als eine echte Summe über <math>\mathbb{Z}_2</math> berechnen lassen. Dabei hat sich der Begriff so sehr eingebürgert, dass er als Bezeichnung für die Berechnung von allgemeinen Kontrollbits übernommen wurde.

Die Prüfpolynome wurden aus einer Vielzahl von möglichen Polynomen so ausgewählt, dass sich für den damit erzeugten Code „günstige“ Eigenschaften ergeben. Beispiel: Wenn ein Polynom eine gerade Anzahl von Termen in x aufweist (CRC16-CCITT:4 und CRC16-IBM:4, nicht aber CRC-4:3), ist das Binom (x + 1) als Faktor darin enthalten. Dieses Binom bewirkt eine „Paritätsprüfung“, wodurch im entstehenden Code alle Fehler mit einer ungeraden Anzahl von Fehlerstellen in jedem Fall erkennbar sind.


== Siehe auch ==
''Siehe auch:'' [[Hash-Funktion]] und die dort genannten Verfahren, [[DFÜ]].
* [[Simple File Verification]]
* [[Slicing by Eight]]


== Weblinks ==
== Weblinks ==
* [http://zorc.breitbandkatze.de/crc.html ''CRC JavaScript Rechner und C-Code'']
* http://www.jonelo.de/java/jacksum/index_de.html
* [http://www.lammertbies.nl/comm/info/crc-calculation.html ''Online CRC Rechner für die gängigsten CRCs mit CRC Berechnungsroutinen in C++ und ANSI C zum Download''] ''engl.''
** Jacksum (''Ja''va Che''cksum'') ist ein freies und plattformunabhängiges Programm, u. a. zur Berechnung und Verifizierung von Prüfsummen, CRCs und Message Digests (mit [[Java_(Programmiersprache)|Java]]-[[Quelltext]])
* [http://www.ross.net/crc/ ''A Painless Guide to CRC Error Detection Algorithms'']
* {{Webarchiv | url=http://www.ross.net/crc/ | wayback=20190519134454 | text=''A Painless Guide to CRC Error Detection Algorithms''}} ''engl.''
* [http://www.aweiler.com/crc/ ''The CRC++ Project''] ''engl'' Eine Implementierung von CRC in C++ mit Template-Klassen
* [http://www.4d.com/docs/CMU/CMU79909.HTM ''Understanding Cyclic Redundancy Check'']
* [http://www.netzmafia.de/skripten/modem/codes.html#4.11 ''Fehlererkennung mittels CRC'']
* [http://einstein.informatik.uni-oldenburg.de/forschung/crc/index.html ''Analyse des CRC-Verfahrens mit Bitfiltern'']


== Einzelnachweise ==
[[Kategorie:Algorithmus]]
<references />
[[Kategorie:Theoretische_Informatik]]
[[Kategorie:Hardware]]


{{SORTIERUNG:Zyklische Redundanzprufung}}
[[en:Cyclic redundancy check]]
[[Kategorie:Hash]]
[[fr:Cyclic redundancy check]]
[[Kategorie:Technische Informatik]]
[[id:CRC]]
[[Kategorie:Fehlermanagement]]
[[ja:巡回冗長検査]]
[[ko:순환 중복 검사]]
[[nl:Cyclic Redundancy Check]]
[[pl:CRC]]
[[ru:CRC]]
[[sv:Cyclic Redundancy Check]]

Aktuelle Version vom 5. April 2025, 13:13 Uhr

Die zyklische Redundanzprüfung (ZRP, englisch cyclic redundancy check, daher meist CRC) ist ein Verfahren zur Bestimmung eines Prüfwerts für Daten, um Fehler bei der Übertragung oder Speicherung erkennen zu können. Im Idealfall kann das Verfahren sogar die empfangenen Daten selbständig korrigieren, um eine erneute Übertragung zu vermeiden.

Es wurde 1961 von W. Wesley Peterson entwickelt.[1]

Vor der Datenspeicherung oder Übertragung wird für jeden Datenblock der Nutzdaten zusätzliche Redundanz in Form eines sogenannten CRC-Werts angefügt. Dieser ist ein nach einem bestimmten Verfahren berechneter Prüfwert, mit dessen Hilfe man während der Speicherung bzw. Übertragung eventuell aufgetretene Fehler erkennen kann. Zur Überprüfung der Daten wird dasselbe Berechnungsverfahren auf den Datenblock einschließlich des angefügten CRC-Werts angewandt. Ist das Ergebnis dann null, kann angenommen werden, dass der Datenblock unverfälscht ist. Verschiedene technische Anwendungen weichen allerdings von diesem Schema ab, indem sie beispielsweise die Berechnung mit einem bestimmten Wert initialisieren oder den CRC-Wert vor der Übermittlung invertieren.

CRC ist so ausgelegt, dass Fehler bei der Übertragung der Daten, wie sie beispielsweise durch Rauschen auf der Leitung verursacht werden könnten, mit hoher Wahrscheinlichkeit entdeckt werden. CRCs von seriellen Datenübertragungen können sehr einfach in Hardware realisiert werden. Zum Beispiel werden Datenübertragungen über Ethernet sowie die meisten Festplatten-Übertragungen mit CRC-Verfahren geprüft.

Das CRC-Verfahren ist nur für die Erkennung von zufälligen Fehlern ausgelegt. Es ist nicht geeignet, die Integrität der Daten zu bestätigen. Das heißt, es ist verhältnismäßig leicht, durch beabsichtigte Modifikation einen Datenstrom zu erzeugen, der den gleichen CRC-Wert wie eine gegebene Nachricht hat. Wenn eine solche Sicherheit gefordert ist, müssen kryptografische Hash-Funktionen wie beispielsweise SHA oder Signatur-Funktionen wie beispielsweise RSA zum Einsatz kommen.

Der Name des Verfahrens beruht darauf, dass der angefügte Wert keinen Informationsgehalt besitzt, der nicht bereits in dem zugrunde liegenden Datenblock enthalten ist. Er ist deshalb redundant. CRCs beruhen auf zyklischen Codes. Das sind Block-Codes, die die Eigenschaft haben, dass jede zyklische Verschiebung der Bits eines gültigen Code-Worts ebenfalls ein gültiges Code-Wort ist.

Die Berechnung des CRC-Werts beruht auf dem Prinzip der Polynomdivision. Die zu übertragenden Bits werden als Faktoren eines Polynoms interpretiert, mit welchen Berechnungen angestellt werden können, die das nachfolgende Verfahren ermöglichen. Insbesondere entspricht die Polynomdivision einem bitweisen XOR (exklusiv-oder bzw. entweder-oder). Sind die Bits gleich, ist das Ergebnis 0. Sind sie verschieden, ist das Ergebnis 1.

Es wird ein Prüfwert der Länge n bestimmt (das CRC-Polynom) und die zu übertragende Bitfolge mit n-1 0en verlängert. Dies ergibt den sogenannte Rahmen. Anschließend wird der Rahmen wiederholt durch den Prüfwert geteilt, wobei die beiden Bitfolgen jeweils an der ersten Ziffer ausgerichtet werden, die 1 ist. Dieses Verfahren ist nicht mit normaler Division von Binärzahlen zu verwechseln, welche andere Ergebnisse liefert. Für den Rahmen bzw. das Zwischenergebnis 000110101 und den Prüfwert 01011, würden die Werte wie folgend ausgerichtet und verrechnet werden:

Zwischenergebnis   000110100
Prüfwert             01011
Division                   /
Ergebnis           000011000

Das Ergebnis dieser Berechnung wird mit jedem Schritt kleiner. Hat das Ergebnis weniger relevante Stellen als der Prüfwert, werden die letzten n-1 Stellen als Rest übernommen, der sogenannte CRC-Wert. Dieser Rest wird an die zu übertragende Bitfolge angehängt und gemeinsam übertragen.

Um zu verifizieren, dass die Daten fehlerfrei übertragen wurden, wiederholt der Empfänger die Berechnung mit der übertragenen Bitfolge und dem CRC-Polynom. Da die Bitfolge um den ermittelten Rest ergänzt wurde, bleibt dieses Mal kein Rest übrig, wenn die Daten fehlerfrei übertragen wurden (oder wenn ein sehr seltener Fehler auftrat, der einem Vielfachen des CRC-Polynoms entsprach).

Das Verfahren setzt voraus, dass Sender und Empfänger wissen, dass gesicherte Daten übertragen werden und wie das CRC-Polynom lautet. Den Daten selbst ist beides nicht zu entnehmen.

Für die Bitfolge 11011 und dem Prüfwert 110101 (Länge n = 6), ergibt sich der Rahmen 1101100000 (Bitfolge um n-1 = 5 0en verlängert). Anschließend wird der Rahmen durch das Generatorpolynom dividiert. Die beiden Zahlen werden jeweils an der ersten Ziffer ausgerichtet, da diese beide eine 1 sind.

Rahmen             1101100000
Prüfwert           110101
Division                    /
Zwischenergebnis   0000110000

Das Zwischenergebnis hat sechs relevante Stellen (110000), der Prüfwert ebenfalls. Also wird erneut dividiert. Dieses Mal wird der Prüfwert an der fünften Stelle des Zwischenergebnisses ausgerichtet.

Zwischenergebnis   0000110000
Prüfwert               110101
Division                    /
Ergebnis           0000000101

Das Ergebnis hat nun nur noch drei relevante Stellen, also werden die letzten n-1 (=5) Stellen als CRC-Wert übernommen, in diesem Fall also 00101. Die Bitfolge 11011 und der Rest 00101 ergeben die zu übertragenden Daten 1101100101. Möchte der Empfänger die Korrektheit der Daten verifizieren, führt er die Polynomdivision mit dem Rahmen 1101100101 und dem Prüfwert 110101 durch:

Rahmen             1101100101
Prüfwert           110101
Division                    /
Zwischenergebnis   0000110101
Prüfwert               110101
Division                    /
Ergebnis                    0

Das Ergebnis ist 0, also trat wahrscheinlich kein Fehler auf. Wurde stattdessen der fehlerhafte Rahmen 1001100101 empfangen, ergibt sich folgende Berechnung:

Rahmen             1001100101
Prüfwert           110101
Division                    /
Zwischenergebnis   0100110101
Prüfwert            110101
Division                    /
Zwischenergebnis     10011101
Prüfwert             110101
Division                    /
Zwischenergebnis      1001001
Prüfwert              110101
Division                    /
Zwischenergebnis       100011
Prüfwert               110101
Division                    /
Zwischenergebnis        10110

Der Rest der Division (10110) ist ungleich null. Also ist ein Fehler aufgetreten.

Bei der Überprüfung auf Richtigkeit können folgende vier Fälle auftreten:

  1. Der Rest der Division ist null und die Nachricht ist richtig
  2. Der Rest der Division ist null und die Nachricht ist fehlerhaft (dieser Fall ist unwahrscheinlich, kann aber vorkommen, wenn das Fehlerpolynom ein Vielfaches des Generatorpolynoms ist oder wenn sich zwei Fehler in der gleichen Übertragung gegenseitig aufheben)
  3. Der Rest der Division ist ungleich null und die Nachricht ist fehlerhaft
  4. Der Rest der Division ist ungleich null und die Nachricht ist richtig (dieser Fall tritt ein, wenn lediglich der angehängte Rest fehlerhaft übertragen wird; dies ist jedoch ebenfalls unwahrscheinlich, da der übertragene Rest im Vergleich zur Gesamtlänge des Pakets kurz ist)

Das CRC-Verfahren lässt sich sowohl in einfachen Hardware-Bausteinen als auch in Software realisieren. Verwendet werden

  • ein Schieberegister mit n Bits, dabei ist n die Länge des Prüfwerts (etwa ein 32-Bit-Schieberegister bei CRC-32) und
  • ein Bit-Datenstrom beliebiger Länge gefolgt von n Null-Bits.

Pseudocode des Algorithmus, höchstwertiges Bit ganz links, Multiplikation mit 2 bedeutet ein Schieben um eine Stelle nach links:

crc := 0000… (Startwert)
für alle Bits b im Datenstrom:
  wenn  das am weitesten links stehende Bit von crc 1 ist:
    crc := (crc * 2 + b) xor CRC-Polynom
  sonst:
    crc := crc * 2 + b
crc enthält das Ergebnis.

Durch Verwendung einer Tabelle, die beim Verfahren CRC-8 beispielsweise für jedes der 256 möglichen Bytes den zugehörigen CRC-Wert enthält, lässt sich obiger Algorithmus um den Faktor 8 beschleunigen. Das resultiert daraus, dass ein Tabelleneintrag 8 Bits = 1 Byte enthält und verschiedene Tabelleneinträge existieren. Die Geschwindigkeitssteigerung wird durch den direkten Zugriff auf die Tabelle mithilfe der zu berechnenden Bitfolge realisiert, indem die gesuchte CRC-8-Berechnung an der Stelle in der Tabelle steht, welche den binären Wert der zu berechnenden Bitfolge als Index hat.

Die Operationen Linksschieben und Exklusiv-Oder machen die CRC hervorragend geeignet zur Verwendung in Logikschaltungen. Die CRC eines Datenstroms kann bitweise (oder auch Byte-weise usf.) berechnet und vom Sender an die Daten angehängt werden. Der Empfänger des Datenstroms kann den CRC genauso wie der Sender berechnen, jedoch unter Einbeziehung des CRC. Das Ergebnis inklusive des CRC muss dann gleich null sein, sonst enthält der Strom Bitfehler.

CRC-Typen werden oft anhand des als Divisor verwendeten Polynoms unterschieden (im Hexadezimal-Format). Eines der meistverwendeten CRCs (u. a. von Ethernet, FDDI, ZIP und PNG benutzt) ist das Polynom 0x04C11DB7, bekannt als CRC-32. Es stellte sich heraus, dass einige Polynome besser „schützen“ als andere. Für CRC häufig verwendete Polynome sind das Ergebnis umfangreicher mathematischer und empirischer Analysen und keine Zufallszahlen, auch wenn sie so aussehen.

Andere Startwerte

[Bearbeiten | Quelltext bearbeiten]

Die Implementierung führt eine Polynomdivision aus, wenn als Startwert 0000… verwendet wird. Oft findet man andere Startwerte, etwa 1111…. Dies entspricht einer Polynomdivision, wenn die ersten n Bits des Datenstroms invertiert werden.

Ein Startwert ungleich 0000… ist vorzuziehen, da fehlende Bits innerhalb führender Nullen im Datenstrom sonst nicht erkannt werden (ebenso wie bei einer gewöhnlichen Division zählen bei einer Polynomdivision führende Nullen nicht).

Nullproblem und Nachbearbeitung

[Bearbeiten | Quelltext bearbeiten]

Eine weitere Problematik stellt das Nullproblem dar, das in zweierlei Form auftritt:

  1. Produziert ein Datenstrom zufällig einen CRC gleich null, so ist der CRC auch dann null, wenn dem Datenstrom zusätzliche Nullen angehängt werden, oder – falls der Datenstrom mit einer oder mehreren Nullen endet – einige dieser letzten Nullen entfernt werden.
  2. Ist dem Ende des Datenstroms der CRC angehängt (so wie es ein Sender eben verschickt) und bei der Übertragung werden (nach dem gesendeten CRC) noch zusätzliche Nullen angefügt, so können diese zusätzlichen Nullen am Ende nicht erkannt werden.

Das Nullproblem in beiden Ausführungen ist unabhängig davon, ob Startwerte gleich null oder ungleich null verwendet werden.

Das Nullproblem in beiden Ausführungen wird vermieden, indem die Bits des CRC-Ergebnisses invertiert werden. Erfolgt im Empfänger die CRC-Prüfung derart, dass der Empfänger einen CRC aus dem empfangenen Datenpaket berechnet, wobei das Datenpaket aus Datenstrom und angehängtem CRC besteht, so ist im Falle eines unveränderten (nichtinvertierten) CRC des Senders der berechnete CRC im Empfänger stets null. Im Falle eines invertierten CRC des Senders ist der berechnete CRC im Empfänger immer der gleiche Wert, dieser wird auch als Magic Number bezeichnet.

Das Nullproblem der zweiten Ausführung kann auch vermieden werden, indem die Reihenfolge der CRC-Bits umgekehrt wird. Unerkannt bleibt jedoch der Fall, wo der CRC gleich null ist, was das Nullproblem der ersten Art darstellt.

Das bisher beschriebene Nullproblem bezieht sich also auf die Problematik, am Ende des Datenstroms zusätzlich hinzugefügte oder verlorengegangene Nullen zu erkennen. Dies ist jedoch nur dann nötig, wenn aufgrund vorherrschender Randbedingungen nicht sichergestellt werden kann, dass die Größe der Daten unverändert bleibt.

Von einem Nullproblem spricht man jedoch bisweilen auch dann, wenn es problematisch ist, wenn ein Datenstrom aus lauter Nullen auch einen CRC gleich Null erzeugt. Ein CRC gleich null aus Null-Daten entsteht unabhängig vom Generatorpolynom grundsätzlich, wenn der CRC-Startwert gleich null ist und die Bits des resultierenden CRC nicht invertiert werden. Dieses Problem kann somit vermieden werden, indem ein Startwert ungleich null festgelegt wird oder aber auch die resultierenden CRC-Bits invertiert werden.

Der bekannte CRC-32 verwendet sowohl 1111... als Startwert als auch ein inverses Ergebnis. Bei CRC-16 wird ebenfalls meist 1111.. verwendet, das Ergebnis jedoch nicht invertiert. In beiden Fällen bleibt die Reihenfolge der CRC-Bits unverändert.

Erkannte Fehler

[Bearbeiten | Quelltext bearbeiten]

Ist das CRC-Polynom gut gewählt, können mit dem oben beschriebenen Verfahren alle Einbitfehler, jede ungerade Anzahl von verfälschten Bits, sowie alle Bündelfehler der Länge erkannt werden, wobei der Grad des CRC-Polynoms ist. Zusätzlich werden alle Fehler (also auch unabhängige Vierbit-, Sechsbit-, Achtbitfehler usw.) erkannt, deren Polynomdarstellung einen kleineren Grad als das CRC-Polynom hat. Zweibitfehler werden entgegen der landläufigen Meinung nicht grundsätzlich erkannt. Warum das so ist bzw. wie das CRC-Polynom zu wählen ist, folgt aus den kommenden Überlegungen.

Sei das CRC-Polynom (Generatorpolynom) und die Polynomdarstellung der um den CRC-Wert erweiterten zu übertragenden Bitfolge. Wenn ein Fehler bei der Übertragung auftritt, kommt (in Polynomdarstellung) beim Empfänger nicht , sondern an. Die zu gehörende Bitfolge hat an jeder Bitposition, die bei der zu übertragenden Bitfolge invertiert bzw. verfälscht wurde, eine 1. Wenn der Empfänger die um den CRC-Wert erweiterte Bitfolge erhält, berechnet er . Da (per Definition von ), ist das Ergebnis .

Wenn ein Ein-Bit-Fehler aufgetreten ist, gilt , wobei bestimmt, welches Bit invertiert ist. Wenn nun zwei oder mehr Terme enthält, wird niemals teilen.

Zwei isolierte Ein-Bit-Fehler

[Bearbeiten | Quelltext bearbeiten]

Sind zwei isolierte Ein-Bit-Fehler aufgetreten, gilt , wobei . Klammert man aus, lässt sich dies auch als schreiben. Da nicht durch teilbar sein kann, reicht es zu fordern, dass nicht teilt (für alle bis zum maximalen Wert von , das heißt der maximalen Rahmenlänge). Einfache Polynome geringen Grades, die eine sichere Übertragung für lange Rahmen ermöglichen, sind bekannt. Zum Beispiel teilt den Term nicht für jedes kleiner 32767.

Ungerade Anzahl von Fehlern

[Bearbeiten | Quelltext bearbeiten]

Ist eine ungerade Anzahl von Bits verfälscht, enthält eine ungerade Anzahl von Termen (z. B. , aber nicht z. B. ). Wählt man das CRC-Polynom so, dass es als Faktor hat, werden alle Fehler mit einer ungeraden Anzahl von verfälschten Bits erkannt.

Beweis: Bei der Division durch ein Polynom mit gerader Parität (= Anzahl der Terme in dem Polynom, also Anzahl der Einsen in der Bitfolge) ist die Geradheit oder Ungeradheit der Parität im Divisions-Rest gleich der des Dividenden, denn aus 00 wird 11 (und umgekehrt) und aus 01 wird 10 (und umgekehrt).

ist das kleinste Polynom mit gerader Parität. Bei wird also stets oder als Rest bleiben, wenn ungerade Parität hat. Damit ist nicht durch teilbar.

Alle Bündelfehler (eng. Burst) der Länge , wobei der Grad des CRC-Polynoms ist, werden erkannt. Ein Bündelfehler der Länge lässt sich schreiben als , wobei bestimmt, wie viele Bitpositionen von der rechten Seite der empfangenen Bitfolge (bzw. des empfangenen Rahmens) der Bündelfehler entfernt ist. Wenn der Fehler erkannt werden soll, muss die Division von durch einen Rest ergeben.

Da immer den Term enthält, sind und teilerfremd. Das heißt, wenn , dann muss . Dies ist jedoch nicht möglich, da per Annahme der Grad von kleiner ist () als der Grad von . Der Rest kann niemals 0 sein und der Bündelfehler wird erkannt.

Das Generatorpolynom (IBM-CRC-16) lässt sich als faktorisieren. Wegen des Faktors ist dieser CRC in der Lage, alle Fehler ungerader Anzahl erkennen zu können. Weiterhin ist die kleinste positive ganze Zahl k, bei welcher das Generatorpolynom das Polynom teilt, k=32767. Dies bedeutet, dass alle beliebig angeordneten, zweifachen Bitfehler sicher erkannt werden, wenn die Blocklänge kleiner als 32768 ist. Weiter werden alle Bündelfehler der Länge 16 oder kleiner sicher erkannt. Bündelfehler mit einer Länge von 17 sind mit einer Wahrscheinlichkeit von 0,99997 erkennbar. Alle Bündelfehler mit einer Länge von 18 und mehr sind mit einer Wahrscheinlichkeit von 0,99998 erkennbar.[2]

Erkannte Fehler (nach der Bitfiltertheorie)

[Bearbeiten | Quelltext bearbeiten]

Der Vollständigkeit halber sei hier folgendes ergänzt:

  1. Ein beliebiges Generatorpolynom erkennt sämtliche Bündelfehler, die nicht länger als das Generatorpolynom sind – bis auf eines, nämlich jenes, welches das gleiche Bitmuster hat wie das Generatorpolynom. Das beinhaltet natürlich auch Ein-Bit-Fehler als Bündelfehler der Länge 1.
  2. Ein Generatorpolynom mit gerader Anzahl von Termen erkennt jede ungerade Anzahl von Bitfehlern.
  3. Mit der Bitfiltertheorie lässt sich zeigen, dass nur solche Zweibitfehler nicht erkannt werden, deren Abstand ein Vielfaches des Zyklus der Periode des längsten Bitfilters ist. Bei optimal gewählten Generatorpolynomen vom Grad mit gerader Anzahl von Termen ist dieser Abstand , also beispielsweise bei beträgt diese Periode immerhin 32767, also mehr als 4000 Bytes!
  4. Es lässt sich ähnlich zeigen, dass alle Ein-Bit-Fehler korrigiert werden können, wenn der Datenblock nicht länger als die eben erwähnte Periode ist. Das folgt daraus, dass die Reste nach Division durch das Generatorpolynom alle verschieden sind – so weit man verschiedene Reste, von denen es höchstens gibt, haben kann. Allerdings lassen unter Umständen Drei-Bit-Fehler die gleichen Reste, so dass in diesem Fall eine Korrektur das Ergebnis noch mehr verfälschen kann. Allerdings sind Ein- und Zwei-Bit-Fehler immer mit Sicherheit zu unterscheiden.

Genaueres entnehme man der Referenz Analyse des CRC-Verfahrens mit Bitfiltern. Dort findet sich auch eine Liste optimaler Generatorpolynome verschiedener Grade.

Berechnung einer CRC-Prüfsumme in C und Pascal bzw. Delphi

[Bearbeiten | Quelltext bearbeiten]

CRC-32-Implementierung in der Programmiersprache C

Das folgende C-Programm berechnet die CRC-32 des 8 Bit langen Datenstroms 10001100:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
/* typedef unsigned __int32 uint32_t; => für MS-VS */

#define CRC32POLY   0x04C11DB7      /* CRC-32 Polynom */

const uint8_t   bitstream[] = { 1,0,0,0,1,1,0,0 };
const int       bitcount    = 8;
uint32_t        crc32       = 0;    /* Schieberegister */

int main ()
{
    for (int i = 0; i < bitcount; i++)
    {
        if ( ((crc32 >> 31) & 1) != bitstream[i])
            crc32 = (crc32 << 1) ^ CRC32POLY;
        else
            crc32 = (crc32 << 1);
    }
    printf ("0x%08X\n", crc32);
}

Modifizierte CRC32: Startwert 111..., invertiertes Ergebnis mit umgekehrter Bitfolge

Standards wie Ethernet modifizieren den Algorithmus:

  • Als Startwert wird 111....111 verwendet (dies entspricht einer Invertierung der ersten 32 Bits im Datenstrom).
  • Besteht der Datenstrom aus Bytes, wird das niedrigstwertige Bit zuerst verwendet.
  • Alle Bits im Ergebnis werden invertiert und die Bitreihenfolge wird gedreht, das heißt, das höchstwertige Bit erscheint zuerst.

Das folgende Programm berechnet einen solchen modifizierten CRC-Wert:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#define CRC32MASKREV   0xEDB88320   /* CRC-32 Bitmaske, umgekehrte Bitfolge */

const uint8_t   bitstream[] = { 1,0,0,0,1,1,0,0 };  /* ASCII-"1", LSB zuerst */
const int       bitcount    = 8;
uint32_t        crc32_rev   = ~0;                   /* Schieberegister, Startwert (111...) */

int main ()
{
    for (int i = 0; i < bitcount; i++)
    {
        if ((crc32_rev & 1) != bitstream[i])
            crc32_rev = (crc32_rev >> 1) ^ CRC32MASKREV;
        else
            crc32_rev = (crc32_rev >> 1);
    }
    printf("0x%08X\n", ~crc32_rev);          /* inverses Ergebnis, MSB zuerst */
}

IBM-CRC-16 Implementierung in der Programmiersprache Pascal/Delphi

Das folgende Pascal Programm berechnet einen IBM-CRC-16-Wert mit Startwert 111... und umgekehrter Bitfolge über ein Array of Byte und gibt diese aus:

const
  Polynom: Word = $A001;
  Initial: Word = $FFFF;
var
  CRC: Word;
  N, I: Integer;
  B: Byte;

begin
  CRC := Initial;
  for I := Low(Buffer) to High(Buffer) do
  begin
    B := Buffer[I];
    CRC := CRC xor B;
    for N := 1 to 8 do
      if (CRC and 1) > 0 then
        CRC := (CRC shr 1) xor Polynom
      else
        CRC := (CRC shr 1);
  end;
  Showmessage(IntToHex(CRC, 4)); (* Ausgabe *)
end;

CRC-CCITT Implementierung in der Programmiersprache Pascal/Delphi

Das folgende Pascal Programm berechnet einen CRC-CITT-Wert mit Startwert 0 über ein Array of Byte und gibt diese aus:

const
  Polynom: Word = $1021;
  Initial: Word = 0;
var
  CRC: Word;
  N, I: Integer;
  B: Word;

begin
  CRC := Initial;
  for I := Low(Buffer) to High(Buffer) do
  begin
    B := Buffer[I];
    CRC := CRC xor (B shl 8);
    for N := 1 to 8 do
      if (CRC and $8000) <> 0 then
        CRC := (CRC shl 1) xor Polynom
      else
        CRC := CRC shl 1;
  end;
  CRC := CRC and $FFFF;
  Showmessage(IntToHex(CRC, 4)); (* Ausgabe *)
end;

Polynome und Typen

[Bearbeiten | Quelltext bearbeiten]

Die Faktorisierungen der nachfolgenden binären Generatorpolynome sind modulo 2 zu betrachten.

Name Polynom Länge MHD Anmerkungen
CRC-CCITT (CRC-4) 15 3 Identisch mit dem (15,11)-Hamming-Code
USB (CRC-5) 31 3 Identisch mit dem (31,26)-Hamming-Code
Bluetooth 15 Verkürzter (15,10)-Hamming-Code.
SD/MMC-Card (CRC-7) 127 3 Identisch mit dem (127,120)-Hamming-Code
CRC-8 (Dallas/Maxim 1-Wire Bus) 127 4 Beschrieben bei Dallas/Maxim[3]
CRC-8 (ITU-T) 127 4 ISDN Header Error Control[4] (Kap. 7.3.2.2)
CRC-8 (SAE-J1850) 255 3 Verwendet bei AES/EBU
CRC-12
CAN-CRC 127 6
CRC-CCITT (CRC-16) 32767 4 Verwendet bei XMODEM CRC, HDLC, X.25[5] (Kap. 2.2.7.4, Anhang I)
IBM-CRC-16 32767 4
CRC-DNP (CRC-16)
CRC-16 VÖV 04.05.1
CRC-24 (IETF RFC2440)
CRC-24 (Mode-S) Bei Framelänge bis 112 Bits fehlerkorrigierend bis 5 Bit
CRC-32 (IEEE 802.3) 3 Verwendet bei Ethernet[6]
CRC-64 (ISO 3309)
CRC-64 (ECMA-182[7]) Verwendet bei XZ Utils

Die Spalte MHD gibt die minimale Hamming-Distanz an, die zwei Bitfolgen mit gültigem CRC-Wert unterscheidet. Ein CRC-Algorithmus kann also jeden Fehler erkennen, der innerhalb der angegebenen maximalen Länge weniger als MHD Bit-Positionen betrifft. Wird die maximale Länge überschritten, gibt es bei jedem CRC-Algorithmus Zwei-Bit-Fehler, die nicht erkannt werden (z. B. zwei Fehler, die genau Länge Positionen auseinanderliegen).

CRC-Werte werden häufig als Prüfsummen bezeichnet, obwohl die Berechnung der Kontrollbits nicht nur durch (gewöhnliche) Addition geschieht. Der Begriff „Prüfsumme“ wurde zuerst im Zusammenhang mit Paritätsbits benutzt, die sich als eine echte Summe über berechnen lassen. Dabei hat sich der Begriff so sehr eingebürgert, dass er als Bezeichnung für die Berechnung von allgemeinen Kontrollbits übernommen wurde.

Die Prüfpolynome wurden aus einer Vielzahl von möglichen Polynomen so ausgewählt, dass sich für den damit erzeugten Code „günstige“ Eigenschaften ergeben. Beispiel: Wenn ein Polynom eine gerade Anzahl von Termen in x aufweist (CRC16-CCITT:4 und CRC16-IBM:4, nicht aber CRC-4:3), ist das Binom (x + 1) als Faktor darin enthalten. Dieses Binom bewirkt eine „Paritätsprüfung“, wodurch im entstehenden Code alle Fehler mit einer ungeraden Anzahl von Fehlerstellen in jedem Fall erkennbar sind.

Einzelnachweise

[Bearbeiten | Quelltext bearbeiten]
  1. W. W. Peterson: Cyclic Codes for Error Detection. In: Proceedings of the IRE, Vol. 49, No. 1, 1961, S. 228–235
  2. Todd K. Moon: Error Correction Coding. John Wiley & Sons, 2005, ISBN 0-471-64800-0, S. 149.
  3. Dallas/Maxim DS18S20, S. 6 (Memento vom 1. April 2010 im Internet Archive) (PDF; 250 kB) auf datasheets.maxim-ic.com
  4. ITU-T Recommendation I432.1. International Telecommunication Union, Februar 1999, S. 5–6, abgerufen am 9. März 2011 (englisch).
  5. ITU-T Recommendation X.25. International Telecommunication Union, Oktober 1996, S. 9, 145, abgerufen am 9. März 2011 (englisch).
  6. IEEE Std 802.3-2015 Section 1. IEEE Computer Society, 9. September 2015, S. 112, archiviert vom Original am 4. Mai 2018; abgerufen am 4. Mai 2018.
  7. ECMA-182