![]() |
Mini-SHA1
Vielleicht hat es schonmal jemand gesehn (hab's ja in einigen Projekten verbaut).
Delphi-Quellcode:
Und da ich Records so sehr mag, hatte ich's jetzt nochmal etwas überarbeitet :cheer:
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';
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));
|
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:
Wo liegt mein Fehler? Danke schon mal für die Hilfe ...
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; |
AW: Mini-SHA1
Zitat:
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; |
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:
den Hash von dem String 'abc' ermitteln möchte dann sollte eigentlich das rauskommen:
var s, h: String;
s := 'abc'; h := TSHA1.CalcBase(PChar(s), Length(s)); 'A9993E364706816ABA3E25717850C26C9CD0D89D' ... ich erhalte aber das hier: '4A3DEC2D1F8245280855C42DB0EE4239F917FDB8' ... Auf welchem abenteuerlichen Holzweg bin ich jetzt wieder gelandet ?!? Danke schonmal im Vorraus |
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:
sollte den Testwert ergeben. Wenn Du unbedingt Strings haschen willst, solltest Du
var
s: ansistring: h: String; s := 'abc'; h := TSHA1.CalcBase(PChar(s), Length(s));
Delphi-Quellcode:
verwenden.
TSHA1.CalcBase(PChar(s), Length(s)*Sizeof(char));
|
AW: Mini-SHA1
Den AnsiString natürlich mit PAnsiChar, ansonsten war's gut erklärt :)
|
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!
|
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:
Vielen Dank für eure Hilfe |
AW: Mini-SHA1
ich denke das sollte For heißen - macht für mich jedenfalls Sinn.
Grüße Klaus |
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:
wie
var
s: String; p: PansiChar; begin s := 'abc'; p := pAnsiChar(s); end
Delphi-Quellcode:
p := 'abc';
Alles klar weils AnsiString und nicht String sein muss ;) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:49 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz