Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi MD5 Implementation für Delphi 2009 (https://www.delphipraxis.net/121118-md5-implementation-fuer-delphi-2009-a.html)

wth 22. Sep 2008 17:20


MD5 Implementation für Delphi 2009
 
Hi,

Hat bzw. kennt jemand eine funktionierende MD5 Implementation für Delphi 2009.
Alles was ich bisher gefunden habe, funktioniert mit Delphi 2009 nicht mehr, auch nicht, wenn ich im Source alle Strings in AnsiStrings umwandle.

Was muss man bei diesem Code z.B ändern, damit er mit Delphi 2009 funktioniert?

Danke!

gammatester 22. Sep 2008 18:43

Re: MD5 Implementation für Delphi 2009
 
Ich weiß zwar nicht, was für Schweinerein in D2009 eingebaut sind, aber meine CRC/Hash-Routinen laufen bis D2006/7 und Lazarus/FPC2.2.2 sogar unter Linux/ARM (in der PurPascal-Version).

Ich sehe also kein Problem für D2009 bzw. wäre interessiert an Hinweisen, falls es doch welche geben sollte.

Gruß Gammatester

Uwe Raabe 22. Sep 2008 19:44

Re: MD5 Implementation für Delphi 2009
 
Zitat:

Zitat von gammatester
Ich weiß zwar nicht, was für Schweinerein in D2009 eingebaut sind, aber meine CRC/Hash-Routinen laufen bis D2006/7 und Lazarus/FPC2.2.2 sogar unter Linux/ARM (in der PurPascal-Version).

Ich sehe also kein Problem für D2009 bzw. wäre interessiert an Hinweisen, falls es doch welche geben sollte.

Gruß Gammatester

Überprüfe mal alle Stellen, an denen du davon ausgehst, daß Sizeof(char) = 1 ist bzw. daß die Anzahl der Zeichen eines Strings gleich der Speichergröße dieses Strings ist.

Beispiel: MD5.pas - MD5SelfTest - SingleTest

Delphi-Quellcode:
 
  function SingleTest(s: string; TDig: TMD5Digest): boolean;
    {-do a single test, const not allowed for VER<7}
    { Two sub tests: 1. whole string, 2. one update per char}
  var
    i: integer;
  begin
    SingleTest := false;
    {1. Hash complete string}
    MD5Full(Digest, @s[1],length(s));
    {Compare with known value}
    if not HashSameDigest(@MD5_Desc, PHashDigest(@Digest), PHashDigest(@TDig)) then exit;
    {2. one update call for all chars}
    MD5Init(Context);
    for i:=1 to length(s) do MD5Update(Context,@s[i],1);
    MD5Final(Context,Digest);
    {Compare with known value}
    if not HashSameDigest(@MD5_Desc, PHashDigest(@Digest), PHashDigest(@TDig)) then exit;
    SingleTest := true;
  end;
Der Aufruf von MD5Full wird unter D2009 etwas anders ausgehen, als noch unter D2007. Eine Lösung, die in beiden Fällen läuft wäre

Delphi-Quellcode:
MD5Full(Digest, @s[1], length(s)*sizeof(Char));
Allerdings glaube ich kaum, daß die Hashwerte eines AnsiStrings mit denen eines UnicodeStrings übereinstimmen, welbst wenn sie die gleiche Zeichenfolge enthalten.

gammatester 22. Sep 2008 20:03

Re: MD5 Implementation für Delphi 2009
 
Zitat:

Zitat von Uwe Raabe
Überprüfe mal alle Stellen, an denen du davon ausgehst, daß Sizeof(char) = 1 ist bzw. daß die Anzahl der Zeichen eines Strings gleich der Speichergröße dieses Strings ist.

Beispiel: MD5.pas - MD5SelfTest - SingleTest

Hallo Uwe,

vielen Dank für die Hinweise. Ich hatte mich zwar bemüht, möglichst keine 'nackten' strings zu benutzen, aber bei den Selbstests sind also noch welche.

Ich denke, ich werde bei den nächsten Updates dort statt string zB einen Typ str128 = string[128] benutzen, oder geht die Quälerei soweit daß ein Zeichen eines str128 mehr als ein Byte haben kann?

Gruß Gammatester

wth 22. Sep 2008 20:10

Re: MD5 Implementation für Delphi 2009
 
OK, Danke, ich denke mal, dass ich es damit hinbekomme, ansonsten melde ich mich hier wieder. :chat:

Uwe Raabe 22. Sep 2008 20:12

Re: MD5 Implementation für Delphi 2009
 
Zitat:

Zitat von gammatester
Ich denke, ich werde bei den nächsten Updates dort statt string zB einen Typ str128 = string[128] benutzen, oder geht die Quälerei soweit daß ein Zeichen eines str128 mehr als ein Byte haben kann?

Nein, ShortStrings sind so geblieben. Damit brauchst du auch die Testergebnisse nicht neu ermitteln...

hitzi 20. Okt 2008 13:08

Re: MD5 Implementation für Delphi 2009
 
Hallo,

ich reihe mich mal hier mit ein.
Unter Delphi 2009 und den Units von Gammatester bekomme ich nicht den richtigen CRC.

Hier ist mein Beispielprogramm:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, md5, hash, mem_util;

type
  TForm1 = class(TForm)
    edt1: TEdit;
    btn1: TButton;
    edt2: TEdit;
    procedure btn1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function HexString(const x: array of byte): string;
  {-HEX string from memory}
begin
  Result := HexStr(@x, sizeof(x));
end;

procedure TForm1.btn1Click(Sender: TObject);
var MD5Context  : TMD5Digest;
begin
  MD5Full(MD5Context, @edt1.Text[1], length(edt1.Text) * SizeOf(Char));
  edt2.Text := HexString(MD5Context);
end;

end.
Beispieltext ist
Zitat:

Thomas
Vergleichsresultat von http://www.hashgenerator.de/: ef6e65efc188e7dffd7335b646a85a21
Das falsche Resultat von meinem Testprogramm: e7153adbc66d908704b472c4d58e96d3

Liegt garantiert an der Unicode Geschichte. Wie kann ich nun unter Delphi 2009 einen MD5 Hash aus einem String errechnen lassen?

Viele Grüße

Gerome 20. Okt 2008 13:25

Re: MD5 Implementation für Delphi 2009
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von hitzi
Liegt garantiert an der Unicode Geschichte. Wie kann ich nun unter Delphi 2009 einen MD5 Hash aus einem String errechnen lassen?

Sagt mal ... wie arbeitet denn MD5? Wenn - falls - ich richtig liege, dann betrachtet doch MD5 die Daten als Byte-Strom. Dass diese Bytes u.U. von uns zusammenhängend als MD5 betrachtet werden, ist doch dem MD5 egal, oder? Anbei ein Screenshot mit Speicherauszug. Da ist zu sehen, dass der String "Thomas" bei den neuen Unicode-Strings (wenig überraschend) breiter im Speicher liegt als mit den Ansi-Strings. Aus diesem Grund denke ich, dass ein Vergleich mit einem MD5-Rechner auf einer Webseite insofern nicht gültig ist, da man der Webseite - zumindest der im gegebenen Beispiel - wirklich nur die Bytes übergibt, die den String "Thomas" ausmachen.

hitzi 20. Okt 2008 13:34

Re: MD5 Implementation für Delphi 2009
 
Hmmm ... also kann ich dann davon ausgehen, dass zum Beispiel die bei PHP vorhanden md5() Funktion nur auf Basis von Ansistrings arbeitet, da ja dort auch nur der angezeigte Text durch diese Funktion gejagt wird?

Wenn's nur mit Ansistrings funktioniert dann funktioniert die MD5 Funktion von hier(http://forum.vingrad.ru/forum/topic-230076.html):
Delphi-Quellcode:
function md5(s : AnsiString) : AnsiString;
var a : array[0..15] of byte;
    i : integer;
    LenHi, LenLo : longword;
    Index : DWord;
    HashBuffer : array[0..63] of byte;
    CurrentHash : array[0..3] of DWord;

  procedure Burn;
  begin
    LenHi := 0;
    LenLo := 0;
    Index := 0;
    FillChar(HashBuffer, Sizeof(HashBuffer), 0);
    FillChar(CurrentHash, Sizeof(CurrentHash), 0);
  end;

  procedure Init;
  begin
    Burn;
    CurrentHash[0] := $67452301;
    CurrentHash[1] := $efcdab89;
    CurrentHash[2] := $98badcfe;
    CurrentHash[3] := $10325476;
  end;

  function LRot32(a, b : longword) : longword;
  begin
    Result:= (a shl b) or (a shr (32 - b));
  end;

  procedure Compress;
  var Data : array[0..15] of dword;
      A, B, C, D : dword;
  begin
    Move(HashBuffer, Data, Sizeof(Data));
    A := CurrentHash[0];
    B := CurrentHash[1];
    C := CurrentHash[2];
    D := CurrentHash[3];
    A := B + LRot32(A + (D xor (B and (C xor D))) + Data[ 0] + $d76aa478,7);
    D := A + LRot32(D + (C xor (A and (B xor C))) + Data[ 1] + $e8c7b756,12);
    C := D + LRot32(C + (B xor (D and (A xor B))) + Data[ 2] + $242070db,17);
    B := C + LRot32(B + (A xor (C and (D xor A))) + Data[ 3] + $c1bdceee,22);
    A := B + LRot32(A + (D xor (B and (C xor D))) + Data[ 4] + $f57c0faf,7);
    D := A + LRot32(D + (C xor (A and (B xor C))) + Data[ 5] + $4787c62a,12);
    C := D + LRot32(C + (B xor (D and (A xor B))) + Data[ 6] + $a8304613,17);
    B := C + LRot32(B + (A xor (C and (D xor A))) + Data[ 7] + $fd469501,22);
    A := B + LRot32(A + (D xor (B and (C xor D))) + Data[ 8] + $698098d8,7);
    D := A + LRot32(D + (C xor (A and (B xor C))) + Data[ 9] + $8b44f7af,12);
    C := D + LRot32(C + (B xor (D and (A xor B))) + Data[10] + $ffff5bb1,17);
    B := C + LRot32(B + (A xor (C and (D xor A))) + Data[11] + $895cd7be,22);
    A := B + LRot32(A + (D xor (B and (C xor D))) + Data[12] + $6b901122,7);
    D := A + LRot32(D + (C xor (A and (B xor C))) + Data[13] + $fd987193,12);
    C := D + LRot32(C + (B xor (D and (A xor B))) + Data[14] + $a679438e,17);
    B := C + LRot32(B + (A xor (C and (D xor A))) + Data[15] + $49b40821,22);
    A := B + LRot32(A + (C xor (D and (B xor C))) + Data[ 1] + $f61e2562,5);
    D := A + LRot32(D + (B xor (C and (A xor B))) + Data[ 6] + $c040b340,9);
    C := D + LRot32(C + (A xor (B and (D xor A))) + Data[11] + $265e5a51,14);
    B := C + LRot32(B + (D xor (A and (C xor D))) + Data[ 0] + $e9b6c7aa,20);
    A := B + LRot32(A + (C xor (D and (B xor C))) + Data[ 5] + $d62f105d,5);
    D := A + LRot32(D + (B xor (C and (A xor B))) + Data[10] + $02441453,9);
    C := D + LRot32(C + (A xor (B and (D xor A))) + Data[15] + $d8a1e681,14);
    B := C + LRot32(B + (D xor (A and (C xor D))) + Data[ 4] + $e7d3fbc8,20);
    A := B + LRot32(A + (C xor (D and (B xor C))) + Data[ 9] + $21e1cde6,5);
    D := A + LRot32(D + (B xor (C and (A xor B))) + Data[14] + $c33707d6,9);
    C := D + LRot32(C + (A xor (B and (D xor A))) + Data[ 3] + $f4d50d87,14);
    B := C + LRot32(B + (D xor (A and (C xor D))) + Data[ 8] + $455a14ed,20);
    A := B + LRot32(A + (C xor (D and (B xor C))) + Data[13] + $a9e3e905,5);
    D := A + LRot32(D + (B xor (C and (A xor B))) + Data[ 2] + $fcefa3f8,9);
    C := D + LRot32(C + (A xor (B and (D xor A))) + Data[ 7] + $676f02d9,14);
    B := C + LRot32(B + (D xor (A and (C xor D))) + Data[12] + $8d2a4c8a,20);
    A := B + LRot32(A + (B xor C xor D) + Data[ 5] + $fffa3942,4);
    D := A + LRot32(D + (A xor B xor C) + Data[ 8] + $8771f681,11);
    C := D + LRot32(C + (D xor A xor B) + Data[11] + $6d9d6122,16);
    B := C + LRot32(B + (C xor D xor A) + Data[14] + $fde5380c,23);
    A := B + LRot32(A + (B xor C xor D) + Data[ 1] + $a4beea44,4);
    D := A + LRot32(D + (A xor B xor C) + Data[ 4] + $4bdecfa9,11);
    C := D + LRot32(C + (D xor A xor B) + Data[ 7] + $f6bb4b60,16);
    B := C + LRot32(B + (C xor D xor A) + Data[10] + $bebfbc70,23);
    A := B + LRot32(A + (B xor C xor D) + Data[13] + $289b7ec6,4);
    D := A + LRot32(D + (A xor B xor C) + Data[ 0] + $eaa127fa,11);
    C := D + LRot32(C + (D xor A xor B) + Data[ 3] + $d4ef3085,16);
    B := C + LRot32(B + (C xor D xor A) + Data[ 6] + $04881d05,23);
    A := B + LRot32(A + (B xor C xor D) + Data[ 9] + $d9d4d039,4);
    D := A + LRot32(D + (A xor B xor C) + Data[12] + $e6db99e5,11);
    C := D + LRot32(C + (D xor A xor B) + Data[15] + $1fa27cf8,16);
    B := C + LRot32(B + (C xor D xor A) + Data[ 2] + $c4ac5665,23);
    A := B + LRot32(A + (C xor (B or (not D))) + Data[ 0] + $f4292244,6);
    D := A + LRot32(D + (B xor (A or (not C))) + Data[ 7] + $432aff97,10);
    C := D + LRot32(C + (A xor (D or (not B))) + Data[14] + $ab9423a7,15);
    B := C + LRot32(B + (D xor (C or (not A))) + Data[ 5] + $fc93a039,21);
    A := B + LRot32(A + (C xor (B or (not D))) + Data[12] + $655b59c3,6);
    D := A + LRot32(D + (B xor (A or (not C))) + Data[ 3] + $8f0ccc92,10);
    C := D + LRot32(C + (A xor (D or (not B))) + Data[10] + $ffeff47d,15);
    B := C + LRot32(B + (D xor (C or (not A))) + Data[ 1] + $85845dd1,21);
    A := B + LRot32(A + (C xor (B or (not D))) + Data[ 8] + $6fa87e4f,6);
    D := A + LRot32(D + (B xor (A or (not C))) + Data[15] + $fe2ce6e0,10);
    C := D + LRot32(C + (A xor (D or (not B))) + Data[ 6] + $a3014314,15);
    B := C + LRot32(B + (D xor (C or (not A))) + Data[13] + $4e0811a1,21);
    A := B + LRot32(A + (C xor (B or (not D))) + Data[ 4] + $f7537e82,6);
    D := A + LRot32(D + (B xor (A or (not C))) + Data[11] + $bd3af235,10);
    C := D + LRot32(C + (A xor (D or (not B))) + Data[ 2] + $2ad7d2bb,15);
    B := C + LRot32(B + (D xor (C or (not A))) + Data[ 9] + $eb86d391,21);
    Inc(CurrentHash[0], A);
    Inc(CurrentHash[1], B);
    Inc(CurrentHash[2], C);
    Inc(CurrentHash[3], D);
    Index := 0;
    FillChar(HashBuffer, Sizeof(HashBuffer), 0);
  end;

  procedure Update(const Buffer; Size : longword);
  var PBuf : ^byte;
  begin
    Inc(LenHi, Size shr 29);
    Inc(LenLo, Size*8);
    if LenLo < (Size*8) then Inc(LenHi);
    PBuf := @Buffer;
    while Size > 0 do begin
      if (Sizeof(HashBuffer) - Index) <= DWord(Size) then begin
        Move(PBuf^, HashBuffer[Index], Sizeof(HashBuffer) - Index);
        Dec(Size, Sizeof(HashBuffer) - Index);
        Inc(PBuf, Sizeof(HashBuffer) - Index);
        Compress;
      end else begin
        Move(PBuf^, HashBuffer[Index], Size);
        Inc(Index, Size);
        Size := 0;
      end;
    end;
  end;

  procedure Final(var Digest);
  begin
    HashBuffer[Index] := $80;
    if Index >= 56 then Compress;
    PDWord(@HashBuffer[56])^ := LenLo;
    PDWord(@HashBuffer[60])^ := LenHi;
    Compress;
    Move(CurrentHash, Digest, Sizeof(CurrentHash));
    Burn;
  end;

begin
  Init;
  Update(s[1], Length(s));
  Final(a);
  Result := '';
  for i := 0 to 15 do Result := Result + AnsiLowerCase(IntToHex(a[i], 2));
  Burn;
end;

Daniel 20. Okt 2008 13:48

Re: MD5 Implementation für Delphi 2009
 
Zitat:

Zitat von hitzi
Hmmm ... also kann ich dann davon ausgehen, dass zum Beispiel die bei PHP vorhanden md5() Funktion nur auf Basis von Ansistrings arbeitet, da ja dort auch nur der angezeigte Text durch diese Funktion gejagt wird?

Nicht zwingend. Man kann gesamte Webseiten auch auf Unicode umstellen und dann ist diese Codierung auch in den Datenströmen "POST" und "GET" enthalten. Ich habe eben nachgesehen: MD5 interessiert sich tatsächlich nur für Byte-Sequenzen. Und die sind eben bei Unicode- und Ansi-Strings unterschiedlich.


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:41 Uhr.
Seite 1 von 2  1 2      

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