|
@@ -0,0 +1,1164 @@
|
|
|
+{
|
|
|
+ This file is part of the Free Component Library (FCL)
|
|
|
+ Copyright (c) 2023 the Free Pascal team
|
|
|
+
|
|
|
+ Delphi-compatible hash unit
|
|
|
+
|
|
|
+ See the file COPYING.FPC, included in this distribution,
|
|
|
+ for details about the copyright.
|
|
|
+
|
|
|
+ This program is distributed in the hope that it will be useful,
|
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
+
|
|
|
+ **********************************************************************}
|
|
|
+unit System.Hash;
|
|
|
+
|
|
|
+{$mode objfpc}
|
|
|
+{$modeswitch advancedrecords}
|
|
|
+{$macro on}
|
|
|
+
|
|
|
+interface
|
|
|
+
|
|
|
+uses
|
|
|
+{$IFDEF FPC_DOTTEDUNITS}
|
|
|
+ System.Classes, System.SysUtils, System.Hash.Md5, System.Hash.Sha1, System.Hash.Fnv, System.Hash.Sha256, System.Hash.Sha512;
|
|
|
+{$ELSE}
|
|
|
+ Classes, SysUtils, md5, sha1, fnvhash, fpsha256, fpsha512;
|
|
|
+{$ENDIF}
|
|
|
+
|
|
|
+const
|
|
|
+ HashReadBufferSize = 4096; // Use 4k buffer.
|
|
|
+
|
|
|
+type
|
|
|
+ EHashException = class(Exception);
|
|
|
+
|
|
|
+ { THash }
|
|
|
+
|
|
|
+ THash = record
|
|
|
+ class function DigestAsInteger(const aDigest: TBytes): Integer; static;
|
|
|
+ class function DigestAsString(const aDigest: TBytes; UpperCase : Boolean = false): UnicodeString; static;
|
|
|
+ class function DigestAsStringGUID(const aDigest: TBytes): UnicodeString; static;
|
|
|
+ class function GetRandomString(const aLen: Integer = 10): UnicodeString; static;
|
|
|
+ class function ToBigEndian(aValue: Cardinal): Cardinal; overload; static; inline;
|
|
|
+ class function ToBigEndian(aValue: UInt64): UInt64; overload; static; inline;
|
|
|
+ end;
|
|
|
+
|
|
|
+ { THashMD5 }
|
|
|
+
|
|
|
+ THashMD5 = record
|
|
|
+ Private
|
|
|
+ _MD5 : TMD5Context;
|
|
|
+ _Digest : TMD5Digest;
|
|
|
+ _DidFinal : Boolean;
|
|
|
+ public
|
|
|
+ class function Create: THashMD5; static; inline;
|
|
|
+ class function GetHashBytes(const aData: UnicodeString): TBytes; overload; static;
|
|
|
+ class function GetHashString(const aData: UnicodeString): UnicodeString; overload; static; inline;
|
|
|
+ class function GetHashBytes(const aStream: TStream): TBytes; overload; static;
|
|
|
+ class function GetHashString(const aStream: TStream): UnicodeString; overload; static; inline;
|
|
|
+ class function GetHashBytesFromFile(const aFileName: TFileName): TBytes; static;
|
|
|
+ class function GetHashStringFromFile(const aFileName: TFileName): UnicodeString; static; inline;
|
|
|
+ class function GetHMAC(const aData,aKey: UnicodeString): UnicodeString; static; inline;
|
|
|
+ class function GetHMACAsBytes(const aData,aKey: UnicodeString): TBytes; overload; static;
|
|
|
+ class function GetHMACAsBytes(const aData: UnicodeString; const aKey: TBytes): TBytes; overload; static;
|
|
|
+ class function GetHMACAsBytes(const aData: TBytes; const aKey: UnicodeString): TBytes; overload; static;
|
|
|
+ class function GetHMACAsBytes(const aData,aKey: TBytes): TBytes; overload; static;
|
|
|
+ procedure Reset;
|
|
|
+ procedure Update(var aData; aLength: Cardinal); overload;
|
|
|
+ procedure Update(const aData: TBytes; aLength: Cardinal = 0); overload; {inline;}
|
|
|
+ procedure Update(const aData: UnicodeString); overload; {inline;}
|
|
|
+ function GetDigest: TBytes;
|
|
|
+ function GetBlockSize: Integer; inline;
|
|
|
+ function GetHashSize: Integer; inline;
|
|
|
+ function HashAsBytes: TBytes; inline;
|
|
|
+ function HashAsString: UnicodeString; // inline;
|
|
|
+ end;
|
|
|
+
|
|
|
+ { THashSHA1 }
|
|
|
+
|
|
|
+ THashSHA1 = record
|
|
|
+ private
|
|
|
+ _SHA1 : TSHA1Context;
|
|
|
+ _Digest : TSHA1Digest;
|
|
|
+ _DidFinal : Boolean;
|
|
|
+ public
|
|
|
+ class function Create: THashSHA1; static; // inline;
|
|
|
+ class function GetHashBytes(const aData: UnicodeString): TBytes; overload; static;
|
|
|
+ class function GetHashString(const aData: UnicodeString): UnicodeString; overload; static; // inline;
|
|
|
+ class function GetHashBytes(const aStream: TStream): TBytes; overload; static;
|
|
|
+ class function GetHashString(const aStream: TStream): UnicodeString; overload; static; // inline;
|
|
|
+ class function GetHashBytesFromFile(const aFileName: TFileName): TBytes; static;
|
|
|
+ class function GetHashStringFromFile(const aFileName: TFileName): UnicodeString; static; // inline;
|
|
|
+ class function GetHMAC(const aData, aKey: UnicodeString): UnicodeString; static; // inline;
|
|
|
+ class function GetHMACAsBytes(const aData, aKey: UnicodeString): TBytes; overload; static;
|
|
|
+ class function GetHMACAsBytes(const aData: UnicodeString; const aKey: TBytes): TBytes; overload; static;
|
|
|
+ class function GetHMACAsBytes(const aData: TBytes; const aKey: UnicodeString): TBytes; overload; static;
|
|
|
+ class function GetHMACAsBytes(const aData, aKey: TBytes): TBytes; overload; static;
|
|
|
+ procedure Reset; inline;
|
|
|
+ procedure Update(var aData; aLength: Cardinal); overload;
|
|
|
+ procedure Update(const aData: TBytes; aLength: Cardinal = 0); overload;
|
|
|
+ procedure Update(const aData: UnicodeString); overload; // inline;
|
|
|
+ function GetDigest: TBytes;
|
|
|
+ function GetBlockSize: Integer; inline;
|
|
|
+ function GetHashSize: Integer; inline;
|
|
|
+ function HashAsBytes: TBytes; inline;
|
|
|
+ function HashAsString: UnicodeString; // inline;
|
|
|
+ end;
|
|
|
+
|
|
|
+ { THashSHA2 }
|
|
|
+
|
|
|
+ THashSHA2 = record
|
|
|
+ public type
|
|
|
+ TSHA2Version = (SHA224, SHA256, SHA384, SHA512, SHA512_224, SHA512_256);
|
|
|
+ public
|
|
|
+ class function Create(aHashVersion: TSHA2Version = TSHA2Version.SHA256): THashSHA2; static; inline;
|
|
|
+ class function GetHashBytes(const aData: UnicodeString; aHashVersion: TSHA2Version = TSHA2Version.SHA256): TBytes; overload; static;
|
|
|
+ class function GetHashString(const aData: UnicodeString; aHashVersion: TSHA2Version = TSHA2Version.SHA256): UnicodeString; overload; static; inline;
|
|
|
+ class function GetHashBytes(const aStream: TStream; aHashVersion: TSHA2Version = TSHA2Version.SHA256): TBytes; overload; static;
|
|
|
+ class function GetHashString(const aStream: TStream; aHashVersion: TSHA2Version = TSHA2Version.SHA256): UnicodeString; overload; static; inline;
|
|
|
+ class function GetHashBytesFromFile(const aFileName: TFileName; aHashVersion: TSHA2Version = TSHA2Version.SHA256): TBytes; static;
|
|
|
+ class function GetHashStringFromFile(const aFileName: TFileName; aHashVersion: TSHA2Version = TSHA2Version.SHA256): UnicodeString; static; inline;
|
|
|
+ class function GetHMAC(const aData, aKey: UnicodeString; aHashVersion: TSHA2Version = TSHA2Version.SHA256): UnicodeString; static; inline;
|
|
|
+ class function GetHMACAsBytes(const aData, aKey: UnicodeString; aHashVersion: TSHA2Version = TSHA2Version.SHA256): TBytes; overload; static;
|
|
|
+ class function GetHMACAsBytes(const aData: UnicodeString; const aKey: TBytes; aHashVersion: TSHA2Version = TSHA2Version.SHA256): TBytes; overload; static;
|
|
|
+ class function GetHMACAsBytes(const aData: TBytes; const aKey: UnicodeString; aHashVersion: TSHA2Version = TSHA2Version.SHA256): TBytes; overload; static;
|
|
|
+ class function GetHMACAsBytes(const aData, aKey: TBytes; aHashVersion: TSHA2Version = TSHA2Version.SHA256): TBytes; overload; static;
|
|
|
+ procedure Reset; inline;
|
|
|
+ procedure Update(var aData; aLength: Cardinal); overload;
|
|
|
+ procedure Update(const aData : PByte; aLength: Cardinal); overload;
|
|
|
+ procedure Update(const aData: TBytes; aLength: Cardinal = 0); overload;
|
|
|
+ procedure Update(const aData: UnicodeString); overload;
|
|
|
+ procedure Update(const aData: RawByteString); overload;
|
|
|
+ function GetDigest: TBytes;
|
|
|
+ function GetBlockSize: Integer; inline;
|
|
|
+ function GetHashSize: Integer; inline;
|
|
|
+ function HashAsBytes: TBytes; // inline;
|
|
|
+ function HashAsString: UnicodeString; // inline;
|
|
|
+ Private
|
|
|
+ procedure DoFinal;
|
|
|
+ private
|
|
|
+ FDidFinal : Boolean;
|
|
|
+ case FHashVersion: TSHA2Version of
|
|
|
+ Sha256 : (_S256 : TSHA256);
|
|
|
+ Sha384 : (_S384 : TSHA384);
|
|
|
+ Sha512 : (_S512 : TSHA512);
|
|
|
+ end;
|
|
|
+
|
|
|
+ { THashBobJenkins }
|
|
|
+
|
|
|
+ THashBobJenkins = record
|
|
|
+ Private
|
|
|
+ FCurrent : Cardinal;
|
|
|
+ public
|
|
|
+ class function Create: THashBobJenkins; static;
|
|
|
+ class function GetHashBytes(const aData: UnicodeString): TBytes; static;
|
|
|
+ class function GetHashString(const aData: UnicodeString): UnicodeString; static;
|
|
|
+ class function GetHashString(const aData: RawByteString): UnicodeString; static;
|
|
|
+ class function GetHashValue(const aData: UnicodeString): Integer; overload; static;
|
|
|
+ class function GetHashValue(const aData: RawByteString): Integer; overload; static;
|
|
|
+ class function GetHashValue(var aData; aLength: Integer; aInitialValue: Integer = 0): Integer; overload; static;
|
|
|
+ class function GetHashValue(const aData : PByte; aLength: Integer; aInitialValue: Integer = 0): Integer; overload; static;
|
|
|
+ procedure Reset(aInitialValue: Integer = 0);
|
|
|
+ procedure Update(var aData; aLength: Cardinal); overload;
|
|
|
+ procedure Update(aData : PByte; aLength: Cardinal); overload;
|
|
|
+ procedure Update(const aData: TBytes; aLength: Cardinal = 0); overload;
|
|
|
+ procedure Update(const aData: UnicodeString); overload;
|
|
|
+ procedure Update(const aData: RawByteString); overload;
|
|
|
+ function HashAsBytes: TBytes;
|
|
|
+ function HashAsInteger: Integer;
|
|
|
+ function HashAsString: UnicodeString;
|
|
|
+ end;
|
|
|
+
|
|
|
+ { THashFNV1a32 }
|
|
|
+
|
|
|
+ THashFNV1a32 = record
|
|
|
+ public const
|
|
|
+ FNV_PRIME = FNV_32_PRIME;
|
|
|
+ FNV_SEED = FNV1_32_INIT;
|
|
|
+ private
|
|
|
+ FCurrent : Fnv32_t;
|
|
|
+ public
|
|
|
+ class function Create: THashFNV1a32; static;
|
|
|
+ class function GetHashBytes(const aData: UnicodeString): TBytes; static;
|
|
|
+ class function GetHashString(const aData: UnicodeString): UnicodeString; overload; static;
|
|
|
+ class function GetHashString(const aData: RawByteString): UnicodeString; overload; static;
|
|
|
+ class function GetHashValue(const aData: UnicodeString): Integer; overload; static; // inline;
|
|
|
+ class function GetHashValue(const aData: RawByteString): Integer; overload; static; // inline;
|
|
|
+ class function GetHashValue(const aData; aLength: Cardinal; aInitialValue: Cardinal = FNV_SEED): Integer; overload; static; // inline;
|
|
|
+ procedure Reset(aInitialValue: Cardinal = FNV_SEED);
|
|
|
+ procedure Update(const aData; aLength: Cardinal); overload; // inline;
|
|
|
+ procedure Update(const aData: TBytes; aLength: Cardinal = 0); overload; // inline;
|
|
|
+ procedure Update(const aData: UnicodeString); overload; // inline;
|
|
|
+ procedure Update(const aData: RawByteString); overload; // inline;
|
|
|
+ function GetDigest : TBytes;
|
|
|
+ function HashAsBytes: TBytes;
|
|
|
+ function HashAsInteger: Integer;
|
|
|
+ function HashAsString: UnicodeString;
|
|
|
+ end;
|
|
|
+
|
|
|
+const
|
|
|
+ SHashCanNotUpdateMD5 = 'MD5: Cannot update a finalized hash';
|
|
|
+ SHashCanNotUpdateSHA1 = 'SHA1: Cannot update a finalized hash';
|
|
|
+ SHashCanNotUpdateSHA2 = 'SHA2: Cannot update a finalized hash';
|
|
|
+ RandomStringChars = UnicodeString('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+-/*_');
|
|
|
+ RandomStringCharCount = Length(RandomStringChars);
|
|
|
+
|
|
|
+
|
|
|
+implementation
|
|
|
+
|
|
|
+Uses
|
|
|
+{$IFDEF FPC_DOTTEDUNITS}
|
|
|
+ System.Types, System.SysConst, System.Generics.Hashes;
|
|
|
+{$ELSE}
|
|
|
+ Types, SysConst, Generics.Hashes;
|
|
|
+{$ENDIF}
|
|
|
+
|
|
|
+Resourcestring
|
|
|
+ SErrDigestSizeMustBe4 = 'Digest size must be 4, got %d instead.';
|
|
|
+
|
|
|
+
|
|
|
+{ THash }
|
|
|
+
|
|
|
+class function THash.ToBigEndian(aValue: Cardinal): Cardinal;
|
|
|
+begin
|
|
|
+ Result:=NtoBE(aValue);
|
|
|
+end;
|
|
|
+
|
|
|
+class function THash.ToBigEndian(aValue: UInt64): UInt64;
|
|
|
+begin
|
|
|
+ Result:=NtoBE(aValue);
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+class function THash.DigestAsInteger(const aDigest: TBytes): Integer;
|
|
|
+begin
|
|
|
+ if Length(aDigest) <> 4 then
|
|
|
+ raise EHashException.CreateFmt(SErrDigestSizeMustBe4,[Length(aDigest)]);
|
|
|
+ Result:= PLongInt(@ADigest[0])^;
|
|
|
+end;
|
|
|
+
|
|
|
+class function THash.DigestAsString(const aDigest: TBytes; UpperCase: Boolean): UnicodeString;
|
|
|
+
|
|
|
+const
|
|
|
+ HexDigitsWL: array[0..15] of widechar = '0123456789abcdef';
|
|
|
+
|
|
|
+
|
|
|
+var
|
|
|
+ S : UnicodeString;
|
|
|
+ I,Len: Integer;
|
|
|
+ H,Res : PWideChar;
|
|
|
+ PB : PByte;
|
|
|
+ B : Byte;
|
|
|
+
|
|
|
+begin
|
|
|
+ S:='';
|
|
|
+ if Uppercase then
|
|
|
+ H:=@HexDigitsW
|
|
|
+ else
|
|
|
+ H:=@HexDigitsWL;
|
|
|
+ Len:=Length(aDigest);
|
|
|
+ SetLength(S,2*Len);
|
|
|
+ Res:=PWideChar(S);
|
|
|
+ PB:=PByte(aDigest);
|
|
|
+ for I:=1 to Len do
|
|
|
+ begin
|
|
|
+ B:=PB^;
|
|
|
+ Res^:=H[B shr 4];
|
|
|
+ inc(Res);
|
|
|
+ Res^:=H[B and 15];
|
|
|
+ Inc(Res);
|
|
|
+ Inc(PB);
|
|
|
+ end;
|
|
|
+ Result:=S;
|
|
|
+end;
|
|
|
+
|
|
|
+class function THash.DigestAsStringGUID(const aDigest: TBytes): UnicodeString;
|
|
|
+
|
|
|
+
|
|
|
+begin
|
|
|
+ With TGUID.Create(aDigest,TEndian.Little) do
|
|
|
+ begin
|
|
|
+ D1:=ToBigEndian(D1);
|
|
|
+ D2:=Swap(D2);
|
|
|
+ D3:=Swap(D3);
|
|
|
+{$IF SIZEOF(Char)=2}
|
|
|
+ Result:=ToString;
|
|
|
+{$ELSE}
|
|
|
+ Result:=Utf8Decode(ToString);
|
|
|
+{$ENDIF}
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+class function THash.GetRandomString(const aLen: Integer): UnicodeString;
|
|
|
+
|
|
|
+var
|
|
|
+ I : Integer;
|
|
|
+ Res: PWideChar;
|
|
|
+
|
|
|
+begin
|
|
|
+ Result:='';
|
|
|
+ SetLength(Result,aLen);
|
|
|
+ Res:=PWideChar(Result);
|
|
|
+ for I:=1 to ALen do
|
|
|
+ begin
|
|
|
+ Res^:=RandomStringChars[1+Random(RandomStringCharCount)];
|
|
|
+ Inc(Res);
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+{ THashMD5 }
|
|
|
+
|
|
|
+class function THashMD5.Create: THashMD5;
|
|
|
+begin
|
|
|
+ Result:=Default(THashMD5);
|
|
|
+ Result.Reset;
|
|
|
+end;
|
|
|
+
|
|
|
+function THashMD5.GetBlockSize: Integer;
|
|
|
+begin
|
|
|
+ Result:=64;
|
|
|
+end;
|
|
|
+
|
|
|
+function THashMD5.GetHashSize: Integer;
|
|
|
+begin
|
|
|
+ Result:=SizeOf(TMD5Digest);
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashMD5.GetHashBytes(const aData: UnicodeString): TBytes;
|
|
|
+
|
|
|
+begin
|
|
|
+ With THashMD5.Create do
|
|
|
+ begin
|
|
|
+ Update(aData);
|
|
|
+ Result:=GetDigest;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashMD5.GetHashString(const aData: UnicodeString): UnicodeString;
|
|
|
+
|
|
|
+begin
|
|
|
+ With THashMD5.Create do
|
|
|
+ begin
|
|
|
+ Update(aData);
|
|
|
+ Result:=HashAsString;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashMD5.GetHashBytes(const aStream: TStream): TBytes;
|
|
|
+
|
|
|
+var
|
|
|
+ Buf: TBytes;
|
|
|
+ Len,Count: Longint;
|
|
|
+
|
|
|
+begin
|
|
|
+ Buf:=Default(TBytes);
|
|
|
+ Len:=HashReadBufferSize;
|
|
|
+ SetLength(Buf,Len);
|
|
|
+ With THashMD5.Create do
|
|
|
+ begin
|
|
|
+ Count:=aStream.Read(Buf,Len);
|
|
|
+ While (Count>0) do
|
|
|
+ begin
|
|
|
+ Update(Buf,Count);
|
|
|
+ Count:=aStream.Read(Buf,Len);
|
|
|
+ end;
|
|
|
+ Result:=GetDigest;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashMD5.GetHashString(const aStream: TStream): UnicodeString;
|
|
|
+begin
|
|
|
+ Result:=THash.DigestAsString(GetHashBytes(aStream));
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashMD5.GetHashBytesFromFile(const aFileName: TFileName): TBytes;
|
|
|
+
|
|
|
+var
|
|
|
+ F: TFileStream;
|
|
|
+
|
|
|
+begin
|
|
|
+ F:=TFileStream.Create(aFileName,fmOpenRead or fmShareDenyWrite);
|
|
|
+ try
|
|
|
+ Result:=GetHashBytes(F);
|
|
|
+ finally
|
|
|
+ F.Free;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashMD5.GetHashStringFromFile(const aFileName: TFileName): UnicodeString;
|
|
|
+begin
|
|
|
+ Result:=THash.DigestAsString(GetHashBytesFromFile(aFileName));
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashMD5.GetHMAC(const aData,aKey: UnicodeString): UnicodeString;
|
|
|
+begin
|
|
|
+ Result:=THash.DigestAsString(GetHMACAsBytes(aData,aKey));
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashMD5.GetHMACAsBytes(const aData, aKey: UnicodeString): TBytes;
|
|
|
+begin
|
|
|
+ With TEncoding.UTF8 do
|
|
|
+ Result:=GetHMACAsBytes(GetBytes(aData),GetBytes(aKey));
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashMD5.GetHMACAsBytes(const aData: UnicodeString; const aKey: TBytes): TBytes;
|
|
|
+begin
|
|
|
+ With TEncoding.UTF8 do
|
|
|
+ Result:=GetHMACAsBytes(GetBytes(aData),aKey);
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashMD5.GetHMACAsBytes(const aData: TBytes; const aKey: UnicodeString): TBytes;
|
|
|
+begin
|
|
|
+ With TEncoding.UTF8 do
|
|
|
+ Result:=GetHMACAsBytes(aData,GetBytes(aKey));
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashMD5.GetHMACAsBytes(const aData, aKey: TBytes): TBytes;
|
|
|
+
|
|
|
+var
|
|
|
+ I: Byte;
|
|
|
+ MD5_BLOCK_SIZE : Integer;
|
|
|
+ VLength: PtrUInt;
|
|
|
+ PKey, POPad, PIPad: PByte;
|
|
|
+ VKey, VOPad, VIPad: TBytes;
|
|
|
+ MD5 : THashMD5;
|
|
|
+
|
|
|
+begin
|
|
|
+ VKey:=Default(TBytes);
|
|
|
+ VOPad:=Default(TBytes);
|
|
|
+ VIPad:=Default(TBytes);
|
|
|
+ MD5:=THashMD5.Create;
|
|
|
+ MD5_BLOCK_SIZE:=MD5.GetBlockSize;
|
|
|
+ VLength:=Length(aKey);
|
|
|
+ if VLength > MD5_BLOCK_SIZE then
|
|
|
+ begin
|
|
|
+ SetLength(VKey,MD5_BLOCK_SIZE);
|
|
|
+ FillChar(VKey[0],MD5_BLOCK_SIZE, #0);
|
|
|
+ MD5.Update(aKey);
|
|
|
+ VKey:=Concat(MD5.GetDigest,VKey);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ SetLength(VKey,MD5_BLOCK_SIZE-VLength);
|
|
|
+ FillChar(VKey[0],MD5_BLOCK_SIZE-VLength, #0);
|
|
|
+ VKey:=Concat(aKey,VKey);
|
|
|
+ end;
|
|
|
+ SetLength(VOPad,MD5_BLOCK_SIZE);
|
|
|
+ POPad:=PByte(VOPad);
|
|
|
+ FillChar(POPad^, MD5_BLOCK_SIZE, $5c);
|
|
|
+ SetLength(VIPad, MD5_BLOCK_SIZE);
|
|
|
+ PIPad := PByte(VIPad);
|
|
|
+ FillChar(PIPad^, MD5_BLOCK_SIZE, $36);
|
|
|
+ PKey := PByte(VKey);
|
|
|
+ for I:=1 to VLength do
|
|
|
+ begin
|
|
|
+ POPad^:=(POPad^ xor PKey^);
|
|
|
+ PIPad^:=(PIPad^ xor PKey^);
|
|
|
+ Inc(POPad);
|
|
|
+ Inc(PIPad);
|
|
|
+ Inc(PKey);
|
|
|
+ end;
|
|
|
+ VIPad:=Concat(VIPad,aData);
|
|
|
+ MD5.Reset;
|
|
|
+ MD5.Update(VIPad);
|
|
|
+ Result:=Concat(VOPad,MD5.GetDigest);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure THashMD5.Reset;
|
|
|
+begin
|
|
|
+ MD5Init(_MD5);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure THashMD5.Update(var aData; aLength: Cardinal);
|
|
|
+begin
|
|
|
+ MD5Update(_MD5,aData,aLength);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure THashMD5.Update(const aData: TBytes; aLength: Cardinal);
|
|
|
+begin
|
|
|
+ if aLength=0 then
|
|
|
+ aLength:=Length(aData);
|
|
|
+ MD5Update(_MD5,aData[0],aLength);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure THashMD5.Update(const aData: UnicodeString);
|
|
|
+begin
|
|
|
+ Update(TEncoding.UTF8.GetBytes(aData));
|
|
|
+end;
|
|
|
+
|
|
|
+function THashMD5.GetDigest: TBytes;
|
|
|
+
|
|
|
+begin
|
|
|
+ Result:=[];
|
|
|
+ if not _DidFinal then
|
|
|
+ begin
|
|
|
+ _DidFinal:=True;
|
|
|
+ MD5Final(_MD5,_Digest);
|
|
|
+ end;
|
|
|
+ SetLength(Result,Length(_Digest));
|
|
|
+ Move(_Digest,Result[0],Length(_Digest));
|
|
|
+end;
|
|
|
+
|
|
|
+function THashMD5.HashAsBytes: TBytes;
|
|
|
+begin
|
|
|
+ Result:=GetDigest;
|
|
|
+end;
|
|
|
+
|
|
|
+function THashMD5.HashAsString: UnicodeString;
|
|
|
+begin
|
|
|
+ Result:=THash.DigestAsString(GetDigest);
|
|
|
+end;
|
|
|
+
|
|
|
+{ THashSHA1 }
|
|
|
+
|
|
|
+procedure THashSHA1.Reset;
|
|
|
+begin
|
|
|
+ SHA1Init(_SHA1);
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashSHA1.Create: THashSHA1;
|
|
|
+begin
|
|
|
+ Result:=Default(THashSHA1);
|
|
|
+ Result.Reset;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure THashSHA1.Update(var aData; aLength: Cardinal);
|
|
|
+
|
|
|
+begin
|
|
|
+ SHA1Update(_SHA1,aData,aLength);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure THashSHA1.Update(const aData: TBytes; aLength: Cardinal);
|
|
|
+begin
|
|
|
+ if ALength=0 then
|
|
|
+ ALength:=Length(aData);
|
|
|
+ Update(aData[0],aLength);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure THashSHA1.Update(const aData: UnicodeString);
|
|
|
+begin
|
|
|
+ Update(TEncoding.UTF8.GetBytes(aData));
|
|
|
+end;
|
|
|
+
|
|
|
+function THashSHA1.GetBlockSize: Integer;
|
|
|
+begin
|
|
|
+ Result:=64;
|
|
|
+end;
|
|
|
+
|
|
|
+function THashSHA1.GetHashSize: Integer;
|
|
|
+begin
|
|
|
+ Result:=20;
|
|
|
+end;
|
|
|
+
|
|
|
+function THashSHA1.HashAsBytes: TBytes;
|
|
|
+begin
|
|
|
+ Result:=GetDigest;
|
|
|
+end;
|
|
|
+
|
|
|
+function THashSHA1.HashAsString: UnicodeString;
|
|
|
+begin
|
|
|
+ Result:=THash.DigestAsString(GetDigest);
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashSHA1.GetHashBytes(const aData: UnicodeString): TBytes;
|
|
|
+begin
|
|
|
+ With THashSha1.Create do
|
|
|
+ begin
|
|
|
+ Update(aData);
|
|
|
+ Result:=GetDigest;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashSHA1.GetHashString(const aData: UnicodeString): UnicodeString;
|
|
|
+begin
|
|
|
+ With THashSha1.Create do
|
|
|
+ begin
|
|
|
+ Update(aData);
|
|
|
+ Result:=HashAsString;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashSHA1.GetHashBytes(const aStream: TStream): TBytes;
|
|
|
+
|
|
|
+var
|
|
|
+ Buf: TBytes;
|
|
|
+ Len,Count: Longint;
|
|
|
+
|
|
|
+begin
|
|
|
+ Buf:=Default(TBytes);
|
|
|
+ Len:=HashReadBufferSize;
|
|
|
+ SetLength(Buf,Len);
|
|
|
+ With THashSha1.Create do
|
|
|
+ begin
|
|
|
+ Count:=aStream.Read(Buf,Len);
|
|
|
+ While (Count>0) do
|
|
|
+ begin
|
|
|
+ Update(Buf,Count);
|
|
|
+ Count:=aStream.Read(Buf,Len);
|
|
|
+ end;
|
|
|
+ Result:=GetDigest;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashSHA1.GetHashString(const aStream: TStream): UnicodeString;
|
|
|
+begin
|
|
|
+ Result:=THash.DigestAsString(GetHashBytes(aStream));
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashSHA1.GetHashBytesFromFile(const aFileName: TFileName): TBytes;
|
|
|
+
|
|
|
+var
|
|
|
+ F: TFileStream;
|
|
|
+
|
|
|
+begin
|
|
|
+ F:=TFileStream.Create(aFileName,fmOpenRead or fmShareDenyWrite);
|
|
|
+ try
|
|
|
+ Result:=GetHashBytes(F);
|
|
|
+ finally
|
|
|
+ F.Free;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashSHA1.GetHashStringFromFile(const aFileName: TFileName): UnicodeString;
|
|
|
+begin
|
|
|
+ Result:=THash.DigestAsString(GetHashBytesFromFile(aFileName));
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashSHA1.GetHMAC(const aData, aKey: UnicodeString): UnicodeString;
|
|
|
+begin
|
|
|
+ Result:=THash.DigestAsString(GetHMACAsBytes(aData,aKey));
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashSHA1.GetHMACAsBytes(const aData, aKey: UnicodeString): TBytes;
|
|
|
+begin
|
|
|
+ With TEncoding.UTF8 do
|
|
|
+ Result:=GetHMACAsBytes(GetBytes(aData),GetBytes(aKey));
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashSHA1.GetHMACAsBytes(const aData: UnicodeString; const aKey: TBytes): TBytes;
|
|
|
+begin
|
|
|
+ With TEncoding.UTF8 do
|
|
|
+ Result:=GetHMACAsBytes(GetBytes(aData),aKey);
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashSHA1.GetHMACAsBytes(const aData: TBytes; const aKey: UnicodeString): TBytes;
|
|
|
+begin
|
|
|
+ With TEncoding.UTF8 do
|
|
|
+ Result:=GetHMACAsBytes(aData,GetBytes(aKey));
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashSHA1.GetHMACAsBytes(const aData, aKey: TBytes): TBytes;
|
|
|
+
|
|
|
+var
|
|
|
+ I: Byte;
|
|
|
+ SHA1_BLOCK_SIZE : Integer;
|
|
|
+ VLength: PtrUInt;
|
|
|
+ PKey, POPad, PIPad: PByte;
|
|
|
+ VKey, VOPad, VIPad: TBytes;
|
|
|
+ Sha1 : THashSha1;
|
|
|
+
|
|
|
+begin
|
|
|
+ VKey:=Default(TBytes);
|
|
|
+ VOPad:=Default(TBytes);
|
|
|
+ VIPad:=Default(TBytes);
|
|
|
+ Sha1:=THashSha1.Create;
|
|
|
+ SHA1_BLOCK_SIZE:=Sha1.GetBlockSize;
|
|
|
+ VLength:=Length(aKey);
|
|
|
+ if VLength > SHA1_BLOCK_SIZE then
|
|
|
+ begin
|
|
|
+ SetLength(VKey,SHA1_BLOCK_SIZE);
|
|
|
+ FillChar(VKey[0],SHA1_BLOCK_SIZE, #0);
|
|
|
+ Sha1.Update(aKey);
|
|
|
+ VKey:=Concat(Sha1.GetDigest,VKey);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ SetLength(VKey,SHA1_BLOCK_SIZE-VLength);
|
|
|
+ FillChar(VKey[0],SHA1_BLOCK_SIZE-VLength, #0);
|
|
|
+ VKey:=Concat(aKey,VKey);
|
|
|
+ end;
|
|
|
+ SetLength(VOPad,SHA1_BLOCK_SIZE);
|
|
|
+ POPad:=PByte(VOPad);
|
|
|
+ FillChar(POPad^, SHA1_BLOCK_SIZE, $5c);
|
|
|
+ SetLength(VIPad, SHA1_BLOCK_SIZE);
|
|
|
+ PIPad := PByte(VIPad);
|
|
|
+ FillChar(PIPad^, SHA1_BLOCK_SIZE, $36);
|
|
|
+ PKey := PByte(VKey);
|
|
|
+ for I:=1 to VLength do
|
|
|
+ begin
|
|
|
+ POPad^:=(POPad^ xor PKey^);
|
|
|
+ PIPad^:=(PIPad^ xor PKey^);
|
|
|
+ Inc(POPad);
|
|
|
+ Inc(PIPad);
|
|
|
+ Inc(PKey);
|
|
|
+ end;
|
|
|
+ VIPad:=Concat(VIPad,aData);
|
|
|
+ Sha1.Reset;
|
|
|
+ Sha1.Update(VIPad);
|
|
|
+ Result:=Concat(VOPad,Sha1.GetDigest);
|
|
|
+end;
|
|
|
+
|
|
|
+function THashSHA1.GetDigest: TBytes;
|
|
|
+
|
|
|
+begin
|
|
|
+ Result:=[];
|
|
|
+ if not _DidFinal then
|
|
|
+ begin
|
|
|
+ _DidFinal:=True;
|
|
|
+ SHA1Final(_SHA1,_Digest);
|
|
|
+ end;
|
|
|
+ SetLength(Result,Length(_Digest));
|
|
|
+ Move(_Digest,Result[0],Length(_Digest));
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+{ THashSHA2 }
|
|
|
+
|
|
|
+Procedure NotSupportedVersion(aHashVersion : THashSHA2.TSHA2Version);
|
|
|
+
|
|
|
+var
|
|
|
+ S : String;
|
|
|
+
|
|
|
+begin
|
|
|
+ WriteStr(S,aHashversion);
|
|
|
+ Raise EHashException.CreateFmt('SHA2 - %s not yet supported',[S]);
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashSHA2.Create(aHashVersion: TSHA2Version): THashSHA2;
|
|
|
+
|
|
|
+begin
|
|
|
+ if aHashVersion in [SHA224, SHA512_224, SHA512_256] then
|
|
|
+ NotSupportedVersion(aHashVersion);
|
|
|
+ Result.FHashVersion:=aHashVersion;
|
|
|
+ Result.Reset;
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashSHA2.GetHashBytes(const aData: UnicodeString; aHashVersion: TSHA2Version): TBytes;
|
|
|
+
|
|
|
+var
|
|
|
+ H : THashSHA2;
|
|
|
+
|
|
|
+begin
|
|
|
+ H:=THashSHA2.Create(aHashVersion);
|
|
|
+ H.Update(AData);
|
|
|
+ Result:=H.GetDigest;
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashSHA2.GetHashString(const aData: UnicodeString; aHashVersion: TSHA2Version): UnicodeString;
|
|
|
+
|
|
|
+var
|
|
|
+ H: THashSHA2;
|
|
|
+
|
|
|
+begin
|
|
|
+ H:=THashSHA2.Create(aHashVersion);
|
|
|
+ H.Update(aData);
|
|
|
+ Result:=H.HashAsString;
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashSHA2.GetHashBytes(const aStream: TStream; aHashVersion: TSHA2Version): TBytes;
|
|
|
+
|
|
|
+var
|
|
|
+ Buf: TBytes;
|
|
|
+ Len,Count: Longint;
|
|
|
+
|
|
|
+begin
|
|
|
+ Buf:=Default(TBytes);
|
|
|
+ Len:=HashReadBufferSize;
|
|
|
+ SetLength(Buf,Len);
|
|
|
+ With THashSha2.Create(aHashVersion) do
|
|
|
+ begin
|
|
|
+ Count:=aStream.Read(Buf,Len);
|
|
|
+ While (Count>0) do
|
|
|
+ begin
|
|
|
+ Update(Buf,Count);
|
|
|
+ Count:=aStream.Read(Buf,Len);
|
|
|
+ end;
|
|
|
+ Result:=GetDigest;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashSHA2.GetHashString(const aStream: TStream; aHashVersion: TSHA2Version): UnicodeString;
|
|
|
+begin
|
|
|
+ Result:=THash.DigestAsString(GetHashBytes(aStream,aHashVersion));
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashSHA2.GetHashBytesFromFile(const aFileName: TFileName; aHashVersion: TSHA2Version): TBytes;
|
|
|
+
|
|
|
+var
|
|
|
+ F: TFileStream;
|
|
|
+
|
|
|
+begin
|
|
|
+ F:=TFileStream.Create(aFileName,fmOpenRead or fmShareDenyWrite);
|
|
|
+ try
|
|
|
+ Result:=GetHashBytes(F,aHashVersion);
|
|
|
+ finally
|
|
|
+ F.Free;
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashSHA2.GetHashStringFromFile(const aFileName: TFileName; aHashVersion: TSHA2Version): UnicodeString;
|
|
|
+begin
|
|
|
+ Result:=THash.DigestAsString(GetHashBytesFromFile(aFileName,aHashVersion));
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashSHA2.GetHMAC(const aData, aKey: UnicodeString; aHashVersion: TSHA2Version): UnicodeString;
|
|
|
+begin
|
|
|
+ Result:=THash.DigestAsString(GetHMACAsBytes(aData,aKey,aHashVersion));
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashSHA2.GetHMACAsBytes(const aData, aKey: UnicodeString; aHashVersion: TSHA2Version): TBytes;
|
|
|
+begin
|
|
|
+ With TEncoding.UTF8 do
|
|
|
+ Result:=GetHMACAsBytes(GetBytes(aData),GetBytes(aKey),aHashVersion);
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashSHA2.GetHMACAsBytes(const aData: UnicodeString; const aKey: TBytes; aHashVersion: TSHA2Version): TBytes;
|
|
|
+begin
|
|
|
+ With TEncoding.UTF8 do
|
|
|
+ Result:=GetHMACAsBytes(GetBytes(aData),aKey,aHashVersion);
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashSHA2.GetHMACAsBytes(const aData: TBytes; const aKey: UnicodeString; aHashVersion: TSHA2Version): TBytes;
|
|
|
+begin
|
|
|
+ With TEncoding.UTF8 do
|
|
|
+ Result:=GetHMACAsBytes(aData,GetBytes(aKey),aHashVersion);
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashSHA2.GetHMACAsBytes(const aData, aKey: TBytes; aHashVersion: TSHA2Version): TBytes;
|
|
|
+
|
|
|
+var
|
|
|
+ Count: UInt32;
|
|
|
+ KeySize,DataSize,BufSize : Integer;
|
|
|
+ aDigest,KeyBuffer, PadBuffer: TBytes;
|
|
|
+ SHA2,SHA2_ : THashSHA2;
|
|
|
+
|
|
|
+begin
|
|
|
+ Result:=[];
|
|
|
+ KeySize:=Length(akey);
|
|
|
+ DataSize:=Length(aData);
|
|
|
+ if aKey = nil then
|
|
|
+ Exit;
|
|
|
+ if aData = nil then
|
|
|
+ Exit;
|
|
|
+ SHA2:=THashSHA2.Create(aHashversion);
|
|
|
+ BufSize:=SHA2.GetBlockSize;
|
|
|
+ SetLength(KeyBuffer,BufSize);
|
|
|
+ SetLength(PadBuffer,BufSize);
|
|
|
+ if KeySize>BufSize then
|
|
|
+ begin
|
|
|
+ SHA2.Update(aKey);
|
|
|
+ aDigest:=SHA2.GetDigest;
|
|
|
+ System.Move(aDigest[0],KeyBuffer[0],SHA2.GetHashSize);
|
|
|
+ end else
|
|
|
+ System.Move(aKey[0], KeyBuffer[0], KeySize);
|
|
|
+ // XOR the key buffer with the iPad value
|
|
|
+ for Count := 0 to BufSize do
|
|
|
+ PadBuffer[Count] := KeyBuffer[Count] xor $36;
|
|
|
+ SHA2.Reset;
|
|
|
+ SHA2.Update(PadBuffer);
|
|
|
+ SHA2.Update(aData);
|
|
|
+ aDigest:=SHA2.GetDigest;
|
|
|
+ // XOR the key buffer with the oPad value
|
|
|
+ for Count := 0 to 63 do
|
|
|
+ PadBuffer[Count] := KeyBuffer[Count] xor $5C;
|
|
|
+ // SHA256 the key buffer and the result of the inner SHA256 (Outer)
|
|
|
+ SHA2.Reset;
|
|
|
+ SHA2.Update(PadBuffer);
|
|
|
+ SHA2.Update(aDigest);
|
|
|
+ Result:=SHA2_.GetDigest;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure THashSHA2.Reset;
|
|
|
+begin
|
|
|
+ case FHashVersion of
|
|
|
+ Sha256 : _S256.Init;
|
|
|
+ Sha384 : _S384.Init;
|
|
|
+ Sha512 : _S512.Init;
|
|
|
+ end;
|
|
|
+ FDidFinal:=False;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure THashSHA2.Update(var aData; aLength: Cardinal);
|
|
|
+begin
|
|
|
+ Update(PByte(@aData),aLength);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure THashSHA2.Update(const aData: PByte; aLength: Cardinal);
|
|
|
+begin
|
|
|
+ case FHashVersion of
|
|
|
+ Sha256 : _S256.Update(aData,aLength);
|
|
|
+ Sha384 : _S384.Update(aData,aLength);
|
|
|
+ Sha512 : _S512.Update(aData,aLength);
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure THashSHA2.Update(const aData: TBytes; aLength: Cardinal);
|
|
|
+begin
|
|
|
+ if aLength=0 then
|
|
|
+ aLength:=Length(aData);
|
|
|
+ Update(PByte(aData),aLength);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure THashSHA2.Update(const aData: UnicodeString);
|
|
|
+begin
|
|
|
+ Update(TEncoding.UTF8.GetBytes(aData));
|
|
|
+end;
|
|
|
+
|
|
|
+procedure THashSHA2.Update(const aData: RawByteString);
|
|
|
+begin
|
|
|
+ Update(PByte(aData),Length(aData)*SizeOf(AnsiChar));
|
|
|
+end;
|
|
|
+
|
|
|
+procedure THashSHA2.DoFinal;
|
|
|
+
|
|
|
+begin
|
|
|
+ case FHashVersion of
|
|
|
+ Sha256 : _S256.Final;
|
|
|
+ Sha384 : _S384.Final;
|
|
|
+ Sha512 : _S512.Final;
|
|
|
+ end;
|
|
|
+ FDidFinal:=True;
|
|
|
+end;
|
|
|
+
|
|
|
+function THashSHA2.GetDigest: TBytes;
|
|
|
+
|
|
|
+Var
|
|
|
+ P : PByte;
|
|
|
+ L : Integer;
|
|
|
+
|
|
|
+
|
|
|
+begin
|
|
|
+ if Not FDidFinal then
|
|
|
+ DoFinal;
|
|
|
+ // These should normally all be the same...
|
|
|
+ case FHashVersion of
|
|
|
+ Sha256 : P:=@_S256.Digest;
|
|
|
+ Sha384 : P:=@_S384.Digest;
|
|
|
+ Sha512 : P:=@_S512.Digest;
|
|
|
+ end;
|
|
|
+ L:=GetHashSize;
|
|
|
+ SetLength(Result,L);
|
|
|
+ Move(P^,Result[0],L);
|
|
|
+end;
|
|
|
+
|
|
|
+function THashSHA2.GetBlockSize: Integer;
|
|
|
+Const
|
|
|
+ Sizes : Array[TSHA2Version] of integer
|
|
|
+ = (64,64,128,128,128,128);
|
|
|
+begin
|
|
|
+ Result:=Sizes[FHashVersion];
|
|
|
+end;
|
|
|
+
|
|
|
+function THashSHA2.GetHashSize: Integer;
|
|
|
+
|
|
|
+Const
|
|
|
+ Sizes : Array[TSHA2Version] of integer
|
|
|
+ = (28,32,48,64,28,32);
|
|
|
+begin
|
|
|
+ Result:=Sizes[FHashVersion];
|
|
|
+end;
|
|
|
+
|
|
|
+function THashSHA2.HashAsBytes: TBytes;
|
|
|
+begin
|
|
|
+ Result:=GetDigest;
|
|
|
+end;
|
|
|
+
|
|
|
+function THashSHA2.HashAsString: UnicodeString;
|
|
|
+begin
|
|
|
+ Result:=THash.DigestAsString(GetDigest);
|
|
|
+end;
|
|
|
+
|
|
|
+{ THashBobJenkins }
|
|
|
+
|
|
|
+class function THashBobJenkins.Create: THashBobJenkins;
|
|
|
+begin
|
|
|
+ Result.Reset;
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashBobJenkins.GetHashBytes(const aData: UnicodeString): TBytes;
|
|
|
+begin
|
|
|
+ Result:=Default(TBytes);
|
|
|
+ SetLength(Result,SizeOf(Cardinal));
|
|
|
+ PCardinal(Result)^:=GetHashValue(aData)
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashBobJenkins.GetHashString(const aData: UnicodeString): UnicodeString;
|
|
|
+begin
|
|
|
+ Result:=HexStr(GetHashValue(aData),8);
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashBobJenkins.GetHashString(const aData: RawByteString): UnicodeString;
|
|
|
+begin
|
|
|
+ Result:=HexStr(GetHashValue(aData),8);
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+class function THashBobJenkins.GetHashValue(var aData; aLength: Integer; aInitialValue: Integer): Integer;
|
|
|
+begin
|
|
|
+ Result:=Integer(DelphiHashLittle(PByte(@AData),aLength,aInitialValue));
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashBobJenkins.GetHashValue(const aData: PByte; aLength: Integer; aInitialValue: Integer): Integer;
|
|
|
+begin
|
|
|
+ Result:=DelphiHashLittle(AData,aLength,aInitialValue);
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashBobJenkins.GetHashValue(const aData: UnicodeString): Integer;
|
|
|
+begin
|
|
|
+ Result:=GetHashValue(PByte(aData),Length(aData)*SizeOf(UnicodeChar),0);
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashBobJenkins.GetHashValue(const aData: RawByteString): Integer;
|
|
|
+begin
|
|
|
+ Result:=GetHashValue(PByte(aData),Length(aData)*SizeOf(AnsiChar),0);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure THashBobJenkins.Reset(aInitialValue: Integer);
|
|
|
+begin
|
|
|
+ FCurrent:=aInitialValue;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure THashBobJenkins.Update(aData: PByte; aLength: Cardinal);
|
|
|
+begin
|
|
|
+ FCurrent:=DelphiHashLittle(AData,aLength,FCurrent);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure THashBobJenkins.Update(var aData; aLength: Cardinal);
|
|
|
+begin
|
|
|
+ Update(PByte(@AData),aLength);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure THashBobJenkins.Update(const aData: TBytes; aLength: Cardinal);
|
|
|
+begin
|
|
|
+ if aLength=0 then
|
|
|
+ aLength:=Length(aData);
|
|
|
+ Update(PByte(aData),aLength);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure THashBobJenkins.Update(const aData: UnicodeString);
|
|
|
+begin
|
|
|
+ Update(PByte(aData),Length(aData)*SizeOf(UnicodeChar));
|
|
|
+end;
|
|
|
+
|
|
|
+procedure THashBobJenkins.Update(const aData: RawByteString);
|
|
|
+begin
|
|
|
+ Update(PByte(aData),Length(aData)*SizeOf(AnsiChar));
|
|
|
+end;
|
|
|
+
|
|
|
+function THashBobJenkins.HashAsBytes: TBytes;
|
|
|
+begin
|
|
|
+ Result:=[];
|
|
|
+ SetLength(Result,Sizeof(Cardinal));
|
|
|
+ PCardinal(Result)^:=FCurrent;
|
|
|
+end;
|
|
|
+
|
|
|
+function THashBobJenkins.HashAsInteger: Integer;
|
|
|
+begin
|
|
|
+ Result:=FCurrent;
|
|
|
+end;
|
|
|
+
|
|
|
+function THashBobJenkins.HashAsString: UnicodeString;
|
|
|
+begin
|
|
|
+ Result:=HexStr(HashAsInteger,8);
|
|
|
+end;
|
|
|
+
|
|
|
+{ THashFNV1a32 }
|
|
|
+
|
|
|
+class function THashFNV1a32.Create: THashFNV1a32;
|
|
|
+begin
|
|
|
+ Result.Reset;
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashFNV1a32.GetHashBytes(const aData: UnicodeString): TBytes;
|
|
|
+
|
|
|
+var
|
|
|
+ C : Cardinal;
|
|
|
+
|
|
|
+begin
|
|
|
+ Result:=Default(TBytes);
|
|
|
+ SetLength(Result,SizeOf(Fnv32_t));
|
|
|
+ C:=Cardinal(GetHashValue(aData));
|
|
|
+ PFnv32_t(@Result[0])^:=C;
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashFNV1a32.GetHashString(const aData: UnicodeString): UnicodeString;
|
|
|
+begin
|
|
|
+ Result:=HexStr(FNV1_32a(Pointer(aData)^,Length(aData)*SizeOf(UnicodeChar),FNV_SEED),8);
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashFNV1a32.GetHashString(const aData: RawByteString): UnicodeString;
|
|
|
+begin
|
|
|
+ Result:=HexStr(FNV1_32a(Pointer(aData)^,Length(aData),FNV_SEED),8);
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashFNV1a32.GetHashValue(const aData: UnicodeString): Integer;
|
|
|
+
|
|
|
+var
|
|
|
+ C : Cardinal;
|
|
|
+
|
|
|
+begin
|
|
|
+ C:=FNV1_32a(PByte(aData),Length(aData)*SizeOf(UnicodeChar),FNV_SEED);
|
|
|
+ Result:=Integer(C);
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashFNV1a32.GetHashValue(const aData: RawByteString): Integer;
|
|
|
+begin
|
|
|
+ Result:=Integer(FNV1_32a(Pointer(aData)^,Length(aData), FNV_SEED));
|
|
|
+end;
|
|
|
+
|
|
|
+class function THashFNV1a32.GetHashValue(const aData; aLength: Cardinal; aInitialValue: Cardinal): Integer;
|
|
|
+begin
|
|
|
+ Result:=Integer(FNV1_32a(aData,aLength,aInitialValue));
|
|
|
+end;
|
|
|
+
|
|
|
+procedure THashFNV1a32.Reset(aInitialValue: Cardinal);
|
|
|
+begin
|
|
|
+ FCurrent:=aInitialValue;
|
|
|
+end;
|
|
|
+
|
|
|
+procedure THashFNV1a32.Update(const aData; aLength: Cardinal);
|
|
|
+begin
|
|
|
+ FCurrent:=FNV1_32a(aData,aLength,FCurrent);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure THashFNV1a32.Update(const aData: TBytes; aLength: Cardinal);
|
|
|
+begin
|
|
|
+ if aLength=0 then
|
|
|
+ aLength:=Length(aData);
|
|
|
+ Update(aData[0],aLength);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure THashFNV1a32.Update(const aData: UnicodeString);
|
|
|
+begin
|
|
|
+ FCurrent:=FNV1_32a(PByte(aData),Length(aData)*SizeOf(UnicodeChar),FCurrent);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure THashFNV1a32.Update(const aData: RawByteString);
|
|
|
+begin
|
|
|
+ FCurrent:=FNV1_32a(PByte(aData),Length(aData)*SizeOf(AnsiChar),FCurrent);
|
|
|
+end;
|
|
|
+
|
|
|
+function THashFNV1a32.GetDigest: TBytes;
|
|
|
+begin
|
|
|
+ Result:=Default(TBytes);
|
|
|
+ SetLength(Result,SizeOf(Fnv32_t));
|
|
|
+ PFnv32_t(@Result[0])^:=FCurrent;
|
|
|
+end;
|
|
|
+
|
|
|
+function THashFNV1a32.HashAsBytes: TBytes;
|
|
|
+begin
|
|
|
+ Result:=GetDigest;
|
|
|
+end;
|
|
|
+
|
|
|
+function THashFNV1a32.HashAsInteger: Integer;
|
|
|
+begin
|
|
|
+ Result:=Integer(FCurrent);
|
|
|
+end;
|
|
|
+
|
|
|
+function THashFNV1a32.HashAsString: UnicodeString;
|
|
|
+begin
|
|
|
+ Result:=HexStr(FCurrent,8);
|
|
|
+end;
|
|
|
+
|
|
|
+end.
|