Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - MD5 Funktion erzeugt fehlerhaften Hash


McFarlane - Mo 20.10.08 17:08
Titel: MD5 Funktion erzeugt fehlerhaften Hash
Hi,
ich versuch hier schon seit Stunden mein Porgramm einen String in einen MD5 Hash umwandeln zu lassen.
Hab schon einiges durchsucht und diese Unit dabei im Forum gefunden:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291:
292:
293:
294:
295:
296:
297:
298:
299:
300:
301:
302:
303:
304:
305:
306:
307:
308:
309:
310:
311:
312:
313:
314:
315:
316:
317:
318:
319:
320:
321:
322:
323:
324:
325:
326:
327:
328:
329:
330:
331:
332:
333:
334:
335:
336:
337:
338:
339:
340:
341:
342:
343:
344:
345:
346:
347:
348:
349:
350:
351:
352:
353:
354:
355:
356:
357:
358:
359:
360:
361:
362:
363:
364:
365:
366:
367:
368:
369:
370:
371:
372:
373:
374:
375:
376:
377:
378:
379:
380:
381:
382:
383:
384:
// tabs = 2
// -----------------------------------------------------------------------------------------------
//
//                                 MD5 Message-Digest for Delphi 4
//
//                                 Delphi 4 Unit implementing the
//                      RSA Data Security, Inc. MD5 Message-Digest Algorithm
//
//                          Implementation of Ronald L. Rivest's RFC 1321
//
//                      Copyright © 1997-1999 Medienagentur Fichtner & Meyer
//                                  Written by Matthias Fichtner
//
// -----------------------------------------------------------------------------------------------
//               See RFC 1321 for RSA Data Security's copyright and license notice!
// -----------------------------------------------------------------------------------------------
//
//     14-Jun-97  mf  Implemented MD5 according to RFC 1321                           RFC 1321
//     16-Jun-97  mf  Initial release of the compiled unit (no source code)           RFC 1321
//     28-Feb-99  mf  Added MD5Match function for comparing two digests               RFC 1321
//     13-Sep-99  mf  Reworked the entire unit                                        RFC 1321
//     17-Sep-99  mf  Reworked the "Test Driver" project                              RFC 1321
//     19-Sep-99  mf  Release of sources for MD5 unit and "Test Driver" project       RFC 1321
//
// -----------------------------------------------------------------------------------------------
//                   The latest release of md5.pas will always be available from
//                  the distribution site at: http://www.fichtner.net/delphi/md5/
// -----------------------------------------------------------------------------------------------
//                       Please send questions, bug reports and suggestions
//                      regarding this code to: mfichtner@fichtner-meyer.com
// -----------------------------------------------------------------------------------------------
//                        This code is provided "as is" without express or
//                     implied warranty of any kind. Use it at your own risk.
// -----------------------------------------------------------------------------------------------
unit md5;

// -----------------------------------------------------------------------------------------------
INTERFACE
// -----------------------------------------------------------------------------------------------
uses
  Windows;

type
  MD5Count = array[0..1of DWORD;
  MD5State = array[0..3of DWORD;
  MD5Block = array[0..15of DWORD;
  MD5CBits = array[0..7of byte;
  MD5Digest = array[0..15of byte;
  MD5Buffer = array[0..63of byte;
  MD5Context = record
    State: MD5State;
    Count: MD5Count;
    Buffer: MD5Buffer;
  end;

procedure MD5Init(var Context: MD5Context);
procedure MD5Update(var Context: MD5Context; Input: pChar; Length: longword);
procedure MD5Final(var Context: MD5Context; var Digest: MD5Digest);

function MD5String(M: string): MD5Digest;
function MD5File(N: string): MD5Digest;
function MD5Print(D: MD5Digest): string;

function MD5Match(D1, D2: MD5Digest): boolean;

// -----------------------------------------------------------------------------------------------
IMPLEMENTATION
// -----------------------------------------------------------------------------------------------
var
  PADDING: MD5Buffer = (
    $80$00$00$00$00$00$00$00,
    $00$00$00$00$00$00$00$00,
    $00$00$00$00$00$00$00$00,
    $00$00$00$00$00$00$00$00,
    $00$00$00$00$00$00$00$00,
    $00$00$00$00$00$00$00$00,
    $00$00$00$00$00$00$00$00,
    $00$00$00$00$00$00$00$00
  );

function F(x, y, z: DWORD): DWORD;
begin
  Result := (x and y) or ((not x) and z);
end;

function G(x, y, z: DWORD): DWORD;
begin
  Result := (x and z) or (y and (not z));
end;

function H(x, y, z: DWORD): DWORD;
begin
  Result := x xor y xor z;
end;

function I(x, y, z: DWORD): DWORD;
begin
  Result := y xor (x or (not z));
end;

procedure rot(var x: DWORD; n: BYTE);
begin
  x := (x shl n) or (x shr (32 - n));
end;

procedure FF(var a: DWORD; b, c, d, x: DWORD; s: BYTE; ac: DWORD);
begin
  inc(a, F(b, c, d) + x + ac);
  rot(a, s);
  inc(a, b);
end;

procedure GG(var a: DWORD; b, c, d, x: DWORD; s: BYTE; ac: DWORD);
begin
  inc(a, G(b, c, d) + x + ac);
  rot(a, s);
  inc(a, b);
end;

procedure HH(var a: DWORD; b, c, d, x: DWORD; s: BYTE; ac: DWORD);
begin
  inc(a, H(b, c, d) + x + ac);
  rot(a, s);
  inc(a, b);
end;

procedure II(var a: DWORD; b, c, d, x: DWORD; s: BYTE; ac: DWORD);
begin
  inc(a, I(b, c, d) + x + ac);
  rot(a, s);
  inc(a, b);
end;

// -----------------------------------------------------------------------------------------------
// Encode Count bytes at Source into (Count / 4) DWORDs at Target
procedure Encode(Source, Target: pointer; Count: longword);
var
  S: PByte;
  T: PDWORD;
  I: longword;
begin
  S := Source;
  T := Target;
  for I := 1 to Count div 4 do begin
    T^ := S^;
    inc(S);
    T^ := T^ or (S^ shl 8);
    inc(S);
    T^ := T^ or (S^ shl 16);
    inc(S);
    T^ := T^ or (S^ shl 24);
    inc(S);
    inc(T);
  end;
end;

// Decode Count DWORDs at Source into (Count * 4) Bytes at Target
procedure Decode(Source, Target: pointer; Count: longword);
var
  S: PDWORD;
  T: PByte;
  I: longword;
begin
  S := Source;
  T := Target;
  for I := 1 to Count do begin
    T^ := S^ and $ff;
    inc(T);
    T^ := (S^ shr 8and $ff;
    inc(T);
    T^ := (S^ shr 16and $ff;
    inc(T);
    T^ := (S^ shr 24and $ff;
    inc(T);
    inc(S);
  end;
end;

// Transform State according to first 64 bytes at Buffer
procedure Transform(Buffer: pointer; var State: MD5State);
var
  a, b, c, d: DWORD;
  Block: MD5Block;
begin
  Encode(Buffer, @Block, 64);
  a := State[0];
  b := State[1];
  c := State[2];
  d := State[3];
  FF (a, b, c, d, Block[ 0],  7$d76aa478);
  FF (d, a, b, c, Block[ 1], 12$e8c7b756);
  FF (c, d, a, b, Block[ 2], 17$242070db);
  FF (b, c, d, a, Block[ 3], 22$c1bdceee);
  FF (a, b, c, d, Block[ 4],  7$f57c0faf);
  FF (d, a, b, c, Block[ 5], 12$4787c62a);
  FF (c, d, a, b, Block[ 6], 17$a8304613);
  FF (b, c, d, a, Block[ 7], 22$fd469501);
  FF (a, b, c, d, Block[ 8],  7$698098d8);
  FF (d, a, b, c, Block[ 9], 12$8b44f7af);
  FF (c, d, a, b, Block[10], 17$ffff5bb1);
  FF (b, c, d, a, Block[11], 22$895cd7be);
  FF (a, b, c, d, Block[12],  7$6b901122);
  FF (d, a, b, c, Block[13], 12$fd987193);
  FF (c, d, a, b, Block[14], 17$a679438e);
  FF (b, c, d, a, Block[15], 22$49b40821);
  GG (a, b, c, d, Block[ 1],  5$f61e2562);
  GG (d, a, b, c, Block[ 6],  9$c040b340);
  GG (c, d, a, b, Block[11], 14$265e5a51);
  GG (b, c, d, a, Block[ 0], 20$e9b6c7aa);
  GG (a, b, c, d, Block[ 5],  5$d62f105d);
  GG (d, a, b, c, Block[10],  9,  $2441453);
  GG (c, d, a, b, Block[15], 14$d8a1e681);
  GG (b, c, d, a, Block[ 4], 20$e7d3fbc8);
  GG (a, b, c, d, Block[ 9],  5$21e1cde6);
  GG (d, a, b, c, Block[14],  9$c33707d6);
  GG (c, d, a, b, Block[ 3], 14$f4d50d87);
  GG (b, c, d, a, Block[ 8], 20$455a14ed);
  GG (a, b, c, d, Block[13],  5$a9e3e905);
  GG (d, a, b, c, Block[ 2],  9$fcefa3f8);
  GG (c, d, a, b, Block[ 7], 14$676f02d9);
  GG (b, c, d, a, Block[12], 20$8d2a4c8a);
  HH (a, b, c, d, Block[ 5],  4$fffa3942);
  HH (d, a, b, c, Block[ 8], 11$8771f681);
  HH (c, d, a, b, Block[11], 16$6d9d6122);
  HH (b, c, d, a, Block[14], 23$fde5380c);
  HH (a, b, c, d, Block[ 1],  4$a4beea44);
  HH (d, a, b, c, Block[ 4], 11$4bdecfa9);
  HH (c, d, a, b, Block[ 7], 16$f6bb4b60);
  HH (b, c, d, a, Block[10], 23$bebfbc70);
  HH (a, b, c, d, Block[13],  4$289b7ec6);
  HH (d, a, b, c, Block[ 0], 11$eaa127fa);
  HH (c, d, a, b, Block[ 3], 16$d4ef3085);
  HH (b, c, d, a, Block[ 6], 23,  $4881d05);
  HH (a, b, c, d, Block[ 9],  4$d9d4d039);
  HH (d, a, b, c, Block[12], 11$e6db99e5);
  HH (c, d, a, b, Block[15], 16$1fa27cf8);
  HH (b, c, d, a, Block[ 2], 23$c4ac5665);
  II (a, b, c, d, Block[ 0],  6$f4292244);
  II (d, a, b, c, Block[ 7], 10$432aff97);
  II (c, d, a, b, Block[14], 15$ab9423a7);
  II (b, c, d, a, Block[ 5], 21$fc93a039);
  II (a, b, c, d, Block[12],  6$655b59c3);
  II (d, a, b, c, Block[ 3], 10$8f0ccc92);
  II (c, d, a, b, Block[10], 15$ffeff47d);
  II (b, c, d, a, Block[ 1], 21$85845dd1);
  II (a, b, c, d, Block[ 8],  6$6fa87e4f);
  II (d, a, b, c, Block[15], 10$fe2ce6e0);
  II (c, d, a, b, Block[ 6], 15$a3014314);
  II (b, c, d, a, Block[13], 21$4e0811a1);
  II (a, b, c, d, Block[ 4],  6$f7537e82);
  II (d, a, b, c, Block[11], 10$bd3af235);
  II (c, d, a, b, Block[ 2], 15$2ad7d2bb);
  II (b, c, d, a, Block[ 9], 21$eb86d391);
  inc(State[0], a);
  inc(State[1], b);
  inc(State[2], c);
  inc(State[3], d);
end;

// -----------------------------------------------------------------------------------------------
// Initialize given Context
procedure MD5Init(var Context: MD5Context);
begin
  with Context do begin
    State[0] := $67452301;
    State[1] := $efcdab89;
    State[2] := $98badcfe;
    State[3] := $10325476;
    Count[0] := 0;
    Count[1] := 0;
    ZeroMemory(@Buffer, SizeOf(MD5Buffer));
  end;
end;

// Update given Context to include Length bytes of Input
procedure MD5Update(var Context: MD5Context; Input: pChar; Length: longword);
var
  Index: longword;
  PartLen: longword;
  I: longword;
begin
  with Context do begin
    Index := (Count[0shr 3and $3f;
    inc(Count[0], Length shl 3);
    if Count[0] < (Length shl 3then inc(Count[1]);
    inc(Count[1], Length shr 29);
  end;
  PartLen := 64 - Index;
  if Length >= PartLen then begin
    CopyMemory(@Context.Buffer[Index], Input, PartLen);
    Transform(@Context.Buffer, Context.State);
    I := PartLen;
    while I + 63 < Length do begin
      Transform(@Input[I], Context.State);
      inc(I, 64);
    end;
    Index := 0;
  end else I := 0;
  CopyMemory(@Context.Buffer[Index], @Input[I], Length - I);
end;

// Finalize given Context, create Digest and zeroize Context
procedure MD5Final(var Context: MD5Context; var Digest: MD5Digest);
var
  Bits: MD5CBits;
  Index: longword;
  PadLen: longword;
begin
  Decode(@Context.Count, @Bits, 2);
  Index := (Context.Count[0shr 3and $3f;
  if Index < 56 then PadLen := 56 - Index else PadLen := 120 - Index;
  MD5Update(Context, @PADDING, PadLen);
  MD5Update(Context, @Bits, 8);
  Decode(@Context.State, @Digest, 4);
  ZeroMemory(@Context, SizeOf(MD5Context));
end;

// -----------------------------------------------------------------------------------------------
// Create digest of given Message
function MD5String(M: string): MD5Digest;
var
  Context: MD5Context;
begin
  MD5Init(Context);
  MD5Update(Context, pChar(M), length(M));
  MD5Final(Context, Result);
end;

// Create digest of file with given Name
function MD5File(N: string): MD5Digest;
var
  FileHandle: THandle;
  MapHandle: THandle;
  ViewPointer: pointer;
  Context: MD5Context;
begin
  MD5Init(Context);
  FileHandle := CreateFile(pChar(N), GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE,
    nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_SEQUENTIAL_SCAN, 0);
  if FileHandle <> INVALID_HANDLE_VALUE then try
    MapHandle := CreateFileMapping(FileHandle, nil, PAGE_READONLY, 00nil);
    if MapHandle <> 0 then try
      ViewPointer := MapViewOfFile(MapHandle, FILE_MAP_READ, 000);
      if ViewPointer <> nil then try
        MD5Update(Context, ViewPointer, GetFileSize(FileHandle, nil));
      finally
        UnmapViewOfFile(ViewPointer);
      end;
    finally
      CloseHandle(MapHandle);
    end;
  finally
    CloseHandle(FileHandle);
  end;
  MD5Final(Context, Result);
end;

// Create hex representation of given Digest
function MD5Print(D: MD5Digest): string;
var
  I: byte;
const
  Digits: array[0..15of char =
    ('0''1''2''3''4''5''6''7''8''9''a''b''c''d''e''f');
begin
  Result := '';
  for I := 0 to 15 do Result := Result + Digits[(D[I] shr 4and $0f] + Digits[D[I] and $0f];
end;

// -----------------------------------------------------------------------------------------------
// Compare two Digests
function MD5Match(D1, D2: MD5Digest): boolean;
var
  I: byte;
begin
  I := 0;
  Result := TRUE;
  while Result and (I < 16do begin
    Result := D1[I] = D2[I];
    inc(I);
  end;
end;

end.


Benutzten tu ich sie dann so:


Delphi-Quelltext
1:
passwd := MD5Print(MD5String(passwd));                    


Nur leider bringt die mir jetzt zwar einen 32 stelligen Hash, aber der ist nicht über MD5 gebildet wurden, da er sich von den MySQL und PHP Hashes unterscheidet. Und das ist doof...

Hat jemand von euch da eine Funktion die funktioniert?

Danke, McFarlane


Gausi - Mo 20.10.08 17:18

Sind die wirklich unterschiedlich, oder unterscheiden die sich nur in Groß-/Kleinschreibung der Ziffern A-F?


matze - Mo 20.10.08 18:05

also ich nutze auch diese Unit und bei mir passen PHP- und Delphi-Hashes immer zusammen.
Schau mal, ob dein Input-String auch wirklich immer gleich ist. Stichwort Trim, Lowercase, Unicode,,,


MagicRain - Mo 20.10.08 18:21

Hey, Heck auch mal ob die "Magic-Bytes" die selben sind, oder um sie vielleicht verschieden sind.


Delphi-Quelltext
1:
2:
3:
4:
    State[0] := $67452301;
    State[1] := $efcdab89;
    State[2] := $98badcfe;
    State[3] := $10325476;


McFarlane - Mo 20.10.08 19:14

hoppla, da hatte sich irgendwie ein Leerzeichen eingeschlichen... trim() hat geholfen.
Danke, McFarlane


TheNeon - Di 11.11.08 13:31

Hallo zusammen,

also ich habe auch dieses Problem. Ich habe mir diese MD5.pas runtergeladen, eingebaut, doch gibt mir diese Funktion MD5String() wohl immer einen falschen Wert zurück. Ich habe zum Testen den String 'TEST' eingegeben und verglichen, was PHP und andere Programme so auswerfen, doch mein Programm spuckt dann immer etwas anderes aus. Lediglich der Hashwert eines leeren Strings entspricht den Vorgaben nach MD5.

Mit Trim() habe ich es versucht, aber das brachte nichts Hat jemand einen wertvollen Hinweis für mich?


matze - Di 11.11.08 14:14


Delphi-Quelltext
1:
lowercase()                    


TheNeon - Di 11.11.08 14:26

Also ich hab das jetzt so:


Delphi-Quelltext
1:
Edit2.Text := MD5Print(MD5String( Trim(LowerCase(Edit1.Text)) ));                    


folgende Ergebnisse:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
(Leerstring)
    Programm:  d41d8cd98f00b204e9800998ecf8427e
    PHP:       d41d8cd98f00b204e9800998ecf8427e

a
    Programm:  0cc175b9c0f1b6a831c399e269772661
    PHP:       0cc175b9c0f1b6a831c399e269772661

aa
    Programm:  4144e195f46de78a3623da7364d04f11    FALSCH
    PHP:       4124bc0a9335c27f086f24ba207a4912


Mit einem leerstring funktioniert es, ebenso wenn der String die Länge 1 hat, bin mehrere Buchstaben durchgegangen. Doch sobald ich zwei Buchstaben nehme klappt es nicht mehr.

Könnte es irgendwas damit zu tun haben, dass ich mit Delphi2009 arbeite und diese MD5.pas für ältere versionen von Delphi geschrieben worden ist?


Diamond - Di 11.11.08 14:34

hi

Ich hab die Unit selbst des öfteren gebraucht. Anfangs habe ich den MD5 auch, genau wie du direkt an ein Editfeld übergeben. Genau wie bei dir wurde bei mir ein flascher Hash zurückgeliefert. Zufällig hab ich bemerkt, dass das Problem nicht mehr auftritt, wenn ich den Hash erst einem String zugewiesen habe und erst dann dem Editfeld den String zugewiesen hab.
Klingt komisch, ist aber so :mrgreen:

Kann jetzt leider nicht mehr selbst testen, da ich die Unit nicht hier auf dem PC hab.
Aber ich denk nen Versuch wärs auf jeden Fall wert. :wink:


TheNeon - Di 11.11.08 14:58

Also wäre schön gewesen, aber leider macht das Zwischenspeichern in einen String keinen Unterschied.


Gammatester - Di 11.11.08 18:03

Wenn Du D2009 benutzt, wird's wohl daran liegen, daß Unicodestrings jetzt default sind. Eventuell geht es über den Umweg ansistring. Da die Bytedarstellung der neuen Defaultstrings anders ist als bisher, ist es klar, daß der Hashwert auch anders ist.

Gammatester


TheNeon - Di 11.11.08 19:03

Ah, ein Wegweiser :)

Jetzt muss ich nur mal schauen, ob ich verstehe was du meinst :roll:
Melde mich wieder wenn ich rumprobiert habe.


EDIT:
Nur wieso klappt es dann bei einem 'a' und nicht bei 'aa' ??


Gammatester - Di 11.11.08 19:29

Klappts mit ansistring 'aa' nicht oder mit string 'aa'? Ohne Unicode-Delphi vermute ich, die Bytedarstellung von 'a' ist (ohne Längeninfo)

'a' -> $61 $00 und 'aa' -> $61 $00 $61 $00

Dann wird vielleicht nach dem ersten $00 = byte(0) die Rechnung beendet. Gibt es denn für 'aa' den gleichen Hashwert wie für 'aa'?

Gammatester


TheNeon - Di 11.11.08 19:44

user defined image

Also das war deutlich genug. Ich habe in der MD5.pas nun bei den Funktionen die Parameter von String zu AnsiString umbenannt (nichts weiter) und siehe da, es funktioniert!

user defined image



Jetzt muss ich nur noch in Erfahrung bringen was der Unterschied ist, das inetressiert mich jetzt!


TheNeon - Di 11.11.08 20:06

Falls noch jemand sich diese Frage stellen sollte:
http://www.delphi-treff.de/sprachen/object-pascal/string-typen/


TheNeon - Fr 14.11.08 15:49

An sich funktioniert das ganze, doch gibt es wohl Probleme mit sehr großen Dateien. Ab einer Größe von circa(!!) 2GB liefert die Berechnung den Hashwert eines Leerstrings - in der gleichen Zeit sogar, sprich 0,5sec. Gibt es da eine Möglichkeit auch größere Dateien zuzulassen?


Xentar - Fr 14.11.08 16:28

Ohne mir jetzt den Source genauer angesehen zu haben, aber 2GB klingt nach ner Integer-Begrenzung.
Heißt also: schreib alles, was mit der Datenlänge zu tun hat, auf Cardinal (4GB) oder direkt Int64 um, vielleicht geht das dann.


TheNeon - Fr 14.11.08 16:44

Also bislang sehe ich im Code überall nur DWord, Cardinal und Longword und das sollten ja bereits 32bit-Typen sein, oder?


TheNeon - Fr 14.11.08 16:54


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
// Create digest of file with given Name 
function MD5File(N: string): MD5Digest; 
var 
  FileHandle: THandle; 
  MapHandle: THandle; 
  ViewPointer: pointer; 
  Context: MD5Context; 
begin 
  MD5Init(Context); 
  FileHandle := CreateFile(pChar(N), GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE, 
    nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_SEQUENTIAL_SCAN, 0); 
  if FileHandle <> INVALID_HANDLE_VALUE then try 
    MapHandle := CreateFileMapping(FileHandle, nil, PAGE_READONLY, 00nil); 
    if MapHandle <> 0 then try 
      ViewPointer := MapViewOfFile(MapHandle, FILE_MAP_READ, 000); // HIER PROBLEM
      if ViewPointer <> nil then try 
        MD5Update(Context, ViewPointer, GetFileSize(FileHandle, nil)); 
      finally 
        UnmapViewOfFile(ViewPointer); 
      end
    finally 
      CloseHandle(MapHandle); 
    end
  finally 
    CloseHandle(FileHandle); 
  end
  MD5Final(Context, Result); 
end;


Also mittels showmessages hab ich jetzt den Fehler eingrenzen können, und zwar liegt er in der Zeile

Delphi-Quelltext
1:
ViewPointer := MapViewOfFile(MapHandle, FILE_MAP_READ, 000);                    

Es scheint so, als würde bei großen Dateien NIL zurückgegeben werden, nur woran kann das liegen und wie kann man das beheben? Bin total ratlos :(


littleDave - Fr 14.11.08 17:07

Warum machst du es nicht mit einem Lesepuffer?

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
function MD5File(N: string): MD5Digest;  
const
    BufferSize = 1024*512// 512 KB
var 
    Buffer : Pointer;
    aFile  : TFileStream;
    Context: MD5Context;  
    Readed : integer;
begin
  MD5Init(Context);  
  aFile := TFileStream.Create(n, fmOpenRead or fmShareDenyNone);
  try
    GetMem(Buffer, BufferSize);
    try
      repeat
        Readed := aFile.Read(Buffer^, BufferSize);
        if Readed > 0 then
           MD5Update(Context, Buffer, Readed);
      until Readed < BufferSize;
    finally
      FreeMem(Buffer);
    end;
  finally
    aFile.Free;
  end;
  MD5Final(Context, Result); 
end;


Dann hast du auch keine Probleme mehr mit Dateien > 2GB


TheNeon - Fr 14.11.08 18:29

user defined image user defined image user defined image

So klappt es, Danke!
Auf sowas in der Art bin ich garnicht gekommen :(

Man, hab ich noch viel zu lernen ...