Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi CRC32 für einzelne Wörter! (https://www.delphipraxis.net/49177-crc32-fuer-einzelne-woerter.html)

fes 6. Jul 2005 16:26


CRC32 für einzelne Wörter!
 
Hallo zusammen!

Ich suche die PHP funktion crc 32 () für Delphi, und zwar nicht für Dateien, sondern für einzelne Strings...

Die Boardsuche hab ich schon bemüht, und habe nur CRC32 für komplette Dateien gefunden

(siehe hier)

Wäre cool wenn da jemand nen code für mich hätte.

Thx

fes

Die Muhkuh 6. Jul 2005 16:27

Re: CRC32 für einzelne Wörter!
 
Such mal nach dem DEC von Hagen Reddmann

barf00s 6. Jul 2005 16:33

Re: CRC32 für einzelne Wörter!
 
nen google tuts auch ...

fes 6. Jul 2005 16:36

Re: CRC32 für einzelne Wörter!
 
Hmmm, ich hab zwar gefunden was ihr meint, aber da kann man mit CRC32 auch nur komplette Dateien verschlüsseln, soweit ich das jetzt beim schnellen überfliegen des Programmes gesehen habe...

Die Muhkuh 6. Jul 2005 16:39

Re: CRC32 für einzelne Wörter!
 
Hi,

damit kannst du auch nur einzelne Wörter crc32en^^

fes 6. Jul 2005 16:43

Re: CRC32 für einzelne Wörter!
 
:gruebel: :gruebel: hmmmmm... und wo mach ich des genau??

ich werd aus dem programm ned schlau, warscheinlich bin ich zu dumm dafür... :?

negaH 6. Jul 2005 21:05

Re: CRC32 für einzelne Wörter!
 
du rufst auf:

Delphi-Quellcode:
var
  Result: LongWord;
begin
  Result := TChecksum_CRC32.CRCString('Wort');
end;
Gruß Hagen

fes 6. Jul 2005 21:19

Re: CRC32 für einzelne Wörter!
 
hmm....
vielleicht sollte ich noch erwähnen, dass ich der komplette noob bin, wenn es um units einbinden geht.... :oops: :oops:

wenn man mir sagen könnte, welche unit ich wo und wie einbinden muss, wäre ich sehr dankbar...

negaH 6. Jul 2005 22:49

Re: CRC32 für einzelne Wörter!
 
Delphi-Quellcode:

uses Checksum;
Gruß Hagen

DGL-luke 6. Jul 2005 22:55

Re: CRC32 für einzelne Wörter!
 
aber bitte die anderen units, die schon drin sind, auch drin lassen ;)

also checksum einfach hintendran hängen. wobei man beachten sollte, dass zwischen den einträgen kommas und hinter de mletzten ein strichkomma ist und das so bleiben sollte. :stupid:

negaH 6. Jul 2005 23:00

Re: CRC32 für einzelne Wörter!
 
Ansonsten nimmst du die Unit aus deinem ersten Link. Dort gibt es die Funktion "RecountCRC()" die du benutzen kannst.

Delphi-Quellcode:
function RecountCRC(b: byte; CrcOld: Longint): Longint;
begin
  RecountCRC := CRCTable[byte(CrcOld xor Longint(b))] xor ((CrcOld shr 8) and $00FFFFFF)
end;

function CRCString(const Value: String): Cardinal;
var
  I: Integer;
begin
  Result := $FFFFFFFF; // Init Wert der CRC, schau im PHP nach
  for I := 1 to Length(Value) do
    Result := RecountCRC(Ord(Value[I]), Result);
  Result := not Result; // eventl. Finit Wert, schau im PHP nach
end;
Gruß Hagen

fes 7. Jul 2005 17:43

Re: CRC32 für einzelne Wörter!
 
THX!!!

SaltJohn 21. Jan 2009 16:22

Re: CRC32 für einzelne Wörter!
 
Ist zwar schon etwas älter der Threat aber ich habe gerade genau das gleiche Problem. Habe einen String und möchte gerne eine CRC32 Prüfung machen. Leider ist die Unit vom ersten Link hier im Threat down. Weiß jemand eine Alternative?

himitsu 21. Jan 2009 16:51

Re: CRC32 für einzelne Wörter!
 
als Alternativen hätten wir noch

Hagen's Hier im Forum suchenDEC Bei Google suchenDEC (Delphi Encrytion Compendium)
http://www.michael-puff.de/Developer...agen_Reddmann/

HashLib! v1.03.exe
http://www.delphipraxis.net/internal...?p=96430#96430

vieles vieles mehr

und im Notfall noch was von mir
http://www.delphipraxis.net/internal...t.php?t=135239

Delphi-Quellcode:
Var CRC32: ThxCRC32;
  S: String;
  B: LongWord;


CRC32.InitT; // notfalls das Polynom ändern, oder 'ne andere Tabelle laden
CRC32.Calc('dein Wort');
S := CRC32.asHexString; //B := CRC32.asBin;

// oder

CRC32.InitT; // notfalls das Polynom ändern, oder 'ne andere Tabelle laden
CRC32.Init;
CRC32.Update('dein Wort');
CRC32.Final;
S := CRC32.asHexString; //B := CRC32.asBin;
der CRC32-Teil ließe sich auch "einfach" aus dem Projekt extrahieren

SaltJohn 22. Jan 2009 08:37

Re: CRC32 für einzelne Wörter!
 
Hi himitsu, erstmal danke für die ausführliche Antwort. Am liebsten würde ich auf deinen letzten Vorschlag zurückkommen allerdings weiß ich nicht genau was ich alles aus deinem Projekt benötige. Du schreibst zwar, dass sich der CRC32-Teil auch "einfach" aus dem Projekt extrahieren lassen würde, denke aber, dass dies nicht ganz auf mich zutrifft :)

Zu dem was ich mache:
Ich versuche mit der Snoop Component Suite Ethernet Pakete zu generieren. Der aktuelle Stand ist, dass der Rahmen fast komplett ist. Header, Länge und Daten sind bereits zu einem Hexstring verarbeitet. Mir fehlen jetzt "nur" noch die 4byte (CRC32-Checksumme) die ich zum Schluss als Hexstring anfügen möchte.


dachte da an sowas:
Delphi-Quellcode:
function crc32(Datastring: String): Integer;
begin
(...)
end

string := string + IntTohex(crc32(string))

himitsu 22. Jan 2009 11:48

Re: CRC32 für einzelne Wörter!
 
Liste der Anhänge anzeigen (Anzahl: 2)
Wenn du nur eine Funktion möchtest, dann mußt du dir allerdings selber was basteln,
da ich meine CRC32-Frunktionen ohne feste HashTabelle erstellt hab und diese muß erst initialisert werden.

Nicht wundern, Aufgrund des internen Aufbaus ist wirklich kein freigeben (.Free) nötig.
Und abgesehn vom CRC32 wird auch kein (.InitT aka .Create) benötigt.
Delphi-Quellcode:
Function MyCRC32(Datastring: String): String;
  Var CRC32: ThxCRC32;

  Begin
    CRC32.InitT;
    Result := CRC32.Calc(S).asHexString;
  End

aString := aString + MyCRC32(aString);
oder so
Delphi-Quellcode:
Function MyCRC32(Datastring: String; Polynom: LongWord = $EDB88320): String;
  Var CRC32: ThxCRC32;

  Begin
    CRC32.InitT(Polynom);
    Result := CRC32.Calc(S).asHexString;
  End

aString := aString + MyCRC32(aString, $12345678);
aber am Effektivsten sähe es dann so aus:
(nicht jedesmal die HashTabelle neu berechnen)
Delphi-Quellcode:
Var CRC32: ThxCRC32;

