delphi 64位MD5算法

来源:互联网 发布:网络销售公司介绍 编辑:程序博客网 时间:2024/04/30 03:32

http://blog.csdn.net/bamboocaep/article/details/7212020

看到网上有人说indy的md5在64位下计算结果与32位下不一致。我测试了一下,确实如此,因此把自己用的64位计算结果正确的md5函数代码发出来。

说明1:这个单元的代码是从indy的md5代码修改而来的。

说明2:计算TBytes和String的MD5值可以使用TBytesStream或TStringStream。

说明3:计算结果转换为HEX字符的代码请自行编写。

unit BambooMD5;

interface

uses
SysUtils,
Classes;

function BambooMD5Stream(aStream: TStream): TBytes;

implementation

uses
Math;

type
T4x4LongWordRecord = array [0 .. 3] of LongWord;
T16x4LongWordRecord = array [0 .. 15] of LongWord;

function ROL(const AVal: LongWord; AShift: Byte): LongWord; assembler;
asm
{$IFDEF CPUX64}
mov eax, ecx
{$ELSE}
{$ENDIF !CPUX64}
mov cl, dl
rol eax, cl
end;

const
MD4_INIT_VALUES: T4x4LongWordRecord = ($67452301, $EFCDAB89, $98BADCFE, $10325476);

MD5_SINE: array [1 .. 64] of LongWord = (
{ Round 1. }
$D76AA478, $E8C7B756, $242070DB, $C1BDCEEE, $F57C0FAF, $4787C62A, $A8304613, $FD469501, $698098D8, $8B44F7AF, $FFFF5BB1, $895CD7BE, $6B901122, $FD987193, $A679438E, $49B40821,
{ Round 2. }
$F61E2562, $C040B340, $265E5A51, $E9B6C7AA, $D62F105D, $02441453, $D8A1E681, $E7D3FBC8, $21E1CDE6, $C33707D6, $F4D50D87, $455A14ED, $A9E3E905, $FCEFA3F8, $676F02D9, $8D2A4C8A,
{ Round 3. }
$FFFA3942, $8771F681, $6D9D6122, $FDE5380C, $A4BEEA44, $4BDECFA9, $F6BB4B60, $BEBFBC70, $289B7EC6, $EAA127FA, $D4EF3085, $04881D05, $D9D4D039, $E6DB99E5, $1FA27CF8, $C4AC5665,
{ Round 4. }
$F4292244, $432AFF97, $AB9423A7, $FC93A039, $655B59C3, $8F0CCC92, $FFEFF47D, $85845DD1, $6FA87E4F, $FE2CE6E0, $A3014314, $4E0811A1, $F7537E82, $BD3AF235, $2AD7D2BB, $EB86D391);
{$Q-}

procedure MDCoder(const FCBuffer: TBytes; var FState: T4x4LongWordRecord);
var
A, B, C, D: LongWord;
i: Integer;
X: T16x4LongWordRecord;
begin
A := FState[0];
B := FState[1];
C := FState[2];
D := FState[3];

for i := 0 to 15 do
begin
X[i] := FCBuffer[i * 4 + 0] + (FCBuffer[i * 4 + 1] shl 8) + (FCBuffer[i * 4 + 2] shl 16) + (FCBuffer[i * 4 + 3] shl 24);
end;
{ Round 1 }
A := ROL(A + (((D xor C) and B) xor D) + X[0] + MD5_SINE[1], 7) + B;
D := ROL(D + (((C xor B) and A) xor C) + X[1] + MD5_SINE[2], 12) + A;
C := ROL(C + (((B xor A) and D) xor B) + X[2] + MD5_SINE[3], 17) + D;
B := ROL(B + (((A xor D) and C) xor A) + X[3] + MD5_SINE[4], 22) + C;
A := ROL(A + (((D xor C) and B) xor D) + X[4] + MD5_SINE[5], 7) + B;
D := ROL(D + (((C xor B) and A) xor C) + X[5] + MD5_SINE[6], 12) + A;
C := ROL(C + (((B xor A) and D) xor B) + X[6] + MD5_SINE[7], 17) + D;
B := ROL(B + (((A xor D) and C) xor A) + X[7] + MD5_SINE[8], 22) + C;
A := ROL(A + (((D xor C) and B) xor D) + X[8] + MD5_SINE[9], 7) + B;
D := ROL(D + (((C xor B) and A) xor C) + X[9] + MD5_SINE[10], 12) + A;
C := ROL(C + (((B xor A) and D) xor B) + X[10] + MD5_SINE[11], 17) + D;
B := ROL(B + (((A xor D) and C) xor A) + X[11] + MD5_SINE[12], 22) + C;
A := ROL(A + (((D xor C) and B) xor D) + X[12] + MD5_SINE[13], 7) + B;
D := ROL(D + (((C xor B) and A) xor C) + X[13] + MD5_SINE[14], 12) + A;
C := ROL(C + (((B xor A) and D) xor B) + X[14] + MD5_SINE[15], 17) + D;
B := ROL(B + (((A xor D) and C) xor A) + X[15] + MD5_SINE[16], 22) + C;

{ Round 2 }
A := ROL(A + (C xor (D and (B xor C))) + X[1] + MD5_SINE[17], 5) + B;
D := ROL(D + (B xor (C and (A xor B))) + X[6] + MD5_SINE[18], 9) + A;
C := ROL(C + (A xor (B and (D xor A))) + X[11] + MD5_SINE[19], 14) + D;
B := ROL(B + (D xor (A and (C xor D))) + X[0] + MD5_SINE[20], 20) + C;
A := ROL(A + (C xor (D and (B xor C))) + X[5] + MD5_SINE[21], 5) + B;
D := ROL(D + (B xor (C and (A xor B))) + X[10] + MD5_SINE[22], 9) + A;
C := ROL(C + (A xor (B and (D xor A))) + X[15] + MD5_SINE[23], 14) + D;
B := ROL(B + (D xor (A and (C xor D))) + X[4] + MD5_SINE[24], 20) + C;
A := ROL(A + (C xor (D and (B xor C))) + X[9] + MD5_SINE[25], 5) + B;
D := ROL(D + (B xor (C and (A xor B))) + X[14] + MD5_SINE[26], 9) + A;
C := ROL(C + (A xor (B and (D xor A))) + X[3] + MD5_SINE[27], 14) + D;
B := ROL(B + (D xor (A and (C xor D))) + X[8] + MD5_SINE[28], 20) + C;
A := ROL(A + (C xor (D and (B xor C))) + X[13] + MD5_SINE[29], 5) + B;
D := ROL(D + (B xor (C and (A xor B))) + X[2] + MD5_SINE[30], 9) + A;
C := ROL(C + (A xor (B and (D xor A))) + X[7] + MD5_SINE[31], 14) + D;
B := ROL(B + (D xor (A and (C xor D))) + X[12] + MD5_SINE[32], 20) + C;

{ Round 3. }
A := ROL(A + (B xor C xor D) + X[5] + MD5_SINE[33], 4) + B;
D := ROL(D + (A xor B xor C) + X[8] + MD5_SINE[34], 11) + A;
C := ROL(C + (D xor A xor B) + X[11] + MD5_SINE[35], 16) + D;
B := ROL(B + (C xor D xor A) + X[14] + MD5_SINE[36], 23) + C;
A := ROL(A + (B xor C xor D) + X[1] + MD5_SINE[37], 4) + B;
D := ROL(D + (A xor B xor C) + X[4] + MD5_SINE[38], 11) + A;
C := ROL(C + (D xor A xor B) + X[7] + MD5_SINE[39], 16) + D;
B := ROL(B + (C xor D xor A) + X[10] + MD5_SINE[40], 23) + C;
A := ROL(A + (B xor C xor D) + X[13] + MD5_SINE[41], 4) + B;
D := ROL(D + (A xor B xor C) + X[0] + MD5_SINE[42], 11) + A;
C := ROL(C + (D xor A xor B) + X[3] + MD5_SINE[43], 16) + D;
B := ROL(B + (C xor D xor A) + X[6] + MD5_SINE[44], 23) + C;
A := ROL(A + (B xor C xor D) + X[9] + MD5_SINE[45], 4) + B;
D := ROL(D + (A xor B xor C) + X[12] + MD5_SINE[46], 11) + A;
C := ROL(C + (D xor A xor B) + X[15] + MD5_SINE[47], 16) + D;
B := ROL(B + (C xor D xor A) + X[2] + MD5_SINE[48], 23) + C;

{ Round 4. }
A := ROL(A + ((B or not D) xor C) + X[0] + MD5_SINE[49], 6) + B;
D := ROL(D + ((A or not C) xor B) + X[7] + MD5_SINE[50], 10) + A;
C := ROL(C + ((D or not B) xor A) + X[14] + MD5_SINE[51], 15) + D;
B := ROL(B + ((C or not A) xor D) + X[5] + MD5_SINE[52], 21) + C;
A := ROL(A + ((B or not D) xor C) + X[12] + MD5_SINE[53], 6) + B;
D := ROL(D + ((A or not C) xor B) + X[3] + MD5_SINE[54], 10) + A;
C := ROL(C + ((D or not B) xor A) + X[10] + MD5_SINE[55], 15) + D;
B := ROL(B + ((C or not A) xor D) + X[1] + MD5_SINE[56], 21) + C;
A := ROL(A + ((B or not D) xor C) + X[8] + MD5_SINE[57], 6) + B;
D := ROL(D + ((A or not C) xor B) + X[15] + MD5_SINE[58], 10) + A;
C := ROL(C + ((D or not B) xor A) + X[6] + MD5_SINE[59], 15) + D;
B := ROL(B + ((C or not A) xor D) + X[13] + MD5_SINE[60], 21) + C;
A := ROL(A + ((B or not D) xor C) + X[4] + MD5_SINE[61], 6) + B;
D := ROL(D + ((A or not C) xor B) + X[11] + MD5_SINE[62], 10) + A;
C := ROL(C + ((D or not B) xor A) + X[2] + MD5_SINE[63], 15) + D;
B := ROL(B + ((C or not A) xor D) + X[9] + MD5_SINE[64], 21) + C;

Inc(FState[0], A);
Inc(FState[1], B);
Inc(FState[2], C);
Inc(FState[3], D);
end;
{$Q+}

function ReadTIdBytesFromStream(const aStream: TStream; var VBytes: TBytes; const ACount: Int64): Int64;
var
LActual: Integer;
begin
Assert(aStream <> nil);
Result := 0;

if VBytes = nil then
SetLength(VBytes, 0);

LActual := ACount;
if LActual < 0 then
LActual := aStream.Size - aStream.Position;

if LActual = 0 then
Exit;

if Length(VBytes) < (LActual) then
SetLength(VBytes, LActual);

Assert(VBytes <> nil);
Result := aStream.Read(VBytes[0], LActual);
end;

procedure CopyTIdLongWord(const ASource: LongWord; var VDest: TBytes; const ADestIndex: Integer);
begin
PLongWord(@VDest[ADestIndex])^ := ASource;
end;

function GetHashBytes(aStream: TStream; ASize: Int64): TBytes;
var
LStartPos: Integer;
LSize: Int64;
LBitSize: Int64;
i, LReadSize: Integer;
FState: T4x4LongWordRecord;
FCBuffer: TBytes;
begin
Result := nil;

LSize := ASize;

for i := 0 to 3 do
FState[i] := MD4_INIT_VALUES[i];

while LSize >= 64 do
begin
LReadSize := ReadTIdBytesFromStream(aStream, FCBuffer, 64);

MDCoder(FCBuffer, FState);
Dec(LSize, LReadSize);
end;

LStartPos := ReadTIdBytesFromStream(aStream, FCBuffer, 64);

FCBuffer[LStartPos] := $80;
Inc(LStartPos);

if LStartPos > 56 then
begin
for i := LStartPos to 63 do
FCBuffer[i] := 0;
MDCoder(FCBuffer, FState);
LStartPos := 0;
end;

for i := LStartPos to 55 do
FCBuffer[i] := 0;

LBitSize := ASize * 8;
for i := 56 to 63 do
begin
FCBuffer[i] := LBitSize and $FF;
LBitSize := LBitSize shr 8;
end;
MDCoder(FCBuffer, FState);

SetLength(Result, SizeOf(LongWord) * 4);
for i := 0 to 3 do
CopyTIdLongWord(FState[i], Result, SizeOf(LongWord) * i);
end;

function Hash_Stream(aStream: TStream; const AStartPos, ASize: Int64): TBytes;
var
LSize, LAvailable: Int64;
begin
if AStartPos >= 0 then
aStream.Position := AStartPos;
LAvailable := aStream.Size - aStream.Position;
if ASize < 0 then
LSize := LAvailable
else
LSize := Min(LAvailable, ASize);
Result := GetHashBytes(aStream, LSize);
end;

function BambooMD5Stream(aStream: TStream): TBytes;
begin
if aStream = nil then
begin
Result := nil;
Exit;
end;
aStream.Position := 0;
Result := Hash_Stream(aStream, -1, -1);
end;

end.