Skip to content

Instantly share code, notes, and snippets.

@XProger
Last active August 29, 2015 14:05
Show Gist options
  • Save XProger/08d02d368e002af8a0ab to your computer and use it in GitHub Desktop.
Save XProger/08d02d368e002af8a0ab to your computer and use it in GitHub Desktop.
Calculate SHA1 digest of data
type
TSHA1Digest = array [0..4] of LongWord;
TSHA1Block = array [0..63] of Byte;
TSHA1Context = record
State : TSHA1Digest;
Block : TSHA1Block;
Len : Int64;
Pos : LongInt;
end;
function SwapInt32(const Value: LongWord): LongWord; assembler;
asm
bswap eax
end;
function LeftRotate(x, c: LongWord): LongWord;
begin
Result := (x shl c) or (x shr (32 - c));
end;
procedure SHA1Calc(const SHA1Block: TSHA1Block; var State: TSHA1Digest);
var
i : LongInt;
a, b, c, d, e, f, g, t : LongWord;
w : array [0..79] of LongWord;
begin
a := State[0];
b := State[1];
c := State[2];
d := State[3];
e := State[4];
Move(SHA1Block, w, SizeOf(SHA1Block));
for i := 0 to 15 do
w[i] := SwapInt32(w[i]);
for i := 16 to 79 do
begin
w[i] := w[i - 3] xor w[i - 8] xor w[i - 14] xor w[i - 16];
w[i] := (w[i] shl 1) or (w[i] shr 31);
end;
for i := 0 to 79 do
begin
if i > 59 then
begin
f := b xor c xor d;
g := $CA62C1D6;
end else
if i > 39 then
begin
f := (b and c) or (b and d) or (c and d);
g := $8F1BBCDC;
end else
if i > 19 then
begin
f := b xor c xor d;
g := $6ED9EBA1;
end else
begin
f := d xor (b and (c xor d));
g := $5A827999;
end;
t := LeftRotate(a, 5) + f + e + g + w[i];
e := d;
d := c;
c := LeftRotate(b, 30);
b := a;
a := t;
end;
Inc(State[0], a);
Inc(State[1], b);
Inc(State[2], c);
Inc(State[3], d);
Inc(State[4], e);
end;
procedure SHA1Init(out Context: TSHA1Context);
begin
Context.State[0] := $67452301;
Context.State[1] := $EFCDAB89;
Context.State[2] := $98BADCFE;
Context.State[3] := $10325476;
Context.State[4] := $C3D2E1F0;
Context.Len := 0;
Context.Pos := 0;
end;
procedure SHA1Update(var Context: TSHA1Context; const Data; Size: LongWord);
var
Count : LongWord;
ptr : Pointer;
begin
with Context do
begin
Len := Len + Size * 8;
ptr := @Data;
while Size > 0 do
begin
Count := SizeOf(Block) - Pos;
if Size < Count then
Count := Size;
Move(ptr^, Block[Pos], Count);
Inc(Pos, Count);
Dec(Size, Count);
ptr := Pointer(LongWord(ptr) + Count);
if Pos = SizeOf(Block) then
begin
SHA1Calc(Block, State);
Pos := 0;
end;
end;
end;
end;
procedure SHA1Final(var Context: TSHA1Context; out Digest: TSHA1Digest);
var
i : LongWord;
begin
with Context do
begin
Block[Pos] := $80;
if Pos > SizeOf(Block) - 9 then
begin
FillChar(Block[Pos + 1], SizeOf(Block) - Pos - 1, 0);
SHA1Calc(Block, State);
FillChar(Block, SizeOf(Block), 0);
end else
FillChar(Block[Pos + 1], SizeOf(Block) - Pos - 9, 0);
LongWord(Pointer(@Block[SizeOf(Block) - 8])^) := SwapInt32(Len shr 32 and $FFFFFFFF);
LongWord(Pointer(@Block[SizeOf(Block) - 4])^) := SwapInt32(Len and $FFFFFFFF);
SHA1Calc(Block, State);
for i := 0 to 4 do
Digest[i] := SwapInt32(State[i]);
end;
end;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment