关于在Delphi中实现md5加密的问题(50分)

  • 主题发起人 主题发起人 Zach
  • 开始时间 开始时间
Z

Zach

Unregistered / Unconfirmed
GUEST, unregistred user!
如何实现?有没有自带的函数?谢谢各位大哥!~
 
MD5是不可逆的,意义有多大呢?
 
**声明:这是我以前收藏的别人写的,已记不起来自哪了,此为转贴:

[h1]
MD5算法​
[/h1]

1、MD5算法是对输入的数据进行补位,使得如果数据位
长度LEN对512求余的结果是448。
即数据扩展至K*512+448位。即K*64+56个字节,K为
整数。
具体补位操作:补一个1,然后补0至满足上述要求
2、补数据长度:
用一个64位的数字表示数据的原始长度B,把B用两个
32位数表示。这时,数据就被填
补成长度为512位的倍数。
3. 初始化MD5参数
四个32位整数 (A,B,C,D) 用来计算信息摘要,初始
化使用的是十六进制表示的数字
A=0X01234567
B=0X89abcdef
C=0Xfedcba98
D=0X76543210
4、处理位操作函数
X,Y,Z为32位整数。
F(X,Y,Z) = X&Y|NOT(X)&Z
G(X,Y,Z) = X&Z|Y¬(Z)
H(X,Y,Z) = X xor Y xor Z
I(X,Y,Z) = Y xor (X|not(Z))
5、主要变换过程:
使用常数组T[1 ... 64], T为32位整数用16进制
表示,数据用16个32位的整
数数组M[]表示。
具体过程如下:
/* 处理数据原文 */
For i = 0 to N/16-1 do
/*每一次,把数据原文存放在16个元素的数组X中. */
For j = 0 to 15 do
Set X[j] to M[i*16+j].
end /结束对J的循环
/* Save A as AA, B as BB, C as CC, and D as DD.
*/
AA = A
BB = B
CC = C
DD = D
/* 第1轮*/
/* 以 [abcd k s i]表示如下操作
a = b + ((a + F(b,c,d) + X[k] + T) <<< s). */
/* Do the following 16 operations. */
[ABCD 0 7 1] [DABC 1 12 2] [CDAB 2 17 3] [BCDA 3
22 4]
[ABCD 4 7 5] [DABC 5 12 6] [CDAB 6 17 7] [BCDA 7
22 8]
[ABCD 8 7 9] [DABC 9 12 10] [CDAB 10 17 11] [BCDA
11 22 12]
[ABCD 12 7 13] [DABC 13 12 14] [CDAB 14 17 15]
[BCDA 15 22 16]
/* 第2轮* */
/* 以 [abcd k s i]表示如下操作
a = b + ((a + G(b,c,d) + X[k] + T) <<< s). */
/* Do the following 16 operations. */
[ABCD 1 5 17] [DABC 6 9 18] [CDAB 11 14 19] [BCDA
0 20 20]
[ABCD 5 5 21] [DABC 10 9 22] [CDAB 15 14 23]
[BCDA 4 20 24]
[ABCD 9 5 25] [DABC 14 9 26] [CDAB 3 14 27] [BCDA
8 20 28]
[ABCD 13 5 29] [DABC 2 9 30] [CDAB 7 14 31] [BCDA
12 20 32]
/* 第3轮*/
/* 以 [abcd k s i]表示如下操作
a = b + ((a + H(b,c,d) + X[k] + T) <<< s). */
/* Do the following 16 operations. */
[ABCD 5 4 33] [DABC 8 11 34] [CDAB 11 16 35]
[BCDA 14 23 36]
[ABCD 1 4 37] [DABC 4 11 38] [CDAB 7 16 39] [BCDA
10 23 40]
[ABCD 13 4 41] [DABC 0 11 42] [CDAB 3 16 43]
[BCDA 6 23 44]
[ABCD 9 4 45] [DABC 12 11 46] [CDAB 15 16 47]
[BCDA 2 23 48]
/* 第4轮*/
/* 以 [abcd k s i]表示如下操作
a = b + ((a + I(b,c,d) + X[k] + T) <<< s). */
/* Do the following 16 operations. */
[ABCD 0 6 49] [DABC 7 10 50] [CDAB 14 15 51]
[BCDA 5 21 52]
[ABCD 12 6 53] [DABC 3 10 54] [CDAB 10 15 55]
[BCDA 1 21 56]
[ABCD 8 6 57] [DABC 15 10 58] [CDAB 6 15 59]
[BCDA 13 21 60]
[ABCD 4 6 61] [DABC 11 10 62] [CDAB 2 15 63]
[BCDA 9 21 64]
/* 然后进行如下操作 */
A = A + AA
B = B + BB
C = C + CC
D = D + DD
end /* 结束对I的循环*/

6、输出结果。


{*******************************}
{ }
{ MD5哈希算法单元 }
{ author: 19'98 Yankovsky }
{ Date: 6.1.2002 }
{ }
{*******************************}
{-------------------------------------------------------------------------------
UNIT: MD5Unit

Sample:
procedure TForm1.Button1Click(Sender: TObject);
var
MD5Hash: TMD5;
OutputArray: array[0..15] of Char;
begin
MD5Hash := TMD5.Create;
try
MD5Hash.InputType := itString;
MD5Hash.InputString := Edit1.Text;
MD5Hash.POutputArray := @OutputArray;
MD5Hash.HashCalc;
Edit1.Text := OutputArray;
finally
MD5Hash.Free;
end;
end;
-------------------------------------------------------------------------------}
unit MD5;

interface

uses SysUtils;

type
PLong = ^Longword;
TInputType = (itString, itFile, itByteArray);

PHashDigest = ^THashDigest;
THashDigest = record
A,
B,
C,
D: Longword;
end;

TMD5 = class
private
FInputType: TInputType;
FInputString: string;
FInputFilePath: string;
FPInputArray: PByteArray;
FInputLength: Longword;
FOutputDigest: PHashDigest;
FActiveBlock: array[0..15] of Longword;
FA, FB, FC, FD, FAA, FBB, FCC, FDD: Longword;
FpA, FpB, FpC, FpD: PLong;
procedure FF(a, b, c, d, x: Pointer
s: Byte
ac: Longword);
procedure GG(a, b, c, d, x: Pointer
s: Byte
ac: Longword);
procedure HH(a, b, c, d, x: Pointer
s: Byte
ac: Longword);
procedure II(a, b, c, d, x: Pointer
s: Byte
ac: Longword);
public
procedure HashInit;
procedure HashTransform;
procedure HashFinish;
procedure HashBytes;
procedure HashFile;
procedure HashCalc;
property InputType: TInputType read FInputType write FInputType;
property InputString: string read FInputString write FInputString;
property InputFilePath: string read FInputFilePath write FInputFilePath;
property PInputArray: PByteArray read FPInputArray write FPInputArray;
property InputLength: Longword read FInputLength write FInputLength;
property POutputArray: PHashDigest read FOutputDigest write FOutputDigest;
end;

const
S11 = 7;
S12 = 12;
S13 = 17;
S14 = 22;
S21 = 5;
S22 = 9;
S23 = 14;
S24 = 20;
S31 = 4;
S32 = 11;
S33 = 16;
S34 = 23;
S41 = 6;
S42 = 10;
S43 = 15;
S44 = 21;

implementation

function ROL(val: Longword
shift: Byte): LongWord
assembler;
asm
MOV EAX, val;
MOV CL, shift;
ROL EAX, CL;
end;

procedure TMD5.HashInit;
var
a, b, c, d: Longword;
begin
a := $67452301;
b := $efcdab89;
c := $98badcfe;
d := $10325476;
Move(a, FA, 4);
FpA := @FA;
Move(b, FB, 4);
FpB := @FB;
Move(c, FC, 4);
FpC := @FC;
Move(d, FD, 4);
FpD := @FD;
end;

{Purpose: Round 1 of the Transform.
Equivalent to a = b + ((a + F(b,c,d) + x + ac) <<< s)
Where F(b,c,d) = b And c Or Not(b) And d}
procedure TMD5.FF(a, b, c, d, x: Pointer
s: Byte
ac: Longword);
var
Fret: Longword;
begin
Fret := ((PLong(b)^) and (PLong(c)^)) or ((not(PLong(b)^)) and (PLong(d)^));
PLong(a)^ := PLong(a)^ + Fret + PLong(x)^ + ac;
Longword(a^) := ROL(Longword(a^), s);
Inc(PLong(a)^, PLong(b)^);
end;

{Purpose: Round 2 of the Transform.
Equivalent to a = b + ((a + G(b,c,d) + x + ac) <<< s)
Where G(b,c,d) = b And d Or c Not d}
procedure TMD5.GG(a, b, c, d, x: Pointer
s: Byte
ac: Longword);
var
Gret: Longword;
begin
Gret := (PLong(b)^ and PLong(d)^) or ( PLong(c)^ and (not PLong(d)^));
PLong(a)^ := PLong(a)^ + Gret + PLong(x)^ + ac;
Longword(a^) := ROL(Longword(a^), s);
Inc(PLong(a)^, PLong(b)^);
end;

{Purpose: Round 3 of the Transform.
Equivalent to a = b + ((a + H(b,c,d) + x + ac) <<< s)
Where H(b,c,d) = b Xor c Xor d}
procedure TMD5.HH(a, b, c, d, x: Pointer
s: Byte
ac: Longword);
var
Hret: Longword;
begin
Hret := PLong(b)^ xor PLong(c)^ xor PLong(d)^;
PLong(a)^ := PLong(a)^ + Hret + PLong(x)^ + ac;
Longword(a^) := ROL(Longword(a^), s);
PLong(a)^ := PLong(b)^ + PLong(a)^;
end;

{Purpose: Round 4 of the Transform.
Equivalent to a = b + ((a + I(b,c,d) + x + ac) <<< s)
Where I(b,c,d) = C Xor (b Or Not(d))}
procedure TMD5.II(a, b, c, d, x: Pointer
s: Byte
ac: Longword);
var
Iret: Longword;
begin
Iret := (PLong(c)^ xor (PLong(b)^ or (not PLong(d)^)));
PLong(a)^ := PLong(a)^ + Iret + PLong(x)^ + ac;
Longword(a^) := ROL(PLong(a)^, s );
PLong(a)^ := PLong(b)^ + PLong(a)^;
end;

{Purpose: Perform Step 4 of the algorithm. This is where all the important
stuff happens. This performs the rounds on a 64Byte Block. This
procedure should be called in a loop until all input data has been
transformed.}
procedure TMD5.HashTransform;
begin
FAA := FA;
FBB := FB;
FCC := FC;
FDD := FD;

{ Round 1 }
FF(FpA, FpB, FpC, FpD, @FActiveBlock[ 0], S11, $d76aa478)
{ 1 }
FF(FpD, FpA, FpB, FpC, @FActiveBlock[ 1], S12, $e8c7b756)
{ 2 }
FF(FpC, FpD, FpA, FpB, @FActiveBlock[ 2], S13, $242070db)
{ 3 }
FF(FpB, FpC, FpD, FpA, @FActiveBlock[ 3], S14, $c1bdceee)
{ 4 }
FF(FpA, FpB, FpC, FpD, @FActiveBlock[ 4], S11, $f57c0faf)
{ 5 }
FF(FpD, FpA, FpB, FpC, @FActiveBlock[ 5], S12, $4787c62a)
{ 6 }
FF(FpC, FpD, FpA, FpB, @FActiveBlock[ 6], S13, $a8304613)
{ 7 }
FF(FpB, FpC, FpD, FpA, @FActiveBlock[ 7], S14, $fd469501)
{ 8 }
FF(FpA, FpB, FpC, FpD, @FActiveBlock[ 8], S11, $698098d8)
{ 9 }
FF(FpD, FpA, FpB, FpC, @FActiveBlock[ 9], S12, $8b44f7af)
{ 10 }
FF(FpC, FpD, FpA, FpB, @FActiveBlock[10], S13, $ffff5bb1)
{ 11 }
FF(FpB, FpC, FpD, FpA, @FActiveBlock[11], S14, $895cd7be)
{ 12 }
FF(FpA, FpB, FpC, FpD, @FActiveBlock[12], S11, $6b901122)
{ 13 }
FF(FpD, FpA, FpB, FpC, @FActiveBlock[13], S12, $fd987193)
{ 14 }
FF(FpC, FpD, FpA, FpB, @FActiveBlock[14], S13, $a679438e)
{ 15 }
FF(FpB, FpC, FpD, FpA, @FActiveBlock[15], S14, $49b40821)
{ 16 }

{ Round 2 }
GG(FpA, FpB, FpC, FpD, @FActiveBlock[ 1], S21, $f61e2562)
{ 17 }
GG(FpD, FpA, FpB, FpC, @FActiveBlock[ 6], S22, $c040b340)
{ 18 }
GG(FpC, FpD, FpA, FpB, @FActiveBlock[11], S23, $265e5a51)
{ 19 }
GG(FpB, FpC, FpD, FpA, @FActiveBlock[ 0], S24, $e9b6c7aa)
{ 20 }
GG(FpA, FpB, FpC, FpD, @FActiveBlock[ 5], S21, $d62f105d)
{ 21 }
GG(FpD, FpA, FpB, FpC, @FActiveBlock[10], S22, $02441453)
{ 22 }
GG(FpC, FpD, FpA, FpB, @FActiveBlock[15], S23, $d8a1e681)
{ 23 }
GG(FpB, FpC, FpD, FpA, @FActiveBlock[ 4], S24, $e7d3fbc8)
{ 24 }
GG(FpA, FpB, FpC, FpD, @FActiveBlock[ 9], S21, $21e1cde6)
{ 25 }
GG(FpD, FpA, FpB, FpC, @FActiveBlock[14], S22, $c33707d6)
{ 26 }
GG(FpC, FpD, FpA, FpB, @FActiveBlock[ 3], S23, $f4d50d87)
{ 27 }
GG(FpB, FpC, FpD, FpA, @FActiveBlock[ 8], S24, $455a14ed)
{ 28 }
GG(FpA, FpB, FpC, FpD, @FActiveBlock[13], S21, $a9e3e905)
{ 29 }
GG(FpD, FpA, FpB, FpC, @FActiveBlock[ 2], S22, $fcefa3f8)
{ 30 }
GG(FpC, FpD, FpA, FpB, @FActiveBlock[ 7], S23, $676f02d9)
{ 31 }
GG(FpB, FpC, FpD, FpA, @FActiveBlock[12], S24, $8d2a4c8a)
{ 32 }

{ Round 3 }
HH(FpA, FpB, FpC, FpD, @FActiveBlock[ 5], S31, $fffa3942)
{ 33 }
HH(FpD, FpA, FpB, FpC, @FActiveBlock[ 8], S32, $8771f681)
{ 34 }
HH(FpC, FpD, FpA, FpB, @FActiveBlock[11], S33, $6d9d6122)
{ 35 }
HH(FpB, FpC, FpD, FpA, @FActiveBlock[14], S34, $fde5380c)
{ 36 }
HH(FpA, FpB, FpC, FpD, @FActiveBlock[ 1], S31, $a4beea44)
{ 37 }
HH(FpD, FpA, FpB, FpC, @FActiveBlock[ 4], S32, $4bdecfa9)
{ 38 }
HH(FpC, FpD, FpA, FpB, @FActiveBlock[ 7], S33, $f6bb4b60)
{ 39 }
HH(FpB, FpC, FpD, FpA, @FActiveBlock[10], S34, $bebfbc70)
{ 40 }
HH(FpA, FpB, FpC, FpD, @FActiveBlock[13], S31, $289b7ec6)
{ 41 }
HH(FpD, FpA, FpB, FpC, @FActiveBlock[ 0], S32, $eaa127fa)
{ 42 }
HH(FpC, FpD, FpA, FpB, @FActiveBlock[ 3], S33, $d4ef3085)
{ 43 }
HH(FpB, FpC, FpD, FpA, @FActiveBlock[ 6], S34, $04881d05)
{ 44 }
HH(FpA, FpB, FpC, FpD, @FActiveBlock[ 9], S31, $d9d4d039)
{ 45 }
HH(FpD, FpA, FpB, FpC, @FActiveBlock[12], S32, $e6db99e5)
{ 46 }
HH(FpC, FpD, FpA, FpB, @FActiveBlock[15], S33, $1fa27cf8)
{ 47 }
HH(FpB, FpC, FpD, FpA, @FActiveBlock[ 2], S34, $c4ac5665)
{ 48 }

{ Round 4 }
II(FpA, FpB, FpC, FpD, @FActiveBlock[ 0], S41, $f4292244)
{ 49 }
II(FpD, FpA, FpB, FpC, @FActiveBlock[ 7], S42, $432aff97)
{ 50 }
II(FpC, FpD, FpA, FpB, @FActiveBlock[14], S43, $ab9423a7)
{ 51 }
II(FpB, FpC, FpD, FpA, @FActiveBlock[ 5], S44, $fc93a039)
{ 52 }
II(FpA, FpB, FpC, FpD, @FActiveBlock[12], S41, $655b59c3)
{ 53 }
II(FpD, FpA, FpB, FpC, @FActiveBlock[ 3], S42, $8f0ccc92)
{ 54 }
II(FpC, FpD, FpA, FpB, @FActiveBlock[10], S43, $ffeff47d)
{ 55 }
II(FpB, FpC, FpD, FpA, @FActiveBlock[ 1], S44, $85845dd1)
{ 56 }
II(FpA, FpB, FpC, FpD, @FActiveBlock[ 8], S41, $6fa87e4f)
{ 57 }
II(FpD, FpA, FpB, FpC, @FActiveBlock[15], S42, $fe2ce6e0)
{ 58 }
II(FpC, FpD, FpA, FpB, @FActiveBlock[ 6], S43, $a3014314)
{ 59 }
II(FpB, FpC, FpD, FpA, @FActiveBlock[13], S44, $4e0811a1)
{ 60 }
II(FpA, FpB, FpC, FpD, @FActiveBlock[ 4], S41, $f7537e82)
{ 61 }
II(FpD, FpA, FpB, FpC, @FActiveBlock[11], S42, $bd3af235)
{ 62 }
II(FpC, FpD, FpA, FpB, @FActiveBlock[ 2], S43, $2ad7d2bb)
{ 63 }
II(FpB, FpC, FpD, FpA, @FActiveBlock[ 9], S44, $eb86d391)
{ 64 }

Inc(FA, FAA);
Inc(FB, FBB);
Inc(FC, FCC);
Inc(FD, FDD);

FillChar(FActiveBlock, SizeOf(FActiveBlock), #0);
end;

procedure TMD5.HashCalc;
var
PStr: PChar;
begin
HashInit;
case FInputType of
itFile:
HashFile;
itByteArray:
HashBytes;
itString:
begin
PStr := StrAlloc(Length(FInputString) + 1);
try
StrPCopy(PStr, FInputString);
FInputLength := Length(FInputString);
FPInputArray := Pointer(PStr);
HashBytes;
finally
StrDispose(PStr);
end;
end;
end;
HashFinish;
end;

procedure TMD5.HashBytes;
var
Buffer: array[0..4159] of Byte;
Count64: Comp;
Index: Longword;
begin
Move(FPInputArray^, Buffer, FInputLength);
Count64 := FInputLength * 8;
Buffer[FInputLength] := $80;
Inc(FInputLength);
while (FInputLength mod 64) <> 56 do
begin
Buffer[FInputLength] := 0;
Inc(FInputLength);
end;
Move(Count64, Buffer[FInputLength], SizeOf(Count64));
Index := 0;
Inc(FInputLength, 8);
repeat
Move(Buffer[Index], FActiveBlock, 64);
HashTransform;
Inc(Index, 64);
until Index = FInputLength;
end;

procedure TMD5.HashFile;
var
DoneFile: Boolean;
InputFile: file;
Count64: Comp;
Index, NumRead: Integer;
Buffer: array[0..4159] of Byte;
begin
DoneFile := False;
AssignFile(InputFile, FInputFilePath);
Reset(InputFile, 1);
Count64 := 0;
repeat
BlockRead(InputFile, Buffer, 4096, NumRead);
Count64 := Count64 + NumRead;
if NumRead <> 4096 then
begin
Buffer[NumRead] := $80;
Inc(NumRead);
while (NumRead mod 64) <> 56 do
begin
Buffer[NumRead] := 0;
Inc(NumRead);
end;
Count64 := Count64 * 8;
Move(Count64, Buffer[NumRead], 8);
Inc(NumRead, 8);
DoneFile := True;
end;
Index := 0;
repeat
Move(Buffer[Index], FActiveBlock, 64);
HashTransform;
Inc(Index, 64);
until Index = NumRead;
until DoneFile;
CloseFile(InputFile);
end;

procedure TMD5.HashFinish;
begin
FOutputDigest^.A := Longword(FpA^);
FOutputDigest^.B := Longword(FpB^);
FOutputDigest^.C := Longword(FpC^);
FOutputDigest^.D := Longword(FpD^);
end;

end.

例子不是已经贴出来了吗:
procedure TForm1.Button1Click(Sender: TObject);
var
MD5Hash: TMD5;
OutputArray: array[0..15] of Char;
begin
MD5Hash := TMD5.Create;
try
MD5Hash.InputType := itString;
MD5Hash.InputString := Edit1.Text;
MD5Hash.POutputArray := @OutputArray;
MD5Hash.HashCalc;
Edit1.Text := OutputArray;
finally
MD5Hash.Free;
end;
end;
itString是要进行md5的字符串,Edit1.Text是转换后的字符串
 
下载md5.pas单元,直接调用加密函数就好了
 
MD5的处理远非这么简单 不相试试加密QQ的密码 [^]
 
请问lxw大哥,md5.pas在哪里下呢?
 
其实我是想自己做个md5大作战玩。。。=.=
 
unit MD5;

interface

uses
Windows;

type
MD5Count = array[0..1] of DWORD;
MD5State = array[0..3] of DWORD;
MD5Block = array[0..15] of DWORD;
MD5CBits = array[0..7] of byte;
MD5Digest = array[0..15] of byte;
MD5Buffer = array[0..63] of byte;
MD5Context = record
State: MD5State;
Count: MD5Count;
Buffer: MD5Buffer;
end;

procedure MD5Init(var Context: MD5Context);
procedure MD5Update(var Context: MD5Context
Input: pChar
Length: longword);
procedure MD5Final(var Context: MD5Context
var Digest: MD5Digest);

function MD5String(M: string): MD5Digest;
function MD5File(N: string): MD5Digest;
function MD5Print(D: MD5Digest): string;

function MD5Match(D1, D2: MD5Digest): boolean;

IMPLEMENTATION

var
PADDING: MD5Buffer = (
$80, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00,
$00, $00, $00, $00, $00, $00, $00, $00
);

function F(x, y, z: DWORD): DWORD;
begin
Result := (x and y) or ((not x) and z);
end;

function G(x, y, z: DWORD): DWORD;
begin
Result := (x and z) or (y and (not z));
end;

function H(x, y, z: DWORD): DWORD;
begin
Result := x xor y xor z;
end;

function I(x, y, z: DWORD): DWORD;
begin
Result := y xor (x or (not z));
end;

procedure rot(var x: DWORD
n: BYTE);
begin
x := (x shl n) or (x shr (32 - n));
end;

procedure FF(var a: DWORD
b, c, d, x: DWORD
s: BYTE
ac: DWORD);
begin
inc(a, F(b, c, d) + x + ac);
rot(a, s);
inc(a, b);
end;

procedure GG(var a: DWORD
b, c, d, x: DWORD
s: BYTE
ac: DWORD);
begin
inc(a, G(b, c, d) + x + ac);
rot(a, s);
inc(a, b);
end;

procedure HH(var a: DWORD
b, c, d, x: DWORD
s: BYTE
ac: DWORD);
begin
inc(a, H(b, c, d) + x + ac);
rot(a, s);
inc(a, b);
end;

procedure II(var a: DWORD
b, c, d, x: DWORD
s: BYTE
ac: DWORD);
begin
inc(a, I(b, c, d) + x + ac);
rot(a, s);
inc(a, b);
end;

// -----------------------------------------------------------------------------------------------

// Encode Count bytes at Source into (Count / 4) DWORDs at Target
procedure Encode(Source, Target: pointer
Count: longword);
var
S: PByte;
T: PDWORD;
I: longword;
begin
S := Source;
T := Target;
for I := 1 to Count div 4 do begin
T^ := S^;
inc(S);
T^ := T^ or (S^ shl 8);
inc(S);
T^ := T^ or (S^ shl 16);
inc(S);
T^ := T^ or (S^ shl 24);
inc(S);
inc(T);
end;
end;

// Decode Count DWORDs at Source into (Count * 4) Bytes at Target
procedure Decode(Source, Target: pointer
Count: longword);
var
S: PDWORD;
T: PByte;
I: longword;
begin
S := Source;
T := Target;
for I := 1 to Count do begin
T^ := S^ and $ff;
inc(T);
T^ := (S^ shr 8) and $ff;
inc(T);
T^ := (S^ shr 16) and $ff;
inc(T);
T^ := (S^ shr 24) and $ff;
inc(T);
inc(S);
end;
end;

// Transform State according to first 64 bytes at Buffer
procedure Transform(Buffer: pointer
var State: MD5State);
var
a, b, c, d: DWORD;
Block: MD5Block;
begin
Encode(Buffer, @Block, 64);
a := State[0];
b := State[1];
c := State[2];
d := State[3];
FF (a, b, c, d, Block[ 0], 7, $d76aa478);
FF (d, a, b, c, Block[ 1], 12, $e8c7b756);
FF (c, d, a, b, Block[ 2], 17, $242070db);
FF (b, c, d, a, Block[ 3], 22, $c1bdceee);
FF (a, b, c, d, Block[ 4], 7, $f57c0faf);
FF (d, a, b, c, Block[ 5], 12, $4787c62a);
FF (c, d, a, b, Block[ 6], 17, $a8304613);
FF (b, c, d, a, Block[ 7], 22, $fd469501);
FF (a, b, c, d, Block[ 8], 7, $698098d8);
FF (d, a, b, c, Block[ 9], 12, $8b44f7af);
FF (c, d, a, b, Block[10], 17, $ffff5bb1);
FF (b, c, d, a, Block[11], 22, $895cd7be);
FF (a, b, c, d, Block[12], 7, $6b901122);
FF (d, a, b, c, Block[13], 12, $fd987193);
FF (c, d, a, b, Block[14], 17, $a679438e);
FF (b, c, d, a, Block[15], 22, $49b40821);
GG (a, b, c, d, Block[ 1], 5, $f61e2562);
GG (d, a, b, c, Block[ 6], 9, $c040b340);
GG (c, d, a, b, Block[11], 14, $265e5a51);
GG (b, c, d, a, Block[ 0], 20, $e9b6c7aa);
GG (a, b, c, d, Block[ 5], 5, $d62f105d);
GG (d, a, b, c, Block[10], 9, $2441453);
GG (c, d, a, b, Block[15], 14, $d8a1e681);
GG (b, c, d, a, Block[ 4], 20, $e7d3fbc8);
GG (a, b, c, d, Block[ 9], 5, $21e1cde6);
GG (d, a, b, c, Block[14], 9, $c33707d6);
GG (c, d, a, b, Block[ 3], 14, $f4d50d87);
GG (b, c, d, a, Block[ 8], 20, $455a14ed);
GG (a, b, c, d, Block[13], 5, $a9e3e905);
GG (d, a, b, c, Block[ 2], 9, $fcefa3f8);
GG (c, d, a, b, Block[ 7], 14, $676f02d9);
GG (b, c, d, a, Block[12], 20, $8d2a4c8a);
HH (a, b, c, d, Block[ 5], 4, $fffa3942);
HH (d, a, b, c, Block[ 8], 11, $8771f681);
HH (c, d, a, b, Block[11], 16, $6d9d6122);
HH (b, c, d, a, Block[14], 23, $fde5380c);
HH (a, b, c, d, Block[ 1], 4, $a4beea44);
HH (d, a, b, c, Block[ 4], 11, $4bdecfa9);
HH (c, d, a, b, Block[ 7], 16, $f6bb4b60);
HH (b, c, d, a, Block[10], 23, $bebfbc70);
HH (a, b, c, d, Block[13], 4, $289b7ec6);
HH (d, a, b, c, Block[ 0], 11, $eaa127fa);
HH (c, d, a, b, Block[ 3], 16, $d4ef3085);
HH (b, c, d, a, Block[ 6], 23, $4881d05);
HH (a, b, c, d, Block[ 9], 4, $d9d4d039);
HH (d, a, b, c, Block[12], 11, $e6db99e5);
HH (c, d, a, b, Block[15], 16, $1fa27cf8);
HH (b, c, d, a, Block[ 2], 23, $c4ac5665);
II (a, b, c, d, Block[ 0], 6, $f4292244);
II (d, a, b, c, Block[ 7], 10, $432aff97);
II (c, d, a, b, Block[14], 15, $ab9423a7);
II (b, c, d, a, Block[ 5], 21, $fc93a039);
II (a, b, c, d, Block[12], 6, $655b59c3);
II (d, a, b, c, Block[ 3], 10, $8f0ccc92);
II (c, d, a, b, Block[10], 15, $ffeff47d);
II (b, c, d, a, Block[ 1], 21, $85845dd1);
II (a, b, c, d, Block[ 8], 6, $6fa87e4f);
II (d, a, b, c, Block[15], 10, $fe2ce6e0);
II (c, d, a, b, Block[ 6], 15, $a3014314);
II (b, c, d, a, Block[13], 21, $4e0811a1);
II (a, b, c, d, Block[ 4], 6, $f7537e82);
II (d, a, b, c, Block[11], 10, $bd3af235);
II (c, d, a, b, Block[ 2], 15, $2ad7d2bb);
II (b, c, d, a, Block[ 9], 21, $eb86d391);
inc(State[0], a);
inc(State[1], b);
inc(State[2], c);
inc(State[3], d);
end;

// -----------------------------------------------------------------------------------------------

// Initialize given Context
procedure MD5Init(var Context: MD5Context);
begin
with Context do begin
State[0] := $67452301;
State[1] := $efcdab89;
State[2] := $98badcfe;
State[3] := $10325476;
Count[0] := 0;
Count[1] := 0;
ZeroMemory(@Buffer, SizeOf(MD5Buffer));
end;
end;

// Update given Context to include Length bytes of Input
procedure MD5Update(var Context: MD5Context
Input: pChar
Length: longword);
var
Index: longword;
PartLen: longword;
I: longword;
begin
with Context do begin
Index := (Count[0] shr 3) and $3f;
inc(Count[0], Length shl 3);
if Count[0] < (Length shl 3) then inc(Count[1]);
inc(Count[1], Length shr 29);
end;
PartLen := 64 - Index;
if Length >= PartLen then begin
CopyMemory(@Context.Buffer[Index], Input, PartLen);
Transform(@Context.Buffer, Context.State);
I := PartLen;
while I + 63 < Length do begin
Transform(@Input, Context.State);
inc(I, 64);
end;
Index := 0;
end else I := 0;
CopyMemory(@Context.Buffer[Index], @Input, Length - I);
end;

// Finalize given Context, create Digest and zeroize Context
procedure MD5Final(var Context: MD5Context
var Digest: MD5Digest);
var
Bits: MD5CBits;
Index: longword;
PadLen: longword;
begin
Decode(@Context.Count, @Bits, 2);
Index := (Context.Count[0] shr 3) and $3f;
if Index < 56 then PadLen := 56 - Index else PadLen := 120 - Index;
MD5Update(Context, @PADDING, PadLen);
MD5Update(Context, @Bits, 8);
Decode(@Context.State, @Digest, 4);
ZeroMemory(@Context, SizeOf(MD5Context));
end;

// -----------------------------------------------------------------------------------------------

// Create digest of given Message
function MD5String(M: string): MD5Digest;
var
Context: MD5Context;
begin
MD5Init(Context);
MD5Update(Context, pChar(M), length(M));
MD5Final(Context, Result);
end;

// Create digest of file with given Name
function MD5File(N: string): MD5Digest;
var
FileHandle: THandle;
MapHandle: THandle;
ViewPointer: pointer;
Context: MD5Context;
begin
MD5Init(Context);
FileHandle := CreateFile(pChar(N), GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE,
nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_SEQUENTIAL_SCAN, 0);
if FileHandle <> INVALID_HANDLE_VALUE then try
MapHandle := CreateFileMapping(FileHandle, nil, PAGE_READONLY, 0, 0, nil);
if MapHandle <> 0 then try
ViewPointer := MapViewOfFile(MapHandle, FILE_MAP_READ, 0, 0, 0);
if ViewPointer <> nil then try
MD5Update(Context, ViewPointer, GetFileSize(FileHandle, nil));
finally
UnmapViewOfFile(ViewPointer);
end;
finally
CloseHandle(MapHandle);
end;
finally
CloseHandle(FileHandle);
end;
MD5Final(Context, Result);
end;

// Create hex representation of given Digest
function MD5Print(D: MD5Digest): string;
var
I: byte;
const
Digits: array[0..15] of char =
('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f');
begin
Result := '';
for I := 0 to 15 do Result := Result + Digits[(D shr 4) and $0f] + Digits[D and $0f];
end;

// -----------------------------------------------------------------------------------------------

// Compare two Digests
function MD5Match(D1, D2: MD5Digest): boolean;
var
I: byte;
begin
I := 0;
Result := TRUE;
while Result and (I < 16) do begin
Result := D1 = D2;
inc(I);
end;
end;

end.
 
后退
顶部