Hi,
ich habe mir mal das
RFC 3174 geschnappt und in Delphi eine Funktion geschrieben, die über einen Speicherbereich den SHA-1 Hash berechnet.
Das Ergebnis ist auch korrekt, nur bekomme ich eine Zugriffsverletzung, wenn ich größere Daten hashen möchte.
Ich habe beispielsweise den Puffer mit
4194209 4194304 Bytes (4 MB) gefüllt. Beim 16376. Byte bekomme ich jedoch eine Zugriffsverletzung.
Um das ganze am Code zu zeigen, hier die Funktion:
Delphi-Quellcode:
type
THash = Array [0..4] of Cardinal;
PHash = ^THash;
.
.
.
procedure SHA1(data: Pointer;const mlen_lo:Cardinal;hash: PHash);
function rollL(k: Cardinal;const amount: Byte): Cardinal;
var
l: Cardinal;
begin
l:=k shl amount;
k:=k shr (32-amount);
Result:=l or k;
end;
var
W: Array [0..79] of Cardinal;
h0,h1,h2,h3,h4: Cardinal;
a,b,c,d,e: Cardinal;
temp,i,n: Cardinal;
t: Byte;
paddeddata: Pointer;
pposB: PByte;
padc: Byte;
m_lenbits: Cardinal;
mb: Byte;
begin
h0 := $67452301;
h1 := $EFCDAB89;
h2 := $98BADCFE;
h3 := $10325476;
h4 := $C3D2E1F0;
paddeddata:=GetMemory(mlen_lo+72);
CopyMemory(paddeddata,data,mlen_lo);
pposB:=paddeddata;
inc(pposB,mlen_lo);
pposB^:=$80;
inc(pposB);
padc:=64-(mlen_lo+9) mod 64;
if padc>0 then begin
for t:=1 to padc do begin
pposB^:=$00;
inc(pposB);
end;
end;
n:=(mlen_lo+padc+9) div 64;
m_lenbits:=mlen_lo shl 3;
PCardinal(pposB)^:=$00000000;
inc(pposB,4);
pposB^:=m_lenbits shr 24;
inc(pposB);
pposB^:=m_lenbits shr 16;
inc(pposB);
pposB^:=m_lenbits shr 8;
inc(pposB);
pposB^:=m_lenbits;
pposB:=paddeddata;
//Beginn Debugcode
for i:=0 to 4096 do begin
for t:=0 to 15 do begin
mb:=pposB^;
if mb=0 then;
if Cardinal(pposB)=431800320 then
ShowMessage(IntToStr(i));
inc(pposB);
end;
end;
pposB:=paddeddata;
//Ende Debugcode
for i:=0 to n-1 do begin
for t:=0 to 15 do begin
try
//hier kommt die Zugriffsverletzung
W[t]:=pposB^ shl 24;
inc(pposB);
W[t]:=W[t] or (pposB^ shl 16);
inc(pposB);
W[t]:=W[t] or (pposB^ shl 8);
inc(pposB);
W[t]:=W[t] or pposB^;
inc(pposB);
except showmessage(IntToStr(Cardinal(paddeddata))+' '+IntToStr(Cardinal(pposB)));
end;
end;
for t:=16 to 79 do begin
W[t]:=rollL(W[t-3] XOR W[t-8] XOR W[t-14] XOR W[t-16],1);
end;
a:=h0;
b:=h1;
c:=h2;
d:=h3;
e:=h4;
for t:=0 to 19 do begin
temp:=rollL(a,5) + ((b AND c) OR ((NOT b) AND d)) + e + W[t] + $5A827999;
e:=d;
d:=c;
c:=rollL(b,30);
b:=a;
a:=temp;
end;
for t:=20 to 39 do begin
temp:=rollL(a,5) + (b XOR c XOR d) + e + W[t] + $6ED9EBA1;
e:=d;
d:=c;
c:=rollL(b,30);
b:=a;
a:=temp;
end;
for t:=40 to 59 do begin
temp:=rollL(a,5) + ((b AND c) OR (b AND d) OR (c AND d)) + e + W[t] + $8F1BBCDC;
e:=d;
d:=c;
c:=rollL(b,30);
b:=a;
a:=temp;
end;
for t:=60 to 79 do begin
temp:=rollL(a,5) + (b XOR c XOR d) + e + W[t] + $CA62C1D6;
e:=d;
d:=c;
c:=rollL(b,30);
b:=a;
a:=temp;
end;
FreeMemory(paddeddata);
h0:=h0+a;
h1:=h1+b;
h2:=h2+c;
h3:=h3+d;
h4:=h4+e;
end;
hash^[0]:=h0;
hash^[1]:=h1;
hash^[2]:=h2;
hash^[3]:=h3;
hash^[4]:=h4;
end;
Die Zeilen 64-76 sind Debugcode. Die Zugriffsverletzung kommt bei Adresse 431800320 in Zeile 82. Ich habe versucht, den Wert vorher in eine andere Variable zu übertragen, also statt der direkten Zuweisung in das Array W erst in eine tempvariable. Doch dann kommt die Zugriffsverletzung bei dieser Operation.
Der Debugcode zeigt aber, dass der Speicher eigentlich zugreifbar sein müsste. Ich lasse mir im Debugcode auch den Wert an dieser Adresse ausgeben lassen, der stimmt auch mit den Eingabedaten überein.
Irgend etwas muss ich übersehen haben. Ich bin für jede Hilfe dankbar.
mfG,
Christian
Edit: die Bytezahl stimmte nicht, auch wenn es wohl nicht von Belang ist. Aber der Korrektheit halber...
Edit2: Da ich nicht wusste, dass man die Zeilennummern nicht immer sieht, habe ich den Quellcode um drei kleine Kommentare erweitert und die Zeilennummern unter dem Code angepasst.