AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

CRC-16 berechnen

Ein Thema von brose · begonnen am 11. Feb 2010 · letzter Beitrag vom 3. Mär 2010
Antwort Antwort
Seite 1 von 2  1 2      
brose

Registriert seit: 20. Mai 2007
14 Beiträge
 
#1

CRC-16 berechnen

  Alt 11. Feb 2010, 22:01
Hallo Leute.

Ich habe einen gegebenen Datenstrom, zu dem der CRC-16 berechnet wurde. Um den Datenstrom zu beantworten, muss ich in das Antwort-Telegramm ebenfalls den CRC-Wert einbetten.

Dummerweise bekomme ich es aber nicht hin, diesen CRC-16 korrekt zu berechnen.


Der komplette Datenstrom ist (Hex-Werte)

00 00 00 0E (1) 7D 98 B2 00 (2) CE 64 (3) 00 00 00 00 01 01 01 01

Laut Dokumentation wird der CRC ab (1) berechnet, wobei für den Teil zwischen (2) und (3) die Werte 00 00 eingesetzt werden. Hier wird anschließend der CRC-Wert abgelegt.

Also muss der CRC-16 für 7D 98 B2 00 00 00 00 00 00 00 01 01 01 01 den Wert CE 64 annehmen.

Ich hab schon gegoogelt und getestet ohne Ende, aber ich komm nicht auf CE 64.
Auf http://zorc.breitbandkatze.de/crc.html und http://www.lammertbies.nl/comm/info/...lculation.html war ich schon.

Ich habs mit verschiedenen CRC-16 probiert, hab die Routinen aus dem "Delphi Encryption Compendium" von Hagen Reddmann benutzt und diese Lösung hier:

Delphi-Quellcode:
procedure TForm1.ByteCrc(data:byte;var crc:word);
VAR i:BYTE;
BEGIN
 FOR i:=0 TO 7 DO
  BEGIN
   IF ((data and $01)XOR(crc AND $0001)<>0) THEN
    BEGIN
     crc:=crc shr 1;
     crc:= crc XOR $A001;
    END
   ELSE crc:=crc shr 1;
   data:=data shr 1; // this line is not ELSE and executed anyway.
  END;
END;

function TForm1.StringCrc(s:shortstring):word;
var len,i:integer;
begin
 result:=$0;
 len:=length(s);
 for i:=1 to len do bytecrc(ord(s[i]),result);
end;

procedure TForm1.Button1Click(Sender: TObject);
var str:string; str2:shortstring;
i:integer;
begin
  str2 := {chr($00)+chr($00)+chr($00)+chr($0E)+}chr($7D)+chr($98)+chr($B2)+chr($00)+
   chr($00)+chr($00)+chr($00)+chr($00)+chr($00)+chr($00)+chr($01)
   +chr($01)+chr($01)+chr($01);

   edit1.text := inttohex(stringcrc(str2),4);

end;
auch das hier funktioniert nicht bzw. ich mach da was falsch:
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var
  CRCcc16: Word;
  str :word;
begin
   str := $7D+$98+$B2+$00+$00+$00+$00+$00+$01+$01+$01+$01;

  CRCcc16 := CRCCalc(CRC_16,str, SizeOf(str));
   showmessage(inttohex(CRCcc16,0));

end;
Weiß jemand Rat, was ich da nun falsch mache???


Was ich grds. bis jetzt auch nicht so ganz verstanden habe ist, wie die CRC eigentlich bei so einem Strom berechnet wird. Die Beispiele gehten immer von 5 Bit o.ä. aus, die dann durchs Generator-Polynom geteilt werden. Das ist mir auch klar, aber ich muss doch die ganzen Hex-Bytes erstmal miteinander "verwursten" (addieren, XOR hintereinander verknüpfen, .... was ist mit Überträgen...), um dann 2 Byte = 16 Bit zu bekommen, die ich teilen kann? Oder denk ich da falsch?
  Mit Zitat antworten Zitat
gammatester

Registriert seit: 6. Dez 2005
999 Beiträge
 
#2

Re: CRC-16 berechnen

  Alt 11. Feb 2010, 22:45
Was genau sagt die Doku? Welches Polynom wird da genannt? Dein $A001 deutet auf das Polynom $8005 hin. Hast Du noch einen zweiten (oder dritten) Datensatz mit CRC? Dann stehen die Chancen gut, daß ich Dir den Algo bestimmen kann.

Gruß Gammatester
  Mit Zitat antworten Zitat
brose

Registriert seit: 20. Mai 2007
14 Beiträge
 
#3

Re: CRC-16 berechnen

  Alt 11. Feb 2010, 22:58
Die Doku sagt:

Element CRC16 (Prüfsumme)
Die Prüfsumme wird ab dem Element TC [ab (01)] bis zum Satzende generiert. Vor der Generierung der Prüfsumme wird das Element CRC16 [das ist zwischen (2) und (3)] mit dem Wert 0000H gefüllt.

Das Polynom wird leider nicht genannt. Sonstige Hinweise gibts leider auch nicht.


Hier noch zwei weitere Beispiele:

00 00 00 0D (1) 70 E1 69 8E (2) 0B 4B (3) 01 B6 15 8E 03 01 00
CRC ist also 0B 4B

00 00 00 0E (1) 17 7C 9C 80 (2) 19 67 (3) 7D 98 B2 01 02 01 01 01
CRC ist also 19 67

Wie gesagt, zum Berechnen werden die zwei Byte zwischen (2) und (3) jeweils auf 00 gesetzt. Anschließend wird dort der CRC-Wert eingetragen.

Danke schon jetzt für Deine Hilfe und Gruß
Sebastian
  Mit Zitat antworten Zitat
gammatester

Registriert seit: 6. Dez 2005
999 Beiträge
 
#4

Re: CRC-16 berechnen

  Alt 11. Feb 2010, 23:37
Also für die Standardalgorithmen habe ich nichts gefunden, das für zwei Datensätze paßt (selbst mit variablem Initialwert). Falls Du noch andere Informationen hast, kannst Du ja es selbst versuchen mit dem SRP16-Programm zum Suchen von Rocksoft-Parametern für gegebene Daten-/CRC16-Sätze, Teil meiner CRC-Demoprogramme. Falls Du die Parameter hast, kannst Du sie mit der crc_model-Unit für weitere Berechnungen verwenden.

Gruß Gammmatester
  Mit Zitat antworten Zitat
brose

Registriert seit: 20. Mai 2007
14 Beiträge
 
#5

Re: CRC-16 berechnen (Übersetzung C => Delphi)

  Alt 1. Mär 2010, 11:21
Ja, danke, aber ich hab auch nix rausbekommen.

Vermutlich handelt es sich um "RFC 1071 Internet Checksum" (http://www.codes-sources.com/rfc/RFC...R-24/1071.aspx)

Dort gibts unter Abschnitt 4.3 ne Implementation in C:

Delphi-Quellcode:
4.1 "C"

   The following "C" code algorithm computes the checksum with an inner
   loop that sums 16-bits at a time in a 32-bit accumulator.

   in 6
       {
          /* Compute Internet Checksum for "count" bytes
            *        beginning at location "addr".
            */
      register long sum = 0;

        while( count > 1 )  {
          /*  This is the inner loop */
              sum += * (unsigned short) addr++;
              count -= 2;
       }


           /* Add left-over byte, if any */
       if( count > 0 )
               sum += * (unsigned char *) addr;

           /* Fold 32-bit sum to 16 bits */
       while (sum>>16)
           sum = (sum & 0xffff) + (sum >> 16);

       checksum = ~sum;
   }

Verstehe ich das richtig:

Ich nehme immer zwei Hex-Pärchen und negiere sie. Dann summiere ich sie auf, den Übertrag (5. und weitere Stellen von rechts) schneide ich ab und addiere ihn ebenfalls. Die Summe negiere ich erneut und das ist dann der CRC-Wert?

Besteht evtl. die Möglichkeit, dass mir jemand den C-Code oben "mal eben" von C nach Delphi übersetzt?

Grüße
Sebastian
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.033 Beiträge
 
Delphi 12 Athens
 
#6

Re: CRC-16 berechnen

  Alt 1. Mär 2010, 11:44
So schwer ist das Übersezen doch garnicht?

Einen großteil hätte fast jeder hinbekommen und bei den ein/zwei unklaren Stellen hätte man auch nochmal geziehlt fragen können.
Delphi-Quellcode:
function crc(add: Pointer; ): Word;
var
  sum: LongInt;
begin
  sum := 0;
  while count > 1 do begin
    Inc(sum, PWord(addr)^);
    Inc(Integer(addr), 2);
    Dec(count, 2);
  end;
  if count > 0 then
    Inc(sum, PByte(addr)^);
  while sum shr 16 <> 0 do
    sum = sum and $ffff + (sum shr 16);
  result := not sum;
end;
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.685 Beiträge
 
Delphi 2007 Enterprise
 
#7

Re: CRC-16 berechnen (Übersetzung C => Delphi)

  Alt 1. Mär 2010, 11:53
Probiern wir's mal:
Delphi-Quellcode:
function InternetChecksum(data: PByte; byteCount: Cardinal): Word;
var
  sum: Cardinal;
begin
  sum := 0;
  while byteCount > 1 do
  begin
    Inc(sum, PWord(data)^);
    Inc(data, 2);
    Dec(byteCount, 2)
  end;
  // Add left-over byte, if any
  if byteCount > 0 then
    Inc(sum, PByte(data)^);

  // Fold 32-bit sum to 16 bits
  while (sum shr 16) > 0 do
    sum := (sum and $ffff) + (sum shr 16);

  result := not Word(sum);
end;

Mehr oder minder 1:1 übersetzt und komplett ungetestet. Ein wenig gemein ist, dass die Funktion für beliebig lange Inputs ist, und hier im Grunde einen Pointer auf das erste Element eines packed array of Byte erwartet, bzw. irgend eine andere Datenstruktur die die einzelnen Bytes der Eingangssequenz am Stück hintereinander stehen hat. Da wäre dann die Frage wie du diese Daten in deinem Programm vorliegen hast, um da evtl. noch zu vereinfachen/optimieren, aber das da oben ist ziemlich direkt übersetzt.

Edit: Ach himi... nicht so schnell! (Aber danke für die richtige Variante bei den Pointer-Casts )
Edit2: Hmm, du hast einen "Pointer" statt "PByte". Würde das beim Inc() nicht um 2x32 Bit verschieben? Müsstes nicht 2 Bytes sein?
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
brose

Registriert seit: 20. Mai 2007
14 Beiträge
 
#8

Re: CRC-16 berechnen

  Alt 1. Mär 2010, 12:03
Danke Euch beiden! Ich kanns im Moment leider nicht testen, werde aber berichten.

Die Daten liegen zunächst als STRING-Kette der Hexwerte (00-FF) vor.

Mit Pointern kenn' ich mich leider nicht so aus. Müsste ich die Werte dann in einen Array of Byte schreiben, also immer 32 Bit? Muss ich das ganze vierstellig durchführen, weil ja am Ende ein 32-Bit-Wert stehen muss?

Sorry für die vielleicht doofen Fragen, aber ich hab da im Moment bei dieser Funktion noch nicht so den Durchblick
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.685 Beiträge
 
Delphi 2007 Enterprise
 
#9

Re: CRC-16 berechnen

  Alt 1. Mär 2010, 12:18
Was am Ende dabei raus kommt ist beim Input noch egal. Um einen String entsprechend nutzbar zu machen würde ich so vorgehen:
Delphi-Quellcode:
var
  s: String; // Hier stehen die Hex-Werte drin
  data: packed array of byte;
  i: Integer;
begin
  SetLength(data, Length(s) div 2);
  for i := 0 to (Length(s) div 2)-1 do
    data[i] := Byte(StrToInt('$'+s[i*2+1]+s[i*2+2]));
  // Aufruf dann mit
  foo := InternetCRC(@data[0], Length(data));
end;
Edit: Ausbesserung. Typische Falle: Strings sind 1-basiert... grrrrr!
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.033 Beiträge
 
Delphi 12 Athens
 
#10

Re: CRC-16 berechnen

  Alt 1. Mär 2010, 12:36
Delphi-Referenz durchsuchenHexToBin
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:25 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz