Einzelnen Beitrag anzeigen

cmrudolph

Registriert seit: 14. Aug 2006
29 Beiträge
 
Delphi 7 Professional
 
#1

Zugriffsverletzung in SHA-1 Code

  Alt 14. Jul 2008, 15:41
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.
  Mit Zitat antworten Zitat