CRC32.InitT;

aString := aString + CRC32.Calc(aString).asHexString;
aString := aString + CRC32.Calc(aString).asHexString;
aString := aString + CRC32.Calc(aString).asHexString;

hab das Ganze auch gleich mal an Delphi 2009 angepaßt
und hoff es haben sich keine Fehler beim Umbau eingeschlichen.

SaltJohn 22. Jan 2009 13:38

Re: CRC32 für einzelne Wörter!
 
Hab das gleich mal ausprobiert aber leider kommt bei mir bei allen drei Methoden eine mir bisher unbekannte Fehlermeldung [Pascal Fatal Error] Main.pas(250): F2084 Internal Error: URW821. Dein Beispielprojekt funktioniert allerding.

himitsu 22. Jan 2009 13:55

Re: CRC32 für einzelne Wörter!
 
Wie sieht denn dein TestCode aus und in welcher Delphiversion trat der Fehler auf?


füge mal in FHash_single und deine TestUnit nach dem "Interface" ein "{$INLINE OFF}" ein.
(ich weiß jetzt leider nicht, wo dieser Schalter seine Auswirkung zeigt)
vielleicht hilft's ja ... es kam anscheinend, im Zusammenhang mit mit einem ähnlichem Fehler, schonmal vor
Delphi-Quellcode:
Interface
  {$INLINE OFF}

"Advanced" Records - Internal Errors URW821 and C1624

SaltJohn 22. Jan 2009 14:46

Re: CRC32 für einzelne Wörter!
 
Also ich benutze Delphi2006. Nachdem ich bei beiden units
Delphi-Quellcode:
{$INLINE OFF}
eingefügt habe kommt jetzt die Meldung
Zitat:

[Pascal Fatal Error] Unit1.pas(209): F2084 Internal Error: C1624
Alles was ich gemacht habe ist deine Unit eingebunden

und in meiner Main den Aufruf mit

Delphi-Quellcode:
crcChecksum := MyCRC32(Datastring);
zu

Delphi-Quellcode:
// CRC-Prüfsumme berechnen
Function TForm1.MyCRC32(Datastring: String): String;
var CRC32: ThxCRC32;
begin
  CRC32.InitT;
  Result := CRC32.Calc(Datastring).asHexString;
end;
das Programm wird nur dann fertig compiliert wenn ich
Delphi-Quellcode:
Result := CRC32.Calc(Datastring).asHexString;
auskommmentiere

himitsu 22. Jan 2009 14:58

Re: CRC32 für einzelne Wörter!
 
versuch es mal so :gruebel:
Delphi-Quellcode:
Function TForm1.MyCRC32(Datastring: String): String;
var CRC32: ThxCRC32;
begin
  CRC32.InitT;
  CRC32.Calc(Datastring);
  Result := CRC32.asHexString;
end;

SaltJohn 22. Jan 2009 15:13

Re: CRC32 für einzelne Wörter!
 
Jetzt funktioniert es :) Aber warum das nicht auf einem Wisch geht ist mir schleierhaft. Da wäre ich niemals nicht draufgekommen.

himitsu 22. Jan 2009 15:25

Re: CRC32 für einzelne Wörter!
 
nja, mit neuen Funktionalitäten haben die Compiler anfangs öfters mal kleine Problemchen :stupid:

nach'm Überfliegen der Beschreibung, des oben verlinkten "Advanced Records"-Artikels, hätt ich erstmal vermutet es gibt Probleme, wenn man in soeiner Record-Prozeduren auf wiederum soeine Prozedur zugreift. :?

SaltJohn 22. Jan 2009 15:39

Re: CRC32 für einzelne Wörter!
 
Zum Glück ist es nicht so :) In jedem Fall recht vielen Dank für alles und vor allem für deine Geduld!

SaltJohn 23. Jan 2009 06:07

