Browse Source

Merge downstream

Herman Schoenfeld 7 years ago
parent
commit
89c6ae15c3
76 changed files with 1812 additions and 154 deletions
  1. 1 1
      src/libraries/hashlib4pascal/HashLib.inc
  2. 1 1
      src/libraries/hashlib4pascal/HashLibHelper.inc
  3. 13 0
      src/libraries/hashlib4pascal/HlpAP.pas
  4. 13 0
      src/libraries/hashlib4pascal/HlpAdler32.pas
  5. 12 0
      src/libraries/hashlib4pascal/HlpBKDR.pas
  6. 12 0
      src/libraries/hashlib4pascal/HlpBernstein.pas
  7. 12 0
      src/libraries/hashlib4pascal/HlpBernstein1.pas
  8. 4 0
      src/libraries/hashlib4pascal/HlpBits.pas
  9. 48 8
      src/libraries/hashlib4pascal/HlpBlake2B.pas
  10. 84 6
      src/libraries/hashlib4pascal/HlpBlake2BConfig.pas
  11. 1 1
      src/libraries/hashlib4pascal/HlpBlake2BTreeConfig.pas
  12. 48 8
      src/libraries/hashlib4pascal/HlpBlake2S.pas
  13. 84 6
      src/libraries/hashlib4pascal/HlpBlake2SConfig.pas
  14. 1 1
      src/libraries/hashlib4pascal/HlpBlake2STreeConfig.pas
  15. 31 5
      src/libraries/hashlib4pascal/HlpCRC.pas
  16. 19 2
      src/libraries/hashlib4pascal/HlpDEK.pas
  17. 12 0
      src/libraries/hashlib4pascal/HlpDJB.pas
  18. 12 0
      src/libraries/hashlib4pascal/HlpELF.pas
  19. 12 0
      src/libraries/hashlib4pascal/HlpFNV.pas
  20. 12 0
      src/libraries/hashlib4pascal/HlpFNV1a.pas
  21. 12 0
      src/libraries/hashlib4pascal/HlpFNV1a64.pas
  22. 12 0
      src/libraries/hashlib4pascal/HlpFNV64.pas
  23. 47 7
      src/libraries/hashlib4pascal/HlpGOST3411_2012.pas
  24. 18 2
      src/libraries/hashlib4pascal/HlpGost.pas
  25. 17 0
      src/libraries/hashlib4pascal/HlpGrindahl256.pas
  26. 17 0
      src/libraries/hashlib4pascal/HlpGrindahl512.pas
  27. 16 1
      src/libraries/hashlib4pascal/HlpHAS160.pas
  28. 17 4
      src/libraries/hashlib4pascal/HlpHMACNotBuildInAdapter.pas
  29. 8 3
      src/libraries/hashlib4pascal/HlpHash.pas
  30. 10 2
      src/libraries/hashlib4pascal/HlpHashBuffer.pas
  31. 230 3
      src/libraries/hashlib4pascal/HlpHaval.pas
  32. 12 0
      src/libraries/hashlib4pascal/HlpJS.pas
  33. 18 2
      src/libraries/hashlib4pascal/HlpJenkins3.pas
  34. 17 1
      src/libraries/hashlib4pascal/HlpMD2.pas
  35. 17 1
      src/libraries/hashlib4pascal/HlpMD4.pas
  36. 17 1
      src/libraries/hashlib4pascal/HlpMD5.pas
  37. 3 2
      src/libraries/hashlib4pascal/HlpMultipleTransformNonBlock.pas
  38. 19 3
      src/libraries/hashlib4pascal/HlpMurmur2.pas
  39. 18 3
      src/libraries/hashlib4pascal/HlpMurmur2_64.pas
  40. 17 0
      src/libraries/hashlib4pascal/HlpMurmurHash3_x64_128.pas
  41. 19 0
      src/libraries/hashlib4pascal/HlpMurmurHash3_x86_128.pas
  42. 1 1
      src/libraries/hashlib4pascal/HlpMurmurHash3_x86_32.pas
  43. 13 0
      src/libraries/hashlib4pascal/HlpNullDigest.pas
  44. 12 0
      src/libraries/hashlib4pascal/HlpOneAtTime.pas
  45. 12 0
      src/libraries/hashlib4pascal/HlpPJW.pas
  46. 38 1
      src/libraries/hashlib4pascal/HlpPanama.pas
  47. 17 1
      src/libraries/hashlib4pascal/HlpRIPEMD.pas
  48. 17 1
      src/libraries/hashlib4pascal/HlpRIPEMD128.pas
  49. 17 1
      src/libraries/hashlib4pascal/HlpRIPEMD160.pas
  50. 17 1
      src/libraries/hashlib4pascal/HlpRIPEMD256.pas
  51. 17 1
      src/libraries/hashlib4pascal/HlpRIPEMD320.pas
  52. 13 0
      src/libraries/hashlib4pascal/HlpRS.pas
  53. 24 2
      src/libraries/hashlib4pascal/HlpRadioGatun32.pas
  54. 23 1
      src/libraries/hashlib4pascal/HlpRadioGatun64.pas
  55. 12 0
      src/libraries/hashlib4pascal/HlpRotating.pas
  56. 12 0
      src/libraries/hashlib4pascal/HlpSDBM.pas
  57. 16 1
      src/libraries/hashlib4pascal/HlpSHA0.pas
  58. 19 2
      src/libraries/hashlib4pascal/HlpSHA1.pas
  59. 16 0
      src/libraries/hashlib4pascal/HlpSHA2_224.pas
  60. 16 0
      src/libraries/hashlib4pascal/HlpSHA2_256.pas
  61. 1 1
      src/libraries/hashlib4pascal/HlpSHA2_256Base.pas
  62. 16 0
      src/libraries/hashlib4pascal/HlpSHA2_384.pas
  63. 16 0
      src/libraries/hashlib4pascal/HlpSHA2_512.pas
  64. 1 1
      src/libraries/hashlib4pascal/HlpSHA2_512Base.pas
  65. 16 0
      src/libraries/hashlib4pascal/HlpSHA2_512_224.pas
  66. 16 0
      src/libraries/hashlib4pascal/HlpSHA2_512_256.pas
  67. 56 5
      src/libraries/hashlib4pascal/HlpSHA3.pas
  68. 12 0
      src/libraries/hashlib4pascal/HlpShiftAndXor.pas
  69. 28 8
      src/libraries/hashlib4pascal/HlpSipHash.pas
  70. 49 7
      src/libraries/hashlib4pascal/HlpSnefru.pas
  71. 18 2
      src/libraries/hashlib4pascal/HlpSuperFast.pas
  72. 93 10
      src/libraries/hashlib4pascal/HlpTiger.pas
  73. 94 11
      src/libraries/hashlib4pascal/HlpTiger2.pas
  74. 31 16
      src/libraries/hashlib4pascal/HlpWhirlPool.pas
  75. 30 3
      src/libraries/hashlib4pascal/HlpXXHash32.pas
  76. 30 3
      src/libraries/hashlib4pascal/HlpXXHash64.pas

+ 1 - 1
src/libraries/hashlib4pascal/HashLib.inc

@@ -1,6 +1,6 @@
 { *********************************************************** }
 { *                     HashLib Library                     * }
-{ *      Copyright (c) Ugochukwu Mmaduekwe 2016 - 2017      * }
+{ *      Copyright (c) Ugochukwu Mmaduekwe 2016 - 2018      * }
 { *********************************************************** }
 
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)

+ 1 - 1
src/libraries/hashlib4pascal/HashLibHelper.inc

@@ -1,6 +1,6 @@
 { *********************************************************** }
 { *                     HashLib Library                     * }
-{ *      Copyright (c) Ugochukwu Mmaduekwe 2016 - 2017      * }
+{ *      Copyright (c) Ugochukwu Mmaduekwe 2016 - 2018      * }
 { *********************************************************** }
 
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)

+ 13 - 0
src/libraries/hashlib4pascal/HlpAP.pas

@@ -7,6 +7,7 @@ interface
 uses
   HlpHashLibTypes,
   HlpHash,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashResult,
   HlpIHashResult;
@@ -24,6 +25,7 @@ type
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_length: Int32); override;
     function TransformFinal(): IHashResult; override;
+    function Clone(): IHash; override;
 
   end;
 
@@ -31,6 +33,17 @@ implementation
 
 { TAP }
 
+function TAP.Clone(): IHash;
+var
+  HashInstance: TAP;
+begin
+  HashInstance := TAP.Create();
+  HashInstance.Fm_hash := Fm_hash;
+  HashInstance.Fm_index := Fm_index;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TAP.Create;
 begin
   Inherited Create(4, 1);

+ 13 - 0
src/libraries/hashlib4pascal/HlpAdler32.pas

@@ -8,6 +8,7 @@ uses
   HlpHashLibTypes,
   HlpIHashInfo,
   HlpHash,
+  HlpIHash,
   HlpHashResult,
   HlpIHashResult;
 
@@ -28,6 +29,7 @@ type
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_length: Int32); override;
     function TransformFinal: IHashResult; override;
+    function Clone(): IHash; override;
 
   end;
 
@@ -35,6 +37,17 @@ implementation
 
 { TAdler32 }
 
+function TAdler32.Clone(): IHash;
+var
+  HashInstance: TAdler32;
+begin
+  HashInstance := TAdler32.Create();
+  HashInstance.Fm_a := Fm_a;
+  HashInstance.Fm_b := Fm_b;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TAdler32.Create;
 begin
   Inherited Create(4, 1);

+ 12 - 0
src/libraries/hashlib4pascal/HlpBKDR.pas

@@ -7,6 +7,7 @@ interface
 uses
   HlpHashLibTypes,
   HlpHash,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashResult,
   HlpIHashResult;
@@ -27,12 +28,23 @@ type
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_length: Int32); override;
     function TransformFinal(): IHashResult; override;
+    function Clone(): IHash; override;
   end;
 
 implementation
 
 { TBKDR }
 
+function TBKDR.Clone(): IHash;
+var
+  HashInstance: TBKDR;
+begin
+  HashInstance := TBKDR.Create();
+  HashInstance.Fm_hash := Fm_hash;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TBKDR.Create;
 begin
   Inherited Create(4, 1);

+ 12 - 0
src/libraries/hashlib4pascal/HlpBernstein.pas

@@ -7,6 +7,7 @@ interface
 uses
   HlpHashLibTypes,
   HlpHash,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashResult,
   HlpIHashResult;
@@ -23,12 +24,23 @@ type
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_length: Int32); override;
     function TransformFinal(): IHashResult; override;
+    function Clone(): IHash; override;
   end;
 
 implementation
 
 { TBernstein }
 
+function TBernstein.Clone(): IHash;
+var
+  HashInstance: TBernstein;
+begin
+  HashInstance := TBernstein.Create();
+  HashInstance.Fm_hash := Fm_hash;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TBernstein.Create;
 begin
   Inherited Create(4, 1);

+ 12 - 0
src/libraries/hashlib4pascal/HlpBernstein1.pas

@@ -7,6 +7,7 @@ interface
 uses
   HlpHashLibTypes,
   HlpHash,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashResult,
   HlpIHashResult;
@@ -23,12 +24,23 @@ type
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_length: Int32); override;
     function TransformFinal(): IHashResult; override;
+    function Clone(): IHash; override;
   end;
 
 implementation
 
 { TBernstein1 }
 
+function TBernstein1.Clone(): IHash;
+var
+  HashInstance: TBernstein1;
+begin
+  HashInstance := TBernstein1.Create();
+  HashInstance.Fm_hash := Fm_hash;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TBernstein1.Create;
 begin
   Inherited Create(4, 1);

+ 4 - 0
src/libraries/hashlib4pascal/HlpBits.pas

@@ -150,9 +150,11 @@ begin
 {$ELSE}
   Result := Value shr ShiftBits;
   if (Value and $80000000) > 0 then
+  begin
     // if you don't want to cast ($FFFFFFFF) to an Int32,
     // simply replace it with (-1) to avoid range check error.
     Result := Result or (Int32($FFFFFFFF) shl (32 - ShiftBits));
+  end;
 
   /// ++++++ Alternative Variant ++++++ ///
 
@@ -168,7 +170,9 @@ begin
 {$ELSE}
   Result := Value shr ShiftBits;
   if (Value and $8000000000000000) > 0 then
+  begin
     Result := Result or ($FFFFFFFFFFFFFFFF shl (64 - ShiftBits));
+  end;
 
   /// ++++++ Alternative Variant ++++++ ///
 

+ 48 - 8
src/libraries/hashlib4pascal/HlpBlake2B.pas

@@ -20,7 +20,9 @@ uses
   HlpIHashResult,
   HlpIBlake2BConfig,
   HlpBlake2BConfig,
+  HlpIBlake2BTreeConfig,
   HlpBlake2BIvBuilder,
+  HlpIHash,
   HlpIHashInfo,
   HlpConverters,
   HlpHashLibTypes;
@@ -67,14 +69,13 @@ type
       FDefaultConfig: IBlake2BConfig;
 
   var
+    F_m: array [0 .. 15] of UInt64;
     FrawConfig, Fm_state: THashLibUInt64Array;
     FKey, F_buf: THashLibByteArray;
-    F_m: array [0 .. 15] of UInt64;
 {$IFNDEF USE_UNROLLED_VARIANT}
     F_v: array [0 .. 15] of UInt64;
 {$ENDIF USE_UNROLLED_VARIANT}
-    F_bufferFilled: Int32;
-
+    F_bufferFilled, FHashSize, FBlockSize: Int32;
     F_counter0, F_counter1, F_finalizationFlag0, F_finalizationFlag1: UInt64;
 
     class constructor Blake2BConfig();
@@ -88,16 +89,18 @@ type
 
   strict protected
 
-    FHashSize, FBlockSize: Int32;
     function GetName: String; override;
 
   public
     constructor Create(); overload;
     constructor Create(const config: IBlake2BConfig); overload;
+    constructor Create(const config: IBlake2BConfig;
+      const treeConfig: IBlake2BTreeConfig); overload;
     procedure Initialize; override;
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_data_length: Int32); override;
     function TransformFinal: IHashResult; override;
+    function Clone(): IHash; override;
 
   end;
 
@@ -137,6 +140,29 @@ end;
 
 {$ENDIF USE_UNROLLED_VARIANT}
 
+function TBlake2B.Clone(): IHash;
+var
+  HashInstance: TBlake2B;
+begin
+  HashInstance := TBlake2B.Create(TBlake2BConfig.Create(FHashSize)
+    as IBlake2BConfig);
+  System.Move(F_m, HashInstance.F_m, System.SizeOf(F_m));
+  HashInstance.FrawConfig := System.Copy(FrawConfig);
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.FKey := System.Copy(FKey);
+  HashInstance.F_buf := System.Copy(F_buf);
+{$IFNDEF USE_UNROLLED_VARIANT}
+  System.Move(F_v, HashInstance.F_v, System.SizeOf(F_v));
+{$ENDIF USE_UNROLLED_VARIANT}
+  HashInstance.F_bufferFilled := F_bufferFilled;
+  HashInstance.F_counter0 := F_counter0;
+  HashInstance.F_counter1 := F_counter1;
+  HashInstance.F_finalizationFlag0 := F_finalizationFlag0;
+  HashInstance.F_finalizationFlag1 := F_finalizationFlag1;
+  Result := HashInstance as IHash;
+  Result.BufferSize := BufferSize;
+end;
+
 procedure TBlake2B.Compress(block: PByte; start: Int32);
 var
 {$IFDEF USE_UNROLLED_VARIANT}
@@ -1597,6 +1623,12 @@ begin
 end;
 
 constructor TBlake2B.Create(const config: IBlake2BConfig);
+begin
+  Create(config, Nil);
+end;
+
+constructor TBlake2B.Create(const config: IBlake2BConfig;
+  const treeConfig: IBlake2BTreeConfig);
 var
   Lconfig: IBlake2BConfig;
 begin
@@ -1609,7 +1641,7 @@ begin
     Lconfig := FDefaultConfig;
   end;
 
-  FrawConfig := TBlake2BIvBuilder.ConfigB(Lconfig, Nil);
+  FrawConfig := TBlake2BIvBuilder.ConfigB(Lconfig, treeConfig);
   if ((Lconfig.Key <> Nil) and (System.Length(Lconfig.Key) <> 0)) then
   begin
 
@@ -1646,7 +1678,7 @@ end;
 
 procedure TBlake2B.Initialize;
 var
-  i: Integer;
+  i: Int32;
 begin
   if (FrawConfig = Nil) then
     raise EArgumentNilHashLibException.Create('config');
@@ -1673,6 +1705,14 @@ begin
 
   System.SetLength(F_buf, BlockSizeInBytes);
 
+  System.FillChar(F_buf[0], (System.Length(F_buf) * System.SizeOf(Byte)
+    ), Byte(0));
+
+  System.FillChar(F_m, System.SizeOf(F_m), UInt64(0));
+
+{$IFNDEF USE_UNROLLED_VARIANT}
+  System.FillChar(F_v, System.SizeOf(F_v), UInt64(0));
+{$ENDIF USE_UNROLLED_VARIANT}
   for i := 0 to 7 do
   begin
     Fm_state[i] := Fm_state[i] xor FrawConfig[i];
