Ein kleines aber ziemlich lästiges Problem ist hier aufgetreten :
Ich habe einen code zum errechnen der md5 summe (stammt noch aus Delphi 4.x) Zeiten und wurde nur auf FP/Lazarus angepasst.
Jedenfalls funktioniert der Code korrekt bei einer 32bit CPU.
Wenn ich den Code unter einer 64bit cpu laufen lasse (kompiliert auf einer 64bit cpu - egal ob windows oder linux) funktioniert er auch soweit, nur wenn eine
Datei größer als 2gb ist wird eine falsche prüfsumme errechnet.
Ich bin da jetzt wirklich ratlos wie es dazu kommen kann, da es eben wie gesagt korrekt unter 32bit funktioniert.
Code: Alles auswählen
program project1;
{$mode objfpc}{$H+}
Uses
SysUtils,Classes,LazUTF8Classes;
Type
TDigestStr = String[32];
TDigest = Array[0..15] Of Byte;
TDigestLongWord = Array[0..3] Of LongWord;
TLongWordBuf = Array[0..15] Of LongWord;
TByteBuf = Array[0..63] Of Byte;
TCustomMD5 = class(TObject)
Private
FDigest: TDigest; {the digest to be returned}
CDigest: TDigestLongWord; {digest accumulator}
BitLo, BitHi: LongWord; { number of _bits_ handled mod 2^64 }
bBuf: TByteBuf;
bLen: Cardinal; {bytes in bBuf}
BufferChanged: Boolean;
Procedure ResetBuffer;
Procedure Update (Const ChkBuf; Len: Cardinal);
Function GetDigest: TDigest;
Function GetDigestStr: TDigestStr;
Function GetDigestLongWord: TDigestLongWord;
Protected
{ Protected declarations }
Public
Constructor Create;
Property Digest: TDigest Read GetDigest;
Property DigestLongWord: TDigestLongWord Read GetDigestLongWord;
Property DigestStr: TDigestStr Read GetDigestStr;
End;
TMD5 = Class(TCustomMD5)
Public
Procedure Reset;
Procedure Add (Value: Char); Overload;
Procedure Add (Value: Byte); Overload;
Procedure Add (Value: Word); Overload;
Procedure Add (Value: Integer); Overload;
Procedure Add (Value: Cardinal); Overload;
Procedure Add (Const Value: String); Overload;
Procedure Add (Value: TStrings); Overload;
Function AddFile (Value: String):Longint;
End;
Procedure Transform (Var Accu; Const Buf);
Var
a, b, c, d: LongWord;
lBuf: TLongWordBuf Absolute Buf;
lAccu: TDigestLongWord Absolute Accu;
Function ROL (x: LongWord; n: LongWord): LongWord;
Begin Result:= (x Shl n) Or (x Shr (32-n)) End;
Function FF (a,b,c,d,x,s,ac: LongWord): LongWord;
Begin Result:= ROL (a+x+ac + (b And c Or Not b And d), s) + b End;
Function GG (a,b,c,d,x,s,ac: LongWord): LongWord;
Begin Result:= ROL (a+x+ac + (b And d Or c And Not d), s) + b End;
Function HH (a,b,c,d,x,s,ac: LongWord): LongWord;
Begin Result:= ROL (a+x+ac + (b Xor c Xor d), s) + b End;
Function II (a,b,c,d,x,s,ac: LongWord): LongWord;
Begin Result:= ROL (a+x+ac + (c Xor (b Or Not d)), s) + b End;
Begin
a:= lAccu[0];
b:= lAccu[1];
c:= lAccu[2];
d:= lAccu[3];
a:= FF(a,b,c,d, lBuf[ 0], 7, $d76aa478); { 1 }
d:= FF(d,a,b,c, lBuf[ 1], 12, $e8c7b756); { 2 }
c:= FF(c,d,a,b, lBuf[ 2], 17, $242070db); { 3 }
b:= FF(b,c,d,a, lBuf[ 3], 22, $c1bdceee); { 4 }
a:= FF(a,b,c,d, lBuf[ 4], 7, $f57c0faf); { 5 }
d:= FF(d,a,b,c, lBuf[ 5], 12, $4787c62a); { 6 }
c:= FF(c,d,a,b, lBuf[ 6], 17, $a8304613); { 7 }
b:= FF(b,c,d,a, lBuf[ 7], 22, $fd469501); { 8 }
a:= FF(a,b,c,d, lBuf[ 8], 7, $698098d8); { 9 }
d:= FF(d,a,b,c, lBuf[ 9], 12, $8b44f7af); { 10 }
c:= FF(c,d,a,b, lBuf[10], 17, $ffff5bb1); { 11 }
b:= FF(b,c,d,a, lBuf[11], 22, $895cd7be); { 12 }
a:= FF(a,b,c,d, lBuf[12], 7, $6b901122); { 13 }
d:= FF(d,a,b,c, lBuf[13], 12, $fd987193); { 14 }
c:= FF(c,d,a,b, lBuf[14], 17, $a679438e); { 15 }
b:= FF(b,c,d,a, lBuf[15], 22, $49b40821); { 16 }
a:= GG(a,b,c,d, lBuf[ 1], 5, $f61e2562); { 17 }
d:= GG(d,a,b,c, lBuf[ 6], 9, $c040b340); { 18 }
c:= GG(c,d,a,b, lBuf[11], 14, $265e5a51); { 19 }
b:= GG(b,c,d,a, lBuf[ 0], 20, $e9b6c7aa); { 20 }
a:= GG(a,b,c,d, lBuf[ 5], 5, $d62f105d); { 21 }
d:= GG(d,a,b,c, lBuf[10], 9, $02441453); { 22 }
c:= GG(c,d,a,b, lBuf[15], 14, $d8a1e681); { 23 }
b:= GG(b,c,d,a, lBuf[ 4], 20, $e7d3fbc8); { 24 }
a:= GG(a,b,c,d, lBuf[ 9], 5, $21e1cde6); { 25 }
d:= GG(d,a,b,c, lBuf[14], 9, $c33707d6); { 26 }
c:= GG(c,d,a,b, lBuf[ 3], 14, $f4d50d87); { 27 }
b:= GG(b,c,d,a, lBuf[ 8], 20, $455a14ed); { 28 }
a:= GG(a,b,c,d, lBuf[13], 5, $a9e3e905); { 29 }
d:= GG(d,a,b,c, lBuf[ 2], 9, $fcefa3f8); { 30 }
c:= GG(c,d,a,b, lBuf[ 7], 14, $676f02d9); { 31 }
b:= GG(b,c,d,a, lBuf[12], 20, $8d2a4c8a); { 32 }
a:= HH(a,b,c,d, lBuf[ 5], 4, $fffa3942); { 33 }
d:= HH(d,a,b,c, lBuf[ 8], 11, $8771f681); { 34 }
c:= HH(c,d,a,b, lBuf[11], 16, $6d9d6122); { 35 }
b:= HH(b,c,d,a, lBuf[14], 23, $fde5380c); { 36 }
a:= HH(a,b,c,d, lBuf[ 1], 4, $a4beea44); { 37 }
d:= HH(d,a,b,c, lBuf[ 4], 11, $4bdecfa9); { 38 }
c:= HH(c,d,a,b, lBuf[ 7], 16, $f6bb4b60); { 39 }
b:= HH(b,c,d,a, lBuf[10], 23, $bebfbc70); { 40 }
a:= HH(a,b,c,d, lBuf[13], 4, $289b7ec6); { 41 }
d:= HH(d,a,b,c, lBuf[ 0], 11, $eaa127fa); { 42 }
c:= HH(c,d,a,b, lBuf[ 3], 16, $d4ef3085); { 43 }
b:= HH(b,c,d,a, lBuf[ 6], 23, $04881d05); { 44 }
a:= HH(a,b,c,d, lBuf[ 9], 4, $d9d4d039); { 45 }
d:= HH(d,a,b,c, lBuf[12], 11, $e6db99e5); { 46 }
c:= HH(c,d,a,b, lBuf[15], 16, $1fa27cf8); { 47 }
b:= HH(b,c,d,a, lBuf[ 2], 23, $c4ac5665); { 48 }
a:= II(a,b,c,d, lBuf[ 0], 6, $f4292244); { 49 }
d:= II(d,a,b,c, lBuf[ 7], 10, $432aff97); { 50 }
c:= II(c,d,a,b, lBuf[14], 15, $ab9423a7); { 51 }
b:= II(b,c,d,a, lBuf[ 5], 21, $fc93a039); { 52 }
a:= II(a,b,c,d, lBuf[12], 6, $655b59c3); { 53 }
d:= II(d,a,b,c, lBuf[ 3], 10, $8f0ccc92); { 54 }
c:= II(c,d,a,b, lBuf[10], 15, $ffeff47d); { 55 }
b:= II(b,c,d,a, lBuf[ 1], 21, $85845dd1); { 56 }
a:= II(a,b,c,d, lBuf[ 8], 6, $6fa87e4f); { 57 }
d:= II(d,a,b,c, lBuf[15], 10, $fe2ce6e0); { 58 }
c:= II(c,d,a,b, lBuf[ 6], 15, $a3014314); { 59 }
b:= II(b,c,d,a, lBuf[13], 21, $4e0811a1); { 60 }
a:= II(a,b,c,d, lBuf[ 4], 6, $f7537e82); { 61 }
d:= II(d,a,b,c, lBuf[11], 10, $bd3af235); { 62 }
c:= II(c,d,a,b, lBuf[ 2], 15, $2ad7d2bb); { 63 }
b:= II(b,c,d,a, lBuf[ 9], 21, $eb86d391); { 64 }
Inc(lAccu[0], a);
Inc(lAccu[1], b);
Inc(lAccu[2], c);
Inc(lAccu[3], d)
End;
Constructor TCustomMD5.Create;
Begin
Inherited Create;
ResetBuffer;
End;
Procedure TCustomMD5.ResetBuffer;
Begin
BitLo:= 0;
BitHi:= 0;
bLen:= 0;
{Load magic initialization constants.}
CDigest[0]:= $67452301;
CDigest[1]:= $efcdab89;
CDigest[2]:= $98badcfe;
CDigest[3]:= $10325476;
BufferChanged:= True
End;
Procedure TCustomMD5.Update (Const ChkBuf; Len: Cardinal);
Var
BufPtr: ^Byte;
Left: Cardinal;
Begin
BufferChanged:= True;
If BitLo + LongWord(Len) Shl 3 < BitLo Then
Inc(BitHi);
Inc(BitLo, LongWord(Len) Shl 3);
Inc(BitHi, LongWord(Len) Shr 29);
BufPtr:= @ChkBuf;
If bLen>0 Then Begin
Left:= 64-bLen; If Left>Len Then Left:= Len;
Move(BufPtr^, bBuf[bLen], Left);
Inc(bLen, Left); Inc(BufPtr, Left);
If bLen<64 Then Exit;
Transform(CDigest, bBuf);
bLen:= 0;
Dec(Len, Left)
End;
While Len>=64 Do Begin
Transform(CDigest, BufPtr^);
Inc(BufPtr, 64);
Dec(Len, 64)
End;
If Len>0 Then Begin
bLen:= Len;
Move(BufPtr^, bBuf[0], bLen)
End
End;
Function TCustomMD5.GetDigest: TDigest;
{-get digest without modifying bBuf, bLen and BitLo/Hi}
Var
WorkBuf: TByteBuf;
WorkLen: Cardinal;
Begin
If BufferChanged Then Begin
FDigest:= TDigest(CDigest);
Move(bBuf, WorkBuf, bLen); {make copy of buffer}
{pad out to block of form (0..55, BitLo, BitHi)}
WorkBuf[bLen]:= $80;
WorkLen:= bLen+1;
If WorkLen>56 Then Begin
FillChar(WorkBuf[WorkLen], 64-WorkLen, 0);
TransForm(FDigest, WorkBuf);
WorkLen:= 0
End;
FillChar(WorkBuf[WorkLen], 56-WorkLen, 0);
TLongWordBuf(WorkBuf)[14]:= BitLo;
TLongWordBuf(WorkBuf)[15]:= BitHi;
Transform (FDigest, WorkBuf);
BufferChanged:= False
End;
Result:= FDigest
End;
Function TCustomMD5.GetDigestStr: TDigestStr;
Const
hc: Array[0..$F] Of Char = '0123456789ABCDEF';
Var
aDigest: TDigest;
i: 0..15;
Begin
aDigest:= Digest;
Result[0]:= #32;
For i:= 0 To 15 Do Begin
Result[1+i Shl 1]:= hc[aDigest[i] Shr 4];
Result[2+i Shl 1]:= hc[aDigest[i] And $F]
End
End;
Function TCustomMD5.GetDigestLongWord: TDigestLongWord;
Begin
TDigest(Result):= Digest
End;
{ TMD5 }
Procedure TMD5.Reset;
Begin
ResetBuffer
End;
Procedure TMD5.Add (Value: Char);
Begin
Update(Value, SizeOf(Value))
End;
Procedure TMD5.Add (Value: Byte);
Begin
Update(Value, SizeOf(Value))
End;
Procedure TMD5.Add (Value: Word);
Begin
Update(Value, SizeOf(Value))
End;
Procedure TMD5.Add (Value: Integer);
Begin
Update(Value, SizeOf(Value))
End;
Procedure TMD5.Add (Value: Cardinal);
Begin
Update(Value, SizeOf(Value))
End;
Procedure TMD5.Add (Const Value: String);
Begin
Update(PChar(Value)^, Length(Value));
End;
Procedure TMD5.Add (Value: TStrings);
Var
i: Integer;
Begin
For i:= 0 To Value.Count-1 Do
Add(Value[i])
End;
Function TMD5.AddFile (Value: String):Longint;
var
aBuf: Pointer;
wRd: Cardinal;
ChunkSize:Longint;
md5Stream:TFileStreamUTF8;
Begin
Chunksize:=65536;
TRY
GetMem(aBuf, ChunkSize);
Try
MD5Stream:=TFileStreamUTF8.Create(Value,fmOpenRead); {Create stream and open file}
Except Begin {check for exception on opening}
Writeln('Error opening file');
Result:=-1;
exit;
end;
end;
Repeat
wrd:=MD5Stream.Read(aBuf^,Chunksize);
if wRd>0 then Update(aBuf^, wRd)
Until wRd<ChunkSize;
Result:=0;
Finally
FreeMem(aBuf, ChunkSize);
MD5Stream.Free;
End
End;
{ handy procedures }
Function GetMD5FromFile (Const FileName: TFileName;VAR aChecksum:String): longint;
Begin
With TMD5.Create Do
Try
Result:=AddFile(FileName);
aChecksum:=DigestStr;
Finally
Free
End;
End;
Function StringMD5Digest (S: String): TDigestStr;
Begin
With TMD5.Create Do
Try
Add(S);
Result:= DigestStr
Finally
Free
End
End;
VAR CHeckSum:String;
begin
GetMD5FromFile('aFileName ',Checksum);
writeln(checksum);
end.
Ich bekomme unter 64bit folgende Prüfsumme :
Code: Alles auswählen
81F21E991D8BE4929AD9D71CC8F36628
Code: Alles auswählen
EDA0959A196776132AB9681FDF52CC3C