Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5833116
  • 博文数量: 671
  • 博客积分: 10010
  • 博客等级: 上将
  • 技术积分: 7310
  • 用 户 组: 普通用户
  • 注册时间: 2006-07-14 09:56
文章分类

全部博文(671)

文章存档

2011年(1)

2010年(2)

2009年(24)

2008年(271)

2007年(319)

2006年(54)

我的朋友

分类:

2007-04-24 16:39:40

文件下载:
文件: md5.rar
大小: 3KB
下载: 下载
unit MD5;
{**************************************************************************
   MD5 from rfc1231.txt
   Copyright (C) 2002 Go Maeda <>
   This work is derived from the RSA Data Security, Inc. MD5 Message-Digest
   Algorithm.
   author : Ayakawa,Marinosuke()
   2000/11/17 1st. convert to delphi
   2004/07/04 2nd. change param string to pbyte
   2004/07/09 3rd. fixed for large size file(2G over)
 **************************************************************************}
interface
uses
  windows,sysutils,classes;
function CalcMD5(ASrc:PByte; ASize:integer):string;
function CalcFileMD5(AFilename:string):string;
implementation
type
  UINT2 = WORD;
  UINT4 = DWORD;
  TARYUINT4 = array[0..3] of UINT4;
  TARYBYTE64 = array[0..63] of byte;
  TMD5_CTX = packed record
    state : TARYUINT4;
    count : array[0..1] of UINT4;
    buffer : TARYBYTE64;
  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;
  PADDING = #$80#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0+
            #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0+
            #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0+
            #0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0;
// F, G, H and I are basic MD5 functions.
function F(x,y,z:UINT4):UINT4;
begin
  result:= (x AND y) OR ((NOT x) AND z);
end;
function G(x,y,z:UINT4):UINT4;
begin
  result:= (x AND z) OR (y AND (NOT z));
end;
function H(x,y,z:UINT4):UINT4;
begin
  result:=x XOR y XOR z;
end;
function I(x,y,z:UINT4):UINT4;
begin
  result:=y XOR (x OR (NOT z));
end;
// ROTATE_LEFT rotates x left n bits.
function ROTATE_LEFT(x,n:DWORD):DWORD;
begin
  result:= (x SHL n) OR (x SHR (32-n));
end;
// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
// Rotation is separate from addition to prevent recomputation.
procedure FF(var a:DWORD; b,c,d,x,s,ac:DWORD);
begin
  a:=a+F(b,c,d)+x+ac;
  a:=ROTATE_LEFT(a,s);
  a:=a+b;
end;
procedure GG(var a:DWORD; b,c,d,x,s,ac:DWORD);
begin
  a:=a+G(b,c,d)+x+ac;
  a:=ROTATE_LEFT(a,s);
  a:=a+b;
end;
procedure HH(var a:DWORD; b,c,d,x,s,ac:DWORD);
begin
  a:=a+H(b,c,d)+x+ac;
  a:=ROTATE_LEFT(a,s);
  a:=a+b;
end;
procedure II(var a:DWORD; b,c,d,x,s,ac:DWORD);
begin
  a:=a+I(b,c,d)+x+ac;
  a:=ROTATE_LEFT(a,s);
  a:=a+b;
end;
// for (i=0; ibuffer[bufidx+i]=src[srcidx+i]
procedure MD5_memcpy(var context:TMD5_CTX; bufidx:integer; src:PByte; srcidx:integer; cpylen:integer);
var
  i : integer;
  p : PByte;
begin
  // srcidx 0-origin. but string is 1-origin => 1+srcidx+i
  //FOR i:=0 TO cpylen-1 DO context.buffer[bufidx+i]:=BYTE(ord(src[1+srcidx+i]));
  p:=src;
  Inc(p,srcidx);
  FOR i:=0 TO cpylen-1 DO BEGIN
    context.buffer[bufidx+i]:=p^; Inc(p);
  END;
end;
// MD5 basic transformation. Transforms state based on block.
procedure MD5Transform(var state:TARYUINT4; block:TARYBYTE64);
var
  a,b,c,d : UINT4;
  x : array[0..15] of UINT4;
  procedure Decode;
  var
    i,j : integer;
  begin
    i:=0; j:=0;
    WHILE j<64 DO BEGIN
      x[i]:=block[j] OR (block[j+1] SHL 8) OR (block[j+2] SHL 16) OR (block[j+3] SHL 24);
      INC(i); INC(j,4);
    END;
  end;
begin
  a:=state[0]; b:=state[1]; c:=state[2]; d:=state[3];
  Decode;
  //* Round 1 */
  FF (a, b, c, d, x[ 0], S11, $d76aa478); //* 1 */
  FF (d, a, b, c, x[ 1], S12, $e8c7b756); //* 2 */
  FF (c, d, a, b, x[ 2], S13, $242070db); //* 3 */
  FF (b, c, d, a, x[ 3], S14, $c1bdceee); //* 4 */
  FF (a, b, c, d, x[ 4], S11, $f57c0faf); //* 5 */
  FF (d, a, b, c, x[ 5], S12, $4787c62a); //* 6 */
  FF (c, d, a, b, x[ 6], S13, $a8304613); //* 7 */
  FF (b, c, d, a, x[ 7], S14, $fd469501); //* 8 */
  FF (a, b, c, d, x[ 8], S11, $698098d8); //* 9 */
  FF (d, a, b, c, x[ 9], S12, $8b44f7af); //* 10 */
  FF (c, d, a, b, x[10], S13, $ffff5bb1); //* 11 */
  FF (b, c, d, a, x[11], S14, $895cd7be); //* 12 */
  FF (a, b, c, d, x[12], S11, $6b901122); //* 13 */
  FF (d, a, b, c, x[13], S12, $fd987193); //* 14 */
  FF (c, d, a, b, x[14], S13, $a679438e); //* 15 */
  FF (b, c, d, a, x[15], S14, $49b40821); //* 16 */
 //* Round 2 */
  GG (a, b, c, d, x[ 1], S21, $f61e2562); //* 17 */
  GG (d, a, b, c, x[ 6], S22, $c040b340); //* 18 */
  GG (c, d, a, b, x[11], S23, $265e5a51); //* 19 */
  GG (b, c, d, a, x[ 0], S24, $e9b6c7aa); //* 20 */
  GG (a, b, c, d, x[ 5], S21, $d62f105d); //* 21 */
  GG (d, a, b, c, x[10], S22,  $2441453); //* 22 */
  GG (c, d, a, b, x[15], S23, $d8a1e681); //* 23 */
  GG (b, c, d, a, x[ 4], S24, $e7d3fbc8); //* 24 */
  GG (a, b, c, d, x[ 9], S21, $21e1cde6); //* 25 */
  GG (d, a, b, c, x[14], S22, $c33707d6); //* 26 */
  GG (c, d, a, b, x[ 3], S23, $f4d50d87); //* 27 */
  GG (b, c, d, a, x[ 8], S24, $455a14ed); //* 28 */
  GG (a, b, c, d, x[13], S21, $a9e3e905); //* 29 */
  GG (d, a, b, c, x[ 2], S22, $fcefa3f8); //* 30 */
  GG (c, d, a, b, x[ 7], S23, $676f02d9); //* 31 */
  GG (b, c, d, a, x[12], S24, $8d2a4c8a); //* 32 */
  //* Round 3 */
  HH (a, b, c, d, x[ 5], S31, $fffa3942); //* 33 */
  HH (d, a, b, c, x[ 8], S32, $8771f681); //* 34 */
  HH (c, d, a, b, x[11], S33, $6d9d6122); //* 35 */
  HH (b, c, d, a, x[14], S34, $fde5380c); //* 36 */
  HH (a, b, c, d, x[ 1], S31, $a4beea44); //* 37 */
  HH (d, a, b, c, x[ 4], S32, $4bdecfa9); //* 38 */
  HH (c, d, a, b, x[ 7], S33, $f6bb4b60); //* 39 */
  HH (b, c, d, a, x[10], S34, $bebfbc70); //* 40 */
  HH (a, b, c, d, x[13], S31, $289b7ec6); //* 41 */
  HH (d, a, b, c, x[ 0], S32, $eaa127fa); //* 42 */
  HH (c, d, a, b, x[ 3], S33, $d4ef3085); //* 43 */
  HH (b, c, d, a, x[ 6], S34,  $4881d05); //* 44 */
  HH (a, b, c, d, x[ 9], S31, $d9d4d039); //* 45 */
  HH (d, a, b, c, x[12], S32, $e6db99e5); //* 46 */
  HH (c, d, a, b, x[15], S33, $1fa27cf8); //* 47 */
  HH (b, c, d, a, x[ 2], S34, $c4ac5665); //* 48 */
  //* Round 4 */
  II (a, b, c, d, x[ 0], S41, $f4292244); //* 49 */
  II (d, a, b, c, x[ 7], S42, $432aff97); //* 50 */
  II (c, d, a, b, x[14], S43, $ab9423a7); //* 51 */
  II (b, c, d, a, x[ 5], S44, $fc93a039); //* 52 */
  II (a, b, c, d, x[12], S41, $655b59c3); //* 53 */
  II (d, a, b, c, x[ 3], S42, $8f0ccc92); //* 54 */
  II (c, d, a, b, x[10], S43, $ffeff47d); //* 55 */
  II (b, c, d, a, x[ 1], S44, $85845dd1); //* 56 */
  II (a, b, c, d, x[ 8], S41, $6fa87e4f); //* 57 */
  II (d, a, b, c, x[15], S42, $fe2ce6e0); //* 58 */
  II (c, d, a, b, x[ 6], S43, $a3014314); //* 59 */
  II (b, c, d, a, x[13], S44, $4e0811a1); //* 60 */
  II (a, b, c, d, x[ 4], S41, $f7537e82); //* 61 */
  II (d, a, b, c, x[11], S42, $bd3af235); //* 62 */
  II (c, d, a, b, x[ 2], S43, $2ad7d2bb); //* 63 */
  II (b, c, d, a, x[ 9], S44, $eb86d391); //* 64 */
  INC(state[0],a);
  INC(state[1],b);
  INC(state[2],c);
  INC(state[3],d);
  // Zeroize sensitive information.
  FillChar(x[0],sizeof(x),0); // MD5_memset
