Skip to content

Instantly share code, notes, and snippets.

@XProger
Created August 26, 2014 06:08
Show Gist options
  • Save XProger/8f6666b39a9e51ea00a2 to your computer and use it in GitHub Desktop.
Save XProger/8f6666b39a9e51ea00a2 to your computer and use it in GitHub Desktop.
Calculate MD5 digest of data
type
TMD5Digest = array [0..3] of LongWord;
TMD5Block = array [0..63] of Byte;
TMD5Context = record
State : TMD5Digest;
Block : TMD5Block;
Len : Int64;
Pos : LongInt;
end;
function LeftRotate(x, c: LongWord): LongWord;
begin
Result := (x shl c) or (x shr (32 - c));
end;
procedure MD5Calc(const MD5Block: TMD5Block; var State: TMD5Digest);
const
r : array [0..63] of Byte = (
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21);
var
i : LongInt;
a, b, c, d, e, f, g : LongWord;
w : array [0..15] of LongWord absolute MD5Block;
begin
{$Q-}
{$R-}
a := State[0];
b := State[1];
c := State[2];
d := State[3];
for i := 0 to 63 do
begin
if i > 47 then
begin
f := c xor (b or (not d));
g := (7 * i) mod 16;
end else
if i > 31 then
begin
f := b xor c xor d;
g := (3 * i + 5) mod 16;
end else
if i > 15 then
begin
f := c xor (d and (b xor c));
g := (5 * i + 1) mod 16;
end else
begin
f := d xor (b and (c xor d));
g := i;
end;
e := d;
d := c;
c := b;
b := b + LeftRotate(a + f + MD5Table[i] + w[g], r[i]);
a := e;
end;
Inc(State[0], a);
Inc(State[1], b);
Inc(State[2], c);
Inc(State[3], d);
{$Q+}
end;
procedure MD5Init(out Context: TMD5Context);
begin
Context.State[0] := $67452301;
Context.State[1] := $EFCDAB89;
Context.State[2] := $98BADCFE;
Context.State[3] := $10325476;
Context.Len := 0;
Context.Pos := 0;
end;
procedure MD5Update(var Context: TMD5Context; 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
MD5Calc(Block, State);
Pos := 0;
end;
end;
end;
end;
procedure MD5Final(var Context: TMD5Context; out Digest: TMD5Digest);
begin
with Context do
begin
Block[Pos] := $80;
if Pos > SizeOf(Block) - 9 then
begin
FillChar(Block[Pos + 1], SizeOf(Block) - Pos - 1, 0);
MD5Calc(Block, State);
FillChar(Block, SizeOf(Block), 0);
end else
FillChar(Block[Pos + 1], SizeOf(Block) - Pos - 9, 0);
Move(Len, Block[SizeOf(Block) - 8], 8);
MD5Calc(Block, State);
Digest := State;
end;
end;
function MD5Match(D1, D2: TMD5Digest): Boolean;
var
i : LongInt;
begin
for i := 0 to SizeOf(TMD5Digest) - 1 do
if D1[i] <> D2[i] then
begin
Result := False;
Exit;
end;
Result := True;
end;
function MD5String(const Str: WideString): TMD5Digest;
var
Context : TMD5Context;
begin
MD5Init(Context);
MD5Update(Context, Str);
MD5Final(Context, Result);
end;
var
MD5Table : array [0..63] of LongWord;
initialization
for i := 0 to 63 do
MD5Table[i] := Trunc(abs(sin(i + 1)) * 4294967296);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment