• 支持4G以上文件的MD5单元


    根据网上一个流传很久的基于Delph4的MD5单元修改的, 可以支持4G以上的文件, 可以支持UNICODE字符的Delphi

    恩.......对于大文件速度稍微慢了一点点, 在我自己的电脑上测试, 5.2G文件计算速度86秒...凑合了吧

    如果谁能优化一下速度, 请联系我哦~~~

    (*
    -----------------------------------------------------------------------------------------------
    
                                         MD5 Message-Digest
    
                                     Delphi Unit implementing the
                          RSA Data Security, Inc. MD5 Message-Digest Algorithm
    
                              Implementation of Ronald L. Rivest's RFC 1321
    
                          Copyright ?1997-1999 Medienagentur Fichtner & Meyer
                                      Written by Matthias Fichtner
    
    -----------------------------------------------------------------------------------------------
    2013-11-11 堕落恶魔
      增加对超过4G大小文件支持
      增加对Delphi2009以及更高版本Delphi支持
    
    
    如果有修改, 希望能够将代码同步邮件给我, 谢谢
    hs_kill_god@hotmail.com
    -----------------------------------------------------------------------------------------------
    
    *)
    
    
    Unit MD5;
    
    // -----------------------------------------------------------------------------------------------
    interface
    // -----------------------------------------------------------------------------------------------
    
    uses
      Windows, Classes, SysUtils;
    
    const
      MD5Length: Byte = 32;
    
    type
      MD5Count = array[0..1] of Int64;
      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;
    
    function MD5String(M: AnsiString): MD5Digest;
    function MD5File(N: AnsiString): MD5Digest;
    function MD5Print(D: MD5Digest): AnsiString;
    
    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
      );
    
    type
      MD5Context = record
        State: MD5State;
        Count: MD5Count;
        Buffer: MD5Buffer;
      end;
    
    function F(x, y, z: DWORD): DWORD; inline;
    begin
      Result := (x and y) or ((not x) and z);
    end;
    
    function G(x, y, z: DWORD): DWORD; inline;
    begin
      Result := (x and z) or (y and (not z));
    end;
    
    function H(x, y, z: DWORD): DWORD; inline;
    begin
      Result := x xor y xor z;
    end;
    
    function I(x, y, z: DWORD): DWORD; inline;
    begin
      Result := y xor (x or (not z));
    end;
    
    procedure rot(var x: DWORD; n: BYTE); inline;
    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); inline;
    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); inline;
    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); inline;
    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); inline;
    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;
    
    function MP(P: Pointer; M: Integer): Pointer;
    begin
      Result := Pointer(Integer(P) + M);
    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 AContext: MD5Context);
    begin
      with AContext do
      begin
        State[0] := $67452301;
        State[1] := $EFCDAB89;
        State[2] := $98BADCFE;
        State[3] := $10325476;
        Count[0] := 0;
        Count[1] := 0;
        FillChar(Buffer, SizeOf(MD5Buffer), 0);
      end;
    end;
    
    // Update given Context to include Length bytes of Input
    procedure MD5Update(var AContext: MD5Context; AInput: Pointer; ALength: Int64); overload;
    var
      nIndex: Int64;
      nPartLen: Int64;
      I: Int64;
    begin
      with AContext do
      begin
        nIndex := (Count[0] shr 3) and $3F;
        inc(Count[0], ALength shl 3);
        if Count[0] < (ALength shl 3) then
          inc(Count[1]);
        inc(Count[1], ALength shr 61);
      end;
      nPartLen := 64 - nIndex;
      if ALength >= nPartLen then
      begin
        Move(AInput^, AContext.Buffer[nIndex], nPartLen);
        Transform(@AContext.Buffer, AContext.State);
        I := nPartLen;
        while I + 63 < ALength do
        begin
          Transform(MP(AInput,  I), AContext.State);
          inc(I, 64);
        end;
        nIndex := 0;
      end
      else
        I := 0;
      Move(MP(AInput,  I)^, AContext.Buffer[nIndex], ALength - i);
    end;
    
    procedure MD5Update(var AContext: MD5Context; AInput: TStream; ALength: Int64); overload;
    var
      nIndex: Int64;
      nPartLen: Int64;
      i: Int64;
      x, m: Integer;
      nBuff: array[0..1023] of Byte;
    begin
      with AContext do
      begin
        nIndex := (Count[0] shr 3) and $3F;
        inc(Count[0], ALength shl 3);
        if Count[0] < (ALength shl 3) then
          inc(Count[1]);
        inc(Count[1], ALength shr 61);
      end;
      nPartLen := 64 - nIndex;
      if ALength >= nPartLen then
      begin
        AInput.Read(AContext.Buffer[nIndex], nPartLen);
        Transform(@AContext.Buffer, AContext.State);
        i := nPartLen;
        while i < ALength - 1024 do
        begin
          AInput.Read(nBuff, 1024);
          for x := 0 to 15 do
            Transform(@(nBuff[x * 64]), AContext.State);
          Inc(i, 1024);
        end;
        m := (ALength - i) div 64;
        x := m * 64;
        AInput.Read(nBuff, x);
        Inc(I, x);
        for x := 0 to m - 1 do
          Transform(@(nBuff[x * 64]), AContext.State);
        nIndex := 0;
      end
      else
        i := 0;
      AInput.Read(AContext.Buffer[nIndex], ALength - i);
    end;
    
    // Finalize given Context, create Digest and zeroize Context
    procedure MD5Final(var AContext: MD5Context; var Digest: MD5Digest);
    var
      nBits: MD5CBits;
      nIndex: longword;
      nPadLen: longword;
    begin
      Decode(@AContext.Count, @nBits, 2);
      nIndex := (AContext.Count[0] shr 3) and $3f;
      if nIndex < 56 then
        nPadLen := 56 - nIndex
      else
        nPadLen := 120 - nIndex;
      MD5Update(AContext, @PADDING, nPadLen);
      MD5Update(AContext, @nBits, 8);
      Decode(@AContext.State, @Digest, 4);
      FillChar(AContext, SizeOf(MD5Context), 0);
    end;
    
    // -----------------------------------------------------------------------------------------------
    
    // Create digest of given Message
    function MD5String(M: AnsiString): MD5Digest;
    var
      nContext: MD5Context;
    begin
      MD5Init(nContext);
      MD5Update(nContext, pAnsiChar(M), length(M));
      MD5Final(nContext, Result);
    end;
    
    // Create digest of file with given Name
    function MD5File(N: AnsiString): MD5Digest;
    var
      nContext: MD5Context;
      nFS: TFileStream;
    begin
      MD5Init(nContext);
      if FileExists(N) then
      begin
        nFS := TFileStream.Create(N, fmOpenRead or fmShareDenyWrite);
        try
          nFS.Position := 0;
          MD5Update(nContext, nFS, nFS.Size);
        finally
          nFS.Free;
        end;
      end;
      MD5Final(nContext, Result);
    end;
    
    // Create hex representation of given Digest
    function MD5Print(D: MD5Digest): AnsiString;
    var
      I, x: byte;
    const
      Digits: array[0..15] of AnsiChar =
        ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f');
    begin
      SetLength(Result, 32);
      for I := 0 to 15 do
      begin
        x := i * 2 + 1;
        Result[x] := Digits[(D[I] shr 4) and $0f];
        Result[x + 1] := Digits[D[I] and $0f];
      end;
    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[I] = D2[I];
        inc(I);
      end;
    end;
    
    end.
  • 相关阅读:
    JDA 8.0.0.0小版本升级
    Mybatis中的resultType和resultMap
    FP硬绑
    消息 14607,级别 16,状态 1,过程 sp_send_dbmail,第 141 行 profile 名称无效
    检索 COM 类工厂中 CLSID 为 {00024500-0000-0000-C000-000000000046} 的组件失败,原因是出现以下错误: 8000401a 因为配置标识不正确,系统无法开始服务器进程。请检查用户名和密码。 (异常来自 HRESULT:0x8000401A)。 在 BatchImportEntryTable.GetExcelData(String FileName)
    工单重复回写
    ORACLE 对一个表进行循环查数,再根据MO供给数量写入另一个新表
    siebel切换数据源
    MYSQL TIMESTAMP with implicit DEFAULT value is deprecated.
    多账户的统一登录 (转)
  • 原文地址:https://www.cnblogs.com/lzl_17948876/p/3418282.html
Copyright © 2020-2023  润新知