end;
///////////////////////////////////////////////////////////////////////////
//
// MD5 initialization. Begins an MD5 operation, writing a new context.
//
///////////////////////////////////////////////////////////////////////////
procedure MD5Init(var md5ctx:TMD5_CTX);
begin
  WITH md5ctx DO BEGIN
    count[0]:=0;
    count[1]:=0;
    // Load magic initialization constants.
    state[0]:=$67452301;
    state[1]:=$efcdab89;
    state[2]:=$98badcfe;
    state[3]:=$10325476;
  END;
end;
procedure MD5Update(var context:TMD5_CTX; inputdata:PByte; inputlen:DWORD);
var
  i,index,partLen : DWORD;
  work : TARYBYTE64;
  pB : PByte;
begin
  // Compute number of bytes mod 64
  index := (context.count[0] SHR 3) AND $3F;
  // Update number of bits
  INC(context.count[0],(inputlen SHL 3));
  IF context.count[0]<(inputlen SHL 3) THEN INC(context.count[1]);
  INC(context.count[1],(inputlen SHR 29));
  partLen:=64-index;
  // Transform as many times as possible
  IF inputlen >= partLen THEN BEGIN
    MD5_memcpy(context,index,inputdata,0,partLen);
    MD5Transform(context.state,context.buffer);
    i:=partlen;
    WHILE (i+63)      pB:=inputdata; Inc(pB,i);
      Move(pB^,work[0],64);
      MD5Transform(context.state,work);
      INC(i,64);
    END;
    index:=0;
  END ELSE
    i:=0;
  // Buffer remaining input
  MD5_memcpy(context,index,inputdata,i,inputlen-i);
end;
function  MD5Final(var context:TMD5_CTX):string;
var
  bits : array[0..7] of BYTE;
  work : string;
  index,padlen : DWORD;
  i,j : integer;
  procedure Encode8;
  begin
    i:=0; j:=0;
    WHILE j<8 DO BEGIN
      bits[j]:=context.count[i] AND $FF;
      bits[j+1]:=(context.count[i] SHR 8) AND $FF;
      bits[j+2]:=(context.count[i] SHR 16) AND $FF;
      bits[j+3]:=(context.count[i] SHR 24) AND $FF;
      INC(i); INC(j,4);
    END;
  end;
  function Encode16:string;
  begin
    result:='';
    i:=0; j:=0;
    WHILE j<16 DO BEGIN
      result:=result+IntToHex(context.state[i] AND $FF,2);
      result:=result+IntToHex((context.state[i] SHR 8) AND $FF,2);
      result:=result+IntToHex((context.state[i] SHR 16) AND $FF,2);
      result:=result+IntToHex((context.state[i] SHR 24) AND $FF,2);
      INC(i); INC(j,4);
    END;
    result:=LowerCase(result);
  end;
begin
  // Save number of bits
  Encode8;
  // Pad out to 56 mod 64
  index:=(context.count[0] SHR 3) AND $3F;
  IF index<56 THEN padlen:=56-index ELSE padlen:=120-index;
  MD5Update(context,PByte(@PADDING[1]),padlen);
  // Append length (before padding)
  work:='        '; // need 8byte
  Move(bits[0],work[1],8);
  MD5Update(context,pByte(@work[1]),8);
  // Store state in digest
  result:=Encode16;
  // Zeroize sensitive information.
  FillChar(context,sizeof(context),0);
end;
function CalcMD5(ASrc:PByte; ASize:integer):string;
var
  context : TMD5_CTX;
begin
  MD5Init(context);
  MD5Update(context,ASrc,ASize);
  result:=MD5Final(context);
end;
function CalcFileMD5(AFilename:string):string;
  function GetFSize(h:THandle):int64;
  var
    dwLowSize,dwHighSize : DWORD;
    cw0,cw1 : Int64;
  begin
    dwLowSize:=GetFileSize(h,@dwHighSize);
    IF (dwLowSize=$FFFFFFFF) AND (GetLastError<>NO_ERROR) THEN
      result:=-1
    ELSE BEGIN
      cw0:=dwLowSize;
      cw1:=dwHighSize;
      result:=cw0+cw1*$100000000;
    END;
  end;
const
  BUFSIZE = 4096*2;
var
  h : THANDLE;
  sz : DWORD;
  remain : INT64;
  buf : array[0..BUFSIZE-1] of BYTE;
  context : TMD5_CTX;
  done : boolean;
begin
  result:='';
  h:=CreateFile(PChar(AFilename),GENERIC_READ,FILE_SHARE_READ,
                nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
  IF h=INVALID_HANDLE_VALUE THEN Exit;
  try
    remain:=GetFSize(h);
    IF remain<>-1 THEN BEGIN
      // 嵟弶
      done:=true;
      MD5Init(context);
      // 撉傒崬傒!
      WHILE remain>0 DO BEGIN
        IF NOT ReadFile(h,buf[0],BUFSIZE,sz,nil) THEN BEGIN
          done:=false; break;
        END;
        Dec(remain,sz);
        MD5Update(context,@buf[0],sz);
      END;
      // 嵟屻
      IF done THEN result:=MD5Final(context);
    END;
  finally
    CloseHandle(h);
  end;
end;
end.
阅读(2051) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~