@@ -1745,7 +1785,7 @@ begin
   TConverters.le64_copy(PUInt64(Fm_state), 0, PByte(tempRes), 0,
     System.Length(tempRes));
 
-  result := THashResult.Create(tempRes);
+  Result := THashResult.Create(tempRes);
 
   Initialize();
 
@@ -1753,7 +1793,7 @@ end;
 
 function TBlake2B.GetName: String;
 begin
-  result := Format('%s_%u', [Self.ClassName, Self.HashSize * 8]);
+  Result := Format('%s_%u', [Self.ClassName, Self.HashSize * 8]);
 end;
 
 end.

+ 84 - 6
src/libraries/hashlib4pascal/HlpBlake2BConfig.pas

@@ -11,7 +11,11 @@ uses
 
 resourcestring
   SInvalidHashSize =
-    'BLAKE2B HashSize must be restricted to one of the following [20, 32, 48, 64]';
+    'BLAKE2B HashSize must be restricted to one of the following [1 .. 64], "%d"';
+  SInvalidKeyLength = '"Key" Length Must Not Be Greater Than 64, "%d"';
+  SInvalidPersonalisationLength =
+    '"Personalisation" Length Must Be Equal To 16, "%d"';
+  SInvalidSaltLength = '"Salt" Length Must Be Equal To 16, "%d"';
 
 type
 
@@ -24,6 +28,12 @@ type
     FHashSize: Int32;
     FPersonalisation, FSalt, FKey: THashLibByteArray;
 
+    procedure ValidateHashSize(AHashSize: Int32); inline;
+    procedure ValidateKeyLength(const AKey: THashLibByteArray); inline;
+    procedure ValidatePersonalisationLength(const APersonalisation
+      : THashLibByteArray); inline;
+    procedure ValidateSaltLength(const ASalt: THashLibByteArray); inline;
+
     function GetPersonalisation: THashLibByteArray; inline;
     procedure SetPersonalisation(const value: THashLibByteArray); inline;
 
@@ -38,6 +48,8 @@ type
 
   public
     constructor Create(AHashSize: THashSize = THashSize.hsHashSize512);
+      overload;
+    constructor Create(AHashSize: Int32); overload;
     property Personalisation: THashLibByteArray read GetPersonalisation
       write SetPersonalisation;
     property Salt: THashLibByteArray read GetSalt write SetSalt;
@@ -50,6 +62,61 @@ implementation
 
 { TBlake2BConfig }
 
+procedure TBlake2BConfig.ValidateHashSize(AHashSize: Int32);
+begin
+  if not((AHashSize) in [1 .. 64]) or (((AHashSize * 8) and 7) <> 0) then
+  begin
+    raise EArgumentHashLibException.CreateResFmt(@SInvalidHashSize,
+      [AHashSize]);
+  end;
+end;
+
+procedure TBlake2BConfig.ValidateKeyLength(const AKey: THashLibByteArray);
+var
+  KeyLength: Int32;
+begin
+  if (AKey <> Nil) then
+  begin
+    KeyLength := System.Length(AKey);
+    if (KeyLength > 64) then
+    begin
+      raise EArgumentOutOfRangeHashLibException.CreateResFmt(@SInvalidKeyLength,
+        [KeyLength]);
+    end;
+  end;
+end;
+
+procedure TBlake2BConfig.ValidatePersonalisationLength(const APersonalisation
+  : THashLibByteArray);
+var
+  PersonalisationLength: Int32;
+begin
+  if (APersonalisation <> Nil) then
+  begin
+    PersonalisationLength := System.Length(APersonalisation);
+    if (PersonalisationLength <> 16) then
+    begin
+      raise EArgumentOutOfRangeHashLibException.CreateResFmt
+        (@SInvalidPersonalisationLength, [PersonalisationLength]);
+    end;
+  end;
+end;
+
+procedure TBlake2BConfig.ValidateSaltLength(const ASalt: THashLibByteArray);
+var
+  SaltLength: Int32;
+begin
+  if (ASalt <> Nil) then
+  begin
+    SaltLength := System.Length(ASalt);
+    if (SaltLength <> 16) then
+    begin
+      raise EArgumentOutOfRangeHashLibException.CreateResFmt
+        (@SInvalidSaltLength, [SaltLength]);
+    end;
+  end;
+end;
+
 function TBlake2BConfig.GetHashSize: Int32;
 begin
   result := FHashSize;
@@ -72,32 +139,43 @@ end;
 
 procedure TBlake2BConfig.SetHashSize(value: Int32);
 begin
+  ValidateHashSize(value);
   FHashSize := value;
 end;
 
 procedure TBlake2BConfig.SetKey(const value: THashLibByteArray);
 begin
+  ValidateKeyLength(value);
   FKey := value;
 end;
 
 procedure TBlake2BConfig.SetPersonalisation(const value: THashLibByteArray);
 begin
+  ValidatePersonalisationLength(value);
   FPersonalisation := value;
 end;
 
 procedure TBlake2BConfig.SetSalt(const value: THashLibByteArray);
 begin
+  ValidateSaltLength(value);
   FSalt := value;
 end;
 
 constructor TBlake2BConfig.Create(AHashSize: THashSize);
+var
+  LHashSize: Int32;
 begin
   Inherited Create();
-  if not(Int32(AHashSize) in [20, 32, 48, 64]) then
-  begin
-    raise EArgumentHashLibException.CreateRes(@SInvalidHashSize);
-  end;
-  HashSize := Int32(AHashSize);
+  LHashSize := Int32(AHashSize);
+  ValidateHashSize(LHashSize);
+  FHashSize := LHashSize;
+end;
+
+constructor TBlake2BConfig.Create(AHashSize: Int32);
+begin
+  Inherited Create();
+  ValidateHashSize(AHashSize);
+  FHashSize := AHashSize;
 end;
 
 end.

+ 1 - 1
src/libraries/hashlib4pascal/HlpBlake2BTreeConfig.pas

@@ -95,7 +95,7 @@ end;
 constructor TBlake2BTreeConfig.Create;
 begin
   Inherited Create();
-  IntermediateHashSize := 64;
+  FIntermediateHashSize := 64;
 end;
 
 end.

+ 48 - 8
src/libraries/hashlib4pascal/HlpBlake2S.pas

@@ -20,7 +20,9 @@ uses
   HlpIHashResult,
   HlpIBlake2SConfig,
   HlpBlake2SConfig,
+  HlpIBlake2STreeConfig,
   HlpBlake2SIvBuilder,
+  HlpIHash,
   HlpIHashInfo,
   HlpConverters,
   HlpHashLibTypes;
@@ -67,14 +69,13 @@ type
       FDefaultConfig: IBlake2SConfig;
 
   var
+    F_m: array [0 .. 15] of UInt32;
     FrawConfig, Fm_state: THashLibUInt32Array;
     FKey, F_buf: THashLibByteArray;
-    F_m: array [0 .. 15] of UInt32;
 {$IFNDEF USE_UNROLLED_VARIANT}
     F_v: array [0 .. 15] of UInt32;
 {$ENDIF USE_UNROLLED_VARIANT}
-    F_bufferFilled: Int32;
-
+    F_bufferFilled, FHashSize, FBlockSize: Int32;
     F_counter0, F_counter1, F_finalizationFlag0, F_finalizationFlag1: UInt32;
 
     class constructor Blake2SConfig();
@@ -88,16 +89,18 @@ type
 
   strict protected
 
-    FHashSize, FBlockSize: Int32;
     function GetName: String; override;
 
   public
     constructor Create(); overload;
     constructor Create(const config: IBlake2SConfig); overload;
+    constructor Create(const config: IBlake2SConfig;
+      const treeConfig: IBlake2STreeConfig); overload;
     procedure Initialize; override;
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_data_length: Int32); override;
     function TransformFinal: IHashResult; override;
+    function Clone(): IHash; override;
 
   end;
 
@@ -132,6 +135,29 @@ end;
 
 {$ENDIF USE_UNROLLED_VARIANT}
 
+function TBlake2S.Clone(): IHash;
+var
+  HashInstance: TBlake2S;
+begin
+  HashInstance := TBlake2S.Create(TBlake2SConfig.Create(FHashSize)
+    as IBlake2SConfig);
+  System.Move(F_m, HashInstance.F_m, System.SizeOf(F_m));
+  HashInstance.FrawConfig := System.Copy(FrawConfig);
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.FKey := System.Copy(FKey);
+  HashInstance.F_buf := System.Copy(F_buf);
+{$IFNDEF USE_UNROLLED_VARIANT}
+  System.Move(F_v, HashInstance.F_v, System.SizeOf(F_v));
+{$ENDIF USE_UNROLLED_VARIANT}
+  HashInstance.F_bufferFilled := F_bufferFilled;
+  HashInstance.F_counter0 := F_counter0;
+  HashInstance.F_counter1 := F_counter1;
+  HashInstance.F_finalizationFlag0 := F_finalizationFlag0;
+  HashInstance.F_finalizationFlag1 := F_finalizationFlag1;
+  Result := HashInstance as IHash;
+  Result.BufferSize := BufferSize;
+end;
+
 procedure TBlake2S.Compress(block: PByte; start: Int32);
 var
 {$IFDEF USE_UNROLLED_VARIANT}
@@ -1378,6 +1404,12 @@ begin
 end;
 
 constructor TBlake2S.Create(const config: IBlake2SConfig);
+begin
+  Create(config, Nil);
+end;
+
+constructor TBlake2S.Create(const config: IBlake2SConfig;
+  const treeConfig: IBlake2STreeConfig);
 var
   Lconfig: IBlake2SConfig;
 begin
@@ -1390,7 +1422,7 @@ begin
     Lconfig := FDefaultConfig;
   end;
 
-  FrawConfig := TBlake2SIvBuilder.ConfigS(Lconfig, Nil);
+  FrawConfig := TBlake2SIvBuilder.ConfigS(Lconfig, treeConfig);
   if ((Lconfig.Key <> Nil) and (System.Length(Lconfig.Key) <> 0)) then
   begin
 
@@ -1427,7 +1459,7 @@ end;
 
 procedure TBlake2S.Initialize;
 var
-  i: Integer;
+  i: Int32;
 begin
   if (FrawConfig = Nil) then
     raise EArgumentNilHashLibException.Create('config');
@@ -1454,6 +1486,14 @@ begin
 
   System.SetLength(F_buf, BlockSizeInBytes);
 
+  System.FillChar(F_buf[0], (System.Length(F_buf) * System.SizeOf(Byte)
+    ), Byte(0));
+
+  System.FillChar(F_m, System.SizeOf(F_m), UInt32(0));
+
+{$IFNDEF USE_UNROLLED_VARIANT}
+  System.FillChar(F_v, System.SizeOf(F_v), UInt32(0));
+{$ENDIF USE_UNROLLED_VARIANT}
   for i := 0 to 7 do
   begin
     Fm_state[i] := Fm_state[i] xor FrawConfig[i];
@@ -1526,7 +1566,7 @@ begin
   TConverters.le32_copy(PCardinal(Fm_state), 0, PByte(tempRes), 0,
     System.Length(tempRes));
 
-  result := THashResult.Create(tempRes);
+  Result := THashResult.Create(tempRes);
 
   Initialize();
 
@@ -1534,7 +1574,7 @@ end;
 
 function TBlake2S.GetName: String;
 begin
-  result := Format('%s_%u', [Self.ClassName, Self.HashSize * 8]);
+  Result := Format('%s_%u', [Self.ClassName, Self.HashSize * 8]);
 end;
 
 end.

+ 84 - 6
src/libraries/hashlib4pascal/HlpBlake2SConfig.pas

@@ -11,7 +11,11 @@ uses
 
 resourcestring
   SInvalidHashSize =
-    'BLAKE2S HashSize must be restricted to one of the following [16, 20, 28, 32]';
+    'BLAKE2S HashSize must be restricted to one of the following [1 .. 32], "%d"';
+  SInvalidKeyLength = '"Key" Length Must Not Be Greater Than 32, "%d"';
+  SInvalidPersonalisationLength =
+    '"Personalisation" Length Must Be Equal To 8, "%d"';
+  SInvalidSaltLength = '"Salt" Length Must Be Equal To 8, "%d"';
 
 type
 
@@ -24,6 +28,12 @@ type
     FHashSize: Int32;
     FPersonalisation, FSalt, FKey: THashLibByteArray;
 
+    procedure ValidateHashSize(AHashSize: Int32); inline;
+    procedure ValidateKeyLength(const AKey: THashLibByteArray); inline;
+    procedure ValidatePersonalisationLength(const APersonalisation
+      : THashLibByteArray); inline;
+    procedure ValidateSaltLength(const ASalt: THashLibByteArray); inline;
+
     function GetPersonalisation: THashLibByteArray; inline;
     procedure SetPersonalisation(const value: THashLibByteArray); inline;
 
@@ -38,6 +48,8 @@ type
 
   public
     constructor Create(AHashSize: THashSize = THashSize.hsHashSize256);
+      overload;
+    constructor Create(AHashSize: Int32); overload;
     property Personalisation: THashLibByteArray read GetPersonalisation
       write SetPersonalisation;
     property Salt: THashLibByteArray read GetSalt write SetSalt;
@@ -50,6 +62,61 @@ implementation
 
 { TBlake2SConfig }
 
+procedure TBlake2SConfig.ValidateHashSize(AHashSize: Int32);
+begin
+  if not((AHashSize) in [1 .. 32]) or (((AHashSize * 8) and 7) <> 0) then
+  begin
+    raise EArgumentHashLibException.CreateResFmt(@SInvalidHashSize,
+      [AHashSize]);
+  end;
+end;
+
+procedure TBlake2SConfig.ValidateKeyLength(const AKey: THashLibByteArray);
+var
+  KeyLength: Int32;
+begin
+  if (AKey <> Nil) then
+  begin
+    KeyLength := System.Length(AKey);
+    if (KeyLength > 32) then
+    begin
+      raise EArgumentOutOfRangeHashLibException.CreateResFmt(@SInvalidKeyLength,
+        [KeyLength]);
+    end;
+  end;
+end;
+
+procedure TBlake2SConfig.ValidatePersonalisationLength(const APersonalisation
+  : THashLibByteArray);
+var
+  PersonalisationLength: Int32;
+begin
+  if (APersonalisation <> Nil) then
+  begin
+    PersonalisationLength := System.Length(APersonalisation);
+    if (PersonalisationLength <> 8) then
+    begin
+      raise EArgumentOutOfRangeHashLibException.CreateResFmt
+        (@SInvalidPersonalisationLength, [PersonalisationLength]);
+    end;
+  end;
+end;
+
+procedure TBlake2SConfig.ValidateSaltLength(const ASalt: THashLibByteArray);
+var
+  SaltLength: Int32;
+begin
+  if (ASalt <> Nil) then
+  begin
+    SaltLength := System.Length(ASalt);
+    if (SaltLength <> 8) then
+    begin
+      raise EArgumentOutOfRangeHashLibException.CreateResFmt
+        (@SInvalidSaltLength, [SaltLength]);
+    end;
+  end;
+end;
+
 function TBlake2SConfig.GetHashSize: Int32;
 begin
   result := FHashSize;
@@ -72,32 +139,43 @@ end;
 
 procedure TBlake2SConfig.SetHashSize(value: Int32);
 begin
+  ValidateHashSize(value);
   FHashSize := value;
 end;
 
 procedure TBlake2SConfig.SetKey(const value: THashLibByteArray);
 begin
+  ValidateKeyLength(value);
   FKey := value;
 end;
 
 procedure TBlake2SConfig.SetPersonalisation(const value: THashLibByteArray);
 begin
+  ValidatePersonalisationLength(value);
   FPersonalisation := value;
 end;
 
 procedure TBlake2SConfig.SetSalt(const value: THashLibByteArray);
 begin
+  ValidateSaltLength(value);
   FSalt := value;
 end;
 
 constructor TBlake2SConfig.Create(AHashSize: THashSize);
+var
+  LHashSize: Int32;
 begin
   Inherited Create();
-  if not(Int32(AHashSize) in [16, 20, 28, 32]) then
-  begin
-    raise EArgumentHashLibException.CreateRes(@SInvalidHashSize);
-  end;
-  HashSize := Int32(AHashSize);
+  LHashSize := Int32(AHashSize);
+  ValidateHashSize(LHashSize);
+  FHashSize := LHashSize;
+end;
+
+constructor TBlake2SConfig.Create(AHashSize: Int32);
+begin
+  Inherited Create();
+  ValidateHashSize(AHashSize);
+  FHashSize := AHashSize;
 end;
 
 end.

+ 1 - 1
src/libraries/hashlib4pascal/HlpBlake2STreeConfig.pas

@@ -95,7 +95,7 @@ end;
 constructor TBlake2STreeConfig.Create;
 begin
   Inherited Create();
-  IntermediateHashSize := 32;
+  FIntermediateHashSize := 32;
 end;
 
 end.

+ 31 - 5
src/libraries/hashlib4pascal/HlpCRC.pas

@@ -9,12 +9,15 @@ interface
 
 uses
 {$IFDEF HAS_UNITSCOPE}
+  System.SysUtils,
   System.TypInfo,
 {$ELSE}
+  SysUtils,
   TypInfo,
 {$ENDIF HAS_UNITSCOPE}
   HlpHashLibTypes,
   HlpHash,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashResult,
   HlpIHashResult,