Re: CRC32 für einzelne Wörter!
 
Hab da noch eine kurze Frage zu deinem CRC32 selbst. Bei Ethernet ist das ja so
Auszug aus Wikipedia:
Zitat:

Zur Berechnung der CRC-32-Prüfsumme werden die ersten 32 Bits der Mac-Adresse invertiert und das Ergebnis ebenfalls invertiert (Vermeidung des Nullproblems).
Das wird bei CRC32 nicht generell gemacht bzw. das muss ich noch implementieren, oder?

himitsu 24. Jan 2009 10:40

Re: CRC32 für einzelne Wörter!
 
Solche änderungen mußt du natürlich selber machen (der Code weiß ja nicht was du da berechnen willst und berechnet daher nur das "einfach" CRC32)

PS: ist die "Frame Check Sequence" nicht CRC16?
hmmmmmmm? :gruebel:
hier klingt es nach CRC16: http://de.wikipedia.org/wiki/Frame_Check_Sequence (mit 16 Bit verwendet)
aber hier nach CRC32: http://de.wikipedia.org/wiki/Datenframe (4 Byte)


nach dem Aufbau in http://de.wikipedia.org/wiki/Datenframe würde ich die Brechnung wohl irgendwie in dieser Richtung vermuten: :glaskugel:
Delphi-Quellcode:
Var CRC: ThxCRC32;
  Temp, FCS: LongWord;

CRC.InitT(CRC32Table04);

CRC.Init;
CRC.Update(@SOF, 1);
Temp := not PLongWord(@DestMAC)^;
CRC.Update(@Temp, 4);
CRC.Update(@DestMAC + 4, 2);
Temp := not PLongWord(@SrcMAC)^;
CRC.Update(@SrcMAC, 4);
CRC.Update(@SrcMAC + 4, 2);
CRC.Update(@TypeOrLength, 2)
CRC.Update(@Data, DataLength);
CRC.Final;
FCS := not CRC{.asBin};
(also falls du nicht den ganten FrameBuffer kopieren und darin direct die entsprechenden Stellen invertieren willst)

SaltJohn 25. Jan 2009 09:11

Re: CRC32 für einzelne Wörter!
 
Also laut http://de.wikipedia.org/wiki/Ethernet steht bei FCS geschrieben:

Zitat:

Das FCS-Feld stellt eine 32-Bit-CRC-Prüfsumme dar. Die FCS wird über den eigentlichen Frame berechnet, also beginnend mit der Ziel-MAC-Adresse und endend mit dem PAD-Feld. Die Präambel, der SFD und die FCS selbst sind nicht in der FCS enthalten. Wenn ein Paket beim Sender erstellt wird, wird eine CRC-Berechnung über die Bitfolge durchgeführt und die Prüfsumme an den Datenblock angehängt. Der Empfänger führt nach dem Empfang die gleiche Berechnung aus. Stimmt die empfangene nicht mit der selbst berechneten Prüfsumme überein, geht der Empfänger von einer fehlerhaften Übertragung aus, und der Datenblock wird verworfen.

Zur Berechnung der CRC-32-Prüfsumme werden die ersten 32 Bits der Mac-Adresse invertiert und das Ergebnis ebenfalls invertiert (Vermeidung des Nullproblems).

Die FCS wird, anders als die Datenbits, mit dem höchstwertigen Bit voran übertragen, womit der Empfänger seine CRC-Prüfung auch über das PAD-Feld hinaus auf die FCS anwenden kann. Ist die Prüfsumme nach Verwendung der FCS ungleich Null, war die Übertragung fehlerhaft.
Also sollte dann doch CRC32 sein, oder? Ich meine sehen werde ich es ja spätestend wenn die Frames bei einem Switchdurchlauf verworfen werden :)

Aber zu deinem Code: Werden da die jetzt schon die ersten 4 Bytes der MAC-Adresse und das Ergebniss invertiert? Kann deinem Code leider nur minimal folgen, was wohl an meinen rudimentären Pointerkenntnissen liegt :oops:

himitsu 25. Jan 2009 09:30

Re: CRC32 für einzelne Wörter!
 
Wie gesagt, ob die Berechnung jetzt so ganz richtg ist, weiß ich nicht ...
- ich glaub irgendwo gelesen zu haben, daß irgendwas am Anfang (evtl, SOF?) nicht mit eingerechnet wird
- und dann kommt es ja auch noch auf den Aufbau (deiner Variablen) an ... bin im Beispiel jetzt einfach mal von einzelnen Variablen für die einzelnen Teile der Struktur ausgegangen (und hoff deren Größe richtig gewählt zu haben)
- jupp, die ersten 4 Byte der MACs werden schon invertiert, aber das könnte man auch noch entsprechend deinen Typen-/Variablendefinitionen verbessern/optimieren
- beim .InitT mußt du aufpassen ... ohne die Richtige Hash-Tabelle wird das Ergebnis falsch sein
CRC32Table04 ist eine vorberechnete Tabelle aus dem Polynom $04C11DB7, welches zwar vorwiegend bei AUTODIN II, Ethernet und &FDDI verwendet wird, aber ob das nun in diesem Fall stimmt :?:

Delphi-Quellcode:
Temp := not PLongWord(@DestMAC)^; // 1. 4 Byte in LongInt(=4 Byte) konvertieren und invertieren(not)
CRC.Update(@Temp, 4);            // diese 4 invertierten Byte ins CRC einberechnen
CRC.Update(@DestMAC + 4, 2);     // die letzen 2 Byte einberechnen

FCS := not CRC.asBin; // hier wird das Ergebnis invertiert
wie gesagt, man könnte auch eine Kopie deines Frames(der ganzen Struktur) machen, darin die 2*4 Byte invertieren und dann über alles zusammen den Hash anlegen ... das geht aber nur/besser, wenn alles schon schön in einer Struktur (z.B. als Record) vorliegt

saltjohn2 27. Jan 2009 10:48

Re: CRC32 für einzelne Wörter!
 
Also ich hab mich jetzt nochmal drangesetzt und deinen Vorschlag versucht zu übernehmen. Doch leider kommt bei mir die Meldung
Zitat:

[Pascal Fehler] ConfigTelegramm.pas(190): E2015 Operator ist auf diesen Operandentyp nicht anwendbar
in der Zeile mit
Delphi-Quellcode:
CRC.Update(@DestMAC + 4, 2);
Delphi-Quellcode:
//globale Variablen:
var DestMac,SrcMAC,TypeOrLength,Data: String;

// CRC-Prüfsumme berechnen
Function TForm1.MyCRC32: String;
Var CRC: ThxCRC32;
  Temp, FCS: LongWord;
begin
CRC.InitT(CRC32Table04);
CRC.Init;
Temp := not PLongWord(@DestMAC)^;    // 4 Byte in LongInt(=4 Byte) konvertieren und invertieren(not)
CRC.Update(@Temp, 4);             // diese 4 invertierten Byte ins CRC einberechnen
CRC.Update(@DestMAC + 4, 2);       // die letzen 2 Byte einberechnen HIER TAUCHT DER FEHLER AUF
Temp := not PLongWord(@SrcMAC)^;
CRC.Update(@SrcMAC, 4);
CRC.Update(@SrcMAC + 4, 2);
CRC.Update(@TypeOrLength, 2);
CRC.Update(@Data, 46);
CRC.Final;
FCS := not CRC{.asBin};
// Result := CRC im Hexstring?
Result := FCS.asHexstring;
end;
Das SOF wird in die CRC-Berechnugn nicht einbezogen deshalb hab ich es entfernt.

himitsu 27. Jan 2009 11:08

Re: CRC32 für einzelne Wörter!
 
