Entwickler-Ecke

Algorithmen, Optimierung und Assembler - Problem mit MD5


Marco D. - Sa 01.10.05 15:08
Titel: Problem mit MD5
Hab halt MD5.pas:


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:
385:
386:
387:
388:
389:
390:
391:
// 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.


Und welche Funktion muss ich aufrufen um einen String zu verschlüsseln. Es gab da auch immer nen Problem da der übergebene Wert 'MD5Digest' ist aber ich will ja dann wieder einen String erhalten. Könnt ihr mal son Beispiel geben wie man eienn String verssschlüsselt?


Neidhard von Reuental - Sa 01.10.05 15:24


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


ganz einfach ^^


BenBE - So 02.10.05 10:31

Eins mal unter uns, ganz im Vertrauen: MD5 ist keine Verschlüsslung, sondern ein Hash-Verfahren. Der Unterschied ist zwar nur marginal, aber vielleicht hilft es Dir, mal etwas Literatur dazu zu lesen, um ihn zu verstehen ;-)


Alstar - So 02.10.05 10:36

Sry, wenn das jetzt Klugscheißer-mäßig klingt: Ein Hash ist eine unumkehrbare Verschlüsselung :wink:

Alstar


Motzi - So 02.10.05 10:54

user profile iconAlstar hat folgendes geschrieben:
Sry, wenn das jetzt Klugscheißer-mäßig klingt: Ein Hash ist eine unumkehrbare Verschlüsselung :wink:

Nein, man kann einen Hash-Algo eigentlich auch nicht als umkehrbare Verschlüsselung bezeichnen :P (was hätte eine nicht umkehrbare Verschlüsselung auch für einen Sinn :?). Ein Hash ist vielmehr ein Fingerabdruck der Eingabedaten.
Wer es genauer wissen will soll sich einfach mal die Ausarbeitung dazu auf meiner Homepage angucken (bei den Tutorials): http://www.manuel-poeter.de


Alstar - So 02.10.05 11:00

Ich zitiere aus dem Wikipedia:
Zitat:

Hash-Funktionen können unter Umständen auch zur Einweg-Verschlüsselung verwendet werden.

Quelle: Wikipedia [http://de.wikipedia.org/wiki/Hash-Funktion]

Alstar


BenBE - So 02.10.05 11:19

Da gibt es allerdings ein Problem, da eine Verschlüsslung ein umkehrbarer Vorgang ist. Eine Hash-Funktion ist nicht umkehrbar.

Eine Verschlüsslung ist eine ein-eindeutige Abbildung von D auf W, eine Hashfunktion ist nur eindeutig. Der Unterschied zwischen "eineindeutig" und "eindeutig" steht in jedem guten Mathelehrbuch drin ...


Motzi - So 02.10.05 12:13

Kurze Erklärung.. was ist der Unterschied zwischen einer nicht umkehrbaren Verschlüsselung und einer Hash-Funktion?
Ich könnte ein Programm schreiben das, unabhängig von den Eingabedaten, die Zeichenkette "qwertzuiop" zurückgibt und das meine nicht umkehrbare Verschlüsselung nennen. Nicht umkehrbar, da das Ergebnis ja unabhängig von den Eingabedaten ist und daher jede mögliche Kombination von Zeichen als Eingabe gleich wahrscheinlich ist. Frage - ist es sinnvoll eine solche Einweg-Verschlüsselung zu verwenden?
Der Unterschied zu einer Hash-Funktion ist der, dass eine Hash-Funktion einen sogenannten Fingerabdruck der Daten berechnet. Man kann von einem Hashwert zwar nicht auf die Eingabedaten zurückrechnen, Hash-Funktionen sind aber (quasi) kollisionsfrei. Man kann also mit ausreichender Sicherheit sagen, dass 2 gleiche Hashwerte auch dieselben Eingabedaten haben müssen.


Alstar - So 02.10.05 12:18

Ja. Ist ja auch logisch, aber ich hab das halt so in der Wikipedia gelesen :nixweiss:

Alstar


Motzi - So 02.10.05 12:24

user profile iconAlstar hat folgendes geschrieben:
Ja. Ist ja auch logisch, aber ich hab das halt so in der Wikipedia gelesen :nixweiss:

Ja, ist ja auch kein Problem.. ich wollte das nur richtigstellen bzw. näher erläutern, für alle die nicht wissen was Hash-Funktionen sind und das hier lesen..! ;)