@@ -550,7 +553,6 @@ type
     FReflectIn, FReflectOut, FIsTableGenerated: Boolean;
 
     Fm_CRCTable: THashLibUInt64Array;
-    Fptr_Fm_CRCTable: PUInt64;
 
   const
     Delta = Int32(7);
@@ -591,6 +593,9 @@ type
     property XOROut: UInt64 read GetXOROut write SetXOROut;
     property CheckValue: UInt64 read GetCheckValue write SetCheckValue;
 
+  strict protected
+    function GetName: String; override;
+
   public
 
     constructor Create(_Width: Int32; _poly, _Init: UInt64;
@@ -602,6 +607,8 @@ type
       a_index, a_length: Int32); override;
     function TransformFinal(): IHashResult; override;
 
+    function Clone(): IHash; override;
+
     class function CreateCRCObject(a_value: TCRCStandard): ICRC; static;
 
   end;
@@ -690,6 +697,11 @@ begin
   FXorOut := value;
 end;
 
+function TCRC.GetName: String;
+begin
+  result := Format('T%s', [(Self as ICRC).Names[0]]);
+end;
+
 procedure TCRC.CalculateCRCbyTable(a_data: PByte;
   a_data_length, a_index: Int32);
 var
@@ -705,7 +717,7 @@ begin
   begin
     while Length > 0 do
     begin
-      tmp := (tmp shr 8) xor Fptr_Fm_CRCTable[Byte(tmp xor a_data[i])];
+      tmp := (tmp shr 8) xor Fm_CRCTable[Byte(tmp xor a_data[i])];
       System.Inc(i);
       System.Dec(Length);
     end;
@@ -716,7 +728,7 @@ begin
 
     while Length > 0 do
     begin
-      tmp := (tmp shl 8) xor Fptr_Fm_CRCTable
+      tmp := (tmp shl 8) xor Fm_CRCTable
         [Byte((tmp shr (Width - 8)) xor a_data[i])];
       System.Inc(i);
       System.Dec(Length);
@@ -761,6 +773,21 @@ begin
 
 end;
 
+function TCRC.Clone(): IHash;
+var
+  HashInstance: TCRC;
+begin
+  HashInstance := TCRC.Create(Width, Polynomial, Init, ReflectIn, ReflectOut,
+    XOROut, CheckValue, System.Copy(Names));
+  HashInstance.Fm_CRCMask := Fm_CRCMask;
+  HashInstance.Fm_CRCHighBitMask := Fm_CRCHighBitMask;
+  HashInstance.Fm_hash := Fm_hash;
+  HashInstance.FIsTableGenerated := FIsTableGenerated;
+  HashInstance.Fm_CRCTable := System.Copy(Fm_CRCTable);
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TCRC.Create(_Width: Int32; _poly, _Init: UInt64;
   _refIn, _refOut: Boolean; _XorOut, _check: UInt64;
   const _Names: THashLibStringArray);
@@ -1244,7 +1271,6 @@ var
   i, j: Int32;
 begin
   System.SetLength(Fm_CRCTable, 256);
-  Fptr_Fm_CRCTable := PUInt64(Fm_CRCTable);
   i := 0;
   while i < 256 do
   begin
@@ -1270,7 +1296,7 @@ begin
       crc := Reflect(crc, Width);
     end;
     crc := crc and Fm_CRCMask;
-    Fptr_Fm_CRCTable[i] := crc;
+    Fm_CRCTable[i] := crc;
     System.Inc(i);
   end;
 

+ 19 - 2
src/libraries/hashlib4pascal/HlpDEK.pas

@@ -6,7 +6,11 @@ interface
 
 uses
   HlpHashLibTypes,
+{$IFDEF DELPHI}
+  HlpHash,
+{$ENDIF DELPHI}
   HlpBits,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashResult,
   HlpIHashResult,
@@ -17,10 +21,11 @@ type
   TDEK = class sealed(TMultipleTransformNonBlock, IHash32, ITransformBlock)
 
   strict protected
-    function ComputeAggregatedBytes(a_data: THashLibByteArray)
+    function ComputeAggregatedBytes(const a_data: THashLibByteArray)
       : IHashResult; override;
   public
     constructor Create();
+    function Clone(): IHash; override;
 
   end;
 
@@ -33,7 +38,19 @@ begin
   Inherited Create(4, 1);
 end;
 
-function TDEK.ComputeAggregatedBytes(a_data: THashLibByteArray): IHashResult;
+function TDEK.Clone(): IHash;
+var
+  HashInstance: TDEK;
+begin
+  HashInstance := TDEK.Create();
+  FBuffer.Position := 0;
+  HashInstance.FBuffer.CopyFrom(FBuffer, FBuffer.Size);
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
+function TDEK.ComputeAggregatedBytes(const a_data: THashLibByteArray)
+  : IHashResult;
 var
   hash: UInt32;
   i: Int32;

+ 12 - 0
src/libraries/hashlib4pascal/HlpDJB.pas

@@ -7,6 +7,7 @@ interface
 uses
   HlpHashLibTypes,
   HlpHash,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashResult,
   HlpIHashResult;
@@ -23,12 +24,23 @@ type
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_length: Int32); override;
     function TransformFinal(): IHashResult; override;
+    function Clone(): IHash; override;
   end;
 
 implementation
 
 { TDJB }
 
+function TDJB.Clone(): IHash;
+var
+  HashInstance: TDJB;
+begin
+  HashInstance := TDJB.Create();
+  HashInstance.Fm_hash := Fm_hash;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TDJB.Create;
 begin
   Inherited Create(4, 1);

+ 12 - 0
src/libraries/hashlib4pascal/HlpELF.pas

@@ -7,6 +7,7 @@ interface
 uses
   HlpHashLibTypes,
   HlpHash,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashResult,
   HlpIHashResult;
@@ -23,12 +24,23 @@ type
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_length: Int32); override;
     function TransformFinal(): IHashResult; override;
+    function Clone(): IHash; override;
   end;
 
 implementation
 
 { TELF }
 
+function TELF.Clone(): IHash;
+var
+  HashInstance: TELF;
+begin
+  HashInstance := TELF.Create();
+  HashInstance.Fm_hash := Fm_hash;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TELF.Create;
 begin
   Inherited Create(4, 1);

+ 12 - 0
src/libraries/hashlib4pascal/HlpFNV.pas

@@ -7,6 +7,7 @@ interface
 uses
   HlpHashLibTypes,
   HlpHash,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashResult,
   HlpIHashResult;
@@ -23,12 +24,23 @@ type
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_length: Int32); override;
     function TransformFinal(): IHashResult; override;
+    function Clone(): IHash; override;
   end;
 
 implementation
 
 { TFNV }
 
+function TFNV.Clone(): IHash;
+var
+  HashInstance: TFNV;
+begin
+  HashInstance := TFNV.Create();
+  HashInstance.Fm_hash := Fm_hash;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TFNV.Create;
 begin
   Inherited Create(4, 1);

+ 12 - 0
src/libraries/hashlib4pascal/HlpFNV1a.pas

@@ -7,6 +7,7 @@ interface
 uses
   HlpHashLibTypes,
   HlpHash,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashResult,
   HlpIHashResult;
@@ -23,12 +24,23 @@ type
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_length: Int32); override;
     function TransformFinal(): IHashResult; override;
+    function Clone(): IHash; override;
   end;
 
 implementation
 
 { TFNV1a }
 
+function TFNV1a.Clone(): IHash;
+var
+  HashInstance: TFNV1a;
+begin
+  HashInstance := TFNV1a.Create();
+  HashInstance.Fm_hash := Fm_hash;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TFNV1a.Create;
 begin
   Inherited Create(4, 1);

+ 12 - 0
src/libraries/hashlib4pascal/HlpFNV1a64.pas

@@ -7,6 +7,7 @@ interface
 uses
   HlpHashLibTypes,
   HlpHash,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashResult,
   HlpIHashResult;
@@ -23,12 +24,23 @@ type
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_length: Int32); override;
     function TransformFinal(): IHashResult; override;
+    function Clone(): IHash; override;
   end;
 
 implementation
 
 { TFNV1a64 }
 
+function TFNV1a64.Clone(): IHash;
+var
+  HashInstance: TFNV1a64;
+begin
+  HashInstance := TFNV1a64.Create();
+  HashInstance.Fm_hash := Fm_hash;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TFNV1a64.Create;
 begin
   Inherited Create(8, 1);

+ 12 - 0
src/libraries/hashlib4pascal/HlpFNV64.pas

@@ -7,6 +7,7 @@ interface
 uses
   HlpHashLibTypes,
   HlpHash,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashResult,
   HlpIHashResult;
@@ -23,12 +24,23 @@ type
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_length: Int32); override;
     function TransformFinal(): IHashResult; override;
+    function Clone(): IHash; override;
   end;
 
 implementation
 
 { TFNV64 }
 
+function TFNV64.Clone(): IHash;
+var
+  HashInstance: TFNV64;
+begin
+  HashInstance := TFNV64.Create();
+  HashInstance.Fm_hash := Fm_hash;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TFNV64.Create;
 begin
   Inherited Create(8, 1);

+ 47 - 7
src/libraries/hashlib4pascal/HlpGOST3411_2012.pas

@@ -6,6 +6,7 @@ interface
 
 uses
   HlpHash,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashResult,
   HlpIHashResult,
@@ -20,11 +21,6 @@ type
     FC: THashLibMatrixByteArray;
     FT: THashLibMatrixUInt64Array;
 
-  var
-    FIV, FN, FSigma, FKi, Fm, Fh, Ftmp, Fblock: THashLibByteArray;
-
-    FbOff: Int32;
-
     procedure InternalUpdate(input: Byte); inline;
     procedure xor512(const A, B: THashLibByteArray); inline;
     procedure E(const K, a_m: THashLibByteArray);
@@ -37,6 +33,12 @@ type
     class constructor GOST3411_2012();
 
   strict protected
+
+  var
+    FIV, FN, FSigma, FKi, Fm, Fh, Ftmp, Fblock: THashLibByteArray;
+
+    FbOff: Int32;
+
     constructor Create(a_hash_size: Int32; const IV: THashLibByteArray);
 
   public
@@ -59,6 +61,7 @@ type
   public
     constructor Create();
     function TransformFinal: IHashResult; override;
+    function Clone(): IHash; override;
   end;
 
 type
@@ -72,6 +75,7 @@ type
     class constructor TGOST3411_2012_512();
   public
     constructor Create();
+    function Clone(): IHash; override;
   end;
 
 implementation
@@ -80,7 +84,7 @@ implementation
 
 procedure TGOST3411_2012.xor512(const A, B: THashLibByteArray);
 var
-  i: Integer;
+  i: Int32;
 begin
   for i := 0 to System.Pred(64) do
   begin
@@ -338,7 +342,7 @@ begin
   V[57] := Byte(r shr 8);
   V[56] := Byte(r);
 
-  System.FillChar(res, System.SizeOf(res), 0);
+  System.FillChar(res, System.SizeOf(res), UInt64(0));
 end;
 
 class constructor TGOST3411_2012.GOST3411_2012;
@@ -1627,6 +1631,24 @@ end;
 
 { TGOST3411_2012_256 }
 
+function TGOST3411_2012_256.Clone(): IHash;
+var
+  HashInstance: TGOST3411_2012_256;
+begin
+  HashInstance := TGOST3411_2012_256.Create();
+  HashInstance.FIV := System.Copy(FIV);
+  HashInstance.FN := System.Copy(FN);
+  HashInstance.FSigma := System.Copy(FSigma);
+  HashInstance.FKi := System.Copy(FKi);
+  HashInstance.Fm := System.Copy(Fm);
+  HashInstance.Fh := System.Copy(Fh);
+  HashInstance.Ftmp := System.Copy(Ftmp);
+  HashInstance.Fblock := System.Copy(Fblock);
+  HashInstance.FbOff := FbOff;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TGOST3411_2012_256.Create();
 begin
   inherited Create(32, FIV_256);
@@ -1653,6 +1675,24 @@ end;
 
 { TGOST3411_2012_512 }
 
+function TGOST3411_2012_512.Clone(): IHash;
+var
+  HashInstance: TGOST3411_2012_512;
+begin
+  HashInstance := TGOST3411_2012_512.Create();
+  HashInstance.FIV := System.Copy(FIV);
+  HashInstance.FN := System.Copy(FN);
+  HashInstance.FSigma := System.Copy(FSigma);
+  HashInstance.FKi := System.Copy(FKi);
+  HashInstance.Fm := System.Copy(Fm);
+  HashInstance.Fh := System.Copy(Fh);
+  HashInstance.Ftmp := System.Copy(Ftmp);
+  HashInstance.Fblock := System.Copy(Fblock);
+  HashInstance.FbOff := FbOff;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TGOST3411_2012_512.Create();
 begin
   inherited Create(64, FIV_512);

+ 18 - 2
src/libraries/hashlib4pascal/HlpGost.pas

@@ -7,11 +7,13 @@ interface
 uses
   HlpHashLibTypes,
 {$IFDEF DELPHI}
+  HlpHash,
   HlpHashBuffer,
   HlpBitConverter,
 {$ENDIF DELPHI}
   HlpBits,
   HlpConverters,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashCryptoNotBuildIn;
 
@@ -39,6 +41,7 @@ type
   public
     constructor Create();
     procedure Initialize(); override;
+    function Clone(): IHash; override;
 
   end;
 
@@ -46,6 +49,19 @@ implementation
 
 { TGost }
 
+function TGost.Clone(): IHash;
+var
+  HashInstance: TGost;
+begin
+  HashInstance := TGost.Create();
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 procedure TGost.Compress(a_m: PCardinal);
 var
   u0, u1, u2, u3, u4, u5, u6, u7, v0, v1, v2, v3, v4, v5, v6, v7, w0, w1, w2,
@@ -452,8 +468,8 @@ begin
 
   Compress(@(m[0]));
 
-  System.FillChar(m, System.SizeOf(m), 0);
-  System.FillChar(data, System.SizeOf(data), 0);
+  System.FillChar(m, System.SizeOf(m), UInt32(0));
+  System.FillChar(data, System.SizeOf(data), UInt32(0));
 
 end;
 

+ 17 - 0
src/libraries/hashlib4pascal/HlpGrindahl256.pas

@@ -10,9 +10,12 @@ uses
 {$ENDIF DELPHI2010}
   HlpHashLibTypes,
 {$IFDEF DELPHI}
+  HlpHash,
+  HlpHashBuffer,
   HlpBitConverter,
 {$ENDIF DELPHI}
   HlpConverters,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashCryptoNotBuildIn;
 
@@ -92,6 +95,7 @@ type
   public
     constructor Create();
     procedure Initialize(); override;
+    function Clone(): IHash; override;
 
   end;
 
@@ -113,6 +117,19 @@ begin
   end;
 end;
 
+function TGrindahl256.Clone(): IHash;
+var
+  HashInstance: TGrindahl256;
+begin
+  HashInstance := TGrindahl256.Create();
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.Fm_temp := System.Copy(Fm_temp);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TGrindahl256.Create;
 begin
   Inherited Create(32, 4);

+ 17 - 0
src/libraries/hashlib4pascal/HlpGrindahl512.pas

@@ -10,10 +10,13 @@ uses
 {$ENDIF DELPHI2010}
   HlpHashLibTypes,
 {$IFDEF DELPHI}
+  HlpHash,
+  HlpHashBuffer,
   HlpBitConverter,
 {$ENDIF DELPHI}
   HlpBits,
   HlpConverters,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashCryptoNotBuildIn;
 
@@ -179,6 +182,7 @@ type
   public
     constructor Create();
     procedure Initialize(); override;
+    function Clone(): IHash; override;
 
   end;
 
@@ -199,6 +203,19 @@ begin
   end;
 end;
 
+function TGrindahl512.Clone(): IHash;
+var
+  HashInstance: TGrindahl512;
+begin
+  HashInstance := TGrindahl512.Create();
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.Fm_temp := System.Copy(Fm_temp);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TGrindahl512.Create;
 begin
   Inherited Create(64, 8);

+ 16 - 1
src/libraries/hashlib4pascal/HlpHAS160.pas

@@ -10,10 +10,12 @@ uses
 {$ENDIF DELPHI2010}
   HlpHashLibTypes,
 {$IFDEF DELPHI}
+  HlpHash,
   HlpHashBuffer,
   HlpBitConverter,
 {$ENDIF DELPHI}
   HlpConverters,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashCryptoNotBuildIn;
 
@@ -50,12 +52,25 @@ type
   public
     constructor Create();
     procedure Initialize(); override;
+    function Clone(): IHash; override;
   end;
 
 implementation
 
 { THAS160 }
 
+function THAS160.Clone(): IHash;
+var
+  HashInstance: THAS160;
+begin
+  HashInstance := THAS160.Create();
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor THAS160.Create;
 begin
   Inherited Create(20, 64);
@@ -202,7 +217,7 @@ begin
   Fm_hash[3] := Fm_hash[3] + D;
   Fm_hash[4] := Fm_hash[4] + E;
 
-  System.FillChar(data, System.SizeOf(data), 0);
+  System.FillChar(data, System.SizeOf(data), UInt32(0));
 
 end;
 

+ 17 - 4
src/libraries/hashlib4pascal/HlpHMACNotBuildInAdapter.pas

@@ -44,6 +44,7 @@ type
     function TransformFinal(): IHashResult; override;
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_length: Int32); override;
+    function Clone(): IHash; override;
     property Key: THashLibByteArray read GetKey write SetKey;
     property Name: String read GetName;
     property KeyLength: TNullableInteger read GetKeyLength;
@@ -54,6 +55,19 @@ implementation
 
 { THMACNotBuildInAdapter }
 
+function THMACNotBuildInAdapter.Clone(): IHash;
+var
+  HmacInstance: THMACNotBuildInAdapter;
+begin
+  HmacInstance := THMACNotBuildInAdapter.Create(Fm_hash.Clone());
+  HmacInstance.Fm_opad := System.Copy(Fm_opad);
+  HmacInstance.Fm_ipad := System.Copy(Fm_ipad);
+  HmacInstance.Fm_key := System.Copy(Fm_key);
+  HmacInstance.Fm_blocksize := Fm_blocksize;
+  result := HmacInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor THMACNotBuildInAdapter.Create(const a_underlyingHash: IHash);
 begin
   Inherited Create(a_underlyingHash.HashSize, a_underlyingHash.BlockSize);
@@ -102,8 +116,8 @@ begin
     LKey := Key;
   end;
 
-  System.FillChar(Fm_ipad[0], LBlockSize * System.SizeOf(Byte), $36);
-  System.FillChar(Fm_opad[0], LBlockSize * System.SizeOf(Byte), $5C);
+  System.FillChar(Fm_ipad[0], LBlockSize * System.SizeOf(Byte), Byte($36));
+  System.FillChar(Fm_opad[0], LBlockSize * System.SizeOf(Byte), Byte($5C));
 
   Idx := 0;
   while (Idx < System.Length(LKey)) and (Idx < LBlockSize) do
@@ -145,8 +159,7 @@ end;
 
 function THMACNotBuildInAdapter.GetName: String;
 begin
-  result := Format('%s(%s)', [Self.ClassName, (Self.Fm_hash as THash)
-    .ClassName]);
+  result := Format('%s(%s)', ['THMAC', Fm_hash.Name]);
 
 end;
 

+ 8 - 3
src/libraries/hashlib4pascal/HlpHash.pas

@@ -24,7 +24,7 @@ resourcestring
   // SInvalidHashSize = '"HashSize" Must Be Greater Than Zero';
   SUnAssignedStream = 'Input Stream Is Unassigned';
   SFileNotExist = 'Specified File Not Found';
-  SNotYetImplemented = 'Not Yet Implemented For "%s"';
+  SCloneNotYetImplemented = 'Clone Not Yet Implemented For "%s"';
 
 type
   THash = class abstract(TInterfacedObject, IHash)
@@ -236,7 +236,7 @@ end;
 function THash.Clone(): IHash;
 begin
   raise ENotImplementedHashLibException.CreateResFmt
-    (@SNotYetImplemented, [Name]);
+    (@SCloneNotYetImplemented, [Name]);
 end;
 
 function THash.ComputeBytes(const a_data: THashLibByteArray): IHashResult;
@@ -287,13 +287,16 @@ begin
   begin
     if (a_length > -1) then
     begin
-
       if ((a_stream.Position + a_length) > a_stream.Size) then
+      begin
         raise EIndexOutOfRangeHashLibException.CreateRes(@SIndexOutOfRange);
+      end;
     end;
 
     if (a_stream.Position >= a_stream.Size) then
+    begin
       Exit;
+    end;
   end
   else
   begin
@@ -365,7 +368,9 @@ begin
   System.Assert((a_length = -1) or (a_length > 0));
 {$ENDIF DEBUG}
   if not FileExists(a_file_name) then
+  begin
     raise EArgumentHashLibException.CreateRes(@SFileNotExist);
+  end;
 
   MyFileStream := TFileStream.Create(a_file_name, fmOpenRead or
     fmShareDenyWrite);

+ 10 - 2
src/libraries/hashlib4pascal/HlpHashBuffer.pas

@@ -36,6 +36,7 @@ type
     function Feed(a_data: PByte; a_length_a_data: Int32; a_length: Int32)
       : Boolean; overload;
     function ToString(): String;
+    function Clone(): THashBuffer; inline;
 
     property IsEmpty: Boolean read GetIsEmpty;
     property IsFull: Boolean read GetIsFull;
@@ -47,6 +48,13 @@ implementation
 
 { THashBuffer }
 
+function THashBuffer.Clone(): THashBuffer;
+begin
+  result := Default(THashBuffer);
+  result.Fm_data := System.Copy(Fm_data);
+  result.Fm_pos := Fm_pos;
+end;
+
 constructor THashBuffer.Create(a_length: Int32);
 begin
 {$IFDEF DEBUG}
@@ -148,7 +156,7 @@ end;
 function THashBuffer.GetBytesZeroPadded: THashLibByteArray;
 begin
   System.FillChar(Fm_data[Fm_pos], (System.Length(Fm_data) - Fm_pos) *
-    System.SizeOf(Byte), 0);
+    System.SizeOf(Byte), Byte(0));
   Fm_pos := 0;
   result := Fm_data;
 end;
@@ -171,7 +179,7 @@ end;
 procedure THashBuffer.Initialize;
 begin
   Fm_pos := 0;
-  System.FillChar(Fm_data[0], System.Length(Fm_data) * System.SizeOf(Byte), 0);
+  System.FillChar(Fm_data[0], System.Length(Fm_data) * System.SizeOf(Byte), Byte(0));
 end;
 
 function THashBuffer.ToString: String;

+ 230 - 3
src/libraries/hashlib4pascal/HlpHaval.pas

@@ -10,6 +10,7 @@ uses
 {$ENDIF DELPHI2010}
   HlpHashLibTypes,
 {$IFDEF DELPHI}
+  HlpHash,
   HlpHashBuffer,
   HlpBitConverter,
 {$ENDIF DELPHI}
@@ -17,6 +18,7 @@ uses
   HlpHashSize,
   HlpHashRounds,
   HlpConverters,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashCryptoNotBuildIn;
 
@@ -93,6 +95,7 @@ type
 
   public
     constructor Create();
+    function Clone(): IHash; override;
 
   end;
 
@@ -102,6 +105,7 @@ type
 
   public
     constructor Create();
+    function Clone(): IHash; override;
 
   end;
 
@@ -111,6 +115,7 @@ type
 
   public
     constructor Create();
+    function Clone(): IHash; override;
 
   end;
 
@@ -120,6 +125,7 @@ type
 
   public
     constructor Create();
+    function Clone(): IHash; override;
 
   end;
 
@@ -129,6 +135,7 @@ type
 
   public
     constructor Create();
+    function Clone(): IHash; override;
 
   end;
 
@@ -138,6 +145,7 @@ type
 
   public
     constructor Create();
+    function Clone(): IHash; override;
 
   end;
 
@@ -147,6 +155,7 @@ type
 
   public
     constructor Create();
+    function Clone(): IHash; override;
 
   end;
 
@@ -156,6 +165,7 @@ type
 
   public
     constructor Create();
+    function Clone(): IHash; override;
 
   end;
 
@@ -165,6 +175,7 @@ type
 
   public
     constructor Create();
+    function Clone(): IHash; override;
 
   end;
 
@@ -174,6 +185,7 @@ type
 
   public
     constructor Create();
+    function Clone(): IHash; override;
 
   end;
 
@@ -183,6 +195,7 @@ type
 
   public
     constructor Create();
+    function Clone(): IHash; override;
 
   end;
 
@@ -192,6 +205,7 @@ type
 
   public
     constructor Create();
+    function Clone(): IHash; override;
 
   end;
 
@@ -201,6 +215,7 @@ type
 
   public
     constructor Create();
+    function Clone(): IHash; override;
 
   end;
 
@@ -210,6 +225,7 @@ type
 
   public
     constructor Create();
+    function Clone(): IHash; override;
 
   end;
 
@@ -219,6 +235,7 @@ type
 
   public
     constructor Create();
+    function Clone(): IHash; override;
 
   end;
 
@@ -784,7 +801,7 @@ begin
   Fm_hash[6] := Fm_hash[6] + g;
   Fm_hash[7] := Fm_hash[7] + h;
 
-  System.FillChar(temp, System.SizeOf(temp), 0);
+  System.FillChar(temp, System.SizeOf(temp), UInt32(0));
 end;
 
 { THaval4 }
@@ -1365,7 +1382,7 @@ begin
   Fm_hash[6] := Fm_hash[6] + g;
   Fm_hash[7] := Fm_hash[7] + h;
 
-  System.FillChar(temp, System.SizeOf(temp), 0);
+  System.FillChar(temp, System.SizeOf(temp), UInt32(0));
 
 end;
 
@@ -2074,12 +2091,26 @@ begin
   Fm_hash[6] := Fm_hash[6] + g;
   Fm_hash[7] := Fm_hash[7] + h;
 
-  System.FillChar(temp, System.SizeOf(temp), 0);
+  System.FillChar(temp, System.SizeOf(temp), UInt32(0));
 
 end;
 
 { THaval_3_128 }
 
+function THaval_3_128.Clone(): IHash;
+var
+  HashInstance: THaval_3_128;
+begin
+  HashInstance := THaval_3_128.Create();
+  HashInstance.Fm_rounds := Fm_rounds;
+  HashInstance.FHashSize := FHashSize;
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor THaval_3_128.Create;
 begin
   inherited Create(THashSize.hsHashSize128);
@@ -2087,6 +2118,20 @@ end;
 
 { THaval_4_128 }
 
+function THaval_4_128.Clone(): IHash;
+var
+  HashInstance: THaval_4_128;
+begin
+  HashInstance := THaval_4_128.Create();
+  HashInstance.Fm_rounds := Fm_rounds;
+  HashInstance.FHashSize := FHashSize;
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor THaval_4_128.Create;
 begin
   inherited Create(THashSize.hsHashSize128);
@@ -2094,6 +2139,20 @@ end;
 
 { THaval_5_128 }
 
+function THaval_5_128.Clone(): IHash;
+var
+  HashInstance: THaval_5_128;
+begin
+  HashInstance := THaval_5_128.Create();
+  HashInstance.Fm_rounds := Fm_rounds;
+  HashInstance.FHashSize := FHashSize;
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor THaval_5_128.Create;
 begin
   inherited Create(THashSize.hsHashSize128);
@@ -2101,6 +2160,20 @@ end;
 
 { THaval_3_160 }
 
+function THaval_3_160.Clone(): IHash;
+var
+  HashInstance: THaval_3_160;
+begin
+  HashInstance := THaval_3_160.Create();
+  HashInstance.Fm_rounds := Fm_rounds;
+  HashInstance.FHashSize := FHashSize;
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor THaval_3_160.Create;
 begin
   inherited Create(THashSize.hsHashSize160);
@@ -2108,6 +2181,20 @@ end;
 
 { THaval_4_160 }
 
+function THaval_4_160.Clone(): IHash;
+var
+  HashInstance: THaval_4_160;
+begin
+  HashInstance := THaval_4_160.Create();
+  HashInstance.Fm_rounds := Fm_rounds;
+  HashInstance.FHashSize := FHashSize;
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor THaval_4_160.Create;
 begin
   inherited Create(THashSize.hsHashSize160);
@@ -2115,6 +2202,20 @@ end;
 
 { THaval_5_160 }
 
+function THaval_5_160.Clone(): IHash;
+var
+  HashInstance: THaval_5_160;
+begin
+  HashInstance := THaval_5_160.Create();
+  HashInstance.Fm_rounds := Fm_rounds;
+  HashInstance.FHashSize := FHashSize;
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor THaval_5_160.Create;
 begin
   inherited Create(THashSize.hsHashSize160);
@@ -2122,6 +2223,20 @@ end;
 
 { THaval_3_192 }
 
+function THaval_3_192.Clone(): IHash;
+var
+  HashInstance: THaval_3_192;
+begin
+  HashInstance := THaval_3_192.Create();
+  HashInstance.Fm_rounds := Fm_rounds;
+  HashInstance.FHashSize := FHashSize;
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor THaval_3_192.Create;
 begin
   inherited Create(THashSize.hsHashSize192);
@@ -2129,6 +2244,20 @@ end;
 
 { THaval_4_192 }
 
+function THaval_4_192.Clone(): IHash;
+var
+  HashInstance: THaval_4_192;
+begin
+  HashInstance := THaval_4_192.Create();
+  HashInstance.Fm_rounds := Fm_rounds;
+  HashInstance.FHashSize := FHashSize;
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor THaval_4_192.Create;
 begin
   inherited Create(THashSize.hsHashSize192);
@@ -2136,6 +2265,20 @@ end;
 
 { THaval_5_192 }
 
+function THaval_5_192.Clone(): IHash;
+var
+  HashInstance: THaval_5_192;
+begin
+  HashInstance := THaval_5_192.Create();
+  HashInstance.Fm_rounds := Fm_rounds;
+  HashInstance.FHashSize := FHashSize;
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor THaval_5_192.Create;
 begin
   inherited Create(THashSize.hsHashSize192);
@@ -2143,6 +2286,20 @@ end;
 
 { THaval_3_224 }
 
+function THaval_3_224.Clone(): IHash;
+var
+  HashInstance: THaval_3_224;
+begin
+  HashInstance := THaval_3_224.Create();
+  HashInstance.Fm_rounds := Fm_rounds;
+  HashInstance.FHashSize := FHashSize;
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor THaval_3_224.Create;
 begin
   inherited Create(THashSize.hsHashSize224);
@@ -2150,6 +2307,20 @@ end;
 
 { THaval_4_224 }
 
+function THaval_4_224.Clone(): IHash;
+var
+  HashInstance: THaval_4_224;
+begin
+  HashInstance := THaval_4_224.Create();
+  HashInstance.Fm_rounds := Fm_rounds;
+  HashInstance.FHashSize := FHashSize;
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor THaval_4_224.Create;
 begin
   inherited Create(THashSize.hsHashSize224);
@@ -2157,6 +2328,20 @@ end;
 
 { THaval_5_224 }
 
+function THaval_5_224.Clone(): IHash;
+var
+  HashInstance: THaval_5_224;
+begin
+  HashInstance := THaval_5_224.Create();
+  HashInstance.Fm_rounds := Fm_rounds;
+  HashInstance.FHashSize := FHashSize;
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor THaval_5_224.Create;
 begin
   inherited Create(THashSize.hsHashSize224);
@@ -2164,6 +2349,20 @@ end;
 
 { THaval_3_256 }
 
+function THaval_3_256.Clone(): IHash;
+var
+  HashInstance: THaval_3_256;
+begin
+  HashInstance := THaval_3_256.Create();
+  HashInstance.Fm_rounds := Fm_rounds;
+  HashInstance.FHashSize := FHashSize;
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor THaval_3_256.Create;
 begin
   inherited Create(THashSize.hsHashSize256);
@@ -2171,6 +2370,20 @@ end;
 
 { THaval_4_256 }
 
+function THaval_4_256.Clone(): IHash;
+var
+  HashInstance: THaval_4_256;
+begin
+  HashInstance := THaval_4_256.Create();
+  HashInstance.Fm_rounds := Fm_rounds;
+  HashInstance.FHashSize := FHashSize;
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor THaval_4_256.Create;
 begin
   inherited Create(THashSize.hsHashSize256);
@@ -2178,6 +2391,20 @@ end;
 
 { THaval_5_256 }
 
+function THaval_5_256.Clone(): IHash;
+var
+  HashInstance: THaval_5_256;
+begin
+  HashInstance := THaval_5_256.Create();
+  HashInstance.Fm_rounds := Fm_rounds;
+  HashInstance.FHashSize := FHashSize;
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor THaval_5_256.Create;
 begin
   inherited Create(THashSize.hsHashSize256);

+ 12 - 0
src/libraries/hashlib4pascal/HlpJS.pas

@@ -7,6 +7,7 @@ interface
 uses
   HlpHashLibTypes,
   HlpHash,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashResult,
   HlpIHashResult;
@@ -23,12 +24,23 @@ type
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_length: Int32); override;
     function TransformFinal(): IHashResult; override;
+    function Clone(): IHash; override;
   end;
 
 implementation
 
 { TJS }
 
+function TJS.Clone(): IHash;
+var
+  HashInstance: TJS;
+begin
+  HashInstance := TJS.Create();
+  HashInstance.Fm_hash := Fm_hash;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TJS.Create;
 begin
   Inherited Create(4, 1);

+ 18 - 2
src/libraries/hashlib4pascal/HlpJenkins3.pas

@@ -6,7 +6,11 @@ interface
 
 uses
   HlpHashLibTypes,
+{$IFDEF DELPHI}
+  HlpHash,
+{$ENDIF DELPHI}
   HlpBits,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashResult,
   HlpIHashResult,
@@ -17,10 +21,11 @@ type
   TJenkins3 = class sealed(TMultipleTransformNonBlock, IHash32, ITransformBlock)
 
   strict protected
-    function ComputeAggregatedBytes(a_data: THashLibByteArray)
+    function ComputeAggregatedBytes(const a_data: THashLibByteArray)
       : IHashResult; override;
   public
     constructor Create();
+    function Clone(): IHash; override;
 
   end;
 
@@ -33,7 +38,18 @@ begin
   Inherited Create(4, 12);
 end;
 