ja, nicht mit alle Pointern kann man direkt rechnen

z.B.
Delphi-Quellcode:
PAnsiChar(@DestMAC) + 4
// oder
Pointer(Integer(@DestMAC) + 4)
// und bei Strings
@DestMAC[1] + 1
außerdem zeigt @DestMAC (wenn es ein String ist) nicht auf die Daten (die Zeichen im String), sondern den DatenZeiger (sieht man aber nur, wenn man den internen Aufbau eines Strings kennt)


PS: DestMac, SrcMAC und TypeOrLength sind hier bestimmt als Binärwerte einzurechnen
(es ist wohl sehr unwahrscheinlich, daß die Ethernet-Contoler intern mit Strings arbeiten)

Delphi-Quellcode:
Var DestMAC:   Array[0..5] of Byte;
  SrcMAC:      Array[0..5] of Byte;
  //VLANTag:   LongWord;
  TypeOrLength: Word;
  Data:        Array[0..1499] of Byte;
  CRC:         ThxCRC32;
  RecCRC, Temp: LongWord;

Begin
  CRC.InitT(CRC32Table04);
  CRC.Init;
  Temp := not PLongWord(@DestMAC[0])^;
  CRC.Update(@Temp, 4);
  CRC.Update(@DestMAC[4], 2);
  Temp := not PLongWord(@SrcMAC[0])^;
  CRC.Update(@Temp, 4);
  CRC.Update(@SrcMAC[4], 2);
  //CRC.Update(@VLANTag, 4);
  CRC.Update(@TypeOrLength, 2);
  CRC.Update(@Data[0], DataLen);
  CRC.Final;
  RecCRC := not CRC.asBin;
End;
Delphi-Quellcode:
Var Rec, TempRec: packed Record
    DestMAC:     Array[0..5] of Byte;
    SrcMAC:      Array[0..5] of Byte;
    //VLANTag:   LongWord;
    TypeOrLength: Word;
    Data:        Array[0..1499] of Byte;
  End;
  CRC: ThxCRC32;
  RecCRC: LongWord;

Begin
  TempRec := Rec; // irgendwie kopieren
  CRC.InitT(CRC32Table04);
  CRC.Init;
  For i := 0 to 3 do Begin
    TempRec.DestMAC[i] := not TempRec.DestMAC[i];
    TempRec.SrcMAC[i] := not TempRec.SrcMAC[i];
  End;
  CRC.Update(@TempRec, 6+6{+4}+2+DataLen);
  CRC.Final;
  RecCRC := not CRC.asBin;
End;

saltjohn2 27. Jan 2009 12:57

Re: CRC32 für einzelne Wörter!
 
Also ich würde das ja gerne so mit dem record machen allerdings weiß ich nicht genau wie ich meine MAC-Adressen in Hex umwandel und in das Array of Byte speichern soll. Weil das muss ich ja machen, oder?

himitsu 27. Jan 2009 13:33

Re: CRC32 für einzelne Wörter!
 
Das Array of Byte könnte man ja noch ändern.

ind welchem Formt liegen denn deine MAC-Adressen vor?

saltjohn2 27. Jan 2009 13:47

Re: CRC32 für einzelne Wörter!
 
Sie wird im Edit eingegeben also als String. Ich habe eigentlich alles als String vorliegen. Da ich die Daten auch im Edit eingebe bzw. Snoop einen String verlangt ist das für mich so komfortabler.

SaltJohn 28. Jan 2009 15:56

Re: CRC32 für einzelne Wörter!
 
Also mit Wireshark kann man das schön testen. Obwohl ich meine Paket auf 64Byte aufgeblasen habe werden die Rahmen alle als defekt angezeigt, weil eben die CRC-Prüfsume noch nicht korrekt ist.

Edit also ohne den Invertierungskrahm funktioniert das ja ... nur mit eben leider nicht :?


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:29 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz