269 lines
7.7 KiB
ObjectPascal
269 lines
7.7 KiB
ObjectPascal
{ ****************************************************************************** }
|
|
{ * Fast md5 * }
|
|
{ * https://zpascal.net * }
|
|
{ * https://github.com/PassByYou888/zAI * }
|
|
{ * https://github.com/PassByYou888/ZServer4D * }
|
|
{ * https://github.com/PassByYou888/PascalString * }
|
|
{ * https://github.com/PassByYou888/zRasterization * }
|
|
{ * https://github.com/PassByYou888/CoreCipher * }
|
|
{ * https://github.com/PassByYou888/zSound * }
|
|
{ * https://github.com/PassByYou888/zChinese * }
|
|
{ * https://github.com/PassByYou888/zExpression * }
|
|
{ * https://github.com/PassByYou888/zGameWare * }
|
|
{ * https://github.com/PassByYou888/zAnalysis * }
|
|
{ * https://github.com/PassByYou888/FFMPEG-Header * }
|
|
{ * https://github.com/PassByYou888/zTranslate * }
|
|
{ * https://github.com/PassByYou888/InfiniteIoT * }
|
|
{ * https://github.com/PassByYou888/FastMD5 * }
|
|
{ ****************************************************************************** }
|
|
unit Fast_MD5;
|
|
|
|
{$INCLUDE zDefine.inc}
|
|
|
|
interface
|
|
|
|
|
|
uses CoreClasses, UnicodeMixedLib;
|
|
|
|
function FastMD5(const buffPtr: PByte; bufSiz: nativeUInt): TMD5; overload;
|
|
function FastMD5(stream: TCoreClassStream; StartPos, EndPos: Int64): TMD5; overload;
|
|
|
|
implementation
|
|
|
|
{$IF Defined(MSWINDOWS) and Defined(Delphi)}
|
|
|
|
|
|
uses MemoryStream64;
|
|
|
|
(*
|
|
fastMD5 algorithm by Maxim Masiutin
|
|
https://github.com/maximmasiutin/MD5_Transform-x64
|
|
|
|
delphi imp by 600585@qq.com
|
|
https://github.com/PassByYou888/FastMD5
|
|
*)
|
|
|
|
{$IF Defined(WIN32)}
|
|
(*
|
|
; ==============================================================
|
|
;
|
|
; MD5_386.Asm - 386 optimized helper routine for calculating
|
|
; MD Message-Digest values
|
|
; written 2/2/94 by
|
|
;
|
|
; Peter Sawatzki
|
|
; Buchenhof 3
|
|
; D58091 Hagen, Germany Fed Rep
|
|
;
|
|
; EMail: Peter@Sawatzki.de
|
|
; EMail: 100031.3002@compuserve.com
|
|
; WWW: http://www.sawatzki.de
|
|
;
|
|
;
|
|
; original C Source was found in Dr. Dobbs Journal Sep 91
|
|
; MD5 algorithm from RSA Data Security, Inc.
|
|
*)
|
|
{$L MD5_32.obj}
|
|
{$ELSEIF Defined(WIN64)}
|
|
(*
|
|
; MD5_Transform-x64
|
|
; MD5 transform routine oprimized for x64 processors
|
|
; Copyright 2018 Ritlabs, SRL
|
|
; The 64-bit version is written by Maxim Masiutin <max@ritlabs.com>
|
|
|
|
; The main advantage of this 64-bit version is that
|
|
; it loads 64 bytes of hashed message into 8 64-bit registers
|
|
; (RBP, R8, R9, R10, R11, R12, R13, R14) at the beginning,
|
|
; to avoid excessive memory load operations
|
|
; througout the routine.
|
|
|
|
; To operate with 32-bit values store in higher bits
|
|
; of a 64-bit register (bits 32-63) uses "Ror" by 32;
|
|
; 8 macro variables (M1-M8) are used to keep record
|
|
; or corrent state of whether the register has been
|
|
; Ror'ed or not.
|
|
|
|
; It also has an ability to use Lea instruction instead
|
|
; of two sequental Adds (uncomment UseLea=1), but it is
|
|
; slower on Skylake processors. Also, Intel in the
|
|
; Optimization Reference Maual discourages us of
|
|
; Lea as a replacement of two adds, since it is slower
|
|
; on the Atom processors.
|
|
|
|
; MD5_Transform-x64 is released under a dual license,
|
|
; and you may choose to use it under either the
|
|
; Mozilla Public License 2.0 (MPL 2.1, available from
|
|
; https://www.mozilla.org/en-US/MPL/2.0/) or the
|
|
; GNU Lesser General Public License Version 3,
|
|
; dated 29 June 2007 (LGPL 3, available from
|
|
; https://www.gnu.org/licenses/lgpl.html).
|
|
|
|
; MD5_Transform-x64 is based
|
|
; on the following code by Peter Sawatzki.
|
|
|
|
; The original notice by Peter Sawatzki follows.
|
|
*)
|
|
{$L MD5_64.obj}
|
|
{$ENDIF}
|
|
|
|
procedure MD5_Transform(var Accu; const Buf); register; external;
|
|
|
|
function FastMD5(const buffPtr: PByte; bufSiz: nativeUInt): TMD5;
|
|
var
|
|
Digest: TMD5;
|
|
Lo, Hi: Cardinal;
|
|
p: PByte;
|
|
ChunkIndex: Byte;
|
|
ChunkBuff: array [0 .. 63] of Byte;
|
|
begin
|
|
Lo := 0;
|
|
Hi := 0;
|
|
PCardinal(@Digest[0])^ := $67452301;
|
|
PCardinal(@Digest[4])^ := $EFCDAB89;
|
|
PCardinal(@Digest[8])^ := $98BADCFE;
|
|
PCardinal(@Digest[12])^ := $10325476;
|
|
|
|
inc(Lo, bufSiz shl 3);
|
|
inc(Hi, bufSiz shr 29);
|
|
|
|
p := buffPtr;
|
|
|
|
while bufSiz >= $40 do
|
|
begin
|
|
MD5_Transform(Digest, p^);
|
|
inc(p, $40);
|
|
dec(bufSiz, $40);
|
|
end;
|
|
if bufSiz > 0 then
|
|
CopyPtr(p, @ChunkBuff[0], bufSiz);
|
|
|
|
Result := PMD5(@Digest[0])^;
|
|
ChunkBuff[bufSiz] := $80;
|
|
ChunkIndex := bufSiz + 1;
|
|
if ChunkIndex > $38 then
|
|
begin
|
|
if ChunkIndex < $40 then
|
|
FillPtrByte(@ChunkBuff[ChunkIndex], $40 - ChunkIndex, 0);
|
|
MD5_Transform(Result, ChunkBuff);
|
|
ChunkIndex := 0
|
|
end;
|
|
FillPtrByte(@ChunkBuff[ChunkIndex], $38 - ChunkIndex, 0);
|
|
PCardinal(@ChunkBuff[$38])^ := Lo;
|
|
PCardinal(@ChunkBuff[$3C])^ := Hi;
|
|
MD5_Transform(Result, ChunkBuff);
|
|
end;
|
|
|
|
function FastMD5(stream: TCoreClassStream; StartPos, EndPos: Int64): TMD5;
|
|
const
|
|
deltaSize: Cardinal = $40 * $FFFF;
|
|
|
|
var
|
|
Digest: TMD5;
|
|
Lo, Hi: Cardinal;
|
|
DeltaBuf: Pointer;
|
|
bufSiz: Int64;
|
|
Rest: Cardinal;
|
|
p: PByte;
|
|
ChunkIndex: Byte;
|
|
ChunkBuff: array [0 .. 63] of Byte;
|
|
begin
|
|
if StartPos > EndPos then
|
|
Swap(StartPos, EndPos);
|
|
StartPos := umlClamp(StartPos, 0, stream.Size);
|
|
EndPos := umlClamp(EndPos, 0, stream.Size);
|
|
if EndPos - StartPos <= 0 then
|
|
begin
|
|
Result := FastMD5(nil, 0);
|
|
exit;
|
|
end;
|
|
{$IFDEF OptimizationMemoryStreamMD5}
|
|
if stream is TCoreClassMemoryStream then
|
|
begin
|
|
Result := FastMD5(Pointer(nativeUInt(TCoreClassMemoryStream(stream).Memory) + StartPos), EndPos - StartPos);
|
|
exit;
|
|
end;
|
|
if stream is TMemoryStream64 then
|
|
begin
|
|
Result := FastMD5(TMemoryStream64(stream).PositionAsPtr(StartPos), EndPos - StartPos);
|
|
exit;
|
|
end;
|
|
{$ENDIF}
|
|
//
|
|
Lo := 0;
|
|
Hi := 0;
|
|
PCardinal(@Digest[0])^ := $67452301;
|
|
PCardinal(@Digest[4])^ := $EFCDAB89;
|
|
PCardinal(@Digest[8])^ := $98BADCFE;
|
|
PCardinal(@Digest[12])^ := $10325476;
|
|
|
|
bufSiz := EndPos - StartPos;
|
|
Rest := 0;
|
|
|
|
inc(Lo, bufSiz shl 3);
|
|
inc(Hi, bufSiz shr 29);
|
|
|
|
DeltaBuf := GetMemory(deltaSize);
|
|
stream.Position := StartPos;
|
|
|
|
if bufSiz < $40 then
|
|
begin
|
|
stream.read(DeltaBuf^, bufSiz);
|
|
p := DeltaBuf;
|
|
end
|
|
else
|
|
while bufSiz >= $40 do
|
|
begin
|
|
if Rest = 0 then
|
|
begin
|
|
if bufSiz >= deltaSize then
|
|
Rest := deltaSize
|
|
else
|
|
Rest := bufSiz;
|
|
stream.ReadBuffer(DeltaBuf^, Rest);
|
|
|
|
p := DeltaBuf;
|
|
end;
|
|
MD5_Transform(Digest, p^);
|
|
inc(p, $40);
|
|
dec(bufSiz, $40);
|
|
dec(Rest, $40);
|
|
end;
|
|
|
|
if bufSiz > 0 then
|
|
CopyPtr(p, @ChunkBuff[0], bufSiz);
|
|
|
|
FreeMemory(DeltaBuf);
|
|
|
|
Result := PMD5(@Digest[0])^;
|
|
ChunkBuff[bufSiz] := $80;
|
|
ChunkIndex := bufSiz + 1;
|
|
if ChunkIndex > $38 then
|
|
begin
|
|
if ChunkIndex < $40 then
|
|
FillPtrByte(@ChunkBuff[ChunkIndex], $40 - ChunkIndex, 0);
|
|
MD5_Transform(Result, ChunkBuff);
|
|
ChunkIndex := 0
|
|
end;
|
|
FillPtrByte(@ChunkBuff[ChunkIndex], $38 - ChunkIndex, 0);
|
|
PCardinal(@ChunkBuff[$38])^ := Lo;
|
|
PCardinal(@ChunkBuff[$3C])^ := Hi;
|
|
MD5_Transform(Result, ChunkBuff);
|
|
end;
|
|
|
|
{$ELSE}
|
|
|
|
|
|
function FastMD5(const buffPtr: PByte; bufSiz: nativeUInt): TMD5;
|
|
begin
|
|
Result := umlMD5(buffPtr, bufSiz);
|
|
end;
|
|
|
|
function FastMD5(stream: TCoreClassStream; StartPos, EndPos: Int64): TMD5;
|
|
begin
|
|
Result := umlStreamMD5(stream, StartPos, EndPos);
|
|
end;
|
|
|
|
{$ENDIF Defined(MSWINDOWS) and Defined(Delphi)}
|
|
|
|
end.
|