-function TJenkins3.ComputeAggregatedBytes(a_data: THashLibByteArray)
+function TJenkins3.Clone(): IHash;
+var
+  HashInstance: TJenkins3;
+begin
+  HashInstance := TJenkins3.Create();
+  FBuffer.Position := 0;
+  HashInstance.FBuffer.CopyFrom(FBuffer, FBuffer.Size);
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
+function TJenkins3.ComputeAggregatedBytes(const a_data: THashLibByteArray)
   : IHashResult;
 var
   &length, currentIndex, i1, i2, i3, i4: Int32;

+ 17 - 1
src/libraries/hashlib4pascal/HlpMD2.pas

@@ -8,7 +8,9 @@ uses
   HlpHashLibTypes,
 {$IFDEF DELPHI}
   HlpHashBuffer,
+  HlpHash,
 {$ENDIF DELPHI}
+  HlpIHash,
   HlpIHashInfo,
   HlpHashCryptoNotBuildIn;
 
@@ -68,6 +70,7 @@ type
   public
     constructor Create();
     procedure Initialize(); override;
+    function Clone(): IHash; override;
 
   end;
 
@@ -75,6 +78,19 @@ implementation
 
 { TMD2 }
 
+function TMD2.Clone(): IHash;
+var
+  HashInstance: TMD2;
+begin
+  HashInstance := TMD2.Create();
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.Fm_checksum := System.Copy(Fm_checksum);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TMD2.Create;
 begin
   Inherited Create(16, 16);
@@ -163,7 +179,7 @@ begin
     t := Fm_checksum[i];
   end;
 
-  System.FillChar(temp, System.SizeOf(temp), 0);
+  System.FillChar(temp, System.SizeOf(temp), Byte(0));
 
 end;
 

+ 17 - 1
src/libraries/hashlib4pascal/HlpMD4.pas

@@ -11,9 +11,12 @@ uses
   HlpMDBase,
 {$IFDEF DELPHI}
   HlpBitConverter,
+  HlpHashBuffer,
+  HlpHash,
 {$ENDIF DELPHI}
   HlpBits,
   HlpConverters,
+  HlpIHash,
   HlpIHashInfo;
 
 type
@@ -25,6 +28,7 @@ type
 
   public
     constructor Create();
+    function Clone(): IHash; override;
 
   end;
 
@@ -32,6 +36,18 @@ implementation
 
 { TMD4 }
 
+function TMD4.Clone(): IHash;
+var
+  HashInstance: TMD4;
+begin
+  HashInstance := TMD4.Create();
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TMD4.Create;
 begin
   Inherited Create(4, 16);
@@ -155,7 +171,7 @@ begin
   Fm_state[2] := Fm_state[2] + c;
   Fm_state[3] := Fm_state[3] + d;
 
-  System.FillChar(data, System.SizeOf(data), 0);
+  System.FillChar(data, System.SizeOf(data), UInt32(0));
 end;
 
 end.

+ 17 - 1
src/libraries/hashlib4pascal/HlpMD5.pas

@@ -12,7 +12,10 @@ uses
   HlpMDBase,
 {$IFDEF DELPHI}
   HlpBitConverter,
+  HlpHashBuffer,
+  HlpHash,
 {$ENDIF DELPHI}
+  HlpIHash,
   HlpConverters,
   HlpIHashInfo;
 
@@ -25,6 +28,7 @@ type
 
   public
     constructor Create();
+    function Clone(): IHash; override;
 
   end;
 
@@ -32,6 +36,18 @@ implementation
 
 { TMD5 }
 
+function TMD5.Clone(): IHash;
+var
+  HashInstance: TMD5;
+begin
+  HashInstance := TMD5.Create();
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TMD5.Create;
 begin
   Inherited Create(4, 16);
@@ -188,7 +204,7 @@ begin
   Fm_state[2] := Fm_state[2] + C;
   Fm_state[3] := Fm_state[3] + D;
 
-  System.FillChar(data, System.SizeOf(data), 0);
+  System.FillChar(data, System.SizeOf(data), UInt32(0));
 
 end;
 

+ 3 - 2
src/libraries/hashlib4pascal/HlpMultipleTransformNonBlock.pas

@@ -20,12 +20,13 @@ type
   TMultipleTransformNonBlock = class abstract(THash, INonBlockHash)
 
   strict private
-    FBuffer: TMemoryStream;
 
     function Aggregate(): THashLibByteArray;
 
   strict protected
-    function ComputeAggregatedBytes(a_data: THashLibByteArray): IHashResult;
+    FBuffer: TMemoryStream;
+
+    function ComputeAggregatedBytes(const a_data: THashLibByteArray): IHashResult;
       virtual; abstract;
 
   public

+ 19 - 3
src/libraries/hashlib4pascal/HlpMurmur2.pas

@@ -10,8 +10,9 @@ uses
 {$ENDIF DELPHI2010}
   HlpHashLibTypes,
 {$IFDEF DELPHI}
-  HlpBitConverter,
+  HlpHash,
 {$ENDIF DELPHI}
+  HlpIHash,
   HlpConverters,
   HlpIHashInfo,
   HlpHashResult,
@@ -43,12 +44,13 @@ type
     procedure SetKey(const value: THashLibByteArray); inline;
 
   strict protected
-    function ComputeAggregatedBytes(a_data: THashLibByteArray)
+    function ComputeAggregatedBytes(const a_data: THashLibByteArray)
       : IHashResult; override;
 
   public
     constructor Create();
     procedure Initialize(); override;
+    function Clone(): IHash; override;
     property KeyLength: TNullableInteger read GetKeyLength;
     property Key: THashLibByteArray read GetKey write SetKey;
 
@@ -175,7 +177,21 @@ begin
   result := Int32(Fm_h);
 end;
 
-function TMurmur2.ComputeAggregatedBytes(a_data: THashLibByteArray)
+function TMurmur2.Clone(): IHash;
+var
+  HashInstance: TMurmur2;
+begin
+  HashInstance := TMurmur2.Create();
+  HashInstance.Fm_key := Fm_key;
+  HashInstance.Fm_working_key := Fm_working_key;
+  HashInstance.Fm_h := Fm_h;
+  FBuffer.Position := 0;
+  HashInstance.FBuffer.CopyFrom(FBuffer, FBuffer.Size);
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
+function TMurmur2.ComputeAggregatedBytes(const a_data: THashLibByteArray)
   : IHashResult;
 
 begin

+ 18 - 3
src/libraries/hashlib4pascal/HlpMurmur2_64.pas

@@ -7,9 +7,10 @@ interface
 uses
   HlpHashLibTypes,
 {$IFDEF DELPHI}
-  HlpBitConverter,
+  HlpHash,
 {$ENDIF DELPHI}
   HlpConverters,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashResult,
   HlpIHashResult,
@@ -45,12 +46,13 @@ type
     procedure SetKey(const value: THashLibByteArray); inline;
 
   strict protected
-    function ComputeAggregatedBytes(a_data: THashLibByteArray)
+    function ComputeAggregatedBytes(const a_data: THashLibByteArray)
       : IHashResult; override;
 
   public
     constructor Create();
     procedure Initialize(); override;
+    function Clone(): IHash; override;
     property KeyLength: TNullableInteger read GetKeyLength;
     property Key: THashLibByteArray read GetKey write SetKey;
 
@@ -60,7 +62,20 @@ implementation
 
 { TMurmur2_64 }
 
-function TMurmur2_64.ComputeAggregatedBytes(a_data: THashLibByteArray)
+function TMurmur2_64.Clone(): IHash;
+var
+  HashInstance: TMurmur2_64;
+begin
+  HashInstance := TMurmur2_64.Create();
+  HashInstance.Fm_key := Fm_key;
+  HashInstance.Fm_working_key := Fm_working_key;
+  FBuffer.Position := 0;
+  HashInstance.FBuffer.CopyFrom(FBuffer, FBuffer.Size);
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
+function TMurmur2_64.ComputeAggregatedBytes(const a_data: THashLibByteArray)
   : IHashResult;
 var
   &length, current_index: Int32;

+ 17 - 0
src/libraries/hashlib4pascal/HlpMurmurHash3_x64_128.pas

@@ -16,6 +16,7 @@ uses
   HlpIHashInfo,
   HlpNullable,
   HlpHash,
+  HlpIHash,
   HlpHashResult,
   HlpIHashResult,
   HlpBits;
@@ -69,6 +70,7 @@ type
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_length: Int32); override;
     function TransformFinal: IHashResult; override;
+    function Clone(): IHash; override;
     property KeyLength: TNullableInteger read GetKeyLength;
     property Key: THashLibByteArray read GetKey write SetKey;
   end;
@@ -117,6 +119,21 @@ begin
   ProcessPendings();
 end;
 
+function TMurmurHash3_x64_128.Clone(): IHash;
+var
+  HashInstance: TMurmurHash3_x64_128;
+begin
+  HashInstance := TMurmurHash3_x64_128.Create();
+  HashInstance.Fm_h1 := Fm_h1;
+  HashInstance.Fm_h2 := Fm_h2;
+  HashInstance.Fm_total_length := Fm_total_length;
+  HashInstance.Fm_key := Fm_key;
+  HashInstance.Fm_idx := Fm_idx;
+  HashInstance.Fm_buf := System.Copy(Fm_buf);
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TMurmurHash3_x64_128.Create;
 begin
   Inherited Create(16, 16);

+ 19 - 0
src/libraries/hashlib4pascal/HlpMurmurHash3_x86_128.pas

@@ -16,6 +16,7 @@ uses
   HlpBitConverter,
 {$ENDIF DELPHI}
   HlpHash,
+  HlpIHash,
   HlpHashResult,
   HlpIHashResult,
   HlpBits;
@@ -65,6 +66,7 @@ type
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_length: Int32); override;
     function TransformFinal: IHashResult; override;
+    function Clone(): IHash; override;
     property KeyLength: TNullableInteger read GetKeyLength;
     property Key: THashLibByteArray read GetKey write SetKey;
   end;
@@ -137,6 +139,23 @@ begin
   ProcessPendings();
 end;
 
+function TMurmurHash3_x86_128.Clone(): IHash;
+var
+  HashInstance: TMurmurHash3_x86_128;
+begin
+  HashInstance := TMurmurHash3_x86_128.Create();
+    HashInstance.Fm_key := Fm_key;
+  HashInstance.Fm_h1 := Fm_h1;
+  HashInstance.Fm_h2 := Fm_h2;
+  HashInstance.Fm_h3 := Fm_h3;
+  HashInstance.Fm_h4 := Fm_h4;
+  HashInstance.Fm_total_length := Fm_total_length;
+  HashInstance.Fm_idx := Fm_idx;
+  HashInstance.Fm_buf := System.Copy(Fm_buf);
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TMurmurHash3_x86_128.Create;
 begin
   Inherited Create(16, 16);

+ 1 - 1
src/libraries/hashlib4pascal/HlpMurmurHash3_x86_32.pas

@@ -68,7 +68,7 @@ implementation
 
 { TMurmurHash3_x86_32 }
 
-function TMurmurHash3_x86_32.Clone: IHash;
+function TMurmurHash3_x86_32.Clone(): IHash;
 var
   HashInstance: TMurmurHash3_x86_32;
 begin

+ 13 - 0
src/libraries/hashlib4pascal/HlpNullDigest.pas

@@ -9,6 +9,7 @@ uses
   SysUtils,
   HlpHashLibTypes,
   HlpHash,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashResult,
   HlpIHashResult;
@@ -26,12 +27,24 @@ type
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_length: Int32); override;
     function TransformFinal(): IHashResult; override;
+    function Clone(): IHash; override;
   end;
 
 implementation
 
 { TNullDigest }
 
+function TNullDigest.Clone(): IHash;
+var
+  HashInstance: TNullDigest;
+begin
+  HashInstance := TNullDigest.Create();
+  FbOut.Position := 0;
+  HashInstance.FbOut.CopyFrom(FbOut, FbOut.Size);
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TNullDigest.Create;
 begin
   Inherited Create(-1, -1); // Dummy State

+ 12 - 0
src/libraries/hashlib4pascal/HlpOneAtTime.pas

@@ -7,6 +7,7 @@ interface
 uses
   HlpHashLibTypes,
   HlpHash,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashResult,
   HlpIHashResult;
@@ -23,12 +24,23 @@ type
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_length: Int32); override;
     function TransformFinal(): IHashResult; override;
+    function Clone(): IHash; override;
   end;
 
 implementation
 
 { TOneAtTime }
 
+function TOneAtTime.Clone(): IHash;
+var
+  HashInstance: TOneAtTime;
+begin
+  HashInstance := TOneAtTime.Create();
+  HashInstance.Fm_hash := Fm_hash;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TOneAtTime.Create;
 begin
   Inherited Create(4, 1);

+ 12 - 0
src/libraries/hashlib4pascal/HlpPJW.pas

@@ -7,6 +7,7 @@ interface
 uses
   HlpHashLibTypes,
   HlpHash,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashResult,
   HlpIHashResult;
@@ -30,12 +31,23 @@ type
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_length: Int32); override;
     function TransformFinal(): IHashResult; override;
+    function Clone(): IHash; override;
   end;
 
 implementation
 
 { TPJW }
 
+function TPJW.Clone(): IHash;
+var
+  HashInstance: TPJW;
+begin
+  HashInstance := TPJW.Create();
+  HashInstance.Fm_hash := Fm_hash;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TPJW.Create;
 begin
   Inherited Create(4, 1);

+ 38 - 1
src/libraries/hashlib4pascal/HlpPanama.pas

@@ -9,8 +9,11 @@ uses
   HlpBits,
 {$IFDEF DELPHI}
   HlpBitConverter,
+  HlpHashBuffer,
+  HlpHash,
 {$ENDIF DELPHI}
   HlpConverters,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashCryptoNotBuildIn;
 
@@ -38,6 +41,7 @@ type
   public
     constructor Create();
     procedure Initialize(); override;
+    function Clone(): IHash; override;
 
   end;
 
@@ -45,6 +49,28 @@ implementation
 
 { TPanama }
 
+function TPanama.Clone(): IHash;
+var
+  HashInstance: TPanama;
+  Idx: Int32;
+begin
+  HashInstance := TPanama.Create();
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.Ftheta := System.Copy(Ftheta);
+  HashInstance.Fgamma := System.Copy(Fgamma);
+  HashInstance.Fpi := System.Copy(Fpi);
+  // since System.Copy() does not support jagged arrays (multidimensional dynamic arrays, we improvise)
+  for Idx := System.Low(Fm_stages) to System.High(Fm_stages) do
+  begin
+    HashInstance.Fm_stages[Idx] := System.Copy(Fm_stages[Idx]);
+  end;
+  HashInstance.Fm_tap := Fm_tap;
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TPanama.Create;
 var
   i: Int32;
@@ -214,6 +240,17 @@ begin
   System.FillChar(Fm_state[0], System.Length(Fm_state) * System.SizeOf(UInt32),
     UInt32(0));
 
+  System.FillChar(Ftheta[0], System.Length(Ftheta) * System.SizeOf(UInt32),
+    UInt32(0));
+
+  System.FillChar(Fgamma[0], System.Length(Fgamma) * System.SizeOf(UInt32),
+    UInt32(0));
+
+  System.FillChar(Fpi[0], System.Length(Fpi) * System.SizeOf(UInt32),
+    UInt32(0));
+
+  Fm_tap := 0;
+
   for i := System.Low(Fm_stages) to System.High(Fm_stages) do
   begin
     System.FillChar(Fm_stages[i, 0], System.Length(Fm_stages[i]) *
@@ -276,7 +313,7 @@ begin
   Fm_state[15] := Ftheta[15] xor Fm_stages[tap16, 6];
   Fm_state[16] := Ftheta[16] xor Fm_stages[tap16, 7];
 
-  System.FillChar(work_buffer, System.SizeOf(work_buffer), 0);
+  System.FillChar(work_buffer, System.SizeOf(work_buffer), UInt32(0));
 
 end;
 

+ 17 - 1
src/libraries/hashlib4pascal/HlpRIPEMD.pas

@@ -11,9 +11,12 @@ uses
   HlpBits,
 {$IFDEF DELPHI}
   HlpBitConverter,
+  HlpHashBuffer,
+  HlpHash,
 {$ENDIF DELPHI}
   HlpMDBase,
   HlpConverters,
+  HlpIHash,
   HlpIHashInfo;
 
 type
@@ -30,6 +33,7 @@ type
 
   public
     constructor Create();
+    function Clone(): IHash; override;
 
   end;
 
@@ -37,6 +41,18 @@ implementation
 
 { TRIPEMD }
 
+function TRIPEMD.Clone(): IHash;
+var
+  HashInstance: TRIPEMD;
+begin
+  HashInstance := TRIPEMD.Create();
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TRIPEMD.Create;
 begin
   Inherited Create(4, 16);
@@ -183,7 +199,7 @@ begin
   Fm_state[2] := Fm_state[3] + a + bb;
   Fm_state[3] := cc;
 
-  System.FillChar(data, System.SizeOf(data), 0);
+  System.FillChar(data, System.SizeOf(data), UInt32(0));
 
 end;
 

+ 17 - 1
src/libraries/hashlib4pascal/HlpRIPEMD128.pas

@@ -11,9 +11,12 @@ uses
   HlpMDBase,
 {$IFDEF DELPHI}
   HlpBitConverter,
+  HlpHashBuffer,
+  HlpHash,
 {$ENDIF DELPHI}
   HlpBits,
   HlpConverters,
+  HlpIHash,
   HlpIHashInfo;
 
 type
@@ -25,6 +28,7 @@ type
 
   public
     constructor Create();
+    function Clone(): IHash; override;
 
   end;
 
@@ -32,6 +36,18 @@ implementation
 
 { TRIPEMD128 }
 
+function TRIPEMD128.Clone(): IHash;
+var
+  HashInstance: TRIPEMD128;
+begin
+  HashInstance := TRIPEMD128.Create();
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TRIPEMD128.Create;
 begin
   Inherited Create(4, 16);
@@ -325,7 +341,7 @@ begin
   Fm_state[3] := Fm_state[0] + b + cc;
   Fm_state[0] := dd;
 
-  System.FillChar(data, System.SizeOf(data), 0);
+  System.FillChar(data, System.SizeOf(data), UInt32(0));
 
 end;
 

+ 17 - 1
src/libraries/hashlib4pascal/HlpRIPEMD160.pas

@@ -11,9 +11,12 @@ uses
   HlpMDBase,
 {$IFDEF DELPHI}
   HlpBitConverter,
+  HlpHashBuffer,
+  HlpHash,
 {$ENDIF DELPHI}
   HlpBits,
   HlpConverters,
+  HlpIHash,
   HlpIHashInfo;
 
 type
@@ -26,6 +29,7 @@ type
   public
     constructor Create();
     procedure Initialize(); override;
+    function Clone(): IHash; override;
 
   end;
 
@@ -33,6 +37,18 @@ implementation
 
 { TRIPEMD160 }
 
+function TRIPEMD160.Clone(): IHash;
+var
+  HashInstance: TRIPEMD160;
+begin
+  HashInstance := TRIPEMD160.Create();
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TRIPEMD160.Create;
 begin
   Inherited Create(5, 20);
@@ -563,7 +579,7 @@ begin
   Fm_state[4] := Fm_state[0] + b + cc;
   Fm_state[0] := dd;
 
-  System.FillChar(data, System.SizeOf(data), 0);
+  System.FillChar(data, System.SizeOf(data), UInt32(0));
 
 end;
 

+ 17 - 1
src/libraries/hashlib4pascal/HlpRIPEMD256.pas

@@ -12,8 +12,11 @@ uses
   HlpBits,
 {$IFDEF DELPHI}
   HlpBitConverter,
+  HlpHashBuffer,
+  HlpHash,
 {$ENDIF DELPHI}
   HlpConverters,
+  HlpIHash,
   HlpIHashInfo;
 
 type
@@ -26,6 +29,7 @@ type
   public
     constructor Create();
     procedure Initialize(); override;
+    function Clone(): IHash; override;
 
   end;
 
@@ -33,6 +37,18 @@ implementation
 
 { TRIPEMD256 }
 
+function TRIPEMD256.Clone(): IHash;
+var
+  HashInstance: TRIPEMD256;
+begin
+  HashInstance := TRIPEMD256.Create();
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TRIPEMD256.Create;
 begin
   Inherited Create(8, 32);
@@ -340,7 +356,7 @@ begin
   Fm_state[6] := Fm_state[6] + c;
   Fm_state[7] := Fm_state[7] + d;
 
-  System.FillChar(data, System.SizeOf(data), 0);
+  System.FillChar(data, System.SizeOf(data), UInt32(0));
 
 end;
 

+ 17 - 1
src/libraries/hashlib4pascal/HlpRIPEMD320.pas

@@ -11,9 +11,12 @@ uses
   HlpMDBase,
 {$IFDEF DELPHI}
   HlpBitConverter,
+  HlpHashBuffer,
+  HlpHash,
 {$ENDIF DELPHI}
   HlpBits,
   HlpConverters,
+  HlpIHash,
   HlpIHashInfo;
 
 type
@@ -26,6 +29,7 @@ type
   public
     constructor Create();
     procedure Initialize(); override;
+    function Clone(): IHash; override;
 
   end;
 
@@ -33,6 +37,18 @@ implementation
 
 { TRIPEMD320 }
 
+function TRIPEMD320.Clone(): IHash;
+var
+  HashInstance: TRIPEMD320;
+begin
+  HashInstance := TRIPEMD320.Create();
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TRIPEMD320.Create;
 begin
   Inherited Create(10, 40);
@@ -572,7 +588,7 @@ begin
   Fm_state[8] := Fm_state[8] + d;
   Fm_state[9] := Fm_state[9] + e;
 
-  System.FillChar(data, System.SizeOf(data), 0);
+  System.FillChar(data, System.SizeOf(data), UInt32(0));
 
 end;
 

+ 13 - 0
src/libraries/hashlib4pascal/HlpRS.pas

@@ -7,6 +7,7 @@ interface
 uses
   HlpHashLibTypes,
   HlpHash,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashResult,
   HlpIHashResult;
@@ -26,12 +27,24 @@ type
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_length: Int32); override;
     function TransformFinal(): IHashResult; override;
+    function Clone(): IHash; override;
   end;
 
 implementation
 
 { TRS }
 
+function TRS.Clone(): IHash;
+var
+  HashInstance: TRS;
+begin
+  HashInstance := TRS.Create();
+  HashInstance.Fm_hash := Fm_hash;
+  HashInstance.Fm_a := Fm_a;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TRS.Create;
 begin
   Inherited Create(4, 1);

+ 24 - 2
src/libraries/hashlib4pascal/HlpRadioGatun32.pas

@@ -8,9 +8,12 @@ uses
   HlpHashLibTypes,
 {$IFDEF DELPHI}
   HlpBitConverter,
+  HlpHashBuffer,
+  HlpHash,
 {$ENDIF DELPHI}
   HlpBits,
   HlpConverters,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashCryptoNotBuildIn;
 
@@ -34,6 +37,7 @@ type
   public
     constructor Create();
     procedure Initialize(); override;
+    function Clone(): IHash; override;
 
   end;
 
@@ -41,6 +45,24 @@ implementation
 
 { TRadioGatun32 }
 
+function TRadioGatun32.Clone(): IHash;
+var
+  HashInstance: TRadioGatun32;
+  Idx: Int32;
+begin
+  HashInstance := TRadioGatun32.Create();
+  HashInstance.Fm_mill := System.Copy(Fm_mill);
+  // since System.Copy() does not support jagged arrays (multidimensional dynamic arrays, we improvise)
+  for Idx := System.Low(Fm_belt) to System.High(Fm_belt) do
+  begin
+    HashInstance.Fm_belt[Idx] := System.Copy(Fm_belt[Idx]);
+  end;
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TRadioGatun32.Create;
 var
   i: Int32;
@@ -100,7 +122,6 @@ begin
 
   TConverters.le32_copy(PCardinal(tempRes), 0, PByte(result), 0,
     System.Length(result));
-
 end;
 
 procedure TRadioGatun32.Initialize;
@@ -117,6 +138,7 @@ begin
 
     System.FillChar(Fm_belt[i][0], System.Length(Fm_belt[i]) *
       System.SizeOf(UInt32), UInt32(0));
+
     System.Inc(i);
   end;
 
@@ -207,7 +229,7 @@ begin
 
   RoundFunction();
 
-  System.FillChar(data, System.SizeOf(data), 0);
+  System.FillChar(data, System.SizeOf(data), UInt32(0));
 end;
 
 end.

+ 23 - 1
src/libraries/hashlib4pascal/HlpRadioGatun64.pas

@@ -8,9 +8,12 @@ uses
   HlpHashLibTypes,
 {$IFDEF DELPHI}
   HlpBitConverter,
+  HlpHashBuffer,
+  HlpHash,
 {$ENDIF DELPHI}
   HlpBits,
   HlpConverters,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashCryptoNotBuildIn;
 
@@ -34,6 +37,7 @@ type
   public
     constructor Create();
     procedure Initialize(); override;
+    function Clone(): IHash; override;
 
   end;
 
@@ -41,6 +45,24 @@ implementation
 
 { TRadioGatun64 }
 
+function TRadioGatun64.Clone(): IHash;
+var
+  HashInstance: TRadioGatun64;
+  Idx: Int32;
+begin
+  HashInstance := TRadioGatun64.Create();
+  HashInstance.Fm_mill := System.Copy(Fm_mill);
+  // since System.Copy() does not support jagged arrays (multidimensional dynamic arrays, we improvise)
+  for Idx := System.Low(Fm_belt) to System.High(Fm_belt) do
+  begin
+    HashInstance.Fm_belt[Idx] := System.Copy(Fm_belt[Idx]);
+  end;
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TRadioGatun64.Create;
 var
   i: Int32;
@@ -205,7 +227,7 @@ begin
 
   RoundFunction();
 
-  System.FillChar(data, System.SizeOf(data), 0);
+  System.FillChar(data, System.SizeOf(data), UInt64(0));
 end;
 
 end.

+ 12 - 0
src/libraries/hashlib4pascal/HlpRotating.pas

@@ -8,6 +8,7 @@ uses
   HlpHashLibTypes,
   HlpBits,
   HlpHash,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashResult,
   HlpIHashResult;
@@ -24,12 +25,23 @@ type
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_length: Int32); override;
     function TransformFinal(): IHashResult; override;
+    function Clone(): IHash; override;
   end;
 
 implementation
 
 { TRotating }
 
+function TRotating.Clone(): IHash;
+var
+  HashInstance: TRotating;
+begin
+  HashInstance := TRotating.Create();
+  HashInstance.Fm_hash := Fm_hash;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TRotating.Create;
 begin
   Inherited Create(4, 1);

+ 12 - 0
src/libraries/hashlib4pascal/HlpSDBM.pas

@@ -7,6 +7,7 @@ interface
 uses
   HlpHashLibTypes,
   HlpHash,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashResult,
   HlpIHashResult;
@@ -23,12 +24,23 @@ type
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_length: Int32); override;
     function TransformFinal(): IHashResult; override;
+    function Clone(): IHash; override;
   end;
 
 implementation
 
 { TSDBM }
 
+function TSDBM.Clone(): IHash;
+var
+  HashInstance: TSDBM;
+begin
+  HashInstance := TSDBM.Create();
+  HashInstance.Fm_hash := Fm_hash;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TSDBM.Create;
 begin
   Inherited Create(4, 1);

+ 16 - 1
src/libraries/hashlib4pascal/HlpSHA0.pas

@@ -12,9 +12,11 @@ uses
 {$IFDEF DELPHI}
   HlpHashBuffer,
   HlpBitConverter,
+  HlpHash,
 {$ENDIF DELPHI}
   HlpHashLibTypes,
   HlpConverters,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashCryptoNotBuildIn;
 
@@ -44,6 +46,7 @@ type
   public
     constructor Create();
     procedure Initialize(); override;
+    function Clone(): IHash; override;
 
   end;
 
@@ -51,6 +54,18 @@ implementation
 
 { TSHA0 }
 
+function TSHA0.Clone(): IHash;
+var
+  HashInstance: TSHA0;
+begin
+  HashInstance := TSHA0.Create();
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TSHA0.Create;
 begin
   Inherited Create(20, 64);
@@ -559,7 +574,7 @@ begin
   Fm_state[3] := Fm_state[3] + D;
   Fm_state[4] := Fm_state[4] + E;
 
-  System.FillChar(data, System.SizeOf(data), 0);
+  System.FillChar(data, System.SizeOf(data), UInt32(0));
 
 end;
 

+ 19 - 2
src/libraries/hashlib4pascal/HlpSHA1.pas

@@ -5,9 +5,13 @@ unit HlpSHA1;
 interface
 
 uses
-
   HlpBits,
-  HlpSHA0;
+{$IFDEF DELPHI}
+  HlpHashBuffer,
+  HlpHash,
+{$ENDIF DELPHI}
+  HlpSHA0,
+  HlpIHash;
 
 type
   TSHA1 = class sealed(TSHA0)
@@ -20,6 +24,7 @@ type
     // called for classes if none is defined by the developer but I just put it
     // for readability reasons.
     constructor Create();
+    function Clone(): IHash; override;
 
   end;
 
@@ -27,6 +32,18 @@ implementation
 
 { TSHA1 }
 
+function TSHA1.Clone(): IHash;
+var
+  HashInstance: TSHA1;
+begin
+  HashInstance := TSHA1.Create();
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TSHA1.Create;
 begin
   Inherited Create();

+ 16 - 0
src/libraries/hashlib4pascal/HlpSHA2_224.pas

@@ -11,8 +11,11 @@ uses
   HlpHashLibTypes,
 {$IFDEF DELPHI}
   HlpBitConverter,
+  HlpHashBuffer,
+  HlpHash,
 {$ENDIF DELPHI}
   HlpSHA2_256Base,
+  HlpIHash,
   HlpConverters;
 
 type
@@ -24,6 +27,7 @@ type
   public
     constructor Create();
     procedure Initialize(); override;
+    function Clone(): IHash; override;
 
   end;
 
@@ -31,6 +35,18 @@ implementation
 
 { TSHA2_224 }
 
+function TSHA2_224.Clone(): IHash;
+var
+  HashInstance: TSHA2_224;
+begin
+  HashInstance := TSHA2_224.Create();
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TSHA2_224.Create;
 begin
   Inherited Create(28);

+ 16 - 0
src/libraries/hashlib4pascal/HlpSHA2_256.pas

@@ -11,7 +11,10 @@ uses
   HlpHashLibTypes,
 {$IFDEF DELPHI}
   HlpBitConverter,
+  HlpHashBuffer,
+  HlpHash,
 {$ENDIF DELPHI}
+  HlpIHash,
   HlpSHA2_256Base,
   HlpConverters;
 
@@ -24,6 +27,7 @@ type
   public
     constructor Create();
     procedure Initialize(); override;
+    function Clone(): IHash; override;
 
   end;
 
@@ -31,6 +35,18 @@ implementation
 
 { TSHA2_256 }
 
+function TSHA2_256.Clone(): IHash;
+var
+  HashInstance: TSHA2_256;
+begin
+  HashInstance := TSHA2_256.Create();
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TSHA2_256.Create;
 begin
   Inherited Create(32);

+ 1 - 1
src/libraries/hashlib4pascal/HlpSHA2_256Base.pas

@@ -941,7 +941,7 @@ begin
   Fm_state[6] := Fm_state[6] + G;
   Fm_state[7] := Fm_state[7] + H;
 
-  System.FillChar(data, System.SizeOf(data), 0);
+  System.FillChar(data, System.SizeOf(data), UInt32(0));
 
 end;
 

+ 16 - 0
src/libraries/hashlib4pascal/HlpSHA2_384.pas

@@ -11,7 +11,10 @@ uses
   HlpHashLibTypes,
 {$IFDEF DELPHI}
   HlpBitConverter,
+  HlpHashBuffer,
+  HlpHash,
 {$ENDIF DELPHI}
+  HlpIHash,
   HlpSHA2_512Base,
   HlpConverters;
 
@@ -24,6 +27,7 @@ type
   public
     constructor Create();
     procedure Initialize(); override;
+    function Clone(): IHash; override;
 
   end;
 
@@ -31,6 +35,18 @@ implementation
 
 { TSHA2_384 }
 
+function TSHA2_384.Clone(): IHash;
+var
+  HashInstance: TSHA2_384;
+begin
+  HashInstance := TSHA2_384.Create();
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TSHA2_384.Create;
 begin
   Inherited Create(48);

+ 16 - 0
src/libraries/hashlib4pascal/HlpSHA2_512.pas

@@ -11,7 +11,10 @@ uses
   HlpHashLibTypes,
 {$IFDEF DELPHI}
   HlpBitConverter,
+  HlpHashBuffer,
+  HlpHash,
 {$ENDIF DELPHI}
+  HlpIHash,
   HlpSHA2_512Base,
   HlpConverters;
 
@@ -24,6 +27,7 @@ type
   public
     constructor Create();
     procedure Initialize(); override;
+    function Clone(): IHash; override;
 
   end;
 
@@ -31,6 +35,18 @@ implementation
 
 { TSHA2_512 }
 
+function TSHA2_512.Clone(): IHash;
+var
+  HashInstance: TSHA2_512;
+begin
+  HashInstance := TSHA2_512.Create();
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TSHA2_512.Create;
 begin
   Inherited Create(64);

+ 1 - 1
src/libraries/hashlib4pascal/HlpSHA2_512Base.pas

@@ -1296,7 +1296,7 @@ begin
   Fm_state[6] := Fm_state[6] + g;
   Fm_state[7] := Fm_state[7] + h;
 
-  System.FillChar(data, System.SizeOf(data), 0);
+  System.FillChar(data, System.SizeOf(data), UInt64(0));
 
 end;
 

+ 16 - 0
src/libraries/hashlib4pascal/HlpSHA2_512_224.pas

@@ -11,7 +11,10 @@ uses
   HlpHashLibTypes,
 {$IFDEF DELPHI}
   HlpBitConverter,
+  HlpHashBuffer,
+  HlpHash,
 {$ENDIF DELPHI}
+  HlpIHash,
   HlpSHA2_512Base,
   HlpConverters;
 
@@ -24,6 +27,7 @@ type
   public
     constructor Create();
     procedure Initialize(); override;
+    function Clone(): IHash; override;
 
   end;
 
@@ -31,6 +35,18 @@ implementation
 
 { TSHA2_512_224 }
 
+function TSHA2_512_224.Clone(): IHash;
+var
+  HashInstance: TSHA2_512_224;
+begin
+  HashInstance := TSHA2_512_224.Create();
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TSHA2_512_224.Create;
 begin
   Inherited Create(28);

+ 16 - 0
src/libraries/hashlib4pascal/HlpSHA2_512_256.pas

@@ -11,7 +11,10 @@ uses
   HlpHashLibTypes,
 {$IFDEF DELPHI}
   HlpBitConverter,
+  HlpHashBuffer,
+  HlpHash,
 {$ENDIF DELPHI}
+  HlpIHash,
   HlpSHA2_512Base,
   HlpConverters;
 
@@ -24,6 +27,7 @@ type
   public
     constructor Create();
     procedure Initialize(); override;
+    function Clone(): IHash; override;
 
   end;
 
@@ -31,6 +35,18 @@ implementation
 
 { TSHA2_512_256 }
 
+function TSHA2_512_256.Clone(): IHash;
+var
+  HashInstance: TSHA2_512_256;
+begin
+  HashInstance := TSHA2_512_256.Create();
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TSHA2_512_256.Create;
 begin
   Inherited Create(32);

+ 56 - 5
src/libraries/hashlib4pascal/HlpSHA3.pas

@@ -12,8 +12,10 @@ uses
 {$IFDEF DELPHI}
   HlpHashBuffer,
   HlpBitConverter,
+  HlpHash,
 {$ENDIF DELPHI}
   HlpIHashInfo,
+  HlpIHash,
   HlpHashCryptoNotBuildIn,
   HlpConverters,
   HlpHashSize,
@@ -22,11 +24,8 @@ uses
 type
   TSHA3 = class abstract(TBlockHash, ICryptoNotBuildIn, ITransformBlock)
 
-  strict private
-    Fm_state: THashLibUInt64Array;
-
   strict protected
-
+    Fm_state: THashLibUInt64Array;
     FHashSize, FBlockSize: Int32;
 
     (*
@@ -65,6 +64,7 @@ type
   public
 
     constructor Create();
+    function Clone(): IHash; override;
   end;
 
 type
@@ -74,6 +74,7 @@ type
   public
 
     constructor Create();
+    function Clone(): IHash; override;
   end;
 
 type
@@ -83,6 +84,7 @@ type
   public
 
     constructor Create();
+    function Clone(): IHash; override;
   end;
 
 type
@@ -92,6 +94,7 @@ type
   public
 
     constructor Create();
+    function Clone(): IHash; override;
   end;
 
 implementation
@@ -2780,11 +2783,23 @@ begin
   Fm_state[23] := Aso;
   Fm_state[24] := Asu;
 
-  System.FillChar(data, System.SizeOf(data), 0);
+  System.FillChar(data, System.SizeOf(data), UInt64(0));
 end;
 
 { TSHA3_224 }
 
+function TSHA3_224.Clone(): IHash;
+var
+  HashInstance: TSHA3_224;
+begin
+  HashInstance := TSHA3_224.Create();
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TSHA3_224.Create;
 begin
   Inherited Create(THashSize.hsHashSize224);
@@ -2792,6 +2807,18 @@ end;
 
 { TSHA3_256 }
 
+function TSHA3_256.Clone(): IHash;
+var
+  HashInstance: TSHA3_256;
+begin
+  HashInstance := TSHA3_256.Create();
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TSHA3_256.Create;
 begin
   Inherited Create(THashSize.hsHashSize256);
@@ -2799,6 +2826,18 @@ end;
 
 { TSHA3_384 }
 
+function TSHA3_384.Clone(): IHash;
+var
+  HashInstance: TSHA3_384;
+begin
+  HashInstance := TSHA3_384.Create();
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TSHA3_384.Create;
 begin
   Inherited Create(THashSize.hsHashSize384);
@@ -2806,6 +2845,18 @@ end;
 
 { TSHA3_512 }
 
+function TSHA3_512.Clone(): IHash;
+var
+  HashInstance: TSHA3_512;
+begin
+  HashInstance := TSHA3_512.Create();
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TSHA3_512.Create;
 begin
   Inherited Create(THashSize.hsHashSize512);

+ 12 - 0
src/libraries/hashlib4pascal/HlpShiftAndXor.pas

@@ -7,6 +7,7 @@ interface
 uses
   HlpHashLibTypes,
   HlpHash,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashResult,
   HlpIHashResult;
@@ -23,12 +24,23 @@ type
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_length: Int32); override;
     function TransformFinal(): IHashResult; override;
+    function Clone(): IHash; override;
   end;
 
 implementation
 
 { TShiftAndXor }
 
+function TShiftAndXor.Clone(): IHash;
+var
+  HashInstance: TShiftAndXor;
+begin
+  HashInstance := TShiftAndXor.Create();
+  HashInstance.Fm_hash := Fm_hash;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TShiftAndXor.Create;
 begin
   Inherited Create(4, 1);

+ 28 - 8
src/libraries/hashlib4pascal/HlpSipHash.pas

@@ -13,10 +13,8 @@ uses
   HlpConverters,
   HlpIHashInfo,
   HlpNullable,
-{$IFDEF DELPHI}
-  HlpBitConverter,
-{$ENDIF DELPHI}
   HlpHash,
+  HlpIHash,
   HlpHashResult,
   HlpIHashResult,
   HlpBits;
@@ -29,12 +27,7 @@ type
 
   strict private
 
-    Fm_v0, Fm_v1, Fm_v2, Fm_v3, Fm_key0, Fm_key1, Fm_total_length: UInt64;
-    F_cr, F_fr, Fm_idx: Int32;
-    Fm_buf: THashLibByteArray;
-
 {$REGION 'Consts'}
-
   const
     V0 = UInt64($736F6D6570736575);
     V1 = UInt64($646F72616E646F6D);
@@ -54,6 +47,12 @@ type
     function GetKey: THashLibByteArray;
     procedure SetKey(const value: THashLibByteArray);
 
+  strict protected
+
+    Fm_v0, Fm_v1, Fm_v2, Fm_v3, Fm_key0, Fm_key1, Fm_total_length: UInt64;
+    F_cr, F_fr, Fm_idx: Int32;
+    Fm_buf: THashLibByteArray;
+
   public
     constructor Create(a_compression_rounds: Int32 = 2;
       a_finalization_rounds: Int32 = 4);
@@ -75,6 +74,7 @@ type
   public
 
     constructor Create();
+    function Clone(): IHash; override;
 
   end;
 
@@ -82,6 +82,26 @@ implementation
 
 { TSipHash2_4 }
 
+function TSipHash2_4.Clone(): IHash;
+var
+  HashInstance: TSipHash2_4;
+begin
+  HashInstance := TSipHash2_4.Create();
+  HashInstance.Fm_v0 := Fm_v0;
+  HashInstance.Fm_v1 := Fm_v1;
+  HashInstance.Fm_v2 := Fm_v2;
+  HashInstance.Fm_v3 := Fm_v3;
+  HashInstance.Fm_key0 := Fm_key0;
+  HashInstance.Fm_key1 := Fm_key1;
+  HashInstance.Fm_total_length := Fm_total_length;
+  HashInstance.F_cr := F_cr;
+  HashInstance.F_fr := F_fr;
+  HashInstance.Fm_idx := Fm_idx;
+  HashInstance.Fm_buf := System.Copy(Fm_buf);
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TSipHash2_4.Create;
 begin
   Inherited Create(2, 4);

+ 49 - 7
src/libraries/hashlib4pascal/HlpSnefru.pas

@@ -5,17 +5,21 @@ unit HlpSnefru;
 interface
 
 uses
-{$IFDEF DELPHI2010}
-  SysUtils, // to get rid of compiler hint "not inlined" on Delphi 2010.
-{$ENDIF DELPHI2010}
+{$IFDEF HAS_UNITSCOPE}
+  System.SysUtils,
+{$ELSE}
+  SysUtils,
+{$ENDIF HAS_UNITSCOPE}
   HlpHashLibTypes,
 {$IFDEF DELPHI}
+  HlpHash,
   HlpHashBuffer,
   HlpBitConverter,
 {$ENDIF DELPHI}
   HlpBits,
   HlpHashSize,
   HlpConverters,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashCryptoNotBuildIn;
 
@@ -24,6 +28,7 @@ resourcestring
     'Snefru Security Level Cannot be Less than 1. Standard Level is 8';
   SInvalidSnefruHashSize =
     'Snefru HashSize Must be Either 128 bit(16 byte) or 256 bit(32 byte)';
+  SInvalidHashSize = 'Specified HashSize Is Invalid or UnSupported "%d"';
 
 type
 
@@ -43,7 +48,10 @@ type
 
     class constructor Snefru();
 
+    function GetHashSize(AHashSize: Int32): THashSize; inline;
+
   strict protected
+    function GetName: String; override;
     function GetResult(): THashLibByteArray; override;
     procedure Finish(); override;
     procedure TransformBlock(a_data: PByte; a_data_length: Int32;
@@ -58,6 +66,7 @@ type
     /// <returns></returns>
     constructor Create(a_security_level: Int32; a_hash_size: THashSize);
     procedure Initialize(); override;
+    function Clone(): IHash; override;
 
   end;
 
@@ -65,6 +74,33 @@ implementation
 
 { TSnefru }
 
+function TSnefru.GetHashSize(AHashSize: Int32): THashSize;
+begin
+  case AHashSize of
+    16:
+      Result := THashSize.hsHashSize128;
+    32:
+      Result := THashSize.hsHashSize256
+  else
+    begin
+      raise EArgumentInvalidHashLibException.CreateResFmt(@SInvalidHashSize,
+        [AHashSize]);
+    end;
+  end;
+end;
+
+function TSnefru.Clone(): IHash;
+var
+  HashInstance: TSnefru;
+begin
+  HashInstance := TSnefru.Create(Fm_security_level, GetHashSize(FHashSize));
+  HashInstance.Fm_state := System.Copy(Fm_state);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  Result := HashInstance as IHash;
+  Result.BufferSize := BufferSize;
+end;
+
 constructor TSnefru.Create(a_security_level: Int32; a_hash_size: THashSize);
 begin
 
@@ -100,11 +136,17 @@ begin
 
 end;
 
+function TSnefru.GetName: String;
+begin
+  Result := Format('%s_%u_%u', [Self.ClassName, Fm_security_level,
+    Self.HashSize * 8]);
+end;
+
 function TSnefru.GetResult: THashLibByteArray;
 begin
-  System.SetLength(result, System.Length(Fm_state) * System.SizeOf(UInt32));
-  TConverters.be32_copy(PCardinal(Fm_state), 0, PByte(result), 0,
-    System.Length(result));
+  System.SetLength(Result, System.Length(Fm_state) * System.SizeOf(UInt32));
+  TConverters.be32_copy(PCardinal(Fm_state), 0, PByte(Result), 0,
+    System.Length(Result));
 end;
 
 procedure TSnefru.Initialize;
@@ -206,7 +248,7 @@ begin
     Fm_state[7] := Fm_state[7] xor work[8];
   end;
 
-  System.FillChar(work, System.SizeOf(work), 0);
+  System.FillChar(work, System.SizeOf(work), UInt32(0));
 
 end;
 

+ 18 - 2
src/libraries/hashlib4pascal/HlpSuperFast.pas

@@ -6,6 +6,10 @@ interface
 
 uses
   HlpHashLibTypes,
+{$IFDEF DELPHI}
+  HlpHash,
+{$ENDIF DELPHI}
+  HlpIHash,
   HlpIHashInfo,
   HlpHashResult,
   HlpIHashResult,
@@ -17,10 +21,11 @@ type
     ITransformBlock)
 
   strict protected
-    function ComputeAggregatedBytes(a_data: THashLibByteArray)
+    function ComputeAggregatedBytes(const a_data: THashLibByteArray)
       : IHashResult; override;
   public
     constructor Create();
+    function Clone(): IHash; override;
 
   end;
 
@@ -33,7 +38,18 @@ begin
   Inherited Create(4, 4);
 end;
 
-function TSuperFast.ComputeAggregatedBytes(a_data: THashLibByteArray)
+function TSuperFast.Clone(): IHash;
+var
+  HashInstance: TSuperFast;
+begin
+  HashInstance := TSuperFast.Create();
+  FBuffer.Position := 0;
+  HashInstance.FBuffer.CopyFrom(FBuffer, FBuffer.Size);
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
+function TSuperFast.ComputeAggregatedBytes(const a_data: THashLibByteArray)
   : IHashResult;
 var
   hash, tmp, u1: UInt32;

+ 93 - 10
src/libraries/hashlib4pascal/HlpTiger.pas

@@ -5,32 +5,34 @@ unit HlpTiger;
 interface
 
 uses
-{$IFDEF DELPHI2010}
-  SysUtils, // to get rid of compiler hint "not inlined" on Delphi 2010.
-{$ENDIF DELPHI2010}
+{$IFDEF HAS_UNITSCOPE}
+  System.SysUtils,
+{$ELSE}
+  SysUtils,
+{$ENDIF HAS_UNITSCOPE}
 {$IFDEF DELPHI}
   HlpBitConverter,
   HlpHashBuffer,
+  HlpHash,
 {$ENDIF DELPHI}
   HlpHashLibTypes,
   HlpConverters,
   HlpHashRounds,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashCryptoNotBuildIn;
 
 resourcestring
   SInvalidTigerHashSize =
     'Tiger HashSize Must be Either 128 bit(16 byte), 160 bit(20 byte) or 192 bit(24 byte)';
+  SInvalidHashRound = 'Specified HashRound Is Invalid or UnSupported "%d"';
 
 type
   TTiger = class abstract(TBlockHash, ICryptoNotBuildIn, ITransformBlock)
 
   strict private
 
-    Fm_rounds: Int32;
-
 {$REGION 'Consts'}
-
   const
 
     C1 = UInt64($A5A5A5A5A5A5A5A5);
@@ -558,15 +560,19 @@ type
 
 {$ENDREGION}
   strict protected
+    Fm_rounds: Int32;
     Fm_hash: THashLibUInt64Array;
 
     constructor Create(a_hash_size: Int32; a_rounds: THashRounds);
 
+    function GetName: String; override;
     function GetResult(): THashLibByteArray; override;
     procedure Finish(); override;
     procedure TransformBlock(a_data: PByte; a_data_length: Int32;
       a_index: Int32); override;
 
+    function GetHashRound(AHashRound: Int32): THashRounds; inline;
+
   public
     procedure Initialize(); override;
 
@@ -578,6 +584,7 @@ type
 
   public
     constructor Create(a_hash_size: Int32; a_rounds: THashRounds);
+    function Clone(): IHash; override;
 
   end;
 
@@ -589,6 +596,7 @@ type
     constructor CreateRound3();
     constructor CreateRound4();
     constructor CreateRound5();
+    function Clone(): IHash; override;
 
   end;
 
@@ -600,6 +608,7 @@ type
     constructor CreateRound3();
     constructor CreateRound4();
     constructor CreateRound5();
+    function Clone(): IHash; override;
 
   end;
 
@@ -610,6 +619,7 @@ type
     constructor CreateRound3();
     constructor CreateRound4();
     constructor CreateRound5();
+    function Clone(): IHash; override;
 
   end;
 
@@ -617,6 +627,25 @@ implementation
 
 { TTiger }
 
+function TTiger.GetHashRound(AHashRound: Int32): THashRounds;
+begin
+  case AHashRound of
+    3:
+      Result := THashRounds.hrRounds3;
+    4:
+      Result := THashRounds.hrRounds4;
+    5:
+      Result := THashRounds.hrRounds5;
+    8:
+      Result := THashRounds.hrRounds8
+  else
+    begin
+      raise EArgumentInvalidHashLibException.CreateResFmt(@SInvalidHashRound,
+        [AHashRound]);
+    end;
+  end;
+end;
+
 constructor TTiger.Create(a_hash_size: Int32; a_rounds: THashRounds);
 begin
   Inherited Create(a_hash_size, 64);
@@ -650,11 +679,17 @@ begin
 
 end;
 
+function TTiger.GetName: String;
+begin
+  Result := Format('%s_%u_%u', [Self.ClassParent.ClassName, Fm_rounds,
+    Self.HashSize * 8]);
+end;
+
 function TTiger.GetResult: THashLibByteArray;
 begin
-  System.SetLength(result, HashSize);
-  TConverters.le64_copy(PUInt64(Fm_hash), 0, PByte(result), 0,
-    System.Length(result));
+  System.SetLength(Result, HashSize);
+  TConverters.le64_copy(PUInt64(Fm_hash), 0, PByte(Result), 0,
+    System.Length(Result));
 end;
 
 procedure TTiger.Initialize;
@@ -973,12 +1008,24 @@ begin
   Fm_hash[1] := b - Fm_hash[1];
   Fm_hash[2] := Fm_hash[2] + c;
 
-  System.FillChar(data, System.SizeOf(data), 0);
+  System.FillChar(data, System.SizeOf(data), UInt64(0));
 
 end;
 
 { TTiger_128 }
 
+function TTiger_128.Clone(): IHash;
+var
+  HashInstance: TTiger_128;
+begin
+  HashInstance := TTiger_128.Create(HashSize, GetHashRound(Fm_rounds));
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  Result := HashInstance as IHash;
+  Result.BufferSize := BufferSize;
+end;
+
 constructor TTiger_128.CreateRound3;
 begin
   Inherited Create(16, THashRounds.hrRounds3);
@@ -996,6 +1043,18 @@ end;
 
 { TTiger_160 }
 
+function TTiger_160.Clone(): IHash;
+var
+  HashInstance: TTiger_160;
+begin
+  HashInstance := TTiger_160.Create(HashSize, GetHashRound(Fm_rounds));
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  Result := HashInstance as IHash;
+  Result.BufferSize := BufferSize;
+end;
+
 constructor TTiger_160.CreateRound3;
 begin
   Inherited Create(20, THashRounds.hrRounds3);
@@ -1013,6 +1072,18 @@ end;
 
 { TTiger_192 }
 
+function TTiger_192.Clone(): IHash;
+var
+  HashInstance: TTiger_192;
+begin
+  HashInstance := TTiger_192.Create(HashSize, GetHashRound(Fm_rounds));
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  Result := HashInstance as IHash;
+  Result.BufferSize := BufferSize;
+end;
+
 constructor TTiger_192.CreateRound3;
 begin
   Inherited Create(24, THashRounds.hrRounds3);
@@ -1030,6 +1101,18 @@ end;
 
 { TTiger_Base }
 
+function TTiger_Base.Clone(): IHash;
+var
+  HashInstance: TTiger_Base;
+begin
+  HashInstance := TTiger_Base.Create(HashSize, GetHashRound(Fm_rounds));
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  Result := HashInstance as IHash;
+  Result.BufferSize := BufferSize;
+end;
+
 constructor TTiger_Base.Create(a_hash_size: Int32; a_rounds: THashRounds);
 begin
   Inherited Create(a_hash_size, a_rounds);

+ 94 - 11
src/libraries/hashlib4pascal/HlpTiger2.pas

@@ -5,32 +5,34 @@ unit HlpTiger2;
 interface
 
 uses
-{$IFDEF DELPHI2010}
-  SysUtils, // to get rid of compiler hint "not inlined" on Delphi 2010.
-{$ENDIF DELPHI2010}
-  HlpHashLibTypes,
+{$IFDEF HAS_UNITSCOPE}
+  System.SysUtils,
+{$ELSE}
+  SysUtils,
+{$ENDIF HAS_UNITSCOPE}
 {$IFDEF DELPHI}
   HlpBitConverter,
   HlpHashBuffer,
+  HlpHash,
 {$ENDIF DELPHI}
+  HlpHashLibTypes,
   HlpConverters,
   HlpHashRounds,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashCryptoNotBuildIn;
 
 resourcestring
   SInvalidTiger2HashSize =
     'Tiger2 HashSize Must be Either 128 bit(16 byte), 160 bit(20 byte) or 192 bit(24 byte)';
+  SInvalidHashRound = 'Specified HashRound Is Invalid or UnSupported "%d"';
 
 type
   TTiger2 = class abstract(TBlockHash, ICryptoNotBuildIn, ITransformBlock)
 
   strict private
 
-    Fm_rounds: Int32;
-
 {$REGION 'Consts'}
-
   const
 
     C1 = UInt64($A5A5A5A5A5A5A5A5);
@@ -558,15 +560,19 @@ type
 
 {$ENDREGION}
   strict protected
+    Fm_rounds: Int32;
     Fm_hash: THashLibUInt64Array;
 
     constructor Create(a_hash_size: Int32; a_rounds: THashRounds);
 
+    function GetName: String; override;
     function GetResult(): THashLibByteArray; override;
     procedure Finish(); override;
     procedure TransformBlock(a_data: PByte; a_data_length: Int32;
       a_index: Int32); override;
 
+    function GetHashRound(AHashRound: Int32): THashRounds; inline;
+
   public
     procedure Initialize(); override;
 
@@ -578,6 +584,7 @@ type
 
   public
     constructor Create(a_hash_size: Int32; a_rounds: THashRounds);
+    function Clone(): IHash; override;
 
   end;
 
@@ -589,6 +596,7 @@ type
     constructor CreateRound3();
     constructor CreateRound4();
     constructor CreateRound5();
+    function Clone(): IHash; override;
 
   end;
 
@@ -600,6 +608,7 @@ type
     constructor CreateRound3();
     constructor CreateRound4();
     constructor CreateRound5();
+    function Clone(): IHash; override;
 
   end;
 
@@ -610,6 +619,7 @@ type
     constructor CreateRound3();
     constructor CreateRound4();
     constructor CreateRound5();
+    function Clone(): IHash; override;
 
   end;
 
@@ -617,6 +627,25 @@ implementation
 
 { TTiger2 }
 
+function TTiger2.GetHashRound(AHashRound: Int32): THashRounds;
+begin
+  case AHashRound of
+    3:
+      Result := THashRounds.hrRounds3;
+    4:
+      Result := THashRounds.hrRounds4;
+    5:
+      Result := THashRounds.hrRounds5;
+    8:
+      Result := THashRounds.hrRounds8
+  else
+    begin
+      raise EArgumentInvalidHashLibException.CreateResFmt(@SInvalidHashRound,
+        [AHashRound]);
+    end;
+  end;
+end;
+
 constructor TTiger2.Create(a_hash_size: Int32; a_rounds: THashRounds);
 begin
   Inherited Create(a_hash_size, 64);
@@ -650,11 +679,17 @@ begin
 
 end;
 
+function TTiger2.GetName: String;
+begin
+  Result := Format('%s_%u_%u', [Self.ClassParent.ClassName, Fm_rounds,
+    Self.HashSize * 8]);
+end;
+
 function TTiger2.GetResult: THashLibByteArray;
 begin
-  System.SetLength(result, HashSize);
-  TConverters.le64_copy(PUInt64(Fm_hash), 0, PByte(result), 0,
-    System.Length(result));
+  System.SetLength(Result, HashSize);
+  TConverters.le64_copy(PUInt64(Fm_hash), 0, PByte(Result), 0,
+    System.Length(Result));
 end;
 
 procedure TTiger2.Initialize;
@@ -973,12 +1008,24 @@ begin
   Fm_hash[1] := b - Fm_hash[1];
   Fm_hash[2] := Fm_hash[2] + c;
 
-  System.FillChar(data, System.SizeOf(data), 0);
+  System.FillChar(data, System.SizeOf(data), UInt64(0));
 
 end;
 
 { TTiger2_128 }
 
+function TTiger2_128.Clone(): IHash;
+var
+  HashInstance: TTiger2_128;
+begin
+  HashInstance := TTiger2_128.Create(HashSize, GetHashRound(Fm_rounds));
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  Result := HashInstance as IHash;
+  Result.BufferSize := BufferSize;
+end;
+
 constructor TTiger2_128.CreateRound3;
 begin
   Inherited Create(16, THashRounds.hrRounds3);
@@ -996,6 +1043,18 @@ end;
 
 { TTiger2_160 }
 
+function TTiger2_160.Clone(): IHash;
+var
+  HashInstance: TTiger2_160;
+begin
+  HashInstance := TTiger2_160.Create(HashSize, GetHashRound(Fm_rounds));
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  Result := HashInstance as IHash;
+  Result.BufferSize := BufferSize;
+end;
+
 constructor TTiger2_160.CreateRound3;
 begin
   Inherited Create(20, THashRounds.hrRounds3);
@@ -1013,6 +1072,18 @@ end;
 
 { TTiger2_192 }
 
+function TTiger2_192.Clone(): IHash;
+var
+  HashInstance: TTiger2_192;
+begin
+  HashInstance := TTiger2_192.Create(HashSize, GetHashRound(Fm_rounds));
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  Result := HashInstance as IHash;
+  Result.BufferSize := BufferSize;
+end;
+
 constructor TTiger2_192.CreateRound3;
 begin
   Inherited Create(24, THashRounds.hrRounds3);
@@ -1030,6 +1101,18 @@ end;
 
 { TTiger2_Base }
 
+function TTiger2_Base.Clone(): IHash;
+var
+  HashInstance: TTiger2_Base;
+begin
+  HashInstance := TTiger2_Base.Create(HashSize, GetHashRound(Fm_rounds));
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  Result := HashInstance as IHash;
+  Result.BufferSize := BufferSize;
+end;
+
 constructor TTiger2_Base.Create(a_hash_size: Int32; a_rounds: THashRounds);
 begin
   Inherited Create(a_hash_size, a_rounds);

+ 31 - 16
src/libraries/hashlib4pascal/HlpWhirlPool.pas

@@ -12,8 +12,10 @@ uses
 {$IFDEF DELPHI}
   HlpBitConverter,
   HlpHashBuffer,
+  HlpHash,
 {$ENDIF DELPHI}
   HlpConverters,
+  HlpIHash,
   HlpIHashInfo,
   HlpHashCryptoNotBuildIn;
 
@@ -58,9 +60,9 @@ type
 {$ENDREGION}
     class constructor WhirlPool;
 
-    class function packIntoUInt64(b7, b6, b5, b4, b3, b2, b1, b0: UInt32)
+    class function PackIntoUInt64(b7, b6, b5, b4, b3, b2, b1, b0: UInt32)
       : UInt64; static; inline;
-    class function maskWithReductionPolynomial(input: UInt32): UInt32;
+    class function MaskWithReductionPolynomial(input: UInt32): UInt32;
       static; inline;
 
   strict protected
@@ -72,6 +74,7 @@ type
   public
     constructor Create();
     procedure Initialize(); override;
+    function Clone(): IHash; override;
 
   end;
 
@@ -79,6 +82,18 @@ implementation
 
 { TWhirlPool }
 
+function TWhirlPool.Clone(): IHash;
+var
+  HashInstance: TWhirlPool;
+begin
+  HashInstance := TWhirlPool.Create();
+  HashInstance.Fm_hash := System.Copy(Fm_hash);
+  HashInstance.Fm_buffer := Fm_buffer.Clone();
+  HashInstance.Fm_processed_bytes := Fm_processed_bytes;
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TWhirlPool.Create;
 begin
   Inherited Create(64, 64);
@@ -129,14 +144,14 @@ begin
   Inherited Initialize();
 end;
 
-class function TWhirlPool.maskWithReductionPolynomial(input: UInt32): UInt32;
+class function TWhirlPool.MaskWithReductionPolynomial(input: UInt32): UInt32;
 begin
   if (input >= $100) then
     input := input xor REDUCTION_POLYNOMIAL;
   result := input;
 end;
 
-class function TWhirlPool.packIntoUInt64(b7, b6, b5, b4, b3, b2, b1,
+class function TWhirlPool.PackIntoUInt64(b7, b6, b5, b4, b3, b2, b1,
   b0: UInt32): UInt64;
 begin
   result := (UInt64(b7) shl 56) xor (UInt64(b6) shl 48) xor (UInt64(b5) shl 40)
@@ -223,7 +238,7 @@ begin
     System.Inc(i);
   end;
 
-  System.FillChar(data, System.SizeOf(data), 0);
+  System.FillChar(data, System.SizeOf(data), UInt64(0));
 
 end;
 
@@ -249,20 +264,20 @@ begin
 
   begin
     v1 := s_SBOX[i];
-    v2 := maskWithReductionPolynomial(v1 shl 1);
-    v4 := maskWithReductionPolynomial(v2 shl 1);
+    v2 := MaskWithReductionPolynomial(v1 shl 1);
+    v4 := MaskWithReductionPolynomial(v2 shl 1);
     v5 := v4 xor v1;
-    v8 := maskWithReductionPolynomial(v4 shl 1);
+    v8 := MaskWithReductionPolynomial(v4 shl 1);
     v9 := v8 xor v1;
 
-    Fs_C0[i] := packIntoUInt64(v1, v1, v4, v1, v8, v5, v2, v9);
-    Fs_C1[i] := packIntoUInt64(v9, v1, v1, v4, v1, v8, v5, v2);
-    Fs_C2[i] := packIntoUInt64(v2, v9, v1, v1, v4, v1, v8, v5);
-    Fs_C3[i] := packIntoUInt64(v5, v2, v9, v1, v1, v4, v1, v8);
-    Fs_C4[i] := packIntoUInt64(v8, v5, v2, v9, v1, v1, v4, v1);
-    Fs_C5[i] := packIntoUInt64(v1, v8, v5, v2, v9, v1, v1, v4);
-    Fs_C6[i] := packIntoUInt64(v4, v1, v8, v5, v2, v9, v1, v1);
-    Fs_C7[i] := packIntoUInt64(v1, v4, v1, v8, v5, v2, v9, v1);
+    Fs_C0[i] := PackIntoUInt64(v1, v1, v4, v1, v8, v5, v2, v9);
+    Fs_C1[i] := PackIntoUInt64(v9, v1, v1, v4, v1, v8, v5, v2);
+    Fs_C2[i] := PackIntoUInt64(v2, v9, v1, v1, v4, v1, v8, v5);
+    Fs_C3[i] := PackIntoUInt64(v5, v2, v9, v1, v1, v4, v1, v8);
+    Fs_C4[i] := PackIntoUInt64(v8, v5, v2, v9, v1, v1, v4, v1);
+    Fs_C5[i] := PackIntoUInt64(v1, v8, v5, v2, v9, v1, v1, v4);
+    Fs_C6[i] := PackIntoUInt64(v4, v1, v8, v5, v2, v9, v1, v1);
+    Fs_C7[i] := PackIntoUInt64(v1, v4, v1, v8, v5, v2, v9, v1);
 
     System.Inc(i);
   end;

+ 30 - 3
src/libraries/hashlib4pascal/HlpXXHash32.pas

@@ -7,9 +7,7 @@ interface
 uses
   HlpHashLibTypes,
   HlpHash,
-{$IFDEF DELPHI}
-  HlpBitConverter,
-{$ENDIF DELPHI}
+  HlpIHash,
   HlpConverters,
   HlpIHashInfo,
   HlpHashResult,
@@ -52,6 +50,8 @@ type
       Fmemsize, Fv1, Fv2, Fv3, Fv4: UInt32;
       Fmemory: THashLibByteArray;
 
+      function Clone(): TXXH_State; inline;
+
     end;
 
   strict private
@@ -63,6 +63,7 @@ type
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_length: Int32); override;
     function TransformFinal(): IHashResult; override;
+    function Clone(): IHash; override;
     property KeyLength: TNullableInteger read GetKeyLength;
     property Key: THashLibByteArray read GetKey write SetKey;
 
@@ -70,8 +71,34 @@ type
 
 implementation
 
+{ TXXHash32.TXXH_State }
+
+function TXXHash32.TXXH_State.Clone(): TXXH_State;
+begin
+  result := Default (TXXH_State);
+  result.Ftotal_len := Ftotal_len;
+  result.Fmemsize := Fmemsize;
+  result.Fv1 := Fv1;
+  result.Fv2 := Fv2;
+  result.Fv3 := Fv3;
+  result.Fv4 := Fv4;
+  result.Fmemory := System.Copy(Fmemory);
+end;
+
 { TXXHash32 }
 
+function TXXHash32.Clone(): IHash;
+var
+  HashInstance: TXXHash32;
+begin
+  HashInstance := TXXHash32.Create();
+  HashInstance.Fm_key := Fm_key;
+  HashInstance.Fm_hash := Fm_hash;
+  HashInstance.F_state := F_state.Clone();
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TXXHash32.Create;
 begin
   Inherited Create(4, 16);

+ 30 - 3
src/libraries/hashlib4pascal/HlpXXHash64.pas

@@ -8,9 +8,7 @@ uses
   HlpHashLibTypes,
   HlpHash,
   HlpConverters,
-{$IFDEF DELPHI}
-  HlpBitConverter,
-{$ENDIF DELPHI}
+  HlpIHash,
   HlpIHashInfo,
   HlpHashResult,
   HlpIHashResult,
@@ -60,6 +58,8 @@ type
       Fmemsize: UInt32;
       Fmemory: THashLibByteArray;
 
+      function Clone(): TXXH_State; inline;
+
     end;
 
   strict private
@@ -71,6 +71,7 @@ type
     procedure TransformBytes(const a_data: THashLibByteArray;
       a_index, a_length: Int32); override;
     function TransformFinal(): IHashResult; override;
+    function Clone(): IHash; override;
     property KeyLength: TNullableInteger read GetKeyLength;
     property Key: THashLibByteArray read GetKey write SetKey;
 
@@ -78,8 +79,34 @@ type
 
 implementation
 
+{ TXXHash64.TXXH_State }
+
+function TXXHash64.TXXH_State.Clone(): TXXH_State;
+begin
+  result := Default (TXXH_State);
+  result.Ftotal_len := Ftotal_len;
+  result.Fmemsize := Fmemsize;
+  result.Fv1 := Fv1;
+  result.Fv2 := Fv2;
+  result.Fv3 := Fv3;
+  result.Fv4 := Fv4;
+  result.Fmemory := System.Copy(Fmemory);
+end;
+
 { TXXHash64 }
 
+function TXXHash64.Clone(): IHash;
+var
+  HashInstance: TXXHash64;
+begin
+  HashInstance := TXXHash64.Create();
+  HashInstance.Fm_key := Fm_key;
+  HashInstance.Fm_hash := Fm_hash;
+  HashInstance.F_state := F_state.Clone();
+  result := HashInstance as IHash;
+  result.BufferSize := BufferSize;
+end;
+
 constructor TXXHash64.Create;
 begin
   Inherited Create(8, 32);