Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Mini-SHA1 (https://www.delphipraxis.net/151812-mini-sha1.html)

himitsu 2. Jun 2010 13:50


Mini-SHA1
 
Vielleicht hat es schonmal jemand gesehn (hab's ja in einigen Projekten verbaut).
Delphi-Quellcode:
type
  SHA_CTX = packed Record
    Unknown: Array[0.. 5] of LongWord;
    State:  Array[0.. 4] of LongWord;
    Count:  UInt64;
    Buffer: Array[0..63] of Byte;
  End;
  pSHA_CTX = ^SHA_CTX;
  SHA_RES = Array[0..4] of LongWord;

Procedure SHA_CTX.Init(Var Context: SHA_CTX); StdCall;
  External 'advapi32.dll' Name 'A_SHAInit';

Procedure SHA_CTX.Update(Var Context: SHA_CTX; Input: Pointer; inLen: LongWord); StdCall;
  External 'advapi32.dll' Name 'A_SHAUpdate';

Procedure SHA_CTX.GetResult(Var Context: SHA_CTX; Out Result: SHA_RES); StdCall;
  External 'advapi32.dll' Name 'A_SHAFinal';
Und da ich Records so sehr mag, hatte ich's jetzt nochmal etwas überarbeitet :cheer:
Delphi-Quellcode:
type
{$ALIGN 4}
  TSHA1Res = Array[0..4] of LongWord;
  TSHA1 = Packed Record
    Procedure Init;                                     StdCall;
    Procedure Update (Input: Pointer; inLen: LongWord); StdCall;
    Procedure Finalize(Result: TSHA1Res);               StdCall;
    Function doFinalize:     TSHA1Res;                Inline;

    Class Function toBase64(Res: TSHA1Res): String;                    Static;
    Class Function Calc   (Input: Pointer; inLen: LongWord): TSHA1Res; Static;
    Class Function CalcX  (Input: Pointer; inLen: LongWord): String;  Static;
  Public
    Unknown: Array[0.. 5] of LongWord;
    State:  Array[0.. 4] of LongWord;
    Count:  UInt64;
    Buffer: Array[0..63] of Byte;
  End;
  {$ALIGN 8}

Procedure TSHA1.Init{Var Context: SHA_CTX}; StdCall;
  External 'advapi32.dll' Name 'A_SHAInit';

Procedure TSHA1.Update{Var Context: SHA_CTX; Input: Pointer; inLen: LongWord}; StdCall;
  External 'advapi32.dll' Name 'A_SHAUpdate';

Procedure TSHA1.Finalize{Var Context: SHA_CTX; Out Result: SHA_RES}; StdCall;
  External 'advapi32.dll' Name 'A_SHAFinal';

Function TSHA1.doFinalize: TSHA1Res;
  Begin
    Finalize(Result);
  End;

Class Function TSHA1.toBase64(Res: TSHA1Res): String;
  Const Base64: Array[0..63] of Char = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';

  Var R: packed Record Res: TSHA1Res; Fill: AnsiChar; End;
    A:  packed Array[0..20] of Byte absolute R;
    i:  Integer;

  Begin
    R.Res := Res;
    R.Fill := '=';
    SetLength(Result, 28);
    For i := 0 to 6 do Begin
      Result[i * 4 + 1] := Base64[                         (A[i * 3 + 0] shr 2) and 63];
      Result[i * 4 + 2] := Base64[((A[i * 3 + 0] shl 4) or (A[i * 3 + 1] shr 4)) and 63];
      Result[i * 4 + 3] := Base64[((A[i * 3 + 1] shl 2) or (A[i * 3 + 2] shr 6)) and 63];
      Result[i * 4 + 4] := Base64[  A[i * 3 + 2]                                and 63];
    End;
    Result[28] := '=';
  End;

Class Function TSHA1.Calc(Input: Pointer; inLen: LongWord): TSHA1Res;
  Var X: TSHA1;

  Begin
    X.Init;
    X.Update(Input, inLen);
    X.Finalize(Result);
  End;

Class Function TSHA1.CalcX(Input: Pointer; inLen: LongWord): String;
  Begin
     Result := toBase64(Calc(Input, inLen));
  End;
Delphi-Quellcode:
var
  SHA1: TSHA1;
  Result: TSHA1Res

SHA1.Init;
SHA1.Update(P, len);
SHA1.Finalize(Result);
// irgendwas mit Result machen
Delphi-Quellcode:
ShowMessage(TSHA1.CalcX(P, len));

SittingDuck 15. Okt 2011 17:17

AW: Mini-SHA1
 
Hallo zusammen ...

Ich wollte die Routine von himitsu 'mal eben' umstellen auf die Ausgabe im Hex-Format. In der Bit-Schiebe-Routine stimmt aber was nicht. Dem entsprechend ist das Ergebnis dann leider auch falsch. Ich habe den Base64 Teil einfach mal auskommentiert.

Delphi-Quellcode:
class function TSHA1.toBase64(Res: TSHA1Res): String;
//const Base64:  array[0 .. 63] of Char = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
const HexTable: array[0 .. 15] of Char = '0123456789ABCDEF';
var R: packed record Res: TSHA1Res; Fill: AnsiChar; end; A: packed array[0..20] of Byte absolute R; i: Integer;
begin
 R.Res := Res; R.Fill := '='; SetLength(Result, 28);
    for i := 0 to 6 do begin
//      Result[i * 4 + 1] := Base64[ (A[i * 3 + 0] shr 2) and 63];
//      Result[i * 4 + 2] := Base64[((A[i * 3 + 0] shl 4) or (A[i * 3 + 1] shr 4)) and 63];
//      Result[i * 4 + 3] := Base64[((A[i * 3 + 1] shl 2) or (A[i * 3 + 2] shr 6)) and 63];
//      Result[i * 4 + 4] := Base64[  A[i * 3 + 2] and 63];

      Result[i * 4 + 1] := HexTable[ (A[i * 3 + 0] shr 2) and 15];
      Result[i * 4 + 2] := HexTable[((A[i * 3 + 0] shl 4) or (A[i * 3 + 1] shr 4)) and 15];
      Result[i * 4 + 3] := HexTable[((A[i * 3 + 1] shl 2) or (A[i * 3 + 2] shr 6)) and 15];
      Result[i * 4 + 4] := HexTable[  A[i * 3 + 2] and 15];

 end;
end;
Wo liegt mein Fehler? Danke schon mal für die Hilfe ...

himitsu 15. Okt 2011 19:09

AW: Mini-SHA1
 
Zitat:

Zitat von SittingDuck (Beitrag 1130633)
Wo liegt mein Fehler?

Ersteinmal mußt du verstehen, was Hexadezumal und Base64 eigentlich ist.

Bei Base64 hat jedes "kodierte" Zeichen 64 Werte, wärend es bei Hexadezimal nur 16 Werte sind.
Außerdem ist dabei natürlich der kodierte String länger ... mehr Zeichen, da ja weniger Daten pro Zeichen vorhanden sind.
Base64 = 28 Zeichen (4 Zeichen pro 3 Byte)
Hex = 40 Zeichen (2 Zeichen pro Byte, also 6 Zeichen pro 3 Byte)

Du hast jetzt versucht 64 Werte auf ein 16-Zeichen Array loszulassen, was natürlich schief laufen muß. :zwinker:
PS: Schalte mal die Bereichsprüfung in deinen Projektoptionen an.
(und schon wäre dir das Problem von selber aufgefallen :zwinker: )

Und dann war natürlich der String zu kurz.

Delphi-Quellcode:
Class function TSHA1.toHex(Res: TSHA1Res): String;
  Const HexTable: array[0..15] of Char = '0123456789ABCDEF';

  Var A: packed array[0..19] of Byte absolute Res;
    i: Integer;

  Begin
    SetLength(Result, 40);
    Bor i := 0 to 19 do Begin
      Result[i * 2 + 1] := HexTable[A[i] shr 4];
      Result[i * 2 + 2] := HexTable[A[i] and 15];
    End;
  End;

SittingDuck 16. Okt 2011 13:11

AW: Mini-SHA1
 
Super himitsu ... Danke für Deinen Input, da habe ich es mir wohl etwas zu leicht gemacht. Irgendwas stimmt da aber immer noch nicht.

Wenn ich per
Delphi-Quellcode:
var s, h: String;

 s := 'abc';
 h := TSHA1.CalcBase(PChar(s), Length(s));
den Hash von dem String 'abc' ermitteln möchte dann sollte eigentlich das rauskommen:
'A9993E364706816ABA3E25717850C26C9CD0D89D' ... ich erhalte aber das hier:
'4A3DEC2D1F8245280855C42DB0EE4239F917FDB8' ...

Auf welchem abenteuerlichen Holzweg bin ich jetzt wieder gelandet ?!?
Danke schonmal im Vorraus

gammatester 16. Okt 2011 18:55

AW: Mini-SHA1
 
Ich vermute Du bist vom Unicode-Desaster erwischt worden: 4A3DEC2D1F8245280855C42DB0EE4239F917FDB8 ist der SHA1-Digest der Bytefolge $61,$00,$62. Da Du D2010 benutzt, ist der String 'abc' doch wohl ein Unicodestring. Hashen von Strings halte ich für sinnlos und gefährlich. Kryptographische Hasfunktionen arbeiten auf Bit-/Bytefolgen und die Testwerte sind entsprechend. Für den Testvektor $61,$62,$63 liefert SHA1 den Wert A9993E364706816ABA3E25717850C26C9CD0D89D. Wenn Du unbedingt mit Strings arbeiten willst, nimm für solche Sachen Ansistrings
Delphi-Quellcode:
var
  s: ansistring:
  h: String;

 s := 'abc';
 h := TSHA1.CalcBase(PChar(s), Length(s));
sollte den Testwert ergeben. Wenn Du unbedingt Strings haschen willst, solltest Du
Delphi-Quellcode:
TSHA1.CalcBase(PChar(s), Length(s)*Sizeof(char));
verwenden.

himitsu 16. Okt 2011 20:08

AW: Mini-SHA1
 
Den AnsiString natürlich mit PAnsiChar, ansonsten war's gut erklärt :)

SittingDuck 28. Okt 2011 13:39

AW: Mini-SHA1
 
Vielen Dank für Eure ausführliche Hilfe. Nun läuft alles perfekt. Eins ist klar ... ohne dieses Forum wäre ich ganz oft total aufgeschmissen!

H3llsing 6. Feb 2013 12:19

AW: Mini-SHA1
 
Hallo, ich wollte nochmal das uralte Thema aufgreifen.

Was für ein Datentyp ist denn Bor? ByteOfRecord?
Wie sollte man das initialisieren?

Zitat:

Delphi-Quellcode:
Class function TSHA1.toHex(Res: TSHA1Res): String;
  Const HexTable: array[0..15] of Char = '0123456789ABCDEF';

  Var A: packed array[0..19] of Byte absolute Res;
    i: Integer;

  Begin
    SetLength(Result, 40);
    Bor i := 0 to 19 do Begin
      Result[i * 2 + 1] := HexTable[A[i] shr 4];
      Result[i * 2 + 2] := HexTable[A[i] and 15];
    End;
  End;


Vielen Dank für eure Hilfe

Klaus01 6. Feb 2013 12:28

AW: Mini-SHA1
 
ich denke das sollte For heißen - macht für mich jedenfalls Sinn.

Grüße
Klaus

H3llsing 6. Feb 2013 13:07

AW: Mini-SHA1
 
Autsch!
Natürlich! Ich mach erstmal Mittag. Vielen dank :)

eine Frage zu der Unicode-Umwandlung hätt ich dann noch:
Warum ist das nicht das gleiche ?

Delphi-Quellcode:
var
  s: String;
  p: PansiChar;
begin
  s := 'abc';
  p := pAnsiChar(s);
end
wie
Delphi-Quellcode:
  p := 'abc';

Alles klar weils AnsiString und nicht String sein muss ;)


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:40 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz