Forum: PC-Programmierung CRC16 auf CRC32 erweitern (C)


von Tobias P. (genesis)


Lesenswert?

Hallo zusammen,
ich beschäftige mich derzeit mit der CRC-Programmierung (in C) und 
möchte gerne einen CRC32-Code programmieren. Der CRC16-Code ist soweit 
fertig und funktioniert auch allerdings habe ich nun das Problem dass 
der CRC32-Code falsche Werte anzeigt.

Bei der Erweiterung des funktionierenden CRC16-Codes auf CRC32 wird 
eigentlich "nur" die Maske (für das MSB) und die Anzahl an Bits (die 
verschoben werden) geändert.

Das heißt ich habe für die Maske statt 0x8000 (CRC16) nun 0x80000000 
(CRC32).
Und statt einer Verschiebung um 8 Stellen, nun eine Verschiebung um 24 
Stellen.

Die "LUT-32" funktioniert auch (zumindest stimmen die Hex-Werte dieser 
Tabelle mit dem Online-Calculator überein daher vermute ich einen Fehler 
in der Compute_CRC32() nur sehe ich es leider nicht..


Vielleicht hat jemand eine Idee?





Programmiert wird mit C und Eclipse (MinGW).

Der CRC Code wurde anhand eines Besipiels von folgendem Link erstellt:
http://www.sunshine2k.de/articles/coding/crc/understanding_crc.html

Die Ergebnisse werden geprüft mit:
http://www.sunshine2k.de/coding/javascript/crc/crc_js.html

CRC16-Code
1
#include <stdio.h>
2
#include <stdint.h>
3
#include <stdlib.h>
4
#include <string.h>
5
#include <inttypes.h>
6
7
8
static unsigned short CrcTable16[256] ;
9
static unsigned short crc = 0;
10
11
/*Look-Up Table erstellen */
12
void CalculateTable_CRC16()
13
{
14
  const unsigned short generator = 0x1021;
15
16
 /* iterate over all possible input byte values 0 - 255 */
17
      for (int divident=0 ; divident<256 ; divident++ ) {
18
          unsigned short curByte = divident << 8 ; 
19
20
          for (int bit=0 ; bit<8 ; bit++ ) {
21
              if ( (curByte & 0x8000)!=0 ) {
22
                  curByte <<= 1;
23
                  curByte ^= generator;   
24
              } else {
25
                  curByte <<= 1;
26
              }
27
          }
28
          CrcTable16[divident] = curByte;
29
      }
30
  }
31
32
unsigned short Compute_CRC16(unsigned char str[],int len)      
33
{
34
35
    unsigned int pos;
36
    crc =0;            
37
    for (int b=0 ; b<len ; b++ ) {
38
        pos = ( (crc >> 8) ^ str[b]);
39
        crc = (unsigned short)((crc << 8) ^ (unsigned short)(CrcTable16[pos]));
40
    }
41
    return crc;
42
}
43
44
45
void main(){
46
    unsigned char message[3] = {0xA1, 0xBD, 0xF0};
47
48
    CalculateTable_CRC16();
49
  Compute_CRC16(message,3);
50
51
  printf("CRC-Code ist:  %x\n",crc);
52
}


CRC32-Code:
1
#include <stdio.h>
2
#include <stdint.h>
3
#include <stdlib.h>
4
#include <string.h>
5
#include <inttypes.h>
6
#include <time.h>
7
8
9
static unsigned long CrcTable32[256] ;
10
static unsigned long crc = 0;
11
12
/*Look-Up Table erstellen */
13
void CalculateTable_CRC32(){
14
15
      for (unsigned long divident=0 ; divident < 256 ; divident++ ) { 
16
          unsigned long curByte = divident << 24 ; 
17
18
          for (int bit=0 ; bit<8 ; bit++ ) {
19
              if ( (curByte & 0x80000000)!=0 ) {
20
                  curByte <<= 1;
21
                  curByte ^= generator;   //XOR-Anweisung
22
              } else {
23
                  curByte <<= 1;
24
              }
25
          }
26
          CrcTable32[divident] = curByte;
27
      }
28
  }
29
30
31
//CRC-Code ausführen
32
unsigned long Compute_CRC32(unsigned char str[],int len)      
33
{
34
    unsigned int pos;
35
     crc = 0;                              
36
    for (int b=0 ; b<len ; b++ ) {
37
        pos = ( (crc >> 24) ^ str[b]);
38
        crc = (unsigned  long)((crc << 8) ^ (unsigned long)(CrcTable32[pos]));
39
    }
40
    return crc;
41
}
42
43
void main()
44
{
45
    
46
    unsigned char message[3] = {0x83, 0x01, 0x00};
47
    CalculateTable_CRC32();
48
    Compute_CRC32(message,3);
49
    printf("CRC_32-Code ist:  %lx\n",crc);
50
51
/* Look-up Table ausgeben*/
52
    /*
53
for (int i=0; i<256; i++){
54
  printf("%x\n",CrcTable32[i]);
55
}
56
*/
57
  }

: Verschoben durch User
von Yalu X. (yalu) (Moderator)


Lesenswert?

Tobias P. schrieb:
> Der CRC Code wurde anhand eines Besipiels von folgendem Link erstellt:
> http://www.sunshine2k.de/articles/coding/crc/understanding_crc.html

Weiter unten auf dieser Webseite gibt es auch ein Code-Beispiel für
CRC-32.

von Kaj G. (Firma: RUB) (bloody)


Lesenswert?

Tobias P. schrieb:
> allerdings habe ich nun das Problem dass
> der CRC32-Code falsche Werte anzeigt.
Dann sag doch mal, um was fuer eine Architektur es sich handelt. Denn je 
nach Architektur kann long 32 oder 64 bit breit sein.

Mein Tipp, um Bugs auszuschliessen:
Nutze die Datentypen aus stdint.h, wenn du unsigned long als 32 bit 
breit erwartest, nimm uint32_t. Diese Datentypen haben den Vorteil, dass 
sie auf allen Platformen dieselbe Breite haben, d.h. du kannst den 
Code entspannt auf einem x-bliebigen PC testen (z.B. mit Unittests), 
damit die korrekte Funktion sicherstellen, und dann kannst du den Code 
auch genauso auf einem uC nutzen. Mit int/long ist das nicht oder nur 
umstaendlich moeglich.

Gerade bei Hash- und anderen kryptographischen Funktionen sollte man 
diese Datentypen verwenden.

Und bevor hier wieder jemand schreit, dass das ja performancetechnisch 
kacke ist:
Erstmal die korrekte Funktion sicherstellen! Danach kann man sich 
immernoch um Performance kuemmern.


--- EDIT ---
1. Dein Code fuer CRC32 compiliert nicht. Da fehlt 'generator'.
2. Als 32 bit Applikation compiliert laeuft es immerhin, ob der Wert 
richtig ist: keine Ahnung.
3. Als 64 bit Applikation gibt es einen Segfault.

Pass die Datentypen an und mach das Beispiel compilierfaehig!

von Tobias P. (genesis)


Angehängte Dateien:

Lesenswert?

Vielen Dank für die Antworten :-)

@Yalu: Genau. Und nach dem gegebenen Beispiel hatte ich die 
CRC32-Berechnung umgesetzt. Dort steht ja ziemlich genau drin was 
abgeändert werden muss, allerdings wird bei mir ein falscher Wert 
erzeugt.

Wenn ich meinen Code ausführe mit folgenden Parametern:
Generatorpolynom: 0x4C11DB7
Message: 0xA1, 0xDE, 0x2B

Dann erzeugt mein Programm: d9f6d155
Richtig wäre (laut Online CRC32-Calculator): 94FCFF94


@bloody
Der Code wird auf Win7 64-bit ausgeführt.
Danke dir für den Tipp mit dem Datentyp. Tatsächlich möchte ich später 
den Code auf einem Mikrocontroller übertragen (mit entsprechender 
Anpassung) und da hatte ich mir zunächst um den Datentyp keine Gedanken 
zu gemacht.

Beim "Copy/Paste" habe ich scheinbar den "generator ausgelassen.
Hier nochmal der angepasste (und ausführbare) Code.



----EDIT----
Ach verdammt..Jetzt hab ich den Fehler entdeckt.
Ich habe den Fehler an der falschen Stelle gesucht.

Tatsächlich habe ich beim überprüfen des CRC  (per Online 
CRC-Calculator) nicht darauf geachtet, dass oftmals die Einstellungen 
"Input reflected / Result reflected" automatisch aktiviert sind und 
somit natürlich ein anderes Ergebnis angezeigt wird. :-(

Ziemlicher Anfängerfehler aber dennoch danke für eure Mühen.
Den CRC32 Code hänge ich einfach nochmal an für die die es möglcherweise 
mal benötigen.


1
#include <stdio.h>
2
#include <stdint.h>
3
#include <stdlib.h>
4
#include <string.h>
5
#include <inttypes.h>
6
#include <time.h>
7
8
9
uint32_t CrcTable32[256] ;
10
uint32_t crc = 0;
11
uint32_t generator = 0x4C11DB7;   //Generator-Polynom
12
13
14
/*********************CRC32 Look-Up Tabelle erstellen ************************/
15
void CalculateTable_CRC32(){
16
17
18
      for (uint32_t divident=0 ; divident < 256 ; divident++ ) {
19
        uint32_t curByte = divident << 24 ;
20
21
          for (int bit=0 ; bit<8 ; bit++ ) {
22
              if ( (curByte & 0x80000000)!=0 ) {
23
                  curByte <<= 1;
24
                  curByte ^= generator;   //XOR-Anweisung
25
              } else {
26
                  curByte <<= 1;
27
              }
28
          }
29
          CrcTable32[divident] = curByte;
30
      }
31
  }
32
33
34
35
36
37
/******************CRC32-Code ausführen**********************/
38
39
uint32_t Compute_CRC32(unsigned char str[],int len)
40
{
41
  uint32_t pos;
42
    crc = 0;
43
    for (int b=0 ; b<len ; b++ ) {
44
        pos = ( (crc >> 24) ^ str[b]);
45
        crc = (uint32_t)((crc << 8) ^ (uint32_t)(CrcTable32[pos]));
46
    }
47
   return crc;
48
}
49
50
51
52
53
54
55
int main()
56
{
57
    unsigned char message[3] = {0xA1, 0xDE, 0x2B};
58
59
    CalculateTable_CRC32();
60
    Compute_CRC32(message,3);
61
    printf("CRC_32-Code ist:  %x\n",crc);
62
63
 //Look-Up Tabelle ausgeben
64
65
    /*
66
    for (int i=0; i<256; i++){
67
    printf("%x\n",CrcTable32[i]);
68
    }
69
     */
70
  return 0;
71
}

von Kaj G. (Firma: RUB) (bloody)


Lesenswert?

Hey Tobias,

noch ein kleiner Verbesserungsvorschlag:
Gewoehen dir bitte an Funktionsprototypen hinzuschreiben.

Ich hab deinen Code mal so bearbeitet, wie ich es machen wuerde. Ueber 
das const, usw. kann man streiten. Ist nur ein Vorschlag. Wenigstens 
Funktionsprototypen solltest du dir aber angewoehnen :)
1
#include <stdio.h>
2
#include <stdint.h>
3
4
5
void create_crc32_table(uint32_t *const table, const uint32_t len);
6
uint32_t Compute_CRC32(const uint8_t *const msg, const int32_t len, const uint32_t *const table);
7
8
9
int main(void)
10
{
11
    uint32_t Crc32Table[256] = {0};
12
    uint8_t message[3] = {0xA1, 0xDE, 0x2B};
13
14
    create_crc32_table(Crc32Table, sizeof(Crc32Table)/sizeof(uint32_t));
15
    uint32_t crc = Compute_CRC32(message, sizeof(message), Crc32Table);
16
17
    printf("CRC_32-Code ist:  %x\n", crc);
18
19
    return 0;
20
}
21
22
23
/*********************CRC32 Look-Up Tabelle erstellen ************************/
24
void create_crc32_table(uint32_t *const table, const uint32_t len)
25
{
26
    static const uint32_t generator = 0x4C11DB7;
27
    static const uint32_t mask = 0x80000000;
28
29
    for (uint32_t divident = 0; divident < len; divident++) {
30
        uint32_t curByte = divident << 24 ;
31
32
        for (int32_t bit = 0; bit < 8; bit++) {
33
            if ((curByte & mask) != 0) {
34
                curByte <<= 1;
35
                curByte ^= generator;
36
            } else {
37
                curByte <<= 1;
38
            }
39
        }
40
41
        table[divident] = curByte;
42
    }
43
}
44
45
46
/******************CRC32-Code ausführen**********************/
47
uint32_t Compute_CRC32(const uint8_t *const msg, const int32_t len, const uint32_t *const table)
48
{
49
    uint32_t crc = 0;
50
51
    for (int32_t b = 0; b < len; b++) {
52
        uint32_t pos = (crc >> 24) ^ msg[b];
53
        crc = (crc << 8) ^ table[pos];
54
    }
55
56
    return crc;
57
}
Ob len und pos 32 bit sein muessen, oder ob 8 bzw. 16 bit reichen, musst 
du nachher anhand deines uC und deinen Anforderungen entscheiden.

von Peter D. (peda)


Lesenswert?

Kaj G. schrieb:
> Gewoehen dir bitte an Funktionsprototypen hinzuschreiben.

Bei lokalen (static) Funktionen ist es üblich, die Definition vor den 
Aufruf zu schreiben. Dann spart man sich die Deklaration.
Bei globalen Funktionen erfolgt die Deklaration im .h-File.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.