Browse Source

major refactoring and abstractions.

- added more unit tests.
- minor cleanup.
Ugochukwu Mmaduekwe 7 years ago
parent
commit
50be1c2628
39 changed files with 3183 additions and 286 deletions
  1. 11 3
      CryptoLib.Samples/Delphi.Samples/UsageSamples.dpr
  2. 4 4
      CryptoLib.Samples/src/UsageExamples.pas
  3. 15 3
      CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.dpr
  4. 13 3
      CryptoLib.Tests/FreePascal.Tests/CryptoLib.Tests.lpi
  5. 3 0
      CryptoLib.Tests/FreePascal.Tests/CryptoLib.lpr
  6. 21 6
      CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.Tests.lpi
  7. 3 0
      CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.lpr
  8. 30 27
      CryptoLib.Tests/src/Crypto/AESSICTests.pas
  9. 264 13
      CryptoLib.Tests/src/Crypto/AESTestVectors.pas
  10. 209 20
      CryptoLib.Tests/src/Crypto/AESTests.pas
  11. 304 0
      CryptoLib.Tests/src/Crypto/HMacTests.pas
  12. 4 4
      CryptoLib.Tests/src/Crypto/IESCipherTests.pas
  13. 165 0
      CryptoLib.Tests/src/Crypto/MD5HMacTests.pas
  14. 425 0
      CryptoLib.Tests/src/Crypto/Pkcs5Tests.pas
  15. 15 7
      CryptoLib/src/Asn1/ClpBerOctetString.pas
  16. 9 19
      CryptoLib/src/Asn1/ClpBerTaggedObject.pas
  17. 113 0
      CryptoLib/src/Asn1/Iana/ClpIanaObjectIdentifiers.pas
  18. 143 0
      CryptoLib/src/Asn1/Misc/ClpMiscObjectIdentifiers.pas
  19. 61 9
      CryptoLib/src/Asn1/Nist/ClpNistObjectIdentifiers.pas
  20. 54 7
      CryptoLib/src/Asn1/Pkcs/ClpPkcsObjectIdentifiers.pas
  21. 32 34
      CryptoLib/src/Crypto/Engines/ClpIESEngine.pas
  22. 15 16
      CryptoLib/src/Crypto/Engines/ClpPascalCoinIESEngine.pas
  23. 174 0
      CryptoLib/src/Crypto/Generators/ClpPbeParametersGenerator.pas
  24. 197 0
      CryptoLib/src/Crypto/Generators/ClpPkcs5S2ParametersGenerator.pas
  25. 143 0
      CryptoLib/src/Crypto/Macs/ClpHMac.pas
  26. 3 2
      CryptoLib/src/Interfaces/ClpIBerOctetString.pas
  27. 4 4
      CryptoLib/src/Interfaces/ClpIHMac.pas
  28. 3 3
      CryptoLib/src/Interfaces/ClpIIESEngine.pas
  29. 131 0
      CryptoLib/src/Interfaces/ClpIMac.pas
  30. 116 0
      CryptoLib/src/Interfaces/ClpIPbeParametersGenerator.pas
  31. 12 4
      CryptoLib/src/Interfaces/ClpIPkcs5S2ParametersGenerator.pas
  32. 1 3
      CryptoLib/src/Math/ClpBigInteger.pas
  33. 1 1
      CryptoLib/src/Math/EC/Multiplier/ClpWNafL2RMultiplier.pas
  34. 17 15
      CryptoLib/src/Math/EC/Multiplier/ClpWTauNafMultiplier.pas
  35. 72 39
      CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.lpk
  36. 8 6
      CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.pas
  37. 113 31
      CryptoLib/src/Security/ClpDigestUtilities.pas
  38. 74 3
      CryptoLib/src/Security/ClpGeneratorUtilities.pas
  39. 201 0
      CryptoLib/src/Security/ClpMacUtilities.pas

+ 11 - 3
CryptoLib.Samples/Delphi.Samples/UsageSamples.dpr

@@ -359,11 +359,19 @@ uses
   ClpSicBlockCipher in '..\..\CryptoLib\src\Crypto\Modes\ClpSicBlockCipher.pas',
   ClpSicBlockCipher in '..\..\CryptoLib\src\Crypto\Modes\ClpSicBlockCipher.pas',
   ClpISicBlockCipher in '..\..\CryptoLib\src\Interfaces\ClpISicBlockCipher.pas',
   ClpISicBlockCipher in '..\..\CryptoLib\src\Interfaces\ClpISicBlockCipher.pas',
   ClpIDigest in '..\..\CryptoLib\src\Interfaces\ClpIDigest.pas',
   ClpIDigest in '..\..\CryptoLib\src\Interfaces\ClpIDigest.pas',
-  ClpIDigestMAC in '..\..\CryptoLib\src\Interfaces\ClpIDigestMAC.pas',
-  ClpIPBKDF2_DigestMAC in '..\..\CryptoLib\src\Interfaces\ClpIPBKDF2_DigestMAC.pas',
+  ClpIMac in '..\..\CryptoLib\src\Interfaces\ClpIMac.pas',
   ClpStringUtils in '..\..\CryptoLib\src\Utils\ClpStringUtils.pas',
   ClpStringUtils in '..\..\CryptoLib\src\Utils\ClpStringUtils.pas',
   ClpCipherKeyGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpCipherKeyGenerator.pas',
   ClpCipherKeyGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpCipherKeyGenerator.pas',
-  ClpICipherKeyGenerator in '..\..\CryptoLib\src\Interfaces\ClpICipherKeyGenerator.pas';
+  ClpICipherKeyGenerator in '..\..\CryptoLib\src\Interfaces\ClpICipherKeyGenerator.pas',
+  ClpHMac in '..\..\CryptoLib\src\Crypto\Macs\ClpHMac.pas',
+  ClpIHMac in '..\..\CryptoLib\src\Interfaces\ClpIHMac.pas',
+  ClpMacUtilities in '..\..\CryptoLib\src\Security\ClpMacUtilities.pas',
+  ClpIanaObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Iana\ClpIanaObjectIdentifiers.pas',
+  ClpMiscObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Misc\ClpMiscObjectIdentifiers.pas',
+  ClpPbeParametersGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpPbeParametersGenerator.pas',
+  ClpIPbeParametersGenerator in '..\..\CryptoLib\src\Interfaces\ClpIPbeParametersGenerator.pas',
+  ClpPkcs5S2ParametersGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpPkcs5S2ParametersGenerator.pas',
+  ClpIPkcs5S2ParametersGenerator in '..\..\CryptoLib\src\Interfaces\ClpIPkcs5S2ParametersGenerator.pas';
 
 
 begin
 begin
   try
   try

+ 4 - 4
CryptoLib.Samples/src/UsageExamples.pas

@@ -28,8 +28,9 @@ interface
 uses
 uses
   SysUtils,
   SysUtils,
   ClpIDigest,
   ClpIDigest,
-  ClpIDigestMAC,
+  ClpIMac,
   ClpDigestUtilities,
   ClpDigestUtilities,
+  ClpMacUtilities,
   ClpBigInteger,
   ClpBigInteger,
   ClpSecureRandom,
   ClpSecureRandom,
   ClpISecureRandom,
   ClpISecureRandom,
@@ -591,7 +592,7 @@ var
   blockCipher: ICbcBlockCipher;
   blockCipher: ICbcBlockCipher;
   ECDHBasicAgreementInstance: IECDHBasicAgreement;
   ECDHBasicAgreementInstance: IECDHBasicAgreement;
   KDFInstance: IPascalCoinECIESKdfBytesGenerator;
   KDFInstance: IPascalCoinECIESKdfBytesGenerator;
-  DigestMACInstance: IDigestMAC;
+  DigestMACInstance: IMac;
 
 
 begin
 begin
   // Set up IES Cipher Engine For Compatibility With PascalCoin
   // Set up IES Cipher Engine For Compatibility With PascalCoin
@@ -601,8 +602,7 @@ begin
   KDFInstance := TPascalCoinECIESKdfBytesGenerator.Create
   KDFInstance := TPascalCoinECIESKdfBytesGenerator.Create
     (TDigestUtilities.GetDigest('SHA-512'));
     (TDigestUtilities.GetDigest('SHA-512'));
 
 
-  DigestMACInstance := TDigestUtilities.GetDigestMAC
-    (TDigestUtilities.GetDigest('MD5'));
+  DigestMACInstance := TMacUtilities.GetMac('HMAC-MD5');
 
 
   // Set Up Block Cipher
   // Set Up Block Cipher
   AesEngine := TAesEngine.Create(); // AES Engine
   AesEngine := TAesEngine.Create(); // AES Engine

+ 15 - 3
CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.dpr

@@ -393,12 +393,23 @@ uses
   ClpSicBlockCipher in '..\..\CryptoLib\src\Crypto\Modes\ClpSicBlockCipher.pas',
   ClpSicBlockCipher in '..\..\CryptoLib\src\Crypto\Modes\ClpSicBlockCipher.pas',
   ClpISicBlockCipher in '..\..\CryptoLib\src\Interfaces\ClpISicBlockCipher.pas',
   ClpISicBlockCipher in '..\..\CryptoLib\src\Interfaces\ClpISicBlockCipher.pas',
   ClpIDigest in '..\..\CryptoLib\src\Interfaces\ClpIDigest.pas',
   ClpIDigest in '..\..\CryptoLib\src\Interfaces\ClpIDigest.pas',
-  ClpIDigestMAC in '..\..\CryptoLib\src\Interfaces\ClpIDigestMAC.pas',
-  ClpIPBKDF2_DigestMAC in '..\..\CryptoLib\src\Interfaces\ClpIPBKDF2_DigestMAC.pas',
+  ClpIMac in '..\..\CryptoLib\src\Interfaces\ClpIMac.pas',
   ClpStringUtils in '..\..\CryptoLib\src\Utils\ClpStringUtils.pas',
   ClpStringUtils in '..\..\CryptoLib\src\Utils\ClpStringUtils.pas',
   ClpCipherKeyGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpCipherKeyGenerator.pas',
   ClpCipherKeyGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpCipherKeyGenerator.pas',
   ClpICipherKeyGenerator in '..\..\CryptoLib\src\Interfaces\ClpICipherKeyGenerator.pas',
   ClpICipherKeyGenerator in '..\..\CryptoLib\src\Interfaces\ClpICipherKeyGenerator.pas',
-  AESSICTests in '..\src\Crypto\AESSICTests.pas';
+  AESSICTests in '..\src\Crypto\AESSICTests.pas',
+  ClpHMac in '..\..\CryptoLib\src\Crypto\Macs\ClpHMac.pas',
+  ClpIHMac in '..\..\CryptoLib\src\Interfaces\ClpIHMac.pas',
+  ClpMacUtilities in '..\..\CryptoLib\src\Security\ClpMacUtilities.pas',
+  ClpIanaObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Iana\ClpIanaObjectIdentifiers.pas',
+  ClpMiscObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Misc\ClpMiscObjectIdentifiers.pas',
+  MD5HMacTests in '..\src\Crypto\MD5HMacTests.pas',
+  HMacTests in '..\src\Crypto\HMacTests.pas',
+  ClpPbeParametersGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpPbeParametersGenerator.pas',
+  ClpIPbeParametersGenerator in '..\..\CryptoLib\src\Interfaces\ClpIPbeParametersGenerator.pas',
+  ClpPkcs5S2ParametersGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpPkcs5S2ParametersGenerator.pas',
+  ClpIPkcs5S2ParametersGenerator in '..\..\CryptoLib\src\Interfaces\ClpIPkcs5S2ParametersGenerator.pas',
+  Pkcs5Tests in '..\src\Crypto\Pkcs5Tests.pas';
 
 
 begin
 begin
 
 
@@ -408,4 +419,5 @@ begin
   else
   else
     GUITestRunner.RunRegisteredTests;
     GUITestRunner.RunRegisteredTests;
 
 
+
 end.
 end.

+ 13 - 3
CryptoLib.Tests/FreePascal.Tests/CryptoLib.Tests.lpi

@@ -35,7 +35,7 @@
         <PackageName Value="FCL"/>
         <PackageName Value="FCL"/>
       </Item4>
       </Item4>
     </RequiredPackages>
     </RequiredPackages>
-    <Units Count="24">
+    <Units Count="27">
       <Unit0>
       <Unit0>
         <Filename Value="CryptoLib.lpr"/>
         <Filename Value="CryptoLib.lpr"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
@@ -133,6 +133,18 @@
         <Filename Value="..\src\Crypto\AESSICTests.pas"/>
         <Filename Value="..\src\Crypto\AESSICTests.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit23>
       </Unit23>
+      <Unit24>
+        <Filename Value="..\src\Crypto\HMacTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit24>
+      <Unit25>
+        <Filename Value="..\src\Crypto\MD5HMacTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit25>
+      <Unit26>
+        <Filename Value="..\src\Crypto\Pkcs5Tests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit26>
     </Units>
     </Units>
   </ProjectOptions>
   </ProjectOptions>
   <CompilerOptions>
   <CompilerOptions>
@@ -147,8 +159,6 @@
       <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
       <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
     </SearchPaths>
     </SearchPaths>
     <CodeGeneration>
     <CodeGeneration>
-      <TargetCPU Value="i386"/>
-      <TargetOS Value="win32"/>
       <Optimizations>
       <Optimizations>
         <OptimizationLevel Value="4"/>
         <OptimizationLevel Value="4"/>
       </Optimizations>
       </Optimizations>

+ 3 - 0
CryptoLib.Tests/FreePascal.Tests/CryptoLib.lpr

@@ -27,6 +27,9 @@ uses
   AESTestVectors,
   AESTestVectors,
   IESCipherTests,
   IESCipherTests,
   AESSICTests,
   AESSICTests,
+  MD5HMacTests,
+  HMacTests,
+  Pkcs5Tests,
   ClpFixedSecureRandom,
   ClpFixedSecureRandom,
   ClpIFixedSecureRandom;
   ClpIFixedSecureRandom;
 
 

+ 21 - 6
CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.Tests.lpi

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
 <CONFIG>
 <CONFIG>
   <ProjectOptions>
   <ProjectOptions>
-    <Version Value="11"/>
+    <Version Value="10"/>
     <PathDelim Value="\"/>
     <PathDelim Value="\"/>
     <General>
     <General>
       <SessionStorage Value="InProjectDir"/>
       <SessionStorage Value="InProjectDir"/>
@@ -17,10 +17,9 @@
       <Version Value="2"/>
       <Version Value="2"/>
     </PublishOptions>
     </PublishOptions>
     <RunParams>
     <RunParams>
-      <FormatVersion Value="2"/>
-      <Modes Count="1">
-        <Mode0 Name="default"/>
-      </Modes>
+      <local>
+        <FormatVersion Value="1"/>
+      </local>
     </RunParams>
     </RunParams>
     <RequiredPackages Count="2">
     <RequiredPackages Count="2">
       <Item1>
       <Item1>
@@ -30,7 +29,7 @@
         <PackageName Value="FCL"/>
         <PackageName Value="FCL"/>
       </Item2>
       </Item2>
     </RequiredPackages>
     </RequiredPackages>
-    <Units Count="23">
+    <Units Count="27">
       <Unit0>
       <Unit0>
         <Filename Value="CryptoLibConsole.lpr"/>
         <Filename Value="CryptoLibConsole.lpr"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
@@ -123,6 +122,22 @@
         <Filename Value="..\src\Crypto\IESCipherTests.pas"/>
         <Filename Value="..\src\Crypto\IESCipherTests.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit22>
       </Unit22>
+      <Unit23>
+        <Filename Value="..\src\Crypto\AESSICTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit23>
+      <Unit24>
+        <Filename Value="..\src\Crypto\HMacTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit24>
+      <Unit25>
+        <Filename Value="..\src\Crypto\MD5HMacTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit25>
+      <Unit26>
+        <Filename Value="..\src\Crypto\Pkcs5Tests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit26>
     </Units>
     </Units>
   </ProjectOptions>
   </ProjectOptions>
   <CompilerOptions>
   <CompilerOptions>

+ 3 - 0
CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.lpr

@@ -25,6 +25,9 @@ uses
   AESTestVectors,
   AESTestVectors,
   IESCipherTests,
   IESCipherTests,
   AESSICTests,
   AESSICTests,
+  MD5HMacTests,
+  HMacTests,
+  Pkcs5Tests,
   ClpFixedSecureRandom,
   ClpFixedSecureRandom,
   ClpIFixedSecureRandom;
   ClpIFixedSecureRandom;
 
 

+ 30 - 27
CryptoLib.Tests/src/Crypto/AESSICTests.pas

@@ -61,6 +61,10 @@ type
   TTestAESSIC = class(TCryptoLibTestCase)
   TTestAESSIC = class(TCryptoLibTestCase)
   private
   private
 
 
+  var
+    Fkeys, Fplain: TCryptoLibMatrixByteArray;
+    Fcipher: TCryptoLibGenericArray<TCryptoLibMatrixByteArray>;
+
   protected
   protected
     procedure SetUp; override;
     procedure SetUp; override;
     procedure TearDown; override;
     procedure TearDown; override;
@@ -77,36 +81,20 @@ implementation
 procedure TTestAESSIC.SetUp;
 procedure TTestAESSIC.SetUp;
 begin
 begin
   inherited;
   inherited;
-end;
-
-procedure TTestAESSIC.TearDown;
-begin
-  inherited;
-
-end;
 
 
-procedure TTestAESSIC.TestAESSIC;
-var
-  keys, plain: TCryptoLibMatrixByteArray;
-  cipher: TCryptoLibGenericArray<TCryptoLibMatrixByteArray>;
-  c: IBufferedCipher;
-  i, j: Int32;
-  skey, sk: IKeyParameter;
-  enc, crypt: TBytes;
-begin
-  keys := TCryptoLibMatrixByteArray.Create
+  Fkeys := TCryptoLibMatrixByteArray.Create
     (THex.Decode('2b7e151628aed2a6abf7158809cf4f3c'),
     (THex.Decode('2b7e151628aed2a6abf7158809cf4f3c'),
     THex.Decode('8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b'),
     THex.Decode('8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b'),
     THex.Decode
     THex.Decode
     ('603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4'));
     ('603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4'));
 
 
-  plain := TCryptoLibMatrixByteArray.Create
+  Fplain := TCryptoLibMatrixByteArray.Create
     (THex.Decode('6bc1bee22e409f96e93d7e117393172a'),
     (THex.Decode('6bc1bee22e409f96e93d7e117393172a'),
     THex.Decode('ae2d8a571e03ac9c9eb76fac45af8e51'),
     THex.Decode('ae2d8a571e03ac9c9eb76fac45af8e51'),
     THex.Decode('30c81c46a35ce411e5fbc1191a0a52ef'),
     THex.Decode('30c81c46a35ce411e5fbc1191a0a52ef'),
     THex.Decode('f69f2445df4f9b17ad2b417be66c3710'));
     THex.Decode('f69f2445df4f9b17ad2b417be66c3710'));
 
 
-  cipher := TCryptoLibGenericArray<TCryptoLibMatrixByteArray>.Create
+  Fcipher := TCryptoLibGenericArray<TCryptoLibMatrixByteArray>.Create
     (TCryptoLibMatrixByteArray.Create
     (TCryptoLibMatrixByteArray.Create
     (THex.Decode('874d6191b620e3261bef6864990db6ce'),
     (THex.Decode('874d6191b620e3261bef6864990db6ce'),
     THex.Decode('9806f66b7970fdff8617187bb9fffdff'),
     THex.Decode('9806f66b7970fdff8617187bb9fffdff'),
@@ -122,6 +110,21 @@ begin
     THex.Decode('f443e3ca4d62b59aca84e990cacaf5c5'),
     THex.Decode('f443e3ca4d62b59aca84e990cacaf5c5'),
     THex.Decode('2b0930daa23de94ce87017ba2d84988d'),
     THex.Decode('2b0930daa23de94ce87017ba2d84988d'),
     THex.Decode('dfc9c58db67aada613c2dd08457941a6')));
     THex.Decode('dfc9c58db67aada613c2dd08457941a6')));
+end;
+
+procedure TTestAESSIC.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestAESSIC.TestAESSIC;
+var
+  c: IBufferedCipher;
+  i, j: Int32;
+  skey, sk: IKeyParameter;
+  enc, crypt: TBytes;
+begin
 
 
   c := TCipherUtilities.GetCipher('AES/SIC/NoPadding');
   c := TCipherUtilities.GetCipher('AES/SIC/NoPadding');
 
 
@@ -130,17 +133,17 @@ begin
   //
   //
 
 
   i := 0;
   i := 0;
-  while i <> System.Length(keys) do
+  while i <> System.Length(Fkeys) do
   begin
   begin
-    skey := TParameterUtilities.CreateKeyParameter('AES', keys[i]);
+    skey := TParameterUtilities.CreateKeyParameter('AES', Fkeys[i]);
     c.Init(true, TParametersWithIV.Create(skey,
     c.Init(true, TParametersWithIV.Create(skey,
       THex.Decode('F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF')) as IParametersWithIV);
       THex.Decode('F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF')) as IParametersWithIV);
 
 
     j := 0;
     j := 0;
-    while j <> System.Length(plain) do
+    while j <> System.Length(Fplain) do
     begin
     begin
-      enc := c.ProcessBytes(plain[j]);
-      if (not TArrayUtils.AreEqual(enc, cipher[i, j])) then
+      enc := c.ProcessBytes(Fplain[j]);
+      if (not TArrayUtils.AreEqual(enc, Fcipher[i, j])) then
       begin
       begin
         Fail('AESSIC encrypt failed: key ' + IntToStr(i) + ' block ' +
         Fail('AESSIC encrypt failed: key ' + IntToStr(i) + ' block ' +
           IntToStr(j));
           IntToStr(j));
@@ -152,10 +155,10 @@ begin
       THex.Decode('F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF')) as IParametersWithIV);
       THex.Decode('F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF')) as IParametersWithIV);
 
 
     j := 0;
     j := 0;
-    while j <> System.Length(plain) do
+    while j <> System.Length(Fplain) do
     begin
     begin
-      enc := c.ProcessBytes(cipher[i, j]);
-      if (not TArrayUtils.AreEqual(enc, plain[j])) then
+      enc := c.ProcessBytes(Fcipher[i, j]);
+      if (not TArrayUtils.AreEqual(enc, Fplain[j])) then
       begin
       begin
         Fail('AESSIC decrypt failed: key ' + IntToStr(i) + ' block ' +
         Fail('AESSIC decrypt failed: key ' + IntToStr(i) + ' block ' +
           IntToStr(j));
           IntToStr(j));

+ 264 - 13
CryptoLib.Tests/src/Crypto/AESTestVectors.pas

@@ -30,9 +30,17 @@ type
     class var
     class var
 
 
       FBlockCipherVectorKeys, FBlockCipherVectorInputs,
       FBlockCipherVectorKeys, FBlockCipherVectorInputs,
-      FBlockCipherVectorOutputs, FOfficialVectorKeys__AES256_CBC,
-      FOfficialVectorIVs_AES256_CBC, FOfficialVectorInputs_AES256_CBC,
-      FOfficialVectorOutputs_AES256_CBC: TCryptoLibStringArray;
+      FBlockCipherVectorOutputs, FOfficialVectorKeys_AES_CBC,
+      FOfficialVectorIVs_AES_CBC, FOfficialVectorInputs_AES_CBC,
+      FOfficialVectorOutputs_AES_CBC, FOfficialVectorKeys_AES_CFB,
+      FOfficialVectorIVs_AES_CFB, FOfficialVectorInputs_AES_CFB,
+      FOfficialVectorOutputs_AES_CFB, FOfficialVectorKeys_AES_CTR,
+      FOfficialVectorIVs_AES_CTR, FOfficialVectorInputs_AES_CTR,
+      FOfficialVectorOutputs_AES_CTR, FOfficialVectorKeys_AES_ECB,
+      FOfficialVectorInputs_AES_ECB, FOfficialVectorOutputs_AES_ECB,
+      FOfficialVectorKeys_AES_OFB, FOfficialVectorIVs_AES_OFB,
+      FOfficialVectorInputs_AES_OFB, FOfficialVectorOutputs_AES_OFB
+      : TCryptoLibStringArray;
 
 
     class constructor AESTestVectors();
     class constructor AESTestVectors();
 
 
@@ -72,19 +80,262 @@ begin
 
 
     'DDC6BF790C15760D8D9AEB6F9A75FD4E');
     'DDC6BF790C15760D8D9AEB6F9A75FD4E');
 
 
-  // http://csrc.nist.gov/groups/STM/cavp/documents/aes/KAT_AES.zip
-  FOfficialVectorKeys__AES256_CBC := TCryptoLibStringArray.Create
-    ('C47B0294DBBBEE0FEC4757F22FFEEE3587CA4730C3D33B691DF38BAB076BC558',
-    '28D46CFFA158533194214A91E712FC2B45B518076675AFFD910EDECA5F41AC64');
+  // test vectors gotten from here
+  // https://github.com/ircmaxell/quality-checker/blob/master/tmp/gh_18/PHP-PasswordLib-master/test/Data/Vectors/aes-cbc.test-vectors
 
 
-  FOfficialVectorIVs_AES256_CBC := TCryptoLibStringArray.Create
-    ('00000000000000000000000000000000', '00000000000000000000000000000000');
+  // CBC
 
 
-  FOfficialVectorInputs_AES256_CBC := TCryptoLibStringArray.Create
-    ('00000000000000000000000000000000', '00000000000000000000000000000000');
+  FOfficialVectorKeys_AES_CBC := TCryptoLibStringArray.Create(
+    // 128
+    '2B7E151628AED2A6ABF7158809CF4F3C', '2B7E151628AED2A6ABF7158809CF4F3C',
+    '2B7E151628AED2A6ABF7158809CF4F3C', '2B7E151628AED2A6ABF7158809CF4F3C',
+    // 192
+    '8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B',
+    '8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B',
+    '8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B',
+    '8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B',
+    // 256
+    '603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4',
+    '603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4',
+    '603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4',
+    '603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4');
+
+  FOfficialVectorIVs_AES_CBC := TCryptoLibStringArray.Create(
+    // 128
+    '000102030405060708090A0B0C0D0E0F', '7649ABAC8119B246CEE98E9B12E9197D',
+    '5086CB9B507219EE95DB113A917678B2', '73BED6B8E3C1743B7116E69E22229516',
+    // 192
+    '000102030405060708090A0B0C0D0E0F', '4F021DB243BC633D7178183A9FA071E8',
+    'B4D9ADA9AD7DEDF4E5E738763F69145A', '571B242012FB7AE07FA9BAAC3DF102E0',
+    // 256
+    '000102030405060708090A0B0C0D0E0F', 'F58C4C04D6E5F1BA779EABFB5F7BFBD6',
+    '9CFC4E967EDB808D679F777BC6702C7D', '39F23369A9D9BACFA530E26304231461');
+
+  FOfficialVectorInputs_AES_CBC := TCryptoLibStringArray.Create(
+    // 128
+    '6BC1BEE22E409F96E93D7E117393172A', 'AE2D8A571E03AC9C9EB76FAC45AF8E51',
+    '30C81C46A35CE411E5FBC1191A0A52EF', 'F69F2445DF4F9B17AD2B417BE66C3710',
+    // 192
+    '6BC1BEE22E409F96E93D7E117393172A', 'AE2D8A571E03AC9C9EB76FAC45AF8E51',
+    '30C81C46A35CE411E5FBC1191A0A52EF', 'F69F2445DF4F9B17AD2B417BE66C3710',
+    // 256
+    '6BC1BEE22E409F96E93D7E117393172A', 'AE2D8A571E03AC9C9EB76FAC45AF8E51',
+    '30C81C46A35CE411E5FBC1191A0A52EF', 'F69F2445DF4F9B17AD2B417BE66C3710');
+
+  FOfficialVectorOutputs_AES_CBC := TCryptoLibStringArray.Create(
+    // 128
+    '7649ABAC8119B246CEE98E9B12E9197D', '5086CB9B507219EE95DB113A917678B2',
+    '73BED6B8E3C1743B7116E69E22229516', '3FF1CAA1681FAC09120ECA307586E1A7',
+    // 192
+    '4F021DB243BC633D7178183A9FA071E8', 'B4D9ADA9AD7DEDF4E5E738763F69145A',
+    '571B242012FB7AE07FA9BAAC3DF102E0', '08B0E27988598881D920A9E64F5615CD',
+    // 256
+    'F58C4C04D6E5F1BA779EABFB5F7BFBD6', '9CFC4E967EDB808D679F777BC6702C7D',
+    '39F23369A9D9BACFA530E26304231461', 'B2EB05E2C39BE9FCDA6C19078C6A9D1B');
+
+  // test vectors gotten from here
+  // https://github.com/ircmaxell/quality-checker/blob/master/tmp/gh_18/PHP-PasswordLib-master/test/Data/Vectors/aes-cfb.test-vectors
+
+  // CFB
+
+  FOfficialVectorKeys_AES_CFB := TCryptoLibStringArray.Create(
+    // 128
+    '2B7E151628AED2A6ABF7158809CF4F3C', '2B7E151628AED2A6ABF7158809CF4F3C',
+    '2B7E151628AED2A6ABF7158809CF4F3C', '2B7E151628AED2A6ABF7158809CF4F3C',
+    // 192
+    '8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B',
+    '8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B',
+    '8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B',
+    '8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B',
+    // 256
+    '603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4',
+    '603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4',
+    '603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4',
+    '603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4');
+
+  FOfficialVectorIVs_AES_CFB := TCryptoLibStringArray.Create(
+    // 128
+    '000102030405060708090A0B0C0D0E0F', '3B3FD92EB72DAD20333449F8E83CFB4A',
+    'C8A64537A0B3A93FCDE3CDAD9F1CE58B', '26751F67A3CBB140B1808CF187A4F4DF',
+    // 192
+    '000102030405060708090A0B0C0D0E0F', 'CDC80D6FDDF18CAB34C25909C99A4174',
+    '67CE7F7F81173621961A2B70171D3D7A', '2E1E8A1DD59B88B1C8E60FED1EFAC4C9',
+    // 256
+    '000102030405060708090A0B0C0D0E0F', 'DC7E84BFDA79164B7ECD8486985D3860',
+    '39FFED143B28B1C832113C6331E5407B', 'DF10132415E54B92A13ED0A8267AE2F9');
+
+  FOfficialVectorInputs_AES_CFB := TCryptoLibStringArray.Create(
+    // 128
+    '6BC1BEE22E409F96E93D7E117393172A', 'AE2D8A571E03AC9C9EB76FAC45AF8E51',
+    '30C81C46A35CE411E5FBC1191A0A52EF', 'F69F2445DF4F9B17AD2B417BE66C3710',
+    // 192
+    '6BC1BEE22E409F96E93D7E117393172A', 'AE2D8A571E03AC9C9EB76FAC45AF8E51',
+    '30C81C46A35CE411E5FBC1191A0A52EF', 'F69F2445DF4F9B17AD2B417BE66C3710',
+    // 256
+    '6BC1BEE22E409F96E93D7E117393172A', 'AE2D8A571E03AC9C9EB76FAC45AF8E51',
+    '30C81C46A35CE411E5FBC1191A0A52EF', 'F69F2445DF4F9B17AD2B417BE66C3710');
+
+  FOfficialVectorOutputs_AES_CFB := TCryptoLibStringArray.Create(
+    // 128
+    '3B3FD92EB72DAD20333449F8E83CFB4A', 'C8A64537A0B3A93FCDE3CDAD9F1CE58B',
+    '26751F67A3CBB140B1808CF187A4F4DF', 'C04B05357C5D1C0EEAC4C66F9FF7F2E6',
+    // 192
+    'CDC80D6FDDF18CAB34C25909C99A4174', '67CE7F7F81173621961A2B70171D3D7A',
+    '2E1E8A1DD59B88B1C8E60FED1EFAC4C9', 'C05F9F9CA9834FA042AE8FBA584B09FF',
+    // 256
+    'DC7E84BFDA79164B7ECD8486985D3860', '39FFED143B28B1C832113C6331E5407B',
+    'DF10132415E54B92A13ED0A8267AE2F9', '75A385741AB9CEF82031623D55B1E471');
+
+
+  // test vectors gotten from here
+  // https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf
+
+  // CTR
+
+  FOfficialVectorKeys_AES_CTR := TCryptoLibStringArray.Create(
+    // 128
+    '2B7E151628AED2A6ABF7158809CF4F3C', '2B7E151628AED2A6ABF7158809CF4F3C',
+    '2B7E151628AED2A6ABF7158809CF4F3C', '2B7E151628AED2A6ABF7158809CF4F3C',
+    // 192
+    '8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B',
+    '8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B',
+    '8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B',
+    '8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B',
+    // 256
+    '603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4',
+    '603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4',
+    '603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4',
+    '603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4');
+
+  FOfficialVectorIVs_AES_CTR := TCryptoLibStringArray.Create(
+    // 128
+    'F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF', 'F0F1F2F3F4F5F6F7F8F9FAFBFCFDFF00',
+    'F0F1F2F3F4F5F6F7F8F9FAFBFCFDFF01', 'F0F1F2F3F4F5F6F7F8F9FAFBFCFDFF02',
+    // 192
+    'F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF', 'F0F1F2F3F4F5F6F7F8F9FAFBFCFDFF00',
+    'F0F1F2F3F4F5F6F7F8F9FAFBFCFDFF01', 'F0F1F2F3F4F5F6F7F8F9FAFBFCFDFF02',
+    // 256
+    'F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF', 'F0F1F2F3F4F5F6F7F8F9FAFBFCFDFF00',
+    'F0F1F2F3F4F5F6F7F8F9FAFBFCFDFF01', 'F0F1F2F3F4F5F6F7F8F9FAFBFCFDFF02');
+
+  FOfficialVectorInputs_AES_CTR := TCryptoLibStringArray.Create(
+    // 128
+    '6BC1BEE22E409F96E93D7E117393172A', 'AE2D8A571E03AC9C9EB76FAC45AF8E51',
+    '30C81C46A35CE411E5FBC1191A0A52EF', 'F69F2445DF4F9B17AD2B417BE66C3710',
+    // 192
+    '6BC1BEE22E409F96E93D7E117393172A', 'AE2D8A571E03AC9C9EB76FAC45AF8E51',
+    '30C81C46A35CE411E5FBC1191A0A52EF', 'F69F2445DF4F9B17AD2B417BE66C3710',
+    // 256
+    '6BC1BEE22E409F96E93D7E117393172A', 'AE2D8A571E03AC9C9EB76FAC45AF8E51',
+    '30C81C46A35CE411E5FBC1191A0A52EF', 'F69F2445DF4F9B17AD2B417BE66C3710');
+
+  FOfficialVectorOutputs_AES_CTR := TCryptoLibStringArray.Create(
+    // 128
+    '874D6191B620E3261BEF6864990DB6CE', '9806F66B7970FDFF8617187BB9FFFDFF',
+    '5AE4DF3EDBD5D35E5B4F09020DB03EAB', '1E031DDA2FBE03D1792170A0F3009CEE',
+    // 192
+    '1ABC932417521CA24F2B0459FE7E6E0B', '090339EC0AA6FAEFD5CCC2C6F4CE8E94',
+    '1E36B26BD1EBC670D1BD1D665620ABF7', '4F78A7F6D29809585A97DAEC58C6B050',
+    // 256
+    '601EC313775789A5B7A7F504BBF3D228', 'F443E3CA4D62B59ACA84E990CACAF5C5',
+    '2B0930DAA23DE94CE87017BA2D84988D', 'DFC9C58DB67AADA613C2DD08457941A6');
+
+
+  // test vectors gotten from here
+  // https://github.com/ircmaxell/quality-checker/blob/master/tmp/gh_18/PHP-PasswordLib-master/test/Data/Vectors/aes-ecb.test-vectors
+
+  // ECB
+
+  FOfficialVectorKeys_AES_ECB := TCryptoLibStringArray.Create(
+    // 128
+    '2B7E151628AED2A6ABF7158809CF4F3C', '2B7E151628AED2A6ABF7158809CF4F3C',
+    '2B7E151628AED2A6ABF7158809CF4F3C', '2B7E151628AED2A6ABF7158809CF4F3C',
+    // 192
+    '8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B',
+    '8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B',
+    '8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B',
+    '8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B',
+    // 256
+    '603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4',
+    '603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4',
+    '603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4',
+    '603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4');
+
+  FOfficialVectorInputs_AES_ECB := TCryptoLibStringArray.Create(
+    // 128
+    '6BC1BEE22E409F96E93D7E117393172A', 'AE2D8A571E03AC9C9EB76FAC45AF8E51',
+    '30C81C46A35CE411E5FBC1191A0A52EF', 'F69F2445DF4F9B17AD2B417BE66C3710',
+    // 192
+    '6BC1BEE22E409F96E93D7E117393172A', 'AE2D8A571E03AC9C9EB76FAC45AF8E51',
+    '30C81C46A35CE411E5FBC1191A0A52EF', 'F69F2445DF4F9B17AD2B417BE66C3710',
+    // 256
+    '6BC1BEE22E409F96E93D7E117393172A', 'AE2D8A571E03AC9C9EB76FAC45AF8E51',
+    '30C81C46A35CE411E5FBC1191A0A52EF', 'F69F2445DF4F9B17AD2B417BE66C3710');
+
+  FOfficialVectorOutputs_AES_ECB := TCryptoLibStringArray.Create(
+    // 128
+    '3AD77BB40D7A3660A89ECAF32466EF97', 'F5D3D58503B9699DE785895A96FDBAAF',
+    '43B1CD7F598ECE23881B00E3ED030688', '7B0C785E27E8AD3F8223207104725DD4',
+    // 192
+    'BD334F1D6E45F25FF712A214571FA5CC', '974104846D0AD3AD7734ECB3ECEE4EEF',
+    'EF7AFD2270E2E60ADCE0BA2FACE6444E', '9A4B41BA738D6C72FB16691603C18E0E',
+    // 256
+    'F3EED1BDB5D2A03C064B5A7E3DB181F8', '591CCB10D410ED26DC5BA74A31362870',
+    'B6ED21B99CA6F4F9F153E7B1BEAFED1D', '23304B7A39F9F3FF067D8D8F9E24ECC7');
+
+  // test vectors gotten from here
+  // https://github.com/ircmaxell/quality-checker/blob/master/tmp/gh_18/PHP-PasswordLib-master/test/Data/Vectors/aes-ofb.test-vectors
+
+  // OFB
+
+  FOfficialVectorKeys_AES_OFB := TCryptoLibStringArray.Create(
+    // 128
+    '2B7E151628AED2A6ABF7158809CF4F3C', '2B7E151628AED2A6ABF7158809CF4F3C',
+    '2B7E151628AED2A6ABF7158809CF4F3C', '2B7E151628AED2A6ABF7158809CF4F3C',
+    // 192
+    '8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B',
+    '8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B',
+    '8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B',
+    '8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B',
+    // 256
+    '603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4',
+    '603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4',
+    '603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4',
+    '603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4');
+
+  FOfficialVectorIVs_AES_OFB := TCryptoLibStringArray.Create(
+    // 128
+    '000102030405060708090A0B0C0D0E0F', '50FE67CC996D32B6DA0937E99BAFEC60',
+    'D9A4DADA0892239F6B8B3D7680E15674', 'A78819583F0308E7A6BF36B1386ABF23',
+    // 192
+    '000102030405060708090A0B0C0D0E0F', 'A609B38DF3B1133DDDFF2718BA09565E',
+    '52EF01DA52602FE0975F78AC84BF8A50', 'BD5286AC63AABD7EB067AC54B553F71D',
+    // 256
+    '000102030405060708090A0B0C0D0E0F', 'B7BF3A5DF43989DD97F0FA97EBCE2F4A',
+    'E1C656305ED1A7A6563805746FE03EDC', '41635BE625B48AFC1666DD42A09D96E7');
+
+  FOfficialVectorInputs_AES_OFB := TCryptoLibStringArray.Create(
+    // 128
+    '6BC1BEE22E409F96E93D7E117393172A', 'AE2D8A571E03AC9C9EB76FAC45AF8E51',
+    '30C81C46A35CE411E5FBC1191A0A52EF', 'F69F2445DF4F9B17AD2B417BE66C3710',
+    // 192
+    '6BC1BEE22E409F96E93D7E117393172A', 'AE2D8A571E03AC9C9EB76FAC45AF8E51',
+    '30C81C46A35CE411E5FBC1191A0A52EF', 'F69F2445DF4F9B17AD2B417BE66C3710',
+    // 256
+    '6BC1BEE22E409F96E93D7E117393172A', 'AE2D8A571E03AC9C9EB76FAC45AF8E51',
+    '30C81C46A35CE411E5FBC1191A0A52EF', 'F69F2445DF4F9B17AD2B417BE66C3710');
+
+  FOfficialVectorOutputs_AES_OFB := TCryptoLibStringArray.Create(
+    // 128
+    '3B3FD92EB72DAD20333449F8E83CFB4A', '7789508D16918F03F53C52DAC54ED825',
+    '9740051E9C5FECF64344F7A82260EDCC', '304C6528F659C77866A510D9C1D6AE5E',
+    // 192
+    'CDC80D6FDDF18CAB34C25909C99A4174', 'FCC28B8D4C63837C09E81700C1100401',
+    '8D9A9AEAC0F6596F559C6D4DAF59A5F2', '6D9F200857CA6C3E9CAC524BD9ACC92A',
+    // 256
+    'DC7E84BFDA79164B7ECD8486985D3860', '4FEBDC6740D20B3AC88F6AD82A4FB08D',
+    '71AB47A086E86EEDF39D1C5BBA97C408', '0126141D67F37BE8538F5A8BE740E484');
 
 
-  FOfficialVectorOutputs_AES256_CBC := TCryptoLibStringArray.Create
-    ('46F2FB342D6F0AB477476FC501242C5F', '4BF3B0A69AEB6657794F2901B1440AD4');
 end;
 end;
 
 
 end.
 end.

+ 209 - 20
CryptoLib.Tests/src/Crypto/AESTests.pas

@@ -33,8 +33,8 @@ uses
   TestFramework,
   TestFramework,
 {$ENDIF FPC}
 {$ENDIF FPC}
   AESTestVectors,
   AESTestVectors,
-  // ClpAesEngine,
-  // ClpIAesEngine,
+  ClpAesEngine,
+  ClpIAesEngine,
   ClpKeyParameter,
   ClpKeyParameter,
   ClpIKeyParameter,
   ClpIKeyParameter,
   ClpParametersWithIV,
   ClpParametersWithIV,
@@ -46,8 +46,17 @@ uses
   ClpParameterUtilities,
   ClpParameterUtilities,
   ClpCipherUtilities,
   ClpCipherUtilities,
   ClpNistObjectIdentifiers,
   ClpNistObjectIdentifiers,
-  // ClpCbcBlockCipher,
-  // ClpICbcBlockCipher,
+  ClpCbcBlockCipher,
+  ClpICbcBlockCipher,
+  ClpICfbBlockCipher,
+  ClpCfbBlockCipher,
+  ClpIOfbBlockCipher,
+  ClpOfbBlockCipher,
+  ClpISicBlockCipher,
+  ClpSicBlockCipher,
+  ClpIBlockCipher,
+  ClpBufferedBlockCipher,
+  ClpIBufferedBlockCipher,
   // ClpPaddedBufferedBlockCipher,
   // ClpPaddedBufferedBlockCipher,
   // ClpIPaddedBufferedBlockCipher,
   // ClpIPaddedBufferedBlockCipher,
   // ClpZeroBytePadding,
   // ClpZeroBytePadding,
@@ -69,8 +78,9 @@ type
 
 
     procedure dooidTest(oids, names: TCryptoLibStringArray; groupSize: Int32);
     procedure dooidTest(oids, names: TCryptoLibStringArray; groupSize: Int32);
 
 
-    procedure doAESTestWithIV(const cipher: IBufferedCipher;
-      const param: IParametersWithIV; const input, output: String);
+    procedure doAESTest(const cipher: IBufferedCipher;
+      const param: ICipherParameters; const input, output: String;
+      withpadding: Boolean = False);
 
 
   protected
   protected
     procedure SetUp; override;
     procedure SetUp; override;
@@ -78,7 +88,12 @@ type
   published
   published
 
 
     procedure TestOids;
     procedure TestOids;
-    procedure TestAES256_CBC_PKCS7PADDING;
+    procedure TestAES_CBC_PKCS7PADDING_WITH_IV;
+    procedure TestAES_CBC_NOPADDING_WITH_IV;
+    procedure TestAES_CFB_NOPADDING_WITH_IV;
+    procedure TestAES_OFB_NOPADDING_WITH_IV;
+    procedure TestAES_CTR_NOPADDING_WITH_IV;
+    procedure TestAES_ECB_NOPADDING_NO_IV;
 
 
   end;
   end;
 
 
@@ -86,8 +101,9 @@ implementation
 
 
 { TTestAES }
 { TTestAES }
 
 
-procedure TTestAES.doAESTestWithIV(const cipher: IBufferedCipher;
-  const param: IParametersWithIV; const input, output: String);
+procedure TTestAES.doAESTest(const cipher: IBufferedCipher;
+  const param: ICipherParameters; const input, output: String;
+  withpadding: Boolean);
 var
 var
   len1, len2: Int32;
   len1, len2: Int32;
   LInput, LOutput, EncryptionResult, DecryptionResult: TBytes;
   LInput, LOutput, EncryptionResult, DecryptionResult: TBytes;
@@ -100,6 +116,16 @@ begin
   // Encryption
   // Encryption
   // Single Pass
   // Single Pass
   EncryptionResult := cipher.DoFinal(LInput);
   EncryptionResult := cipher.DoFinal(LInput);
+
+  if not withpadding then
+  begin
+    if (not TArrayUtils.AreEqual(LOutput, EncryptionResult)) then
+    begin
+      Fail(Format('Encryption Failed - Expected %s but got %s',
+        [THex.Encode(LOutput), THex.Encode(EncryptionResult)]));
+    end;
+  end;
+
   { *
   { *
     // Multi Pass
     // Multi Pass
     System.SetLength(EncryptionResult,
     System.SetLength(EncryptionResult,
@@ -111,7 +137,7 @@ begin
     len1 := cipher.DoFinal(EncryptionResult, len1);
     len1 := cipher.DoFinal(EncryptionResult, len1);
     * }
     * }
 
 
-  cipher.Init(false, param);
+  cipher.Init(False, param);
 
 
   // Decryption
   // Decryption
   // Single Pass
   // Single Pass
@@ -168,7 +194,7 @@ begin
     end;
     end;
 
 
     c1.Init(True, cp);
     c1.Init(True, cp);
-    c2.Init(false, cp);
+    c2.Init(False, cp);
 
 
     result := c2.DoFinal(c1.DoFinal(data));
     result := c2.DoFinal(c1.DoFinal(data));
 
 
@@ -197,9 +223,41 @@ begin
 
 
 end;
 end;
 
 
-procedure TTestAES.TestAES256_CBC_PKCS7PADDING;
+procedure TTestAES.TestAES_CBC_NOPADDING_WITH_IV;
+var
+  KeyParametersWithIV: IParametersWithIV;
+  keyBytes, IVBytes: TBytes;
+  cipher: IBufferedCipher;
+  input, output: string;
+  i: Int32;
+  engine: IAesEngine;
+  blockCipher: ICbcBlockCipher;
+begin
+
+  // // Set up
+  engine := TAesEngine.Create();
+  blockCipher := TCbcBlockCipher.Create(engine); // CBC
+  // no padding
+  cipher := TBufferedBlockCipher.Create(blockCipher) as IBufferedBlockCipher;
+
+  for i := System.Low(TAESTestVectors.FOfficialVectorKeys_AES_CBC)
+    to System.High(TAESTestVectors.FOfficialVectorKeys_AES_CBC) do
+  begin
+    keyBytes := THex.Decode(TAESTestVectors.FOfficialVectorKeys_AES_CBC[i]);
+    IVBytes := THex.Decode(TAESTestVectors.FOfficialVectorIVs_AES_CBC[i]);
+    input := TAESTestVectors.FOfficialVectorInputs_AES_CBC[i];
+    output := TAESTestVectors.FOfficialVectorOutputs_AES_CBC[i];
+
+    KeyParametersWithIV := TParametersWithIV.Create
+      (TParameterUtilities.CreateKeyParameter('AES', keyBytes), IVBytes);
+
+    doAESTest(cipher, KeyParametersWithIV as ICipherParameters, input, output);
+  end;
+
+end;
+
+procedure TTestAES.TestAES_CBC_PKCS7PADDING_WITH_IV;
 var
 var
-  keyParameter: IKeyParameter;
   KeyParametersWithIV: IParametersWithIV;
   KeyParametersWithIV: IParametersWithIV;
   keyBytes, IVBytes: TBytes;
   keyBytes, IVBytes: TBytes;
   cipher: IBufferedCipher;
   cipher: IBufferedCipher;
@@ -217,18 +275,149 @@ begin
   // // Default scheme is PKCS5/PKCS7
   // // Default scheme is PKCS5/PKCS7
   cipher := TCipherUtilities.GetCipher('AES/CBC/PKCS7PADDING');
   cipher := TCipherUtilities.GetCipher('AES/CBC/PKCS7PADDING');
 
 
-  for i := System.Low(TAESTestVectors.FOfficialVectorKeys__AES256_CBC)
-    to System.Low(TAESTestVectors.FOfficialVectorKeys__AES256_CBC) do
+  for i := System.Low(TAESTestVectors.FOfficialVectorKeys_AES_CBC)
+    to System.High(TAESTestVectors.FOfficialVectorKeys_AES_CBC) do
+  begin
+    keyBytes := THex.Decode(TAESTestVectors.FOfficialVectorKeys_AES_CBC[i]);
+    IVBytes := THex.Decode(TAESTestVectors.FOfficialVectorIVs_AES_CBC[i]);
+    input := TAESTestVectors.FOfficialVectorInputs_AES_CBC[i];
+    output := TAESTestVectors.FOfficialVectorOutputs_AES_CBC[i];
+
+    KeyParametersWithIV := TParametersWithIV.Create
+      (TParameterUtilities.CreateKeyParameter('AES', keyBytes), IVBytes);
+
+    doAESTest(cipher, KeyParametersWithIV as ICipherParameters, input,
+      output, True);
+  end;
+
+end;
+
+procedure TTestAES.TestAES_CFB_NOPADDING_WITH_IV;
+var
+  KeyParametersWithIV: IParametersWithIV;
+  keyBytes, IVBytes: TBytes;
+  cipher: IBufferedCipher;
+  input, output: string;
+  i: Int32;
+  engine: IAesEngine;
+  blockCipher: ICfbBlockCipher;
+begin
+
+  // // Set up
+  engine := TAesEngine.Create();
+  blockCipher := TCfbBlockCipher.Create(engine, engine.GetBlockSize * 8); // CFB
+  // no padding
+  cipher := TBufferedBlockCipher.Create(blockCipher) as IBufferedBlockCipher;
+
+  for i := System.Low(TAESTestVectors.FOfficialVectorKeys_AES_CFB)
+    to System.High(TAESTestVectors.FOfficialVectorKeys_AES_CFB) do
+  begin
+    keyBytes := THex.Decode(TAESTestVectors.FOfficialVectorKeys_AES_CFB[i]);
+    IVBytes := THex.Decode(TAESTestVectors.FOfficialVectorIVs_AES_CFB[i]);
+    input := TAESTestVectors.FOfficialVectorInputs_AES_CFB[i];
+    output := TAESTestVectors.FOfficialVectorOutputs_AES_CFB[i];
+
+    KeyParametersWithIV := TParametersWithIV.Create
+      (TParameterUtilities.CreateKeyParameter('AES', keyBytes), IVBytes);
+
+    doAESTest(cipher, KeyParametersWithIV as ICipherParameters, input, output);
+  end;
+
+end;
+
+procedure TTestAES.TestAES_CTR_NOPADDING_WITH_IV;
+var
+  KeyParametersWithIV: IParametersWithIV;
+  keyBytes, IVBytes: TBytes;
+  cipher: IBufferedCipher;
+  input, output: string;
+  i: Int32;
+  engine: IAesEngine;
+  blockCipher: ISicBlockCipher;
+begin
+
+  // // Set up
+  engine := TAesEngine.Create();
+  blockCipher := TSicBlockCipher.Create(engine); // CTR
+  // no padding
+  cipher := TBufferedBlockCipher.Create(blockCipher) as IBufferedBlockCipher;
+
+  for i := System.Low(TAESTestVectors.FOfficialVectorKeys_AES_CTR)
+    to System.High(TAESTestVectors.FOfficialVectorKeys_AES_CTR) do
+  begin
+    keyBytes := THex.Decode(TAESTestVectors.FOfficialVectorKeys_AES_CTR[i]);
+    IVBytes := THex.Decode(TAESTestVectors.FOfficialVectorIVs_AES_CTR[i]);
+    input := TAESTestVectors.FOfficialVectorInputs_AES_CTR[i];
+    output := TAESTestVectors.FOfficialVectorOutputs_AES_CTR[i];
+
+    KeyParametersWithIV := TParametersWithIV.Create
+      (TParameterUtilities.CreateKeyParameter('AES', keyBytes), IVBytes);
+
+    doAESTest(cipher, KeyParametersWithIV as ICipherParameters, input, output);
+  end;
+
+end;
+
+procedure TTestAES.TestAES_ECB_NOPADDING_NO_IV;
+var
+  keyParameter: IKeyParameter;
+  keyBytes: TBytes;
+  cipher: IBufferedCipher;
+  input, output: string;
+  i: Int32;
+  engine: IAesEngine;
+  blockCipher: IBlockCipher;
+begin
+
+  // // Set up
+  engine := TAesEngine.Create();
+  blockCipher := engine as IBlockCipher; // ECB
+  // no padding
+  cipher := TBufferedBlockCipher.Create(blockCipher) as IBufferedBlockCipher;
+
+  for i := System.Low(TAESTestVectors.FOfficialVectorKeys_AES_ECB)
+    to System.High(TAESTestVectors.FOfficialVectorKeys_AES_ECB) do
+  begin
+    keyBytes := THex.Decode(TAESTestVectors.FOfficialVectorKeys_AES_ECB[i]);
+    input := TAESTestVectors.FOfficialVectorInputs_AES_ECB[i];
+    output := TAESTestVectors.FOfficialVectorOutputs_AES_ECB[i];
+
+    keyParameter := TParameterUtilities.CreateKeyParameter('AES', keyBytes);
+
+    doAESTest(cipher, keyParameter as ICipherParameters, input, output);
+  end;
+
+end;
+
+procedure TTestAES.TestAES_OFB_NOPADDING_WITH_IV;
+var
+  KeyParametersWithIV: IParametersWithIV;
+  keyBytes, IVBytes: TBytes;
+  cipher: IBufferedCipher;
+  input, output: string;
+  i: Int32;
+  engine: IAesEngine;
+  blockCipher: IOfbBlockCipher;
+begin
+
+  // // Set up
+  engine := TAesEngine.Create();
+  blockCipher := TOfbBlockCipher.Create(engine, engine.GetBlockSize * 8); // OFB
+  // no padding
+  cipher := TBufferedBlockCipher.Create(blockCipher) as IBufferedBlockCipher;
+
+  for i := System.Low(TAESTestVectors.FOfficialVectorKeys_AES_OFB)
+    to System.High(TAESTestVectors.FOfficialVectorKeys_AES_OFB) do
   begin
   begin
-    keyBytes := THex.Decode(TAESTestVectors.FOfficialVectorKeys__AES256_CBC[i]);
-    IVBytes := THex.Decode(TAESTestVectors.FOfficialVectorIVs_AES256_CBC[i]);
-    input := TAESTestVectors.FOfficialVectorInputs_AES256_CBC[i];
-    output := TAESTestVectors.FOfficialVectorOutputs_AES256_CBC[i];
+    keyBytes := THex.Decode(TAESTestVectors.FOfficialVectorKeys_AES_OFB[i]);
+    IVBytes := THex.Decode(TAESTestVectors.FOfficialVectorIVs_AES_OFB[i]);
+    input := TAESTestVectors.FOfficialVectorInputs_AES_OFB[i];
+    output := TAESTestVectors.FOfficialVectorOutputs_AES_OFB[i];
 
 
     KeyParametersWithIV := TParametersWithIV.Create
     KeyParametersWithIV := TParametersWithIV.Create
       (TParameterUtilities.CreateKeyParameter('AES', keyBytes), IVBytes);
       (TParameterUtilities.CreateKeyParameter('AES', keyBytes), IVBytes);
 
 
-    doAESTestWithIV(cipher, KeyParametersWithIV, input, output);
+    doAESTest(cipher, KeyParametersWithIV as ICipherParameters, input, output);
   end;
   end;
 
 
 end;
 end;

+ 304 - 0
CryptoLib.Tests/src/Crypto/HMacTests.pas

@@ -0,0 +1,304 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit HMacTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+{$HINTS OFF}
+
+uses
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpKeyParameter,
+  ClpIKeyParameter,
+  ClpHMac,
+  ClpIMac,
+  ClpICipherKeyGenerator,
+  ClpDigestUtilities,
+  ClpMacUtilities,
+  ClpGeneratorUtilities,
+  ClpPkcsObjectIdentifiers,
+  ClpIanaObjectIdentifiers,
+  ClpNistObjectIdentifiers,
+  ClpRosstandartObjectIdentifiers,
+  ClpHex,
+  ClpArrayUtils,
+  ClpCryptoLibTypes;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  /// <summary>
+  /// HMAC tester
+  /// </summary>
+  TTestHMac = class(TCryptoLibTestCase)
+  private
+  var
+    FkeyBytes, Fmessage, Foutput1, FoutputMD5, FoutputMD2, FoutputMD4,
+      Foutput224, Foutput256, Foutput384, Foutput512, Foutput512_224,
+      Foutput512_256, FoutputRipeMD128, FoutputRipeMD160, FoutputTiger,
+      FoutputSha3_224, FoutputSha3_256, FoutputSha3_384, FoutputSha3_512,
+      FoutputGost2012_256, FoutputGost2012_512: TBytes;
+
+    procedure DoTestHMac(const hmacName: String; output: TBytes); overload;
+    procedure DoTestHMac(const hmacName: String; defKeySize: Int32;
+      output: TBytes); overload;
+    procedure DoTestExceptions();
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+
+    procedure TestHMac;
+
+  end;
+
+implementation
+
+{ TTestHMac }
+
+procedure TTestHMac.DoTestExceptions;
+var
+  mac: IMac;
+begin
+  mac := TMacUtilities.GetMac('HmacSHA1');
+  try
+    mac.Init(Nil);
+    Fail('bad argument Init test failed.');
+  except
+    on e: Exception do
+    begin
+      // pass
+    end;
+  end;
+end;
+
+procedure TTestHMac.DoTestHMac(const hmacName: String; output: TBytes);
+var
+  key: IKeyParameter;
+  mac: IMac;
+  outBytes: TBytes;
+  kGen: ICipherKeyGenerator;
+begin
+  key := TKeyParameter.Create(FkeyBytes);
+
+  mac := TMacUtilities.GetMac(hmacName);
+  mac.Init(key);
+  mac.Reset();
+  mac.BlockUpdate(Fmessage, 0, System.Length(Fmessage));
+  outBytes := TMacUtilities.DoFinal(mac);
+
+  if (not TArrayUtils.AreEqual(outBytes, output)) then
+  begin
+    Fail('Failed - expected ' + THex.Encode(output) + ' got ' +
+      THex.Encode(outBytes));
+  end;
+
+  kGen := TGeneratorUtilities.GetKeyGenerator(hmacName);
+  key := TKeyParameter.Create(kGen.GenerateKey());
+  mac.Init(key); // hmacName
+  mac.BlockUpdate(Fmessage, 0, System.Length(Fmessage));
+  outBytes := TMacUtilities.DoFinal(mac);
+end;
+
+procedure TTestHMac.DoTestHMac(const hmacName: String; defKeySize: Int32;
+  output: TBytes);
+var
+  key: IKeyParameter;
+  mac: IMac;
+  outBytes: TBytes;
+  kGen: ICipherKeyGenerator;
+begin
+  key := TKeyParameter.Create(FkeyBytes);
+
+  mac := TMacUtilities.GetMac(hmacName);
+  mac.Init(key);
+  mac.Reset();
+  mac.BlockUpdate(Fmessage, 0, System.Length(Fmessage));
+  outBytes := TMacUtilities.DoFinal(mac);
+
+  if (not TArrayUtils.AreEqual(outBytes, output)) then
+  begin
+    Fail('Failed - expected ' + THex.Encode(output) + ' got ' +
+      THex.Encode(outBytes));
+  end;
+
+  kGen := TGeneratorUtilities.GetKeyGenerator(hmacName);
+  key := TKeyParameter.Create(kGen.GenerateKey());
+  mac.Init(key); // hmacName
+  mac.BlockUpdate(Fmessage, 0, System.Length(Fmessage));
+  outBytes := TMacUtilities.DoFinal(mac);
+
+  CheckTrue(System.Length(key.GetKey()) = (defKeySize div 8),
+    'default key wrong length');
+end;
+
+procedure TTestHMac.SetUp;
+begin
+  inherited;
+  FkeyBytes := THex.Decode('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b');
+  Fmessage := TEncoding.ASCII.GetBytes('Hi There');
+  Foutput1 := THex.Decode('b617318655057264e28bc0b6fb378c8ef146be00');
+  FoutputMD5 := THex.Decode('5ccec34ea9656392457fa1ac27f08fbc');
+  FoutputMD2 := THex.Decode('dc1923ef5f161d35bef839ca8c807808');
+  FoutputMD4 := THex.Decode('5570ce964ba8c11756cdc3970278ff5a');
+  Foutput224 := THex.Decode
+    ('896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22');
+  Foutput256 := THex.Decode
+    ('b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7');
+  Foutput384 := THex.Decode
+    ('afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59cfaea9ea9076ede7f4af152e8b2fa9cb6');
+  Foutput512 := THex.Decode
+    ('87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854');
+  Foutput512_224 := THex.Decode
+    ('b244ba01307c0e7a8ccaad13b1067a4cf6b961fe0c6a20bda3d92039');
+  Foutput512_256 := THex.Decode
+    ('9f9126c3d9c3c330d760425ca8a217e31feae31bfe70196ff81642b868402eab');
+  FoutputRipeMD128 := THex.Decode('fda5717fb7e20cf05d30bb286a44b05d');
+  FoutputRipeMD160 := THex.Decode('24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668');
+  FoutputTiger := THex.Decode
+    ('1d7a658c75f8f004916e7b07e2a2e10aec7de2ae124d3647');
+
+  FoutputSha3_224 := THex.Decode
+    ('3b16546bbc7be2706a031dcafd56373d9884367641d8c59af3c860f7');
+  FoutputSha3_256 := THex.Decode
+    ('ba85192310dffa96e2a3a40e69774351140bb7185e1202cdcc917589f95e16bb');
+  FoutputSha3_384 := THex.Decode
+    ('68d2dcf7fd4ddd0a2240c8a437305f61fb7334cfb5d0226e1bc27dc10a2e723a20d370b47743130e26ac7e3d532886bd');
+  FoutputSha3_512 := THex.Decode
+    ('eb3fbd4b2eaab8f5c504bd3a41465aacec15770a7cabac531e482f860b5ec7ba47ccb2c6f2afce8f88d22b6dc61380f23a668fd3888bb80537c0a0b86407689e');
+
+  FoutputGost2012_256 :=
+    THex.Decode
+    ('f03422dfa37a507ca126ce01b8eba6b7fdda8f8a60dd8f2703e3a372120b8294');
+  FoutputGost2012_512 :=
+    THex.Decode
+    ('86b6a06bfa9f1974aff6ccd7fa3f835f0bd850395d6084efc47b9dda861a2cdf0dcaf959160733d5269f6567966dd7a9f932a77cd6f080012cd476f1c2cc31bb');
+
+end;
+
+procedure TTestHMac.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestHMac.TestHMac;
+begin
+  DoTestHMac('HMac-SHA1', Foutput1);
+  DoTestHMac('HMac-MD5', FoutputMD5);
+  DoTestHMac('HMac-MD4', FoutputMD4);
+  DoTestHMac('HMac-MD2', FoutputMD2);
+  DoTestHMac('HMac-SHA224', Foutput224);
+  DoTestHMac('HMac-SHA256', Foutput256);
+  DoTestHMac('HMac-SHA384', Foutput384);
+  DoTestHMac('HMac-SHA512', Foutput512);
+  DoTestHMac('HMac-SHA512/224', Foutput512_224);
+  DoTestHMac('HMac-SHA512/256', Foutput512_256);
+
+  DoTestHMac('HMac-RIPEMD128', FoutputRipeMD128);
+  DoTestHMac('HMac-RIPEMD160', FoutputRipeMD160);
+
+  DoTestHMac('HMac-TIGER', FoutputTiger);
+
+  DoTestHMac('HMac-SHA3-224', 224, FoutputSha3_224);
+  DoTestHMac('HMac-SHA3-256', 256, FoutputSha3_256);
+  DoTestHMac('HMac-SHA3-384', 384, FoutputSha3_384);
+  DoTestHMac('HMac-SHA3-512', 512, FoutputSha3_512);
+
+  DoTestHMac('HMac-GOST3411-2012-256', 256, FoutputGost2012_256);
+  DoTestHMac('HMac-GOST3411-2012-512', 512, FoutputGost2012_512);
+
+  DoTestHMac('HMac/SHA1', Foutput1);
+
+  DoTestHMac('HMac/MD5', FoutputMD5);
+  DoTestHMac('HMac/MD4', FoutputMD4);
+  DoTestHMac('HMac/MD2', FoutputMD2);
+
+  DoTestHMac('HMac/SHA224', Foutput224);
+  DoTestHMac('HMac/SHA256', Foutput256);
+  DoTestHMac('HMac/SHA384', Foutput384);
+  DoTestHMac('HMac/SHA512', Foutput512);
+
+  DoTestHMac('HMac/RIPEMD128', FoutputRipeMD128);
+  DoTestHMac('HMac/RIPEMD160', FoutputRipeMD160);
+  DoTestHMac('HMac/TIGER', FoutputTiger);
+
+  DoTestHMac('HMac/SHA3-224', 224, FoutputSha3_224);
+  DoTestHMac('HMac/SHA3-256', 256, FoutputSha3_256);
+  DoTestHMac('HMac/SHA3-384', 384, FoutputSha3_384);
+  DoTestHMac('HMac/SHA3-512', 512, FoutputSha3_512);
+
+  DoTestHMac('HMac/GOST3411-2012-256', 256, FoutputGost2012_256);
+  DoTestHMac('HMac/GOST3411-2012-512', 512, FoutputGost2012_512);
+
+  DoTestHMac(TPkcsObjectIdentifiers.IdHmacWithSha1.Id, Foutput1);
+  DoTestHMac(TPkcsObjectIdentifiers.IdHmacWithSha224.Id, Foutput224);
+  DoTestHMac(TPkcsObjectIdentifiers.IdHmacWithSha256.Id, Foutput256);
+  DoTestHMac(TPkcsObjectIdentifiers.IdHmacWithSha384.Id, Foutput384);
+  DoTestHMac(TPkcsObjectIdentifiers.IdHmacWithSha512.Id, Foutput512);
+  DoTestHMac(TIanaObjectIdentifiers.HmacSha1.Id, Foutput1);
+
+  DoTestHMac(TIanaObjectIdentifiers.HmacMD5.Id, FoutputMD5);
+
+  DoTestHMac(TIanaObjectIdentifiers.HmacRipeMD160.Id, FoutputRipeMD160);
+
+  DoTestHMac(TIanaObjectIdentifiers.HmacTiger.Id, FoutputTiger);
+
+  DoTestHMac(TNistObjectIdentifiers.IdHMacWithSha3_224.Id, 224,
+    FoutputSha3_224);
+  DoTestHMac(TNistObjectIdentifiers.IdHMacWithSha3_256.Id, 256,
+    FoutputSha3_256);
+  DoTestHMac(TNistObjectIdentifiers.IdHMacWithSha3_384.Id, 384,
+    FoutputSha3_384);
+  DoTestHMac(TNistObjectIdentifiers.IdHMacWithSha3_512.Id, 512,
+    FoutputSha3_512);
+
+  DoTestHMac(TRosstandartObjectIdentifiers.id_tc26_hmac_gost_3411_12_256.Id,
+    256, FoutputGost2012_256);
+  DoTestHMac(TRosstandartObjectIdentifiers.id_tc26_hmac_gost_3411_12_512.Id,
+    512, FoutputGost2012_512);
+
+  DoTestExceptions();
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestHMac);
+{$ELSE}
+  RegisterTest(TTestHMac.Suite);
+{$ENDIF FPC}
+
+end.

+ 4 - 4
CryptoLib.Tests/src/Crypto/IESCipherTests.pas

@@ -33,7 +33,7 @@ uses
   TestFramework,
   TestFramework,
 {$ENDIF FPC}
 {$ENDIF FPC}
   ClpIDigest,
   ClpIDigest,
-  ClpIDigestMAC,
+  ClpIMac,
   ClpAesEngine,
   ClpAesEngine,
   ClpIAesEngine,
   ClpIAesEngine,
   ClpIAsymmetricCipherKeyPairGenerator,
   ClpIAsymmetricCipherKeyPairGenerator,
@@ -75,6 +75,7 @@ uses
   ClpIESCipher,
   ClpIESCipher,
   ClpHex,
   ClpHex,
   ClpDigestUtilities,
   ClpDigestUtilities,
+  ClpMacUtilities,
   ClpArrayUtils;
   ClpArrayUtils;
 
 
 type
 type
@@ -145,7 +146,7 @@ var
   blockCipher: ICbcBlockCipher;
   blockCipher: ICbcBlockCipher;
   ECDHBasicAgreementInstance: IECDHBasicAgreement;
   ECDHBasicAgreementInstance: IECDHBasicAgreement;
   KDFInstance: IKdf2BytesGenerator;
   KDFInstance: IKdf2BytesGenerator;
-  DigestMACInstance: IDigestMAC;
+  DigestMACInstance: IMac;
 
 
 begin
 begin
   // // Set up IES Cipher Engine
   // // Set up IES Cipher Engine
@@ -155,8 +156,7 @@ begin
   KDFInstance := TKdf2BytesGenerator.Create
   KDFInstance := TKdf2BytesGenerator.Create
     (TDigestUtilities.GetDigest('SHA-256'));
     (TDigestUtilities.GetDigest('SHA-256'));
 
 
-  DigestMACInstance := TDigestUtilities.GetDigestMAC
-    (TDigestUtilities.GetDigest('SHA-256'));
+  DigestMACInstance := TMacUtilities.GetMac('HMAC-SHA-256');
 
 
   // Method 1: Set Up Block Cipher
   // Method 1: Set Up Block Cipher
   // Cipher := TCipherUtilities.GetCipher('AES/CBC/PKCS7PADDING') as IBufferedBlockCipher;
   // Cipher := TCipherUtilities.GetCipher('AES/CBC/PKCS7PADDING') as IBufferedBlockCipher;

+ 165 - 0
CryptoLib.Tests/src/Crypto/MD5HMacTests.pas

@@ -0,0 +1,165 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit MD5HMacTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+{$HINTS OFF}
+
+uses
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpKeyParameter,
+  ClpIKeyParameter,
+  ClpHMac,
+  ClpIMac,
+  ClpDigestUtilities,
+  ClpHex,
+  ClpArrayUtils,
+  ClpStringUtils,
+  ClpCryptoLibTypes;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  /// <summary>
+  /// MD5 HMac Test, test vectors from RFC 2202
+  /// </summary>
+  TTestMD5HMac = class(TCryptoLibTestCase)
+  private
+  var
+    Fkeys, Fdigests, Fmessages: TCryptoLibStringArray;
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+
+    procedure TestMD5HMac;
+
+  end;
+
+implementation
+
+{ TTestMD5HMac }
+
+procedure TTestMD5HMac.SetUp;
+begin
+  inherited;
+  Fkeys := TCryptoLibStringArray.Create('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b',
+    '4a656665', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
+    '0102030405060708090a0b0c0d0e0f10111213141516171819',
+    '0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c',
+    'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
+    'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
+
+  Fdigests := TCryptoLibStringArray.Create('9294727a3638bb1c13f48ef8158bfc9d',
+    '750c783e6ab0b503eaa86e310a5db738', '56be34521d144c88dbb8c733f0e8b3f6',
+    '697eaf0aca3a3aea3a75164746ffaa79', '56461ef2342edc00f9bab995690efd4c',
+    '6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd', '6f630fad67cda0ee1fb1f562db3aa53e');
+
+  Fmessages := TCryptoLibStringArray.Create('Hi There',
+    'what do ya want for nothing?',
+    '0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd',
+    '0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd',
+    'Test With Truncation',
+    'Test Using Larger Than Block-Size Key - Hash Key First',
+    'Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data');
+
+end;
+
+procedure TTestMD5HMac.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestMD5HMac.TestMD5HMac;
+var
+  hmac: IMac;
+  resBuf, m, m2: TBytes;
+  i, vector: Int32;
+begin
+  hmac := THMac.Create(TDigestUtilities.GetDigest('MD5'));
+  System.SetLength(resBuf, hmac.GetMacSize());
+
+  for i := 0 to System.Pred(System.Length(Fmessages)) do
+  begin
+    m := TEncoding.ASCII.GetBytes(Fmessages[i]);
+    if (TStringUtils.BeginsWith(Fmessages[i], '0x', True)) then
+    begin
+      m := THex.Decode(System.Copy(Fmessages[i], 3,
+        System.Length(Fmessages[i]) - 2));
+    end;
+    hmac.Init(TKeyParameter.Create(THex.Decode(Fkeys[i])));
+    hmac.BlockUpdate(m, 0, System.Length(m));
+    hmac.DoFinal(resBuf, 0);
+
+    if (not TArrayUtils.AreEqual(resBuf, THex.Decode(Fdigests[i]))) then
+    begin
+      Fail('Vector ' + IntToStr(i) + ' failed');
+    end;
+  end;
+
+  // test reset
+  vector := 0; // vector used for test
+  m2 := TEncoding.ASCII.GetBytes(Fmessages[vector]);
+
+  if (TStringUtils.BeginsWith(Fmessages[vector], '0x', True)) then
+  begin
+    m2 := THex.Decode(System.Copy(Fmessages[vector], 3,
+      System.Length(Fmessages[vector]) - 2));
+  end;
+
+  hmac.Init(TKeyParameter.Create(THex.Decode(Fkeys[vector])));
+  hmac.BlockUpdate(m2, 0, System.Length(m2));
+  hmac.DoFinal(resBuf, 0);
+  hmac.Reset();
+  hmac.BlockUpdate(m2, 0, System.Length(m2));
+  hmac.DoFinal(resBuf, 0);
+
+  if (not TArrayUtils.AreEqual(resBuf, THex.Decode(Fdigests[vector]))) then
+  begin
+    Fail('Reset with vector ' + IntToStr(vector) + ' failed');
+  end;
+
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestMD5HMac);
+{$ELSE}
+  RegisterTest(TTestMD5HMac.Suite);
+{$ENDIF FPC}
+
+end.

+ 425 - 0
CryptoLib.Tests/src/Crypto/Pkcs5Tests.pas

@@ -0,0 +1,425 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit Pkcs5Tests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+{$HINTS OFF}
+
+uses
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpKeyParameter,
+  ClpIKeyParameter,
+  ClpPkcs5S2ParametersGenerator,
+  ClpIPkcs5S2ParametersGenerator,
+  ClpDigestUtilities,
+  ClpHex,
+  ClpArrayUtils,
+  ClpCryptoLibTypes;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  /// <summary>
+  /// A test class for Pkcs5 PbeS2 with PBKDF2(Pkcs5 v2.0).
+  /// </summary>
+  TTestPkcs5 = class(TCryptoLibTestCase)
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+
+    /// <summary>
+    /// Test Vectors gotten from <see href="https://github.com/ircmaxell/PHP-PasswordLib/blob/master/test/Data/Vectors/pbkdf2-draft-josefsson-sha1.test-vectors">
+    /// PKDF2 Test Vectors</see> and some other sources.
+    /// </summary>
+    procedure TestPkcs5_WITH_SHA1;
+
+    /// <summary>
+    /// Test Vectors gotten from <see href="https://github.com/ircmaxell/quality-checker/blob/master/tmp/gh_18/PHP-PasswordLib-master/test/Data/Vectors/pbkdf2-draft-josefsson-sha256.test-vectors">
+    /// PKDF2 Test Vectors</see> and some other sources.
+    /// </summary>
+    procedure TestPkcs5_WITH_SHA256;
+
+  end;
+
+implementation
+
+{ TTestPkcs5 }
+
+procedure TTestPkcs5.SetUp;
+begin
+  inherited;
+
+end;
+
+procedure TTestPkcs5.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestPkcs5.TestPkcs5_WITH_SHA1;
+var
+  PasswordString, SaltString: String;
+  PasswordBytes, SaltBytes: TBytes;
+  generator: IPkcs5S2ParametersGenerator;
+  iteration_count, dkLen: Int32;
+begin
+  //
+  // RFC 3211 tests
+  //
+  SaltBytes := THex.Decode('1234567878563412');
+
+  PasswordString := 'password';
+  PasswordBytes := TEncoding.UTF8.GetBytes(PasswordString);
+  generator := TPkcs5S2ParametersGenerator.Create
+    (TDigestUtilities.GetDigest('SHA-1'));
+
+  generator.Init(PasswordBytes, SaltBytes, 5);
+
+  if (not TArrayUtils.AreEqual((generator.GenerateDerivedMacParameters(64)
+    as IKeyParameter).GetKey(), THex.Decode('D1DAA78615F287E6'))) then
+  begin
+    Fail('PBKDF2 HMAC-SHA1 with iteration count "5", 64 bits key generation test failed');
+  end;
+
+  PasswordString :=
+    'All n-entities must communicate with other n-entities via n-1 entiteeheehees';
+  PasswordBytes := TEncoding.UTF8.GetBytes(PasswordString);
+
+  generator.Init(PasswordBytes, SaltBytes, 500);
+
+  if (not TArrayUtils.AreEqual((generator.GenerateDerivedMacParameters(192)
+    as IKeyParameter).GetKey(),
+    THex.Decode('6A8970BF68C92CAEA84A8DF28510858607126380CC47AB2D'))) then
+  begin
+    Fail('PBKDF2 HMAC-SHA1 with iteration count "500", 192 bits key generation test failed');
+  end;
+
+  generator.Init(PasswordBytes, SaltBytes, 60000);
+
+  if (not TArrayUtils.AreEqual((generator.GenerateDerivedMacParameters(192)
+    as IKeyParameter).GetKey(),
+    THex.Decode('29AAEF810C12ECD2236BBCFB55407F9852B5573DC1C095BB'))) then
+  begin
+    Fail('PBKDF2 HMAC-SHA1 with iteration count "60000", 192 bits key generation test failed');
+  end;
+
+  // https://github.com/ircmaxell/PHP-PasswordLib/blob/master/test/Data/Vectors/pbkdf2-draft-josefsson-sha1.test-vectors
+
+  generator := TPkcs5S2ParametersGenerator.Create
+    (TDigestUtilities.GetDigest('SHA-1'));
+
+  PasswordString := 'password';
+  PasswordBytes := TEncoding.UTF8.GetBytes(PasswordString);
+
+  SaltString := 'salt';
+  SaltBytes := TEncoding.UTF8.GetBytes(SaltString);
+
+  // 1
+
+  iteration_count := 1;
+
+  dkLen := 20 * 8; // multiplied by 8 to get it in bits
+
+  generator.Init(PasswordBytes, SaltBytes, iteration_count);
+
+  if (not TArrayUtils.AreEqual((generator.GenerateDerivedMacParameters(dkLen)
+    as IKeyParameter).GetKey(),
+    THex.Decode('0C60C80F961F0E71F3A9B524AF6012062FE037A6'))) then
+  begin
+    Fail(Format
+      ('PBKDF2 HMAC-SHA1 with iteration count "%u", %u bits key generation test failed',
+      [iteration_count, dkLen]));
+  end;
+
+  // 2
+
+  iteration_count := 2;
+
+  dkLen := 20 * 8; // multiplied by 8 to get it in bits
+
+  generator.Init(PasswordBytes, SaltBytes, iteration_count);
+
+  if (not TArrayUtils.AreEqual((generator.GenerateDerivedMacParameters(dkLen)
+    as IKeyParameter).GetKey(),
+    THex.Decode('EA6C014DC72D6F8CCD1ED92ACE1D41F0D8DE8957'))) then
+  begin
+    Fail(Format
+      ('PBKDF2 HMAC-SHA1 with iteration count "%u", %u bits key generation test failed',
+      [iteration_count, dkLen]));
+  end;
+
+
+  // 3
+
+  iteration_count := 4096;
+
+  dkLen := 20 * 8; // multiplied by 8 to get it in bits
+
+  generator.Init(PasswordBytes, SaltBytes, iteration_count);
+
+  if (not TArrayUtils.AreEqual((generator.GenerateDerivedMacParameters(dkLen)
+    as IKeyParameter).GetKey(),
+    THex.Decode('4B007901B765489ABEAD49D926F721D065A429C1'))) then
+  begin
+    Fail(Format
+      ('PBKDF2 HMAC-SHA1 with iteration count "%u", %u bits key generation test failed',
+      [iteration_count, dkLen]));
+  end;
+
+  // 4
+  // commented out because iteration_count is very large
+  // iteration_count := 16777216;
+  //
+  // dkLen := 20 * 8; // multiplied by 8 to get it in bits
+  //
+  // generator.Init(PasswordBytes, SaltBytes, iteration_count);
+  //
+  // if (not TArrayUtils.AreEqual((generator.GenerateDerivedMacParameters(dkLen)
+  // as IKeyParameter).GetKey(),
+  // THex.Decode('EEFE3D61CD4DA4E4E9945B3D6BA2158C2634E984'))) then
+  // begin
+  // Fail(Format
+  // ('PBKDF2 HMAC-SHA1 with iteration count "%u", %u bits key generation test failed',
+  // [iteration_count, dkLen]));
+  // end;
+
+
+  // 5
+
+  PasswordString := 'passwordPASSWORDpassword';
+  PasswordBytes := TEncoding.UTF8.GetBytes(PasswordString);
+
+  SaltString := 'saltSALTsaltSALTsaltSALTsaltSALTsalt';
+  SaltBytes := TEncoding.UTF8.GetBytes(SaltString);
+
+  iteration_count := 4096;
+
+  dkLen := 25 * 8; // multiplied by 8 to get it in bits
+
+  generator.Init(PasswordBytes, SaltBytes, iteration_count);
+
+  if (not TArrayUtils.AreEqual((generator.GenerateDerivedMacParameters(dkLen)
+    as IKeyParameter).GetKey(),
+    THex.Decode('3D2EEC4FE41C849B80C8D83662C0E44A8B291A964CF2F07038'))) then
+  begin
+    Fail(Format
+      ('PBKDF2 HMAC-SHA1 with iteration count "%u", %u bits key generation test failed',
+      [iteration_count, dkLen]));
+  end;
+
+
+  // 6
+
+  PasswordString := 'pass' + Char(0) + 'word';
+  // Char(0) represents #0 (null char)
+  PasswordBytes := TEncoding.UTF8.GetBytes(PasswordString);
+
+  SaltString := 'sa' + Char(0) + 'lt'; // Char(0) represents #0 (null char)
+  SaltBytes := TEncoding.UTF8.GetBytes(SaltString);
+
+  iteration_count := 4096;
+
+  dkLen := 16 * 8; // multiplied by 8 to get it in bits
+
+  generator.Init(PasswordBytes, SaltBytes, iteration_count);
+
+  if (not TArrayUtils.AreEqual((generator.GenerateDerivedMacParameters(dkLen)
+    as IKeyParameter).GetKey(), THex.Decode('56FA6AA75548099DCC37D7F03425E0C3')))
+  then
+  begin
+    Fail(Format
+      ('PBKDF2 HMAC-SHA1 with iteration count "%u", %u bits key generation test failed',
+      [iteration_count, dkLen]));
+  end;
+
+end;
+
+procedure TTestPkcs5.TestPkcs5_WITH_SHA256;
+var
+  PasswordString, SaltString: String;
+  PasswordBytes, SaltBytes: TBytes;
+  generator: IPkcs5S2ParametersGenerator;
+  iteration_count, dkLen: Int32;
+begin
+
+  // https://github.com/ircmaxell/quality-checker/blob/master/tmp/gh_18/PHP-PasswordLib-master/test/Data/Vectors/pbkdf2-draft-josefsson-sha256.test-vectors
+
+  generator := TPkcs5S2ParametersGenerator.Create
+    (TDigestUtilities.GetDigest('SHA-256'));
+
+  PasswordString := 'password';
+  PasswordBytes := TEncoding.UTF8.GetBytes(PasswordString);
+
+  SaltString := 'salt';
+  SaltBytes := TEncoding.UTF8.GetBytes(SaltString);
+
+  // 1
+
+  iteration_count := 1;
+
+  dkLen := 32 * 8; // multiplied by 8 to get it in bits
+
+  generator.Init(PasswordBytes, SaltBytes, iteration_count);
+
+  if (not TArrayUtils.AreEqual((generator.GenerateDerivedMacParameters(dkLen)
+    as IKeyParameter).GetKey(),
+    THex.Decode
+    ('120FB6CFFCF8B32C43E7225256C4F837A86548C92CCC35480805987CB70BE17B'))) then
+  begin
+    Fail(Format
+      ('PBKDF2 HMAC-SHA256 with iteration count "%u", %u bits key generation test failed',
+      [iteration_count, dkLen]));
+  end;
+
+  // 2
+
+  iteration_count := 2;
+
+  dkLen := 32 * 8; // multiplied by 8 to get it in bits
+
+  generator.Init(PasswordBytes, SaltBytes, iteration_count);
+
+  if (not TArrayUtils.AreEqual((generator.GenerateDerivedMacParameters(dkLen)
+    as IKeyParameter).GetKey(),
+    THex.Decode
+    ('AE4D0C95AF6B46D32D0ADFF928F06DD02A303F8EF3C251DFD6E2D85A95474C43'))) then
+  begin
+    Fail(Format
+      ('PBKDF2 HMAC-SHA256 with iteration count "%u", %u bits key generation test failed',
+      [iteration_count, dkLen]));
+  end;
+
+
+  // 3
+
+  iteration_count := 4096;
+
+  dkLen := 32 * 8; // multiplied by 8 to get it in bits
+
+  generator.Init(PasswordBytes, SaltBytes, iteration_count);
+
+  if (not TArrayUtils.AreEqual((generator.GenerateDerivedMacParameters(dkLen)
+    as IKeyParameter).GetKey(),
+    THex.Decode
+    ('C5E478D59288C841AA530DB6845C4C8D962893A001CE4E11A4963873AA98134A'))) then
+  begin
+    Fail(Format
+      ('PBKDF2 HMAC-SHA256 with iteration count "%u", %u bits key generation test failed',
+      [iteration_count, dkLen]));
+  end;
+
+  // 4
+  // commented out because iteration_count is very large
+  // iteration_count := 16777216;
+  //
+  // dkLen := 32 * 8; // multiplied by 8 to get it in bits
+  //
+  // generator.Init(PasswordBytes, SaltBytes, iteration_count);
+  //
+  // if (not TArrayUtils.AreEqual((generator.GenerateDerivedMacParameters(dkLen)
+  // as IKeyParameter).GetKey(),
+  // THex.Decode
+  // ('CF81C66FE8CFC04D1F31ECB65DAB4089F7F179E89B3B0BCB17AD10E3AC6EBA46'))) then
+  // begin
+  // Fail(Format
+  // ('PBKDF2 HMAC-SHA256 with iteration count "%u", %u bits key generation test failed',
+  // [iteration_count, dkLen]));
+  // end;
+
+
+  // 5
+
+  PasswordString := 'passwordPASSWORDpassword';
+  PasswordBytes := TEncoding.UTF8.GetBytes(PasswordString);
+
+  SaltString := 'saltSALTsaltSALTsaltSALTsaltSALTsalt';
+  SaltBytes := TEncoding.UTF8.GetBytes(SaltString);
+
+  iteration_count := 4096;
+
+  dkLen := 40 * 8; // multiplied by 8 to get it in bits
+
+  generator.Init(PasswordBytes, SaltBytes, iteration_count);
+
+  if (not TArrayUtils.AreEqual((generator.GenerateDerivedMacParameters(dkLen)
+    as IKeyParameter).GetKey(),
+    THex.Decode
+    ('348C89DBCBD32B2F32D814B8116E84CF2B17347EBC1800181C4E2A1FB8DD53E1C635518C7DAC47E9'))
+    ) then
+  begin
+    Fail(Format
+      ('PBKDF2 HMAC-SHA256 with iteration count "%u", %u bits key generation test failed',
+      [iteration_count, dkLen]));
+  end;
+
+
+  // 6
+
+  PasswordString := 'pass' + Char(0) + 'word';
+  // Char(0) represents #0 (null char)
+  PasswordBytes := TEncoding.UTF8.GetBytes(PasswordString);
+
+  SaltString := 'sa' + Char(0) + 'lt'; // Char(0) represents #0 (null char)
+  SaltBytes := TEncoding.UTF8.GetBytes(SaltString);
+
+  iteration_count := 4096;
+
+  dkLen := 16 * 8; // multiplied by 8 to get it in bits
+
+  generator.Init(PasswordBytes, SaltBytes, iteration_count);
+
+  if (not TArrayUtils.AreEqual((generator.GenerateDerivedMacParameters(dkLen)
+    as IKeyParameter).GetKey(), THex.Decode('89B69D0516F829893C696226650A8687')))
+  then
+  begin
+    Fail(Format
+      ('PBKDF2 HMAC-SHA256 with iteration count "%u", %u bits key generation test failed',
+      [iteration_count, dkLen]));
+  end;
+
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestPkcs5);
+{$ELSE}
+  RegisterTest(TTestPkcs5.Suite);
+{$ENDIF FPC}
+
+end.

+ 15 - 7
CryptoLib/src/Asn1/ClpBerOctetString.pas

@@ -67,7 +67,7 @@ type
     /// <summary>
     /// <summary>
     /// return the DER octets that make up this string.
     /// return the DER octets that make up this string.
     /// </summary>
     /// </summary>
-    function GetEnumerator: TEnumerator<IDerOctetString>;
+    function GetEnumerable: TCryptoLibGenericArray<IDerOctetString>;
 
 
     procedure Encode(const derOut: IDerOutputStream); override;
     procedure Encode(const derOut: IDerOutputStream); override;
 
 
@@ -121,7 +121,7 @@ begin
     //
     //
     // write out the octet array
     // write out the octet array
     //
     //
-    for oct in Self do
+    for oct in Self.GetEnumerable do
     begin
     begin
       derOut.WriteObject(oct);
       derOut.WriteObject(oct);
     end;
     end;
@@ -169,18 +169,26 @@ begin
     result.Add(TDerOctetString.Create(nStr) as IDerOctetString);
     result.Add(TDerOctetString.Create(nStr) as IDerOctetString);
     System.Inc(i, MaxLength);
     System.Inc(i, MaxLength);
   end;
   end;
-  Focts := result; // review removal
 end;
 end;
 
 
-function TBerOctetString.GetEnumerator: TEnumerator<IDerOctetString>;
+function TBerOctetString.GetEnumerable: TCryptoLibGenericArray<IDerOctetString>;
+var
+  LList: TList<IDerOctetString>;
 begin
 begin
+
   if (Focts = Nil) then
   if (Focts = Nil) then
   begin
   begin
-    result := GenerateOcts().GetEnumerator();
-    Exit;
+    LList := GenerateOcts();
+    try
+      result := LList.ToArray;
+      Exit;
+    finally
+      LList.Free;
+    end;
   end;
   end;
 
 
-  result := Focts.GetEnumerator();
+  result := Focts.ToArray;
+
 end;
 end;
 
 
 function TBerOctetString.GetOctets: TCryptoLibByteArray;
 function TBerOctetString.GetOctets: TCryptoLibByteArray;

+ 9 - 19
CryptoLib/src/Asn1/ClpBerTaggedObject.pas

@@ -113,10 +113,10 @@ end;
 procedure TBerTaggedObject.Encode(const derOut: IDerOutputStream);
 procedure TBerTaggedObject.Encode(const derOut: IDerOutputStream);
 var
 var
   eObj: TList<IAsn1Encodable>;
   eObj: TList<IAsn1Encodable>;
-  enumeratorIBerOctetString: TEnumerator<IDerOctetString>;
   enumeratorIAsn1Sequence, enumeratorIAsn1Set: TEnumerator<IAsn1Encodable>;
   enumeratorIAsn1Sequence, enumeratorIAsn1Set: TEnumerator<IAsn1Encodable>;
   asn1OctetString: IAsn1OctetString;
   asn1OctetString: IAsn1OctetString;
   berOctetString: IBerOctetString;
   berOctetString: IBerOctetString;
+  derOctetString: IDerOctetString;
   asn1Sequence: IAsn1Sequence;
   asn1Sequence: IAsn1Sequence;
   asn1Set: IAsn1Set;
   asn1Set: IAsn1Set;
   o: IAsn1Encodable;
   o: IAsn1Encodable;
@@ -137,28 +137,18 @@ begin
           begin
           begin
             if (Supports(asn1OctetString, IBerOctetString, berOctetString)) then
             if (Supports(asn1OctetString, IBerOctetString, berOctetString)) then
             begin
             begin
-              enumeratorIBerOctetString := berOctetString.GetEnumerator;
-              try
-                while enumeratorIBerOctetString.MoveNext do
-                begin
-                  eObj.Add(enumeratorIBerOctetString.Current as IAsn1Encodable);
-                end;
-              finally
-                enumeratorIBerOctetString.Free;
+              for derOctetString in berOctetString.GetEnumerable do
+              begin
+                eObj.Add(derOctetString as IAsn1Encodable);
               end;
               end;
             end
             end
             else
             else
             begin
             begin
-              enumeratorIBerOctetString :=
-                TBerOctetString.Create(asn1OctetString.GetOctets())
-                .GetEnumerator;
-              try
-                while enumeratorIBerOctetString.MoveNext do
-                begin
-                  eObj.Add(enumeratorIBerOctetString.Current as IAsn1Encodable);
-                end;
-              finally
-                enumeratorIBerOctetString.Free;
+              berOctetString := TBerOctetString.Create
+                (asn1OctetString.GetOctets());
+              for derOctetString in berOctetString.GetEnumerable do
+              begin
+                eObj.Add(derOctetString as IAsn1Encodable);
               end;
               end;
             end
             end
           end
           end

+ 113 - 0
CryptoLib/src/Asn1/Iana/ClpIanaObjectIdentifiers.pas

@@ -0,0 +1,113 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpIanaObjectIdentifiers;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpDerObjectIdentifier,
+  ClpIDerObjectIdentifier;
+
+type
+  TIanaObjectIdentifiers = class abstract(TObject)
+
+  strict private
+
+    // id-SHA1 OBJECT IDENTIFIER ::=
+    // {iso(1) identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) ipsec(8) isakmpOakley(1)}
+    //
+
+    class var
+
+      FIsakmpOakley, FHmacMD5, FHmacSha1, FHmacTiger, FHmacRipeMD160
+      : IDerObjectIdentifier;
+
+    class function GetIsakmpOakley: IDerObjectIdentifier; static; inline;
+    class function GetHmacMD5: IDerObjectIdentifier; static; inline;
+    class function GetHmacSha1: IDerObjectIdentifier; static; inline;
+
+    class function GetHmacTiger: IDerObjectIdentifier; static; inline;
+    class function GetHmacRipeMD160: IDerObjectIdentifier; static; inline;
+
+    class constructor IanaObjectIdentifiers();
+
+  public
+
+    class property IsakmpOakley: IDerObjectIdentifier read GetIsakmpOakley;
+
+    class property HmacMD5: IDerObjectIdentifier read GetHmacMD5;
+
+    class property HmacSha1: IDerObjectIdentifier read GetHmacSha1;
+
+    class property HmacTiger: IDerObjectIdentifier read GetHmacTiger;
+
+    class property HmacRipeMD160: IDerObjectIdentifier read GetHmacRipeMD160;
+
+    class procedure Boot(); static;
+
+  end;
+
+implementation
+
+{ TIanaObjectIdentifiers }
+
+class procedure TIanaObjectIdentifiers.Boot;
+begin
+  FIsakmpOakley := TDerObjectIdentifier.Create('1.3.6.1.5.5.8.1');
+
+  FHmacMD5 := TDerObjectIdentifier.Create(IsakmpOakley.ID + '.1');
+  FHmacSha1 := TDerObjectIdentifier.Create(IsakmpOakley.ID + '.2');
+
+  FHmacTiger := TDerObjectIdentifier.Create(IsakmpOakley.ID + '.3');
+
+  FHmacRipeMD160 := TDerObjectIdentifier.Create(IsakmpOakley.ID + '.4');
+end;
+
+class function TIanaObjectIdentifiers.GetHmacMD5: IDerObjectIdentifier;
+begin
+  result := FHmacMD5;
+end;
+
+class function TIanaObjectIdentifiers.GetHmacRipeMD160: IDerObjectIdentifier;
+begin
+  result := FHmacRipeMD160;
+end;
+
+class function TIanaObjectIdentifiers.GetHmacSha1: IDerObjectIdentifier;
+begin
+  result := FHmacSha1;
+end;
+
+class function TIanaObjectIdentifiers.GetHmacTiger: IDerObjectIdentifier;
+begin
+  result := FHmacTiger;
+end;
+
+class function TIanaObjectIdentifiers.GetIsakmpOakley: IDerObjectIdentifier;
+begin
+  result := FIsakmpOakley;
+end;
+
+class constructor TIanaObjectIdentifiers.IanaObjectIdentifiers;
+begin
+  TIanaObjectIdentifiers.Boot;
+end;
+
+end.

+ 143 - 0
CryptoLib/src/Asn1/Misc/ClpMiscObjectIdentifiers.pas

@@ -0,0 +1,143 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpMiscObjectIdentifiers;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpDerObjectIdentifier,
+  ClpIDerObjectIdentifier;
+
+type
+  TMiscObjectIdentifiers = class abstract(TObject)
+
+  strict private
+
+    class var
+
+      Fblake2, Fid_blake2b160, Fid_blake2b256, Fid_blake2b384, Fid_blake2b512,
+      Fid_blake2s128, Fid_blake2s160, Fid_blake2s224, Fid_blake2s256
+      : IDerObjectIdentifier;
+
+    class function Getblake2: IDerObjectIdentifier; static; inline;
+
+    class function Getid_blake2b160: IDerObjectIdentifier; static; inline;
+    class function Getid_blake2b256: IDerObjectIdentifier; static; inline;
+    class function Getid_blake2b384: IDerObjectIdentifier; static; inline;
+    class function Getid_blake2b512: IDerObjectIdentifier; static; inline;
+
+    class function Getid_blake2s128: IDerObjectIdentifier; static; inline;
+    class function Getid_blake2s160: IDerObjectIdentifier; static; inline;
+    class function Getid_blake2s224: IDerObjectIdentifier; static; inline;
+    class function Getid_blake2s256: IDerObjectIdentifier; static; inline;
+
+    class constructor MiscObjectIdentifiers();
+
+  public
+
+    class property blake2: IDerObjectIdentifier read Getblake2;
+
+    class property id_blake2b160: IDerObjectIdentifier read Getid_blake2b160;
+    class property id_blake2b256: IDerObjectIdentifier read Getid_blake2b256;
+    class property id_blake2b384: IDerObjectIdentifier read Getid_blake2b384;
+    class property id_blake2b512: IDerObjectIdentifier read Getid_blake2b512;
+
+    class property id_blake2s128: IDerObjectIdentifier read Getid_blake2s128;
+    class property id_blake2s160: IDerObjectIdentifier read Getid_blake2s160;
+    class property id_blake2s224: IDerObjectIdentifier read Getid_blake2s224;
+    class property id_blake2s256: IDerObjectIdentifier read Getid_blake2s256;
+
+    class procedure Boot(); static;
+
+  end;
+
+implementation
+
+{ TMiscObjectIdentifiers }
+
+class procedure TMiscObjectIdentifiers.Boot;
+begin
+  //
+  // Blake2b and Blake2s
+  //
+  Fblake2 := TDerObjectIdentifier.Create('1.3.6.1.4.1.1722.12.2');
+
+  Fid_blake2b160 := blake2.Branch('1.5');
+  Fid_blake2b256 := blake2.Branch('1.8');
+  Fid_blake2b384 := blake2.Branch('1.12');
+  Fid_blake2b512 := blake2.Branch('1.16');
+
+  Fid_blake2s128 := blake2.Branch('2.4');
+  Fid_blake2s160 := blake2.Branch('2.5');
+  Fid_blake2s224 := blake2.Branch('2.7');
+  Fid_blake2s256 := blake2.Branch('2.8');
+end;
+
+class function TMiscObjectIdentifiers.Getblake2: IDerObjectIdentifier;
+begin
+  result := Fblake2;
+end;
+
+class function TMiscObjectIdentifiers.Getid_blake2b160: IDerObjectIdentifier;
+begin
+  result := Fid_blake2b160;
+end;
+
+class function TMiscObjectIdentifiers.Getid_blake2b256: IDerObjectIdentifier;
+begin
+  result := Fid_blake2b256;
+end;
+
+class function TMiscObjectIdentifiers.Getid_blake2b384: IDerObjectIdentifier;
+begin
+  result := Fid_blake2b384;
+end;
+
+class function TMiscObjectIdentifiers.Getid_blake2b512: IDerObjectIdentifier;
+begin
+  result := Fid_blake2b512;
+end;
+
+class function TMiscObjectIdentifiers.Getid_blake2s128: IDerObjectIdentifier;
+begin
+  result := Fid_blake2s128;
+end;
+
+class function TMiscObjectIdentifiers.Getid_blake2s160: IDerObjectIdentifier;
+begin
+  result := Fid_blake2s160;
+end;
+
+class function TMiscObjectIdentifiers.Getid_blake2s224: IDerObjectIdentifier;
+begin
+  result := Fid_blake2s224;
+end;
+
+class function TMiscObjectIdentifiers.Getid_blake2s256: IDerObjectIdentifier;
+begin
+  result := Fid_blake2s256;
+end;
+
+class constructor TMiscObjectIdentifiers.MiscObjectIdentifiers;
+begin
+  TMiscObjectIdentifiers.Boot;
+end;
+
+end.

+ 61 - 9
CryptoLib/src/Asn1/Nist/ClpNistObjectIdentifiers.pas

@@ -32,16 +32,17 @@ type
 
 
     class var
     class var
 
 
-      FNistAlgorithm, FHashAlgs, FAES, FIdSha256, FIdSha384, FIdSha512,
-      FIdSha224, FIdSha512_224, FIdSha512_256, FIdSha3_224, FIdSha3_256,
-      FIdSha3_384, FIdSha3_512, FIdAES128Ecb, FIdAes128Cbc, FIdAes128Ofb,
-      FIdAes128Cfb, FidAes192Ecb, FIdAes192Cbc, FIdAes192Ofb, FIdAes192Cfb,
-      FIdAes256Ecb, FIdAes256Cbc, FIdAes256Ofb, FIdAes256Cfb
-      : IDerObjectIdentifier;
+      FNistAlgorithm, FHashAlgs, FIdSha256, FIdSha384, FIdSha512, FIdSha224,
+      FIdSha512_224, FIdSha512_256, FIdSha3_224, FIdSha3_256, FIdSha3_384,
+      FIdSha3_512, FIdHMacWithSha3_224, FIdHMacWithSha3_256,
+      FIdHMacWithSha3_384, FIdHMacWithSha3_512, FAES, FIdAES128Ecb,
+      FIdAes128Cbc, FIdAes128Ofb, FIdAes128Cfb, FidAes192Ecb, FIdAes192Cbc,
+      FIdAes192Ofb, FIdAes192Cfb, FIdAes256Ecb, FIdAes256Cbc, FIdAes256Ofb,
+      FIdAes256Cfb: IDerObjectIdentifier;
 
 
     class function GetNistAlgorithm: IDerObjectIdentifier; static; inline;
     class function GetNistAlgorithm: IDerObjectIdentifier; static; inline;
     class function GetHashAlgs: IDerObjectIdentifier; static; inline;
     class function GetHashAlgs: IDerObjectIdentifier; static; inline;
-    class function GetAES: IDerObjectIdentifier; static; inline;
+
     class function GetIdSha224: IDerObjectIdentifier; static; inline;
     class function GetIdSha224: IDerObjectIdentifier; static; inline;
     class function GetIdSha256: IDerObjectIdentifier; static; inline;
     class function GetIdSha256: IDerObjectIdentifier; static; inline;
     class function GetIdSha3_224: IDerObjectIdentifier; static; inline;
     class function GetIdSha3_224: IDerObjectIdentifier; static; inline;
@@ -52,6 +53,14 @@ type
     class function GetIdSha512: IDerObjectIdentifier; static; inline;
     class function GetIdSha512: IDerObjectIdentifier; static; inline;
     class function GetIdSha512_224: IDerObjectIdentifier; static; inline;
     class function GetIdSha512_224: IDerObjectIdentifier; static; inline;
     class function GetIdSha512_256: IDerObjectIdentifier; static; inline;
     class function GetIdSha512_256: IDerObjectIdentifier; static; inline;
+
+    class function GetIdHMacWithSha3_224: IDerObjectIdentifier; static; inline;
+    class function GetIdHMacWithSha3_256: IDerObjectIdentifier; static; inline;
+    class function GetIdHMacWithSha3_384: IDerObjectIdentifier; static; inline;
+    class function GetIdHMacWithSha3_512: IDerObjectIdentifier; static; inline;
+
+    class function GetAES: IDerObjectIdentifier; static; inline;
+
     class function GetIdAes128Ecb: IDerObjectIdentifier; static; inline;
     class function GetIdAes128Ecb: IDerObjectIdentifier; static; inline;
     class function GetIdAes128Cbc: IDerObjectIdentifier; static; inline;
     class function GetIdAes128Cbc: IDerObjectIdentifier; static; inline;
     class function GetIdAes128Ofb: IDerObjectIdentifier; static; inline;
     class function GetIdAes128Ofb: IDerObjectIdentifier; static; inline;
@@ -78,7 +87,7 @@ type
     //
     //
     class property NistAlgorithm: IDerObjectIdentifier read GetNistAlgorithm;
     class property NistAlgorithm: IDerObjectIdentifier read GetNistAlgorithm;
     class property HashAlgs: IDerObjectIdentifier read GetHashAlgs;
     class property HashAlgs: IDerObjectIdentifier read GetHashAlgs;
-    class property AES: IDerObjectIdentifier read GetAES;
+
     class property IdSha256: IDerObjectIdentifier read GetIdSha256;
     class property IdSha256: IDerObjectIdentifier read GetIdSha256;
     class property IdSha384: IDerObjectIdentifier read GetIdSha384;
     class property IdSha384: IDerObjectIdentifier read GetIdSha384;
     class property IdSha512: IDerObjectIdentifier read GetIdSha512;
     class property IdSha512: IDerObjectIdentifier read GetIdSha512;
@@ -89,6 +98,18 @@ type
     class property IdSha3_256: IDerObjectIdentifier read GetIdSha3_256;
     class property IdSha3_256: IDerObjectIdentifier read GetIdSha3_256;
     class property IdSha3_384: IDerObjectIdentifier read GetIdSha3_384;
     class property IdSha3_384: IDerObjectIdentifier read GetIdSha3_384;
     class property IdSha3_512: IDerObjectIdentifier read GetIdSha3_512;
     class property IdSha3_512: IDerObjectIdentifier read GetIdSha3_512;
+
+    class property IdHMacWithSha3_224: IDerObjectIdentifier
+      read GetIdHMacWithSha3_224;
+    class property IdHMacWithSha3_256: IDerObjectIdentifier
+      read GetIdHMacWithSha3_256;
+    class property IdHMacWithSha3_384: IDerObjectIdentifier
+      read GetIdHMacWithSha3_384;
+    class property IdHMacWithSha3_512: IDerObjectIdentifier
+      read GetIdHMacWithSha3_512;
+
+    class property AES: IDerObjectIdentifier read GetAES;
+
     class property IdAes128Ecb: IDerObjectIdentifier read GetIdAes128Ecb;
     class property IdAes128Ecb: IDerObjectIdentifier read GetIdAes128Ecb;
     class property IdAes128Cbc: IDerObjectIdentifier read GetIdAes128Cbc;
     class property IdAes128Cbc: IDerObjectIdentifier read GetIdAes128Cbc;
     class property IdAes128Ofb: IDerObjectIdentifier read GetIdAes128Ofb;
     class property IdAes128Ofb: IDerObjectIdentifier read GetIdAes128Ofb;
@@ -114,7 +135,6 @@ class procedure TNistObjectIdentifiers.Boot;
 begin
 begin
   FNistAlgorithm := TDerObjectIdentifier.Create('2.16.840.1.101.3.4');
   FNistAlgorithm := TDerObjectIdentifier.Create('2.16.840.1.101.3.4');
   FHashAlgs := NistAlgorithm.Branch('2');
   FHashAlgs := NistAlgorithm.Branch('2');
-  FAES := TDerObjectIdentifier.Create(NistAlgorithm.id + '.1');
 
 
   FIdSha256 := HashAlgs.Branch('1');
   FIdSha256 := HashAlgs.Branch('1');
   FIdSha384 := HashAlgs.Branch('2');
   FIdSha384 := HashAlgs.Branch('2');
@@ -126,6 +146,14 @@ begin
   FIdSha3_256 := HashAlgs.Branch('8');
   FIdSha3_256 := HashAlgs.Branch('8');
   FIdSha3_384 := HashAlgs.Branch('9');
   FIdSha3_384 := HashAlgs.Branch('9');
   FIdSha3_512 := HashAlgs.Branch('10');
   FIdSha3_512 := HashAlgs.Branch('10');
+
+  FIdHMacWithSha3_224 := HashAlgs.Branch('13');
+  FIdHMacWithSha3_256 := HashAlgs.Branch('14');
+  FIdHMacWithSha3_384 := HashAlgs.Branch('15');
+  FIdHMacWithSha3_512 := HashAlgs.Branch('16');
+
+  FAES := TDerObjectIdentifier.Create(NistAlgorithm.id + '.1');
+
   FIdAES128Ecb := TDerObjectIdentifier.Create(AES.id + '.1');
   FIdAES128Ecb := TDerObjectIdentifier.Create(AES.id + '.1');
   FIdAes128Cbc := TDerObjectIdentifier.Create(AES.id + '.2');
   FIdAes128Cbc := TDerObjectIdentifier.Create(AES.id + '.2');
   FIdAes128Ofb := TDerObjectIdentifier.Create(AES.id + '.3');
   FIdAes128Ofb := TDerObjectIdentifier.Create(AES.id + '.3');
@@ -210,6 +238,30 @@ begin
   result := FIdAes256Ofb;
   result := FIdAes256Ofb;
 end;
 end;
 
 
+class function TNistObjectIdentifiers.GetIdHMacWithSha3_224
+  : IDerObjectIdentifier;
+begin
+  result := FIdHMacWithSha3_224;
+end;
+
+class function TNistObjectIdentifiers.GetIdHMacWithSha3_256
+  : IDerObjectIdentifier;
+begin
+  result := FIdHMacWithSha3_256;
+end;
+
+class function TNistObjectIdentifiers.GetIdHMacWithSha3_384
+  : IDerObjectIdentifier;
+begin
+  result := FIdHMacWithSha3_384;
+end;
+
+class function TNistObjectIdentifiers.GetIdHMacWithSha3_512
+  : IDerObjectIdentifier;
+begin
+  result := FIdHMacWithSha3_512;
+end;
+
 class function TNistObjectIdentifiers.GetIdSha224: IDerObjectIdentifier;
 class function TNistObjectIdentifiers.GetIdSha224: IDerObjectIdentifier;
 begin
 begin
   result := FIdSha224;
   result := FIdSha224;

+ 54 - 7
CryptoLib/src/Asn1/Pkcs/ClpPkcsObjectIdentifiers.pas

@@ -30,24 +30,31 @@ type
 
 
   strict private
   strict private
 
 
+  const
+    //
+    // object identifiers for digests
+    //
+    DigestAlgorithm = '1.2.840.113549.2';
+
     class var
     class var
 
 
-      FMD2, FMD4, FMD5: IDerObjectIdentifier;
+      FMD2, FMD4, FMD5, FIdHmacWithSha1, FIdHmacWithSha224, FIdHmacWithSha256,
+      FIdHmacWithSha384, FIdHmacWithSha512: IDerObjectIdentifier;
 
 
     class function GetMD2: IDerObjectIdentifier; static; inline;
     class function GetMD2: IDerObjectIdentifier; static; inline;
     class function GetMD4: IDerObjectIdentifier; static; inline;
     class function GetMD4: IDerObjectIdentifier; static; inline;
     class function GetMD5: IDerObjectIdentifier; static; inline;
     class function GetMD5: IDerObjectIdentifier; static; inline;
 
 
+    class function GetIdHmacWithSha1: IDerObjectIdentifier; static; inline;
+    class function GetIdHmacWithSha224: IDerObjectIdentifier; static; inline;
+    class function GetIdHmacWithSha256: IDerObjectIdentifier; static; inline;
+    class function GetIdHmacWithSha384: IDerObjectIdentifier; static; inline;
+    class function GetIdHmacWithSha512: IDerObjectIdentifier; static; inline;
+
     class constructor PkcsObjectIdentifiers();
     class constructor PkcsObjectIdentifiers();
 
 
   public
   public
 
 
-    const
-    //
-    // object identifiers for digests
-    //
-    DigestAlgorithm = '1.2.840.113549.2';
-
     //
     //
     // md2 OBJECT IDENTIFIER ::=
     // md2 OBJECT IDENTIFIER ::=
     // {iso(1) member-body(2) US(840) rsadsi(113549) DigestAlgorithm(2) 2}
     // {iso(1) member-body(2) US(840) rsadsi(113549) DigestAlgorithm(2) 2}
@@ -64,6 +71,16 @@ type
     //
     //
     class property MD5: IDerObjectIdentifier read GetMD5;
     class property MD5: IDerObjectIdentifier read GetMD5;
 
 
+    class property IdHmacWithSha1: IDerObjectIdentifier read GetIdHmacWithSha1;
+    class property IdHmacWithSha224: IDerObjectIdentifier
+      read GetIdHmacWithSha224;
+    class property IdHmacWithSha256: IDerObjectIdentifier
+      read GetIdHmacWithSha256;
+    class property IdHmacWithSha384: IDerObjectIdentifier
+      read GetIdHmacWithSha384;
+    class property IdHmacWithSha512: IDerObjectIdentifier
+      read GetIdHmacWithSha512;
+
     class procedure Boot(); static;
     class procedure Boot(); static;
 
 
   end;
   end;
@@ -77,6 +94,36 @@ begin
   FMD2 := TDerObjectIdentifier.Create(DigestAlgorithm + '.2');
   FMD2 := TDerObjectIdentifier.Create(DigestAlgorithm + '.2');
   FMD4 := TDerObjectIdentifier.Create(DigestAlgorithm + '.4');
   FMD4 := TDerObjectIdentifier.Create(DigestAlgorithm + '.4');
   FMD5 := TDerObjectIdentifier.Create(DigestAlgorithm + '.5');
   FMD5 := TDerObjectIdentifier.Create(DigestAlgorithm + '.5');
+  FIdHmacWithSha1 := TDerObjectIdentifier.Create(DigestAlgorithm + '.7');
+  FIdHmacWithSha224 := TDerObjectIdentifier.Create(DigestAlgorithm + '.8');
+  FIdHmacWithSha256 := TDerObjectIdentifier.Create(DigestAlgorithm + '.9');
+  FIdHmacWithSha384 := TDerObjectIdentifier.Create(DigestAlgorithm + '.10');
+  FIdHmacWithSha512 := TDerObjectIdentifier.Create(DigestAlgorithm + '.11');
+end;
+
+class function TPkcsObjectIdentifiers.GetIdHmacWithSha1: IDerObjectIdentifier;
+begin
+  result := FIdHmacWithSha1;
+end;
+
+class function TPkcsObjectIdentifiers.GetIdHmacWithSha224: IDerObjectIdentifier;
+begin
+  result := FIdHmacWithSha224;
+end;
+
+class function TPkcsObjectIdentifiers.GetIdHmacWithSha256: IDerObjectIdentifier;
+begin
+  result := FIdHmacWithSha256;
+end;
+
+class function TPkcsObjectIdentifiers.GetIdHmacWithSha384: IDerObjectIdentifier;
+begin
+  result := FIdHmacWithSha384;
+end;
+
+class function TPkcsObjectIdentifiers.GetIdHmacWithSha512: IDerObjectIdentifier;
+begin
+  result := FIdHmacWithSha512;
 end;
 end;
 
 
 class function TPkcsObjectIdentifiers.GetMD2: IDerObjectIdentifier;
 class function TPkcsObjectIdentifiers.GetMD2: IDerObjectIdentifier;

+ 32 - 34
CryptoLib/src/Crypto/Engines/ClpIESEngine.pas

@@ -24,7 +24,7 @@ interface
 uses
 uses
   Classes,
   Classes,
   SysUtils,
   SysUtils,
-  ClpIDigestMAC,
+  ClpIMac,
   ClpIIESEngine,
   ClpIIESEngine,
   ClpIBasicAgreement,
   ClpIBasicAgreement,
   ClpIDerivationFunction,
   ClpIDerivationFunction,
@@ -76,7 +76,7 @@ type
   var
   var
     Fagree: IBasicAgreement;
     Fagree: IBasicAgreement;
     Fkdf: IDerivationFunction;
     Fkdf: IDerivationFunction;
-    Fmac: IDigestMAC;
+    Fmac: IMac;
     Fcipher: IBufferedBlockCipher;
     Fcipher: IBufferedBlockCipher;
     FmacBuf, FV, FIV: TCryptoLibByteArray;
     FmacBuf, FV, FIV: TCryptoLibByteArray;
     FforEncryption: Boolean;
     FforEncryption: Boolean;
@@ -86,7 +86,7 @@ type
     FkeyParser: IKeyParser;
     FkeyParser: IKeyParser;
 
 
     function GetCipher: IBufferedBlockCipher; inline;
     function GetCipher: IBufferedBlockCipher; inline;
-    function GetMac: IDigestMAC; inline;
+    function GetMac: IMac; inline;
     function EncryptBlock(&in: TCryptoLibByteArray; inOff, inLen: Int32)
     function EncryptBlock(&in: TCryptoLibByteArray; inOff, inLen: Int32)
       : TCryptoLibByteArray; virtual;
       : TCryptoLibByteArray; virtual;
 
 
@@ -109,7 +109,7 @@ type
     /// the message authentication code generator for the message
     /// the message authentication code generator for the message
     /// </param>
     /// </param>
     constructor Create(const agree: IBasicAgreement;
     constructor Create(const agree: IBasicAgreement;
-      const kdf: IDerivationFunction; const mac: IDigestMAC); overload;
+      const kdf: IDerivationFunction; const mac: IMac); overload;
 
 
     /// <summary>
     /// <summary>
     /// Set up for use in conjunction with a block cipher to handle the <br />
     /// Set up for use in conjunction with a block cipher to handle the <br />
@@ -129,7 +129,7 @@ type
     /// the cipher to used for encrypting the message
     /// the cipher to used for encrypting the message
     /// </param>
     /// </param>
     constructor Create(const agree: IBasicAgreement;
     constructor Create(const agree: IBasicAgreement;
-      const kdf: IDerivationFunction; const mac: IDigestMAC;
+      const kdf: IDerivationFunction; const mac: IMac;
       const cipher: IBufferedBlockCipher); overload;
       const cipher: IBufferedBlockCipher); overload;
 
 
     /// <summary>
     /// <summary>
@@ -189,7 +189,7 @@ type
       : TCryptoLibByteArray; virtual;
       : TCryptoLibByteArray; virtual;
 
 
     property cipher: IBufferedBlockCipher read GetCipher;
     property cipher: IBufferedBlockCipher read GetCipher;
-    property mac: IDigestMAC read GetMac;
+    property mac: IMac read GetMac;
 
 
   end;
   end;
 
 
@@ -207,25 +207,25 @@ begin
 end;
 end;
 
 
 constructor TIESEngine.Create(const agree: IBasicAgreement;
 constructor TIESEngine.Create(const agree: IBasicAgreement;
-  const kdf: IDerivationFunction; const mac: IDigestMAC);
+  const kdf: IDerivationFunction; const mac: IMac);
 begin
 begin
   Inherited Create();
   Inherited Create();
   Fagree := agree;
   Fagree := agree;
   Fkdf := kdf;
   Fkdf := kdf;
   Fmac := mac;
   Fmac := mac;
-  System.SetLength(FmacBuf, mac.HashSize);
+  System.SetLength(FmacBuf, mac.GetMacSize);
   Fcipher := Nil;
   Fcipher := Nil;
 end;
 end;
 
 
 constructor TIESEngine.Create(const agree: IBasicAgreement;
 constructor TIESEngine.Create(const agree: IBasicAgreement;
-  const kdf: IDerivationFunction; const mac: IDigestMAC;
+  const kdf: IDerivationFunction; const mac: IMac;
   const cipher: IBufferedBlockCipher);
   const cipher: IBufferedBlockCipher);
 begin
 begin
   Inherited Create();
   Inherited Create();
   Fagree := agree;
   Fagree := agree;
   Fkdf := kdf;
   Fkdf := kdf;
   Fmac := mac;
   Fmac := mac;
-  System.SetLength(FmacBuf, mac.HashSize);
+  System.SetLength(FmacBuf, mac.GetMacSize);
   Fcipher := cipher;
   Fcipher := cipher;
 end;
 end;
 
 
@@ -238,7 +238,7 @@ var
 begin
 begin
   len := 0;
   len := 0;
   // Ensure that the length of the input is greater than the MAC in bytes
   // Ensure that the length of the input is greater than the MAC in bytes
-  if (inLen < (System.Length(FV) + Fmac.HashSize)) then
+  if (inLen < (System.Length(FV) + Fmac.GetMacSize)) then
   begin
   begin
     raise EInvalidCipherTextCryptoLibException.CreateRes
     raise EInvalidCipherTextCryptoLibException.CreateRes
       (@SInvalidCipherTextLength);
       (@SInvalidCipherTextLength);
@@ -248,7 +248,7 @@ begin
   begin
   begin
 
 
     // Streaming mode.
     // Streaming mode.
-    System.SetLength(K1, inLen - System.Length(FV) - Fmac.HashSize);
+    System.SetLength(K1, inLen - System.Length(FV) - Fmac.GetMacSize);
     System.SetLength(K2, Fparam.MacKeySize div 8);
     System.SetLength(K2, Fparam.MacKeySize div 8);
     System.SetLength(K, System.Length(K1) + System.Length(K2));
     System.SetLength(K, System.Length(K1) + System.Length(K2));
 
 
@@ -305,11 +305,11 @@ begin
     Fcipher.Init(False, cp);
     Fcipher.Init(False, cp);
 
 
     System.SetLength(M, Fcipher.GetOutputSize(inLen - System.Length(FV) -
     System.SetLength(M, Fcipher.GetOutputSize(inLen - System.Length(FV) -
-      Fmac.HashSize));
+      Fmac.GetMacSize));
 
 
     // do initial processing
     // do initial processing
     len := Fcipher.ProcessBytes(in_enc, inOff + System.Length(FV),
     len := Fcipher.ProcessBytes(in_enc, inOff + System.Length(FV),
-      inLen - System.Length(FV) - Fmac.HashSize, M, 0);
+      inLen - System.Length(FV) - Fmac.GetMacSize, M, 0);
 
 
   end;
   end;
 
 
@@ -323,23 +323,22 @@ begin
 
 
   // Verify the MAC.
   // Verify the MAC.
   endPoint := inOff + inLen;
   endPoint := inOff + inLen;
-  T1 := TArrayUtils.CopyOfRange(in_enc, endPoint - Fmac.HashSize, endPoint);
+  T1 := TArrayUtils.CopyOfRange(in_enc, endPoint - Fmac.GetMacSize, endPoint);
   System.SetLength(T2, System.Length(T1));
   System.SetLength(T2, System.Length(T1));
-  // set the mac key before calling initialize
-  Fmac.Key := K2;
-  Fmac.Initialize;
 
 
-  Fmac.TransformBytes(in_enc, inOff + System.Length(FV),
-    inLen - System.Length(FV) - System.Length(T2));
+  Fmac.Init((TKeyParameter.Create(K2) as IKeyParameter) as ICipherParameters);
+
+  Fmac.BlockUpdate(in_enc, inOff + System.Length(FV), inLen - System.Length(FV)
+    - System.Length(T2));
   if (p2 <> Nil) then
   if (p2 <> Nil) then
   begin
   begin
-    Fmac.TransformBytes(p2, 0, System.Length(p2));
+    Fmac.BlockUpdate(p2, 0, System.Length(p2));
   end;
   end;
   if (System.Length(FV) <> 0) then
   if (System.Length(FV) <> 0) then
   begin
   begin
-    Fmac.TransformBytes(L2, 0, System.Length(L2));
+    Fmac.BlockUpdate(L2, 0, System.Length(L2));
   end;
   end;
-  T2 := Fmac.TransformFinal.GetBytes;
+  T2 := Fmac.DoFinal();
 
 
   if (not TArrayUtils.ConstantTimeAreEqual(T1, T2)) then
   if (not TArrayUtils.ConstantTimeAreEqual(T1, T2)) then
   begin
   begin
@@ -353,7 +352,7 @@ begin
   end
   end
   else
   else
   begin
   begin
-    len := len + Fcipher.doFinal(M, len);
+    len := len + Fcipher.DoFinal(M, len);
 
 
     Result := TArrayUtils.CopyOfRange(M, 0, len);
     Result := TArrayUtils.CopyOfRange(M, 0, len);
     Exit;
     Exit;
@@ -428,7 +427,7 @@ begin
     System.SetLength(C, Fcipher.GetOutputSize(inLen));
     System.SetLength(C, Fcipher.GetOutputSize(inLen));
 
 
     len := Fcipher.ProcessBytes(&in, inOff, inLen, C, 0);
     len := Fcipher.ProcessBytes(&in, inOff, inLen, C, 0);
-    len := len + Fcipher.doFinal(C, len);
+    len := len + Fcipher.DoFinal(C, len);
   end;
   end;
 
 
   // Convert the length of the encoding vector into a byte array.
   // Convert the length of the encoding vector into a byte array.
@@ -440,20 +439,19 @@ begin
   end;
   end;
 
 
   // Apply the MAC.
   // Apply the MAC.
-  System.SetLength(T, Fmac.HashSize);
-  // set the mac key before calling initialize
-  Fmac.Key := K2;
-  Fmac.Initialize;
-  Fmac.TransformBytes(C, 0, System.Length(C));
+  System.SetLength(T, Fmac.GetMacSize);
+
+  Fmac.Init((TKeyParameter.Create(K2) as IKeyParameter) as ICipherParameters);
+  Fmac.BlockUpdate(C, 0, System.Length(C));
   if (p2 <> Nil) then
   if (p2 <> Nil) then
   begin
   begin
-    Fmac.TransformBytes(p2, 0, System.Length(p2));
+    Fmac.BlockUpdate(p2, 0, System.Length(p2));
   end;
   end;
   if (System.Length(FV) <> 0) then
   if (System.Length(FV) <> 0) then
   begin
   begin
-    Fmac.TransformBytes(L2, 0, System.Length(L2));
+    Fmac.BlockUpdate(L2, 0, System.Length(L2));
   end;
   end;
-  T := Fmac.TransformFinal.GetBytes;
+  T := Fmac.DoFinal;
 
 
   // Output the triple (V,C,T).
   // Output the triple (V,C,T).
   // V := Ephermeral Public Key
   // V := Ephermeral Public Key
@@ -486,7 +484,7 @@ begin
   Result := Fcipher;
   Result := Fcipher;
 end;
 end;
 
 
-function TIESEngine.GetMac: IDigestMAC;
+function TIESEngine.GetMac: IMac;
 begin
 begin
   Result := Fmac;
   Result := Fmac;
 end;
 end;

+ 15 - 16
CryptoLib/src/Crypto/Engines/ClpPascalCoinIESEngine.pas

@@ -24,7 +24,7 @@ interface
 uses
 uses
   SysUtils,
   SysUtils,
   Classes,
   Classes,
-  ClpIDigestMAC,
+  ClpIMac,
   ClpIPascalCoinIESEngine,
   ClpIPascalCoinIESEngine,
   ClpIBufferedBlockCipher,
   ClpIBufferedBlockCipher,
   ClpICipherParameters,
   ClpICipherParameters,
@@ -92,7 +92,7 @@ var
   cp: ICipherParameters;
   cp: ICipherParameters;
 begin
 begin
   // Ensure that the length of the input is greater than the MAC in bytes
   // Ensure that the length of the input is greater than the MAC in bytes
-  if (inLen < (System.Length(FV) + Fmac.HashSize)) then
+  if (inLen < (System.Length(FV) + Fmac.GetMacSize)) then
   begin
   begin
     raise EInvalidCipherTextCryptoLibException.CreateRes
     raise EInvalidCipherTextCryptoLibException.CreateRes
       (@SInvalidCipherTextLength);
       (@SInvalidCipherTextLength);
@@ -131,23 +131,22 @@ begin
   end;
   end;
 
 
   // Verify the MAC.
   // Verify the MAC.
-  T1 := System.Copy(in_enc, System.Length(FV), Fmac.HashSize);
+  T1 := System.Copy(in_enc, System.Length(FV), Fmac.GetMacSize);
   System.SetLength(T2, System.Length(T1));
   System.SetLength(T2, System.Length(T1));
-  // set the mac key before calling initialize
-  Fmac.Key := K2;
-  Fmac.Initialize;
 
 
-  Fmac.TransformBytes(in_enc, inOff + System.Length(FV) + System.Length(T2),
+  Fmac.Init((TKeyParameter.Create(K2) as IKeyParameter) as ICipherParameters);
+
+  Fmac.BlockUpdate(in_enc, inOff + System.Length(FV) + System.Length(T2),
     inLen - System.Length(FV) - System.Length(T2));
     inLen - System.Length(FV) - System.Length(T2));
 
 
-  T2 := Fmac.TransformFinal.GetBytes;
+  T2 := Fmac.DoFinal();
 
 
   if (not TArrayUtils.ConstantTimeAreEqual(T1, T2)) then
   if (not TArrayUtils.ConstantTimeAreEqual(T1, T2)) then
   begin
   begin
     raise EInvalidCipherTextCryptoLibException.CreateRes(@SInvalidMAC);
     raise EInvalidCipherTextCryptoLibException.CreateRes(@SInvalidMAC);
   end;
   end;
 
 
-  Result := Fcipher.doFinal(in_enc, inOff + System.Length(FV) + Fmac.HashSize,
+  Result := Fcipher.DoFinal(in_enc, inOff + System.Length(FV) + Fmac.GetMacSize,
     inLen - System.Length(FV) - System.Length(T2));
     inLen - System.Length(FV) - System.Length(T2));
   Exit;
   Exit;
 end;
 end;
@@ -188,17 +187,17 @@ begin
       Fcipher.Init(true, TKeyParameter.Create(K1) as IKeyParameter);
       Fcipher.Init(true, TKeyParameter.Create(K1) as IKeyParameter);
     end;
     end;
 
 
-    C := Fcipher.doFinal(&in, inOff, inLen);
+    C := Fcipher.DoFinal(&in, inOff, inLen);
   end;
   end;
 
 
   // Apply the MAC.
   // Apply the MAC.
-  System.SetLength(T, Fmac.HashSize);
-  // set the mac key before calling initialize
-  Fmac.Key := K2;
-  Fmac.Initialize;
-  Fmac.TransformBytes(C, 0, System.Length(C));
+  System.SetLength(T, Fmac.GetMacSize);
+
+  Fmac.Init((TKeyParameter.Create(K2) as IKeyParameter) as ICipherParameters);
+
+  Fmac.BlockUpdate(C, 0, System.Length(C));
 
 
-  T := Fmac.TransformFinal.GetBytes;
+  T := Fmac.DoFinal();
 
 
   // Output the quadruple (SECURE_HEAD_SIZE,V,T,C).
   // Output the quadruple (SECURE_HEAD_SIZE,V,T,C).
   // SECURE_HEAD_SIZE := Dummy Random Data for interpolability
   // SECURE_HEAD_SIZE := Dummy Random Data for interpolability

+ 174 - 0
CryptoLib/src/Crypto/Generators/ClpPbeParametersGenerator.pas

@@ -0,0 +1,174 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpPbeParametersGenerator;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpICipherParameters,
+  ClpIPbeParametersGenerator,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SEmptyPassword = 'Password can''t be empty';
+  SEmptySalt = 'Salt can''t be empty';
+  SIterationtooSmall = 'Iteration must be greater than zero.';
+
+type
+
+  /// <summary>
+  /// base class for all Password Based Encryption (Pbe) parameter generator
+  /// classes.
+  /// </summary>
+  TPbeParametersGenerator = class abstract(TInterfacedObject,
+    IPbeParametersGenerator)
+
+  strict protected
+  var
+    FmPassword, FmSalt: TCryptoLibByteArray;
+    FmIterationCount: Int32;
+
+    /// <returns>
+    /// the password byte array.
+    /// </returns>
+    function GetPassword: TCryptoLibByteArray; virtual;
+
+    /// <returns>
+    /// the salt byte array.
+    /// </returns>
+    function GetSalt: TCryptoLibByteArray; virtual;
+
+    /// <returns>
+    /// the iteration count.
+    /// </returns>
+    function GetIterationCount: Int32; virtual;
+
+  public
+
+    procedure Init(password, salt: TCryptoLibByteArray;
+      iterationCount: Int32); virtual;
+
+    /// <value>
+    /// the password byte array.
+    /// </value>
+    property password: TCryptoLibByteArray read GetPassword;
+
+    /// <value>
+    /// the salt byte array.
+    /// </value>
+    property salt: TCryptoLibByteArray read GetSalt;
+
+    /// <value>
+    /// the iteration count.
+    /// </value>
+    property iterationCount: Int32 read GetIterationCount;
+
+    /// <summary>
+    /// Generate derived parameters for a key of length keySize.
+    /// </summary>
+    /// <param name="algorithm">
+    /// a parameters object representing a key.
+    /// </param>
+    /// <param name="keySize">
+    /// the length, in bits, of the key required.
+    /// </param>
+    /// <returns>
+    /// a parameters object representing a key.
+    /// </returns>
+    function GenerateDerivedParameters(const algorithm: String;
+      keySize: Int32): ICipherParameters; overload; virtual; abstract;
+
+    /// <summary>
+    /// Generate derived parameters for a key of length keySize and iv
+    /// of length ivSize.
+    /// </summary>
+    /// <param name="algorithm">
+    /// a parameters object representing a key.
+    /// </param>
+    /// <param name="keySize">
+    /// the length, in bits, of the key required.
+    /// </param>
+    /// <param name="ivSize">
+    /// the length, in bits, of the iv required.
+    /// </param>
+    /// <returns>
+    /// a parameters object representing a key and an iv.
+    /// </returns>
+    function GenerateDerivedParameters(const algorithm: String;
+      keySize, ivSize: Int32): ICipherParameters; overload;
+      virtual; abstract;
+
+    /// <summary>
+    /// Generate derived parameters for a key of length keySize,
+    /// specifically <br />for use with a MAC.
+    /// </summary>
+    /// <param name="keySize">
+    /// the length, in bits, of the key required.
+    /// </param>
+    /// <returns>
+    /// a parameters object representing a key.
+    /// </returns>
+    function GenerateDerivedMacParameters(keySize: Int32)
+      : ICipherParameters; virtual; abstract;
+
+  end;
+
+implementation
+
+{ TPbeParametersGenerator }
+
+function TPbeParametersGenerator.GetIterationCount: Int32;
+begin
+  result := FmIterationCount;
+end;
+
+function TPbeParametersGenerator.GetPassword: TCryptoLibByteArray;
+begin
+  result := System.Copy(FmPassword);
+end;
+
+function TPbeParametersGenerator.GetSalt: TCryptoLibByteArray;
+begin
+  result := System.Copy(FmSalt);
+end;
+
+procedure TPbeParametersGenerator.Init(password, salt: TCryptoLibByteArray;
+  iterationCount: Int32);
+begin
+
+  if (password = Nil) then
+  begin
+    raise EArgumentNilCryptoLibException.CreateRes(@SEmptyPassword);
+  end;
+
+  if (salt = Nil) then
+  begin
+    raise EArgumentNilCryptoLibException.CreateRes(@SEmptySalt);
+  end;
+
+  if (iterationCount < 1) then
+    raise EArgumentCryptoLibException.CreateRes(@SIterationtooSmall);
+
+  FmPassword := System.Copy(password);
+  FmSalt := System.Copy(salt);
+  FmIterationCount := iterationCount;
+end;
+
+end.

+ 197 - 0
CryptoLib/src/Crypto/Generators/ClpPkcs5S2ParametersGenerator.pas

@@ -0,0 +1,197 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpPkcs5S2ParametersGenerator;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+
+  HlpIHashInfo,
+  HlpHashFactory,
+  ClpIDigest,
+  ClpICipherParameters,
+  ClpIPkcs5S2ParametersGenerator,
+  ClpKeyParameter,
+  ClpIKeyParameter,
+  ClpParametersWithIV,
+  ClpIParametersWithIV,
+  ClpParameterUtilities,
+  ClpPbeParametersGenerator,
+  ClpCryptoLibTypes;
+
+type
+
+  /// <summary>
+  /// <see href="https://tools.ietf.org/html/rfc2898#section-5.2">
+  /// Pkcs5S2 Specification</see>
+  /// </summary>
+  TPkcs5S2ParametersGenerator = class sealed(TPbeParametersGenerator,
+    IPkcs5S2ParametersGenerator)
+
+  strict private
+  var
+    Fdigest: IDigest;
+    FPBKDF2_HMAC: HlpIHashInfo.IPBKDF2_HMAC;
+
+    /// <returns>
+    /// the underlying digest.
+    /// </returns>
+    function GetDigest: IDigest; inline;
+
+    function GenerateDerivedKey(dkLen: Int32): TCryptoLibByteArray; inline;
+
+  public
+
+    /// <summary>
+    /// construct a Pkcs5 Scheme 2 Parameters generator.
+    /// </summary>
+    /// <param name="digest">
+    /// digest to use for constructing hmac
+    /// </param>
+    constructor Create(const digest: IDigest);
+
+    procedure Init(password, salt: TCryptoLibByteArray;
+      iterationCount: Int32); override;
+
+    /// <summary>
+    /// Generate a key parameter derived from the password, salt, and
+    /// iteration count we are currently initialised with.
+    /// </summary>
+    /// <param name="algorithm">
+    /// a parameters object representing a key.
+    /// </param>
+    /// <param name="keySize">
+    /// the length, in bits, of the key required.
+    /// </param>
+    /// <returns>
+    /// a parameters object representing a key.
+    /// </returns>
+    function GenerateDerivedParameters(const algorithm: String; keySize: Int32)
+      : ICipherParameters; overload; override;
+
+    /// <summary>
+    /// Generate a key with initialisation vector parameter derived from <br />
+    /// the password, salt, and iteration count we are currently initialised
+    /// with.
+    /// </summary>
+    /// <param name="algorithm">
+    /// a parameters object representing a key.
+    /// </param>
+    /// <param name="keySize">
+    /// the length, in bits, of the key required.
+    /// </param>
+    /// <param name="ivSize">
+    /// the length, in bits, of the iv required.
+    /// </param>
+    /// <returns>
+    /// a parameters object representing a key and an iv.
+    /// </returns>
+    function GenerateDerivedParameters(const algorithm: String;
+      keySize, ivSize: Int32): ICipherParameters; overload; override;
+
+    /// <summary>
+    /// Generate a key parameter for use with a MAC derived from the
+    /// password, salt, and iteration count we are currently initialised
+    /// with.
+    /// </summary>
+    /// <param name="keySize">
+    /// the length, in bits, of the key required.
+    /// </param>
+    /// <returns>
+    /// a parameters object representing a key.
+    /// </returns>
+    function GenerateDerivedMacParameters(keySize: Int32): ICipherParameters;
+      overload; override;
+
+    /// <value>
+    /// the underlying digest.
+    /// </value>
+    property digest: IDigest read GetDigest;
+  end;
+
+implementation
+
+{ TPkcs5S2ParametersGenerator }
+
+constructor TPkcs5S2ParametersGenerator.Create(const digest: IDigest);
+begin
+  Inherited Create();
+  Fdigest := digest;
+end;
+
+function TPkcs5S2ParametersGenerator.GenerateDerivedKey(dkLen: Int32)
+  : TCryptoLibByteArray;
+begin
+  result := FPBKDF2_HMAC.GetBytes(dkLen);
+end;
+
+function TPkcs5S2ParametersGenerator.GenerateDerivedMacParameters
+  (keySize: Int32): ICipherParameters;
+var
+  dKey: TCryptoLibByteArray;
+begin
+  keySize := keySize div 8;
+
+  dKey := GenerateDerivedKey(keySize);
+
+  result := TKeyParameter.Create(dKey, 0, keySize);
+end;
+
+function TPkcs5S2ParametersGenerator.GenerateDerivedParameters(const algorithm
+  : String; keySize: Int32): ICipherParameters;
+var
+  dKey: TCryptoLibByteArray;
+begin
+  keySize := keySize div 8;
+
+  dKey := GenerateDerivedKey(keySize);
+
+  result := TParameterUtilities.CreateKeyParameter(algorithm, dKey, 0, keySize);
+end;
+
+function TPkcs5S2ParametersGenerator.GenerateDerivedParameters(const algorithm
+  : String; keySize, ivSize: Int32): ICipherParameters;
+var
+  dKey: TCryptoLibByteArray;
+  key: IKeyParameter;
+begin
+  keySize := keySize div 8;
+  ivSize := ivSize div 8;
+
+  dKey := GenerateDerivedKey(keySize + ivSize);
+  key := TParameterUtilities.CreateKeyParameter(algorithm, dKey, 0, keySize);
+
+  result := TParametersWithIV.Create(key, dKey, keySize, ivSize);
+end;
+
+function TPkcs5S2ParametersGenerator.GetDigest: IDigest;
+begin
+  result := Fdigest;
+end;
+
+procedure TPkcs5S2ParametersGenerator.Init(password, salt: TCryptoLibByteArray;
+  iterationCount: Int32);
+begin
+  inherited Init(password, salt, iterationCount);
+  FPBKDF2_HMAC := TKDF.TPBKDF2_HMAC.CreatePBKDF2_HMAC(Fdigest, password, salt,
+    iterationCount);
+end;
+
+end.

+ 143 - 0
CryptoLib/src/Crypto/Macs/ClpHMac.pas

@@ -0,0 +1,143 @@
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpHMac;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  HlpIHashInfo,
+  HlpHashFactory,
+  ClpIMac,
+  ClpIHMac,
+  ClpIDigest,
+  ClpIKeyParameter,
+  ClpICipherParameters,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SOutputBufferTooShort = 'Output Buffer Too Short';
+
+type
+
+  /// <summary>
+  /// HMAC implementation based on RFC2104 <br />H(K XOR opad, H(K XOR ipad,
+  /// text))
+  /// </summary>
+  THMac = class sealed(TInterfacedObject, IHMac, IMac)
+
+  strict private
+  var
+    FDigest: IDigest;
+    FHMAC: HlpIHashInfo.IHMac;
+
+    function GetAlgorithmName: string; inline;
+
+  public
+    constructor Create(const digest: IDigest);
+
+    function GetUnderlyingDigest: IDigest; inline;
+    function GetMacSize: Int32; inline;
+
+    procedure Update(input: Byte);
+    procedure BlockUpdate(input: TCryptoLibByteArray; inOff, len: Int32);
+    procedure Init(const parameters: ICipherParameters);
+    function DoFinal(output: TCryptoLibByteArray; outOff: Int32)
+      : Int32; overload;
+    function DoFinal: TCryptoLibByteArray; overload;
+
+    /// <summary>
+    /// Reset the mac generator.
+    /// </summary>
+    procedure Reset();
+
+    property AlgorithmName: String read GetAlgorithmName;
+
+  end;
+
+implementation
+
+{ THMac }
+
+procedure THMac.BlockUpdate(input: TCryptoLibByteArray; inOff, len: Int32);
+begin
+  FHMAC.TransformBytes(input, inOff, len);
+end;
+
+constructor THMac.Create(const digest: IDigest);
+begin
+  Inherited Create();
+  FDigest := digest;
+  FHMAC := THashFactory.THMac.CreateHMAC(FDigest);
+end;
+
+function THMac.DoFinal(output: TCryptoLibByteArray; outOff: Int32): Int32;
+var
+  buf: TCryptoLibByteArray;
+begin
+
+  if (System.Length(output) - outOff) < GetMacSize then
+  begin
+    raise EDataLengthCryptoLibException.CreateRes(@SOutputBufferTooShort);
+  end
+  else
+  begin
+    buf := DoFinal();
+    System.Move(buf[0], output[outOff], System.Length(buf) *
+      System.SizeOf(Byte));
+  end;
+  result := System.Length(buf);
+end;
+
+function THMac.DoFinal: TCryptoLibByteArray;
+begin
+  result := FHMAC.TransformFinal.GetBytes();
+end;
+
+function THMac.GetAlgorithmName: string;
+begin
+  result := FDigest.Name + '/HMAC';
+end;
+
+function THMac.GetMacSize: Int32;
+begin
+  result := FHMAC.HashSize;
+end;
+
+function THMac.GetUnderlyingDigest: IDigest;
+begin
+  result := FDigest;
+end;
+
+procedure THMac.Init(const parameters: ICipherParameters);
+begin
+  FHMAC.Key := (parameters as IKeyParameter).GetKey();
+  FHMAC.Initialize;
+end;
+
+procedure THMac.Reset;
+begin
+  FHMAC.Initialize;
+end;
+
+procedure THMac.Update(input: Byte);
+begin
+  FHMAC.TransformBytes(TCryptoLibByteArray.Create(input));
+end;
+
+end.

+ 3 - 2
CryptoLib/src/Interfaces/ClpIBerOctetString.pas

@@ -23,7 +23,8 @@ interface
 
 
 uses
 uses
   Generics.Collections,
   Generics.Collections,
-  ClpIDerOctetString;
+  ClpIDerOctetString,
+  ClpCryptoLibTypes;
 
 
 type
 type
   IBerOctetString = interface(IDerOctetString)
   IBerOctetString = interface(IDerOctetString)
@@ -36,7 +37,7 @@ type
     /// return the DER octets that make up this string.
     /// return the DER octets that make up this string.
     /// </summary>
     /// </summary>
 
 
-    function GetEnumerator: TEnumerator<IDerOctetString>;
+    function GetEnumerable: TCryptoLibGenericArray<IDerOctetString>;
 
 
   end;
   end;
 
 

+ 4 - 4
CryptoLib/src/Interfaces/ClpIDigestMAC.pas → CryptoLib/src/Interfaces/ClpIHMac.pas

@@ -15,19 +15,19 @@
 
 
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
 
 
-unit ClpIDigestMAC;
+unit ClpIHMac;
 
 
 {$I ..\Include\CryptoLib.inc}
 {$I ..\Include\CryptoLib.inc}
 
 
 interface
 interface
 
 
 uses
 uses
-  HlpIHashInfo;
+  ClpIMac;
 
 
 type
 type
 
 
-  IDigestMAC = interface(IHMAC)
-    ['{D6FC6D29-6624-4264-B527-BF13E3C6D452}']
+  IHMac = interface(IMac)
+ ['{B1182608-04D5-4985-91C8-571C51E07CB5}']
 
 
   end;
   end;
 
 

+ 3 - 3
CryptoLib/src/Interfaces/ClpIIESEngine.pas

@@ -22,7 +22,7 @@ unit ClpIIESEngine;
 interface
 interface
 
 
 uses
 uses
-  ClpIDigestMAC,
+  ClpIMac,
   ClpIBufferedBlockCipher,
   ClpIBufferedBlockCipher,
   ClpICipherParameters,
   ClpICipherParameters,
   ClpIAsymmetricKeyParameter,
   ClpIAsymmetricKeyParameter,
@@ -36,7 +36,7 @@ type
     ['{9FA0E287-9988-467D-9E00-3BECEE4A78C6}']
     ['{9FA0E287-9988-467D-9E00-3BECEE4A78C6}']
 
 
     function GetCipher: IBufferedBlockCipher;
     function GetCipher: IBufferedBlockCipher;
-    function GetMac: IDigestMAC;
+    function GetMac: IMac;
 
 
     /// <summary>
     /// <summary>
     /// Initialise the encryptor/decryptor.
     /// Initialise the encryptor/decryptor.
@@ -95,7 +95,7 @@ type
       : TCryptoLibByteArray;
       : TCryptoLibByteArray;
 
 
     property cipher: IBufferedBlockCipher read GetCipher;
     property cipher: IBufferedBlockCipher read GetCipher;
-    property mac: IDigestMAC read GetMac;
+    property mac: IMac read GetMac;
   end;
   end;
 
 
 implementation
 implementation

+ 131 - 0
CryptoLib/src/Interfaces/ClpIMac.pas

@@ -0,0 +1,131 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpIMac;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIDigest,
+  ClpICipherParameters,
+  ClpCryptoLibTypes;
+
+type
+
+  /// <summary>
+  /// The base interface for implementations of message authentication codes
+  /// (MACs).
+  /// </summary>
+  IMac = interface(IInterface)
+    ['{3273EF2F-AE51-4878-B55C-5F801DB85A74}']
+
+    /// <summary>
+    /// returns the name of the algorithm the MAC implements.
+    /// </summary>
+    function GetAlgorithmName: string;
+
+    function GetUnderlyingDigest: IDigest;
+
+    /// <summary>
+    /// the block size for this MAC (in bytes).
+    /// </summary>
+    function GetMacSize: Int32;
+
+    /// <summary>
+    /// add a single byte to the mac for processing.
+    /// </summary>
+    /// <param name="input">
+    /// the byte to be processed.
+    /// </param>
+    /// <exception cref="EInvalidOperationCryptoLibException">
+    /// if the MAC is not initialised.
+    /// </exception>
+    procedure Update(input: Byte);
+
+    /// <param name="input">
+    /// the array containing the input.
+    /// </param>
+    /// <param name="inOff">
+    /// the index in the array the data begins at.
+    /// </param>
+    /// <param name="len">
+    /// the length of the input starting at inOff.
+    /// </param>
+    /// <exception cref="EInvalidOperationCryptoLibException">
+    /// if the MAC is not initialised.
+    /// </exception>
+    /// <exception cref="EDataLengthCryptoLibException">
+    /// if there isn't enough data in in.
+    /// </exception>
+    procedure BlockUpdate(input: TCryptoLibByteArray; inOff, len: Int32);
+
+    /// <summary>
+    /// Initialise the MAC.
+    /// </summary>
+    /// <param name="parameters">
+    /// the key and other data required by the MAC.
+    /// </param>
+    /// <exception cref="EArgumentCryptoLibException">
+    /// if the parameters argument is inappropriate.
+    /// </exception>
+    procedure Init(const parameters: ICipherParameters);
+
+    /// <summary>
+    /// Compute the final stage of the MAC writing the output to the output
+    /// parameter starting from the outOff parameter
+    /// </summary>
+    /// <param name="output">
+    /// the array the MAC is to be written to.
+    /// </param>
+    /// <param name="outOff">
+    /// the offset into the output buffer the output is to start at.
+    /// </param>
+    /// <exception cref="EDataLengthCryptoLibException">
+    /// if there isn't enough space in output.
+    /// </exception>
+    /// <exception cref="EInvalidOperationCryptoLibException">
+    /// if the MAC is not initialised.
+    /// </exception>
+    function DoFinal(output: TCryptoLibByteArray; outOff: Int32)
+      : Int32; overload;
+
+    /// <summary>
+    /// Compute the final stage of the MAC writing the output to result
+    /// </summary>
+    /// <returns>
+    /// the computed MAC result
+    /// </returns>
+    function DoFinal: TCryptoLibByteArray; overload;
+
+    /// <summary>
+    /// Reset the MAC. At the end of resetting the MAC should be in the <br />
+    /// in the same state it was after the last init (if there was one).
+    /// </summary>
+    procedure Reset();
+
+    /// <summary>
+    /// the name of the algorithm the MAC implements.
+    /// </summary>
+    property AlgorithmName: String read GetAlgorithmName;
+
+  end;
+
+implementation
+
+end.

+ 116 - 0
CryptoLib/src/Interfaces/ClpIPbeParametersGenerator.pas

@@ -0,0 +1,116 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpIPbeParametersGenerator;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpICipherParameters,
+  ClpCryptoLibTypes;
+
+type
+  IPbeParametersGenerator = interface(IInterface)
+
+    ['{8C530FB2-6B8F-4E22-8EA0-D538665471EF}']
+
+    procedure Init(password, salt: TCryptoLibByteArray; iterationCount: Int32);
+
+    /// <returns>
+    /// the password byte array.
+    /// </returns>
+    function GetPassword: TCryptoLibByteArray;
+
+    /// <value>
+    /// the password byte array.
+    /// </value>
+    property password: TCryptoLibByteArray read GetPassword;
+
+    /// <returns>
+    /// the salt byte array.
+    /// </returns>
+    function GetSalt: TCryptoLibByteArray;
+
+    /// <value>
+    /// the salt byte array.
+    /// </value>
+    property salt: TCryptoLibByteArray read GetSalt;
+
+    /// <returns>
+    /// the iteration count.
+    /// </returns>
+    function GetIterationCount: Int32;
+
+    /// <value>
+    /// the iteration count.
+    /// </value>
+    property iterationCount: Int32 read GetIterationCount;
+
+    /// <summary>
+    /// Generate derived parameters for a key of length keySize.
+    /// </summary>
+    /// <param name="algorithm">
+    /// a parameters object representing a key.
+    /// </param>
+    /// <param name="keySize">
+    /// the length, in bits, of the key required.
+    /// </param>
+    /// <returns>
+    /// a parameters object representing a key.
+    /// </returns>
+    function GenerateDerivedParameters(const algorithm: String;
+      keySize: Int32): ICipherParameters; overload;
+
+    /// <summary>
+    /// Generate derived parameters for a key of length keySize and iv
+    /// of length ivSize.
+    /// </summary>
+    /// <param name="algorithm">
+    /// a parameters object representing a key.
+    /// </param>
+    /// <param name="keySize">
+    /// the length, in bits, of the key required.
+    /// </param>
+    /// <param name="ivSize">
+    /// the length, in bits, of the iv required.
+    /// </param>
+    /// <returns>
+    /// a parameters object representing a key and an iv.
+    /// </returns>
+    function GenerateDerivedParameters(const algorithm: String;
+      keySize, ivSize: Int32): ICipherParameters; overload;
+
+    /// <summary>
+    /// Generate derived parameters for a key of length keySize,
+    /// specifically <br />for use with a MAC.
+    /// </summary>
+    /// <param name="keySize">
+    /// the length, in bits, of the key required.
+    /// </param>
+    /// <returns>
+    /// a parameters object representing a key.
+    /// </returns>
+    function GenerateDerivedMacParameters(keySize: Int32)
+      : ICipherParameters;
+
+  end;
+
+implementation
+
+end.

+ 12 - 4
CryptoLib/src/Interfaces/ClpIPBKDF2_DigestMAC.pas → CryptoLib/src/Interfaces/ClpIPkcs5S2ParametersGenerator.pas

@@ -15,19 +15,27 @@
 
 
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
 (* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
 
 
-unit ClpIPBKDF2_DigestMAC;
+unit ClpIPkcs5S2ParametersGenerator;
 
 
 {$I ..\Include\CryptoLib.inc}
 {$I ..\Include\CryptoLib.inc}
 
 
 interface
 interface
 
 
 uses
 uses
-  HlpIHashInfo;
+  ClpIPbeParametersGenerator,
+  ClpIDigest;
 
 
 type
 type
+  IPkcs5S2ParametersGenerator = interface(IPbeParametersGenerator)
 
 
-  IPBKDF2_DigestMAC = interface(IPBKDF2_HMAC)
-  ['{808DBBC9-4F6E-40D9-AE7F-001798637CE4}']
+    ['{AD345DB8-2341-4C56-B401-23444C2A81BA}']
+
+    function GetDigest: IDigest;
+
+    /// <value>
+    /// the underlying digest.
+    /// </value>
+    property digest: IDigest read GetDigest;
 
 
   end;
   end;
 
 

+ 1 - 3
CryptoLib/src/Math/ClpBigInteger.pas

@@ -746,9 +746,7 @@ end;
 
 
 function TBigInteger.QuickPow2Check: Boolean;
 function TBigInteger.QuickPow2Check: Boolean;
 begin
 begin
-
-  // Result := (Fsign > 0) and (FnBits = 1);
-  Result := (Fsign > 0) and (BitCount = 1); // review
+  Result := (Fsign > 0) and (FnBits = 1);
 end;
 end;
 
 
 function TBigInteger.Negate: TBigInteger;
 function TBigInteger.Negate: TBigInteger;

+ 1 - 1
CryptoLib/src/Math/EC/Multiplier/ClpWNafL2RMultiplier.pas

@@ -178,7 +178,7 @@ begin
     lr := table[TBits.Asr32(n, 1)];
     lr := table[TBits.Asr32(n, 1)];
 
 
     R := R.TwicePlus(lr);
     R := R.TwicePlus(lr);
-    R := R.TimesPow2(zeroes);
+   R := R.TimesPow2(zeroes);
   end;
   end;
 
 
   Result := R;
   Result := R;

+ 17 - 15
CryptoLib/src/Math/EC/Multiplier/ClpWTauNafMultiplier.pas

@@ -123,25 +123,25 @@ var
 begin
 begin
   curve := p.curve as IAbstractF2mCurve;
   curve := p.curve as IAbstractF2mCurve;
   a := ShortInt(curve.a.ToBigInteger().Int32Value);
   a := ShortInt(curve.a.ToBigInteger().Int32Value);
-
-  // if ((preCompInfo = Nil) or (not(Supports(preCompInfo, IWTauNafPreCompInfo))))
-  // then
-  // begin
-  pu := TTnaf.GetPreComp(p, a);
-
-  pre := TWTauNafPreCompInfo.Create();
-  pre.PreComp := pu;
-  curve.SetPreCompInfo(p, PRECOMP_NAME, pre);
-  // end
-  // else
-  // begin
-  // pu := (preCompInfo as IWTauNafPreCompInfo).PreComp;
-  // end;
+  // review uncommenting
+//  if ((preCompInfo = Nil) or (not(Supports(preCompInfo, IWTauNafPreCompInfo))))
+//  then
+//  begin
+    pu := TTnaf.GetPreComp(p, a);
+
+    pre := TWTauNafPreCompInfo.Create();
+    pre.PreComp := pu;
+
+    curve.SetPreCompInfo(p, PRECOMP_NAME, pre);
+    // end
+    // else
+    // begin
+    // pu := (preCompInfo as IWTauNafPreCompInfo).PreComp;
+    // end;
 
 
   // TODO Include negations in precomp (optionally) and use from here
   // TODO Include negations in precomp (optionally) and use from here
   System.SetLength(puNeg, System.Length(pu));
   System.SetLength(puNeg, System.Length(pu));
   for i := 0 to System.Pred(System.Length(pu)) do
   for i := 0 to System.Pred(System.Length(pu)) do
-
   begin
   begin
     puNeg[i] := pu[i].Negate() as IAbstractF2mPoint;
     puNeg[i] := pu[i].Negate() as IAbstractF2mPoint;
   end;
   end;
@@ -177,7 +177,9 @@ begin
     q := q.TauPow(tauCount);
     q := q.TauPow(tauCount);
   end;
   end;
   result := q;
   result := q;
+
   pre.PreComp := Nil;
   pre.PreComp := Nil;
+
 end;
 end;
 
 
 function TWTauNafMultiplier.MultiplyWTnaf(const p: IAbstractF2mPoint;
 function TWTauNafMultiplier.MultiplyWTnaf(const p: IAbstractF2mPoint;

+ 72 - 39
CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.lpk

@@ -10,7 +10,7 @@
       <PathDelim Value="\"/>
       <PathDelim Value="\"/>
       <SearchPaths>
       <SearchPaths>
         <IncludeFiles Value="..\..\Include"/>
         <IncludeFiles Value="..\..\Include"/>
-        <OtherUnitFiles Value="..\..\Asn1;..\..\Asn1\CryptoPro;..\..\Asn1\Nist;..\..\Asn1\Oiw;..\..\Asn1\Pkcs;..\..\Asn1\RossStandart;..\..\Asn1\Sec;..\..\Asn1\TeleTrust;..\..\Asn1\X9;..\..\Crypto;..\..\Crypto\Generators;..\..\Crypto\Parameters;..\..\Crypto\Prng;..\..\Crypto\Signers;..\..\Interfaces;..\..\Math;..\..\Math\EC;..\..\Math\EC\Abc;..\..\Math\EC\Endo;..\..\Math\EC\Multiplier;..\..\Math\Field;..\..\Math\Raw;..\..\Security;..\..\Utils;..\..\Utils\Collections;..\..\Utils\Encoders;..\..\Utils\Helpers;..\..\Utils\IO;..\..\Utils\Randoms;..\..\Utils\Rng;..\..\Crypto\Modes;..\..\Crypto\Paddings;..\..\Crypto\Engines;..\..\Crypto\Parsers;..\..\Crypto\Agreement"/>
+        <OtherUnitFiles Value="..\..\Asn1;..\..\Asn1\CryptoPro;..\..\Asn1\Nist;..\..\Asn1\Oiw;..\..\Asn1\Pkcs;..\..\Asn1\RossStandart;..\..\Asn1\Sec;..\..\Asn1\TeleTrust;..\..\Asn1\X9;..\..\Crypto;..\..\Crypto\Generators;..\..\Crypto\Parameters;..\..\Crypto\Prng;..\..\Crypto\Signers;..\..\Interfaces;..\..\Math;..\..\Math\EC;..\..\Math\EC\Abc;..\..\Math\EC\Endo;..\..\Math\EC\Multiplier;..\..\Math\Field;..\..\Math\Raw;..\..\Security;..\..\Utils;..\..\Utils\Collections;..\..\Utils\Encoders;..\..\Utils\Helpers;..\..\Utils\IO;..\..\Utils\Randoms;..\..\Utils\Rng;..\..\Crypto\Modes;..\..\Crypto\Paddings;..\..\Crypto\Engines;..\..\Crypto\Parsers;..\..\Crypto\Agreement;..\..\Crypto\Macs;..\..\Asn1\Misc;..\..\Asn1\Iana"/>
         <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
         <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
       </SearchPaths>
       </SearchPaths>
       <CodeGeneration>
       <CodeGeneration>
@@ -24,8 +24,8 @@
 
 
  Acknowledgements: 
  Acknowledgements: 
 Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring the development of this library "/>
 Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring the development of this library "/>
-    <Version Major="1" Minor="9"/>
-    <Files Count="360">
+    <Version Major="2"/>
+    <Files Count="368">
       <Item1>
       <Item1>
         <Filename Value="..\..\Asn1\ClpAsn1Encodable.pas"/>
         <Filename Value="..\..\Asn1\ClpAsn1Encodable.pas"/>
         <UnitName Value="ClpAsn1Encodable"/>
         <UnitName Value="ClpAsn1Encodable"/>
@@ -1399,74 +1399,106 @@ Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring the devel
         <UnitName Value="ClpICipherKeyGenerator"/>
         <UnitName Value="ClpICipherKeyGenerator"/>
       </Item343>
       </Item343>
       <Item344>
       <Item344>
-        <Filename Value="..\..\Interfaces\ClpIPBKDF2_DigestMAC.pas"/>
-        <UnitName Value="ClpIPBKDF2_DigestMAC"/>
+        <Filename Value="..\..\Interfaces\ClpIDigest.pas"/>
+        <UnitName Value="ClpIDigest"/>
       </Item344>
       </Item344>
       <Item345>
       <Item345>
-        <Filename Value="..\..\Interfaces\ClpIDigestMAC.pas"/>
-        <UnitName Value="ClpIDigestMAC"/>
+        <Filename Value="..\..\Interfaces\ClpISicBlockCipher.pas"/>
+        <UnitName Value="ClpISicBlockCipher"/>
       </Item345>
       </Item345>
       <Item346>
       <Item346>
-        <Filename Value="..\..\Interfaces\ClpIDigest.pas"/>
-        <UnitName Value="ClpIDigest"/>
+        <Filename Value="..\..\Interfaces\ClpIStreamCipher.pas"/>
+        <UnitName Value="ClpIStreamCipher"/>
       </Item346>
       </Item346>
       <Item347>
       <Item347>
-        <Filename Value="..\..\Interfaces\ClpISicBlockCipher.pas"/>
-        <UnitName Value="ClpISicBlockCipher"/>
+        <Filename Value="..\..\Crypto\Modes\ClpOfbBlockCipher.pas"/>
+        <UnitName Value="ClpOfbBlockCipher"/>
       </Item347>
       </Item347>
       <Item348>
       <Item348>
-        <Filename Value="..\..\Interfaces\ClpIStreamCipher.pas"/>
-        <UnitName Value="ClpIStreamCipher"/>
+        <Filename Value="..\..\Interfaces\ClpIOfbBlockCipher.pas"/>
+        <UnitName Value="ClpIOfbBlockCipher"/>
       </Item348>
       </Item348>
       <Item349>
       <Item349>
-        <Filename Value="..\..\Crypto\Modes\ClpOfbBlockCipher.pas"/>
-        <UnitName Value="ClpOfbBlockCipher"/>
+        <Filename Value="..\..\Interfaces\ClpICfbBlockCipher.pas"/>
+        <UnitName Value="ClpICfbBlockCipher"/>
       </Item349>
       </Item349>
       <Item350>
       <Item350>
-        <Filename Value="..\..\Interfaces\ClpIOfbBlockCipher.pas"/>
-        <UnitName Value="ClpIOfbBlockCipher"/>
+        <Filename Value="..\..\Crypto\Paddings\ClpX923Padding.pas"/>
+        <UnitName Value="ClpX923Padding"/>
       </Item350>
       </Item350>
       <Item351>
       <Item351>
-        <Filename Value="..\..\Interfaces\ClpICfbBlockCipher.pas"/>
-        <UnitName Value="ClpICfbBlockCipher"/>
+        <Filename Value="..\..\Interfaces\ClpIX923Padding.pas"/>
+        <UnitName Value="ClpIX923Padding"/>
       </Item351>
       </Item351>
       <Item352>
       <Item352>
-        <Filename Value="..\..\Crypto\Paddings\ClpX923Padding.pas"/>
-        <UnitName Value="ClpX923Padding"/>
+        <Filename Value="..\..\Crypto\Paddings\ClpTTBCPadding.pas"/>
+        <UnitName Value="ClpTTBCPadding"/>
       </Item352>
       </Item352>
       <Item353>
       <Item353>
-        <Filename Value="..\..\Interfaces\ClpIX923Padding.pas"/>
-        <UnitName Value="ClpIX923Padding"/>
+        <Filename Value="..\..\Crypto\Paddings\ClpISO7816d4Padding.pas"/>
+        <UnitName Value="ClpISO7816d4Padding"/>
       </Item353>
       </Item353>
       <Item354>
       <Item354>
-        <Filename Value="..\..\Crypto\Paddings\ClpTTBCPadding.pas"/>
-        <UnitName Value="ClpTTBCPadding"/>
+        <Filename Value="..\..\Interfaces\ClpITBCPadding.pas"/>
+        <UnitName Value="ClpITBCPadding"/>
       </Item354>
       </Item354>
       <Item355>
       <Item355>
-        <Filename Value="..\..\Crypto\Paddings\ClpISO7816d4Padding.pas"/>
-        <UnitName Value="ClpISO7816d4Padding"/>
+        <Filename Value="..\..\Interfaces\ClpIISO7816d4Padding.pas"/>
+        <UnitName Value="ClpIISO7816d4Padding"/>
       </Item355>
       </Item355>
       <Item356>
       <Item356>
-        <Filename Value="..\..\Interfaces\ClpITBCPadding.pas"/>
-        <UnitName Value="ClpITBCPadding"/>
+        <Filename Value="..\..\Crypto\Paddings\ClpISO10126d2Padding.pas"/>
+        <UnitName Value="ClpISO10126d2Padding"/>
       </Item356>
       </Item356>
       <Item357>
       <Item357>
-        <Filename Value="..\..\Interfaces\ClpIISO7816d4Padding.pas"/>
-        <UnitName Value="ClpIISO7816d4Padding"/>
+        <Filename Value="..\..\Interfaces\ClpIISO10126d2Padding.pas"/>
+        <UnitName Value="ClpIISO10126d2Padding"/>
       </Item357>
       </Item357>
       <Item358>
       <Item358>
-        <Filename Value="..\..\Crypto\Paddings\ClpISO10126d2Padding.pas"/>
-        <UnitName Value="ClpISO10126d2Padding"/>
+        <Filename Value="CryptoLib4PascalPackage.pas"/>
+        <AddToUsesPkgSection Value="False"/>
+        <UnitName Value="CryptoLib4PascalPackage"/>
       </Item358>
       </Item358>
       <Item359>
       <Item359>
-        <Filename Value="..\..\Interfaces\ClpIISO10126d2Padding.pas"/>
-        <UnitName Value="ClpIISO10126d2Padding"/>
+        <Filename Value="..\..\Crypto\Generators\ClpPkcs5S2ParametersGenerator.pas"/>
+        <UnitName Value="ClpPkcs5S2ParametersGenerator"/>
       </Item359>
       </Item359>
       <Item360>
       <Item360>
-        <Filename Value="CryptoLib4PascalPackage.pas"/>
-        <AddToUsesPkgSection Value="False"/>
-        <UnitName Value="CryptoLib4PascalPackage"/>
+        <Filename Value="..\..\Interfaces\ClpIPkcs5S2ParametersGenerator.pas"/>
+        <UnitName Value="ClpIPkcs5S2ParametersGenerator"/>
       </Item360>
       </Item360>
+      <Item361>
+        <Filename Value="..\..\Interfaces\ClpIPbeParametersGenerator.pas"/>
+        <UnitName Value="ClpIPbeParametersGenerator"/>
+      </Item361>
+      <Item362>
+        <Filename Value="..\..\Crypto\Generators\ClpPbeParametersGenerator.pas"/>
+        <UnitName Value="ClpPbeParametersGenerator"/>
+      </Item362>
+      <Item363>
+        <Filename Value="..\..\Crypto\Macs\ClpHMac.pas"/>
+        <UnitName Value="ClpHMac"/>
+      </Item363>
+      <Item364>
+        <Filename Value="..\..\Asn1\Misc\ClpMiscObjectIdentifiers.pas"/>
+        <UnitName Value="ClpMiscObjectIdentifiers"/>
+      </Item364>
+      <Item365>
+        <Filename Value="..\..\Asn1\Iana\ClpIanaObjectIdentifiers.pas"/>
+        <UnitName Value="ClpIanaObjectIdentifiers"/>
+      </Item365>
+      <Item366>
+        <Filename Value="..\..\Security\ClpMacUtilities.pas"/>
+        <UnitName Value="ClpMacUtilities"/>
+      </Item366>
+      <Item367>
+        <Filename Value="..\..\Interfaces\ClpIMac.pas"/>
+        <UnitName Value="ClpIMac"/>
+      </Item367>
+      <Item368>
+        <Filename Value="..\..\Interfaces\ClpIHMac.pas"/>
+        <UnitName Value="ClpIHMac"/>
+      </Item368>
     </Files>
     </Files>
     <RequiredPkgs Count="3">
     <RequiredPkgs Count="3">
       <Item1>
       <Item1>
@@ -1475,7 +1507,8 @@ Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring the devel
       </Item1>
       </Item1>
       <Item2>
       <Item2>
         <PackageName Value="HashLib4PascalPackage"/>
         <PackageName Value="HashLib4PascalPackage"/>
-        <MinVersion Major="2" Minor="3" Valid="True"/>
+        <MaxVersion Major="2" Minor="3"/>
+        <MinVersion Major="2" Minor="4" Valid="True"/>
       </Item2>
       </Item2>
       <Item3>
       <Item3>
         <PackageName Value="FCL"/>
         <PackageName Value="FCL"/>

+ 8 - 6
CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.pas

@@ -114,12 +114,14 @@ uses
   ClpIBaseKdfBytesGenerator, ClpIIso18033KdfParameters, ClpIKdfParameters, 
   ClpIBaseKdfBytesGenerator, ClpIIso18033KdfParameters, ClpIKdfParameters, 
   ClpIDerivationFunction, ClpIDerivationParameters, ClpIECDHBasicAgreement, 
   ClpIDerivationFunction, ClpIDerivationParameters, ClpIECDHBasicAgreement, 
   ClpIBasicAgreement, ClpSicBlockCipher, ClpCfbBlockCipher, 
   ClpIBasicAgreement, ClpSicBlockCipher, ClpCfbBlockCipher, 
-  ClpCipherKeyGenerator, ClpStringUtils, ClpICipherKeyGenerator, 
-  ClpIPBKDF2_DigestMAC, ClpIDigestMAC, ClpIDigest, ClpISicBlockCipher, 
-  ClpIStreamCipher, ClpOfbBlockCipher, ClpIOfbBlockCipher, ClpICfbBlockCipher, 
-  ClpX923Padding, ClpIX923Padding, ClpTTBCPadding, ClpISO7816d4Padding, 
-  ClpITBCPadding, ClpIISO7816d4Padding, ClpISO10126d2Padding, 
-  ClpIISO10126d2Padding;
+  ClpCipherKeyGenerator, ClpStringUtils, ClpICipherKeyGenerator, ClpIDigest, 
+  ClpISicBlockCipher, ClpIStreamCipher, ClpOfbBlockCipher, ClpIOfbBlockCipher, 
+  ClpICfbBlockCipher, ClpX923Padding, ClpIX923Padding, ClpTTBCPadding, 
+  ClpISO7816d4Padding, ClpITBCPadding, ClpIISO7816d4Padding, 
+  ClpISO10126d2Padding, ClpIISO10126d2Padding, ClpPkcs5S2ParametersGenerator, 
+  ClpIPkcs5S2ParametersGenerator, ClpIPbeParametersGenerator, 
+  ClpPbeParametersGenerator, ClpHMac, ClpMiscObjectIdentifiers, 
+  ClpIanaObjectIdentifiers, ClpMacUtilities, ClpIMac, ClpIHMac;
 
 
 implementation
 implementation
 
 

+ 113 - 31
CryptoLib/src/Security/ClpDigestUtilities.pas

@@ -27,11 +27,11 @@ uses
   Generics.Collections,
   Generics.Collections,
   HlpHashFactory,
   HlpHashFactory,
   ClpIDigest,
   ClpIDigest,
-  ClpIDigestMAC,
-  ClpIPBKDF2_DigestMAC,
   ClpPkcsObjectIdentifiers,
   ClpPkcsObjectIdentifiers,
+  ClpRosstandartObjectIdentifiers,
   ClpOiwObjectIdentifiers,
   ClpOiwObjectIdentifiers,
   ClpNistObjectIdentifiers,
   ClpNistObjectIdentifiers,
+  ClpMiscObjectIdentifiers,
   ClpTeleTrusTObjectIdentifiers,
   ClpTeleTrusTObjectIdentifiers,
   ClpCryptoProObjectIdentifiers,
   ClpCryptoProObjectIdentifiers,
   ClpCryptoLibTypes,
   ClpCryptoLibTypes,
@@ -52,10 +52,12 @@ type
 
 
   type
   type
 {$SCOPEDENUMS ON}
 {$SCOPEDENUMS ON}
-    TDigestAlgorithm = (NULL, GOST3411, MD2, MD4, MD5, RIPEMD128, RIPEMD160,
-      RIPEMD256, RIPEMD320, SHA_1, SHA_224, SHA_256, SHA_384, SHA_512,
-      SHA_512_224, SHA_512_256, SHA3_224, SHA3_256, SHA3_384, SHA3_512,
-      TIGER_5_192, WHIRLPOOL);
+    TDigestAlgorithm = (BLAKE2B_160, BLAKE2B_256, BLAKE2B_384, BLAKE2B_512,
+      BLAKE2S_128, BLAKE2S_160, BLAKE2S_224, BLAKE2S_256, GOST3411,
+      GOST3411_2012_256, GOST3411_2012_512, MD2, MD4, MD5, NULL, RIPEMD128,
+      RIPEMD160, RIPEMD256, RIPEMD320, SHA_1, SHA_224, SHA_256, SHA_384,
+      SHA_512, SHA_512_224, SHA_512_256, SHA3_224, SHA3_256, SHA3_384, SHA3_512,
+      TIGER, WHIRLPOOL);
 {$SCOPEDENUMS OFF}
 {$SCOPEDENUMS OFF}
   class constructor CreateDigestUtilities();
   class constructor CreateDigestUtilities();
   class destructor DestroyDigestUtilities();
   class destructor DestroyDigestUtilities();
@@ -73,12 +75,6 @@ type
     class function GetDigest(const algorithm: String): IDigest;
     class function GetDigest(const algorithm: String): IDigest;
       overload; static;
       overload; static;
 
 
-    class function GetDigestMAC(const digest: IDigest): IDigestMAC; static;
-
-    class function GetPBKDF2_DigestMAC(const digest: IDigest;
-      a_password, a_salt: TCryptoLibByteArray; a_iterations: UInt32)
-      : IPBKDF2_DigestMAC; static;
-
     class function GetAlgorithmName(const oid: IDerObjectIdentifier): String;
     class function GetAlgorithmName(const oid: IDerObjectIdentifier): String;
       static; inline;
       static; inline;
 
 
@@ -125,9 +121,58 @@ begin
 
 
   case digestAlgorithm of
   case digestAlgorithm of
 
 
-    TDigestAlgorithm.NULL:
+    TDigestAlgorithm.BLAKE2B_160:
       begin
       begin
-        result := IDigest(THashFactory.TNullDigestFactory.CreateNullDigest());
+        result := IDigest(THashFactory.TCrypto.CreateBlake2B_160);
+        result.Initialize;
+        Exit;
+      end;
+
+    TDigestAlgorithm.BLAKE2B_256:
+      begin
+        result := IDigest(THashFactory.TCrypto.CreateBlake2B_256);
+        result.Initialize;
+        Exit;
+      end;
+
+    TDigestAlgorithm.BLAKE2B_384:
+      begin
+        result := IDigest(THashFactory.TCrypto.CreateBlake2B_384);
+        result.Initialize;
+        Exit;
+      end;
+
+    TDigestAlgorithm.BLAKE2B_512:
+      begin
+        result := IDigest(THashFactory.TCrypto.CreateBlake2B_512);
+        result.Initialize;
+        Exit;
+      end;
+
+    TDigestAlgorithm.BLAKE2S_128:
+      begin
+        result := IDigest(THashFactory.TCrypto.CreateBlake2S_128);
+        result.Initialize;
+        Exit;
+      end;
+
+    TDigestAlgorithm.BLAKE2S_160:
+      begin
+        result := IDigest(THashFactory.TCrypto.CreateBlake2S_160);
+        result.Initialize;
+        Exit;
+      end;
+
+    TDigestAlgorithm.BLAKE2S_224:
+      begin
+        result := IDigest(THashFactory.TCrypto.CreateBlake2S_224);
+        result.Initialize;
+        Exit;
+      end;
+
+    TDigestAlgorithm.BLAKE2S_256:
+      begin
+        result := IDigest(THashFactory.TCrypto.CreateBlake2S_256);
         result.Initialize;
         result.Initialize;
         Exit;
         Exit;
       end;
       end;
@@ -139,6 +184,20 @@ begin
         Exit;
         Exit;
       end;
       end;
 
 
+    TDigestAlgorithm.GOST3411_2012_256:
+      begin
+        result := IDigest(THashFactory.TCrypto.CreateGOST3411_2012_256());
+        result.Initialize;
+        Exit;
+      end;
+
+    TDigestAlgorithm.GOST3411_2012_512:
+      begin
+        result := IDigest(THashFactory.TCrypto.CreateGOST3411_2012_512());
+        result.Initialize;
+        Exit;
+      end;
+
     TDigestAlgorithm.MD2:
     TDigestAlgorithm.MD2:
       begin
       begin
         result := IDigest(THashFactory.TCrypto.CreateMD2());
         result := IDigest(THashFactory.TCrypto.CreateMD2());
@@ -160,6 +219,13 @@ begin
         Exit;
         Exit;
       end;
       end;
 
 
+    TDigestAlgorithm.NULL:
+      begin
+        result := IDigest(THashFactory.TNullDigestFactory.CreateNullDigest());
+        result.Initialize;
+        Exit;
+      end;
+
     TDigestAlgorithm.RIPEMD128:
     TDigestAlgorithm.RIPEMD128:
       begin
       begin
         result := IDigest(THashFactory.TCrypto.CreateRIPEMD128());
         result := IDigest(THashFactory.TCrypto.CreateRIPEMD128());
@@ -266,20 +332,19 @@ begin
         Exit;
         Exit;
       end;
       end;
 
 
-    TDigestAlgorithm.TIGER_5_192:
+    TDigestAlgorithm.TIGER:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateTiger_5_192());
+        result := IDigest(THashFactory.TCrypto.CreateTiger_3_192);
         result.Initialize;
         result.Initialize;
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.WHIRLPOOL:
     TDigestAlgorithm.WHIRLPOOL:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateWhirlPool());
+        result := IDigest(THashFactory.TCrypto.CreateWhirlPool);
         result.Initialize;
         result.Initialize;
         Exit;
         Exit;
       end
       end
-
   else
   else
     begin
     begin
       raise ESecurityUtilityCryptoLibException.CreateResFmt
       raise ESecurityUtilityCryptoLibException.CreateResFmt
@@ -290,19 +355,6 @@ begin
 
 
 end;
 end;
 
 
-class function TDigestUtilities.GetDigestMAC(const digest: IDigest): IDigestMAC;
-begin
-  result := IDigestMAC(THashFactory.THMAC.CreateHMAC(digest));
-end;
-
-class function TDigestUtilities.GetPBKDF2_DigestMAC(const digest: IDigest;
-  a_password, a_salt: TCryptoLibByteArray; a_iterations: UInt32)
-  : IPBKDF2_DigestMAC;
-begin
-  result := IPBKDF2_DigestMAC(TKDF.TPBKDF2_HMAC.CreatePBKDF2_HMAC(digest,
-    a_password, a_salt, a_iterations));
-end;
-
 class procedure TDigestUtilities.Boot;
 class procedure TDigestUtilities.Boot;
 begin
 begin
   Falgorithms := TDictionary<string, string>.Create();
   Falgorithms := TDictionary<string, string>.Create();
@@ -356,6 +408,24 @@ begin
   Falgorithms.Add(TNistObjectIdentifiers.IdSha3_384.id, 'SHA3-384');
   Falgorithms.Add(TNistObjectIdentifiers.IdSha3_384.id, 'SHA3-384');
   Falgorithms.Add(TNistObjectIdentifiers.IdSha3_512.id, 'SHA3-512');
   Falgorithms.Add(TNistObjectIdentifiers.IdSha3_512.id, 'SHA3-512');
 
 
+  TMiscObjectIdentifiers.Boot;
+
+  Falgorithms.Add(TMiscObjectIdentifiers.id_blake2b160.id, 'BLAKE2B-160');
+  Falgorithms.Add(TMiscObjectIdentifiers.id_blake2b256.id, 'BLAKE2B-256');
+  Falgorithms.Add(TMiscObjectIdentifiers.id_blake2b384.id, 'BLAKE2B-384');
+  Falgorithms.Add(TMiscObjectIdentifiers.id_blake2b512.id, 'BLAKE2B-512');
+  Falgorithms.Add(TMiscObjectIdentifiers.id_blake2s128.id, 'BLAKE2S-128');
+  Falgorithms.Add(TMiscObjectIdentifiers.id_blake2s160.id, 'BLAKE2S-160');
+  Falgorithms.Add(TMiscObjectIdentifiers.id_blake2s224.id, 'BLAKE2S-224');
+  Falgorithms.Add(TMiscObjectIdentifiers.id_blake2s256.id, 'BLAKE2S-256');
+
+  TRosstandartObjectIdentifiers.Boot;
+
+  Falgorithms.Add(TRosstandartObjectIdentifiers.id_tc26_hmac_gost_3411_12_256.
+    id, 'HMAC-GOST3411-2012-256');
+  Falgorithms.Add(TRosstandartObjectIdentifiers.id_tc26_hmac_gost_3411_12_512.
+    id, 'HMAC-GOST3411-2012-512');
+
   Foids.Add('MD2', TPkcsObjectIdentifiers.MD2);
   Foids.Add('MD2', TPkcsObjectIdentifiers.MD2);
   Foids.Add('MD4', TPkcsObjectIdentifiers.MD4);
   Foids.Add('MD4', TPkcsObjectIdentifiers.MD4);
   Foids.Add('MD5', TPkcsObjectIdentifiers.MD5);
   Foids.Add('MD5', TPkcsObjectIdentifiers.MD5);
@@ -374,6 +444,18 @@ begin
   Foids.Add('RIPEMD160', TTeleTrusTObjectIdentifiers.RIPEMD160);
   Foids.Add('RIPEMD160', TTeleTrusTObjectIdentifiers.RIPEMD160);
   Foids.Add('RIPEMD256', TTeleTrusTObjectIdentifiers.RIPEMD256);
   Foids.Add('RIPEMD256', TTeleTrusTObjectIdentifiers.RIPEMD256);
   Foids.Add('GOST3411', TCryptoProObjectIdentifiers.GostR3411);
   Foids.Add('GOST3411', TCryptoProObjectIdentifiers.GostR3411);
+  Foids.Add('BLAKE2B-160', TMiscObjectIdentifiers.id_blake2b160);
+  Foids.Add('BLAKE2B-256', TMiscObjectIdentifiers.id_blake2b256);
+  Foids.Add('BLAKE2B-384', TMiscObjectIdentifiers.id_blake2b384);
+  Foids.Add('BLAKE2B-512', TMiscObjectIdentifiers.id_blake2b512);
+  Foids.Add('BLAKE2S-128', TMiscObjectIdentifiers.id_blake2s128);
+  Foids.Add('BLAKE2S-160', TMiscObjectIdentifiers.id_blake2s160);
+  Foids.Add('BLAKE2S-224', TMiscObjectIdentifiers.id_blake2s224);
+  Foids.Add('BLAKE2S-256', TMiscObjectIdentifiers.id_blake2s256);
+  Foids.Add('GOST3411-2012-256',
+    TRosstandartObjectIdentifiers.id_tc26_gost_3411_12_256);
+  Foids.Add('GOST3411-2012-512',
+    TRosstandartObjectIdentifiers.id_tc26_gost_3411_12_512);
 end;
 end;
 
 
 class function TDigestUtilities.CalculateDigest(const algorithm: String;
 class function TDigestUtilities.CalculateDigest(const algorithm: String;

+ 74 - 3
CryptoLib/src/Security/ClpGeneratorUtilities.pas

@@ -31,6 +31,9 @@ uses
   ClpIDerObjectIdentifier,
   ClpIDerObjectIdentifier,
   ClpIAsymmetricCipherKeyPairGenerator,
   ClpIAsymmetricCipherKeyPairGenerator,
   ClpNistObjectIdentifiers,
   ClpNistObjectIdentifiers,
+  ClpIanaObjectIdentifiers,
+  ClpPkcsObjectIdentifiers,
+  ClpRosstandartObjectIdentifiers,
   ClpStringUtils,
   ClpStringUtils,
   ClpCryptoLibTypes;
   ClpCryptoLibTypes;
 
 
@@ -66,6 +69,9 @@ type
     class procedure AddKpgAlgorithm(const canonicalName: String;
     class procedure AddKpgAlgorithm(const canonicalName: String;
       aliases: array of String); static;
       aliases: array of String); static;
 
 
+    class procedure AddHMacKeyGenerator(const algorithm: String;
+      aliases: array of String); static;
+
     class constructor CreateGeneratorUtilities();
     class constructor CreateGeneratorUtilities();
     class destructor DestroyGeneratorUtilities();
     class destructor DestroyGeneratorUtilities();
 
 
@@ -138,6 +144,24 @@ begin
 
 
 end;
 end;
 
 
+class procedure TGeneratorUtilities.AddHMacKeyGenerator(const algorithm: String;
+  aliases: array of String);
+var
+  alias, mainName: string;
+begin
+  mainName := 'HMAC' + algorithm;
+
+  FkgAlgorithms.Add(mainName, mainName);
+  FkgAlgorithms.Add('HMAC-' + algorithm, mainName);
+  FkgAlgorithms.Add('HMAC/' + algorithm, mainName);
+
+  for alias in aliases do
+  begin
+    FkgAlgorithms.Add(alias, mainName);
+  end;
+
+end;
+
 class procedure TGeneratorUtilities.Boot;
 class procedure TGeneratorUtilities.Boot;
 begin
 begin
   FkgAlgorithms := TDictionary<String, String>.Create();
   FkgAlgorithms := TDictionary<String, String>.Create();
@@ -168,6 +192,45 @@ begin
     TNistObjectIdentifiers.IdAes256Ecb.ID,
     TNistObjectIdentifiers.IdAes256Ecb.ID,
     TNistObjectIdentifiers.IdAes256Ofb.ID]);
     TNistObjectIdentifiers.IdAes256Ofb.ID]);
 
 
+  //
+  // HMac key generators
+  //
+  TIanaObjectIdentifiers.Boot;
+
+  AddHMacKeyGenerator('MD2', []);
+  AddHMacKeyGenerator('MD4', []);
+  AddHMacKeyGenerator('MD5', [TIanaObjectIdentifiers.HmacMD5.ID]);
+
+  TPkcsObjectIdentifiers.Boot;
+
+  AddHMacKeyGenerator('SHA1', [TPkcsObjectIdentifiers.IdHmacWithSha1.ID,
+    TIanaObjectIdentifiers.HmacSha1.ID]);
+  AddHMacKeyGenerator('SHA224', [TPkcsObjectIdentifiers.IdHmacWithSha224.ID]);
+  AddHMacKeyGenerator('SHA256', [TPkcsObjectIdentifiers.IdHmacWithSha256.ID]);
+  AddHMacKeyGenerator('SHA384', [TPkcsObjectIdentifiers.IdHmacWithSha384.ID]);
+  AddHMacKeyGenerator('SHA512', [TPkcsObjectIdentifiers.IdHmacWithSha512.ID]);
+  AddHMacKeyGenerator('SHA512/224', []);
+  AddHMacKeyGenerator('SHA512/256', []);
+
+  AddHMacKeyGenerator('SHA3-224',
+    [TNistObjectIdentifiers.IdHMacWithSha3_224.ID]);
+  AddHMacKeyGenerator('SHA3-256',
+    [TNistObjectIdentifiers.IdHMacWithSha3_256.ID]);
+  AddHMacKeyGenerator('SHA3-384',
+    [TNistObjectIdentifiers.IdHMacWithSha3_384.ID]);
+  AddHMacKeyGenerator('SHA3-512',
+    [TNistObjectIdentifiers.IdHMacWithSha3_512.ID]);
+  AddHMacKeyGenerator('RIPEMD128', []);
+  AddHMacKeyGenerator('RIPEMD160', [TIanaObjectIdentifiers.HmacRipeMD160.ID]);
+  AddHMacKeyGenerator('TIGER', [TIanaObjectIdentifiers.HmacTiger.ID]);
+
+  TRosstandartObjectIdentifiers.Boot;
+
+  AddHMacKeyGenerator('GOST3411-2012-256',
+    [TRosstandartObjectIdentifiers.id_tc26_hmac_gost_3411_12_256.ID]);
+  AddHMacKeyGenerator('GOST3411-2012-512',
+    [TRosstandartObjectIdentifiers.id_tc26_hmac_gost_3411_12_512.ID]);
+
   //
   //
   // key pair generators.
   // key pair generators.
   //
   //
@@ -175,9 +238,17 @@ begin
   AddKpgAlgorithm('ECDH', ['ECIES']);
   AddKpgAlgorithm('ECDH', ['ECIES']);
   AddKpgAlgorithm('ECDSA', []);
   AddKpgAlgorithm('ECDSA', []);
 
 
-  AddDefaultKeySizeEntries(128, ['AES128']);
-  AddDefaultKeySizeEntries(192, ['AES', 'AES192']);
-  AddDefaultKeySizeEntries(256, ['AES256']);
+  AddDefaultKeySizeEntries(128, ['AES128', 'HMACMD2', 'HMACMD4', 'HMACMD5',
+    'HMACRIPEMD128']);
+  AddDefaultKeySizeEntries(160, ['HMACRIPEMD160', 'HMACSHA1']);
+  AddDefaultKeySizeEntries(192, ['AES', 'AES192', 'HMACTIGER']);
+  AddDefaultKeySizeEntries(224, ['HMACSHA3-224', 'HMACSHA224',
+    'HMACSHA512/224']);
+  AddDefaultKeySizeEntries(256, ['AES256', 'HMACGOST3411-2012-256',
+    'HMACSHA3-256', 'HMACSHA256', 'HMACSHA512/256']);
+  AddDefaultKeySizeEntries(384, ['HMACSHA3-384', 'HMACSHA384']);
+  AddDefaultKeySizeEntries(512, ['HMACGOST3411-2012-512', 'HMACSHA3-512',
+    'HMACSHA512']);
 end;
 end;
 
 
 class constructor TGeneratorUtilities.CreateGeneratorUtilities;
 class constructor TGeneratorUtilities.CreateGeneratorUtilities;

+ 201 - 0
CryptoLib/src/Security/ClpMacUtilities.pas

@@ -0,0 +1,201 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpMacUtilities;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  Generics.Collections,
+  ClpIDerObjectIdentifier,
+  ClpIMac,
+  ClpHMac,
+  ClpICipherParameters,
+  ClpIanaObjectIdentifiers,
+  ClpPkcsObjectIdentifiers,
+  ClpNistObjectIdentifiers,
+  ClpRosstandartObjectIdentifiers,
+  ClpDigestUtilities,
+  ClpStringUtils,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SUnRecognizedMac = '"Mac " %s not recognised.';
+
+type
+  TMacUtilities = class sealed(TObject)
+
+  strict private
+
+    class var
+
+      Falgorithms: TDictionary<String, String>;
+
+    class constructor CreateMacUtilities();
+    class destructor DestroyMacUtilities();
+
+  public
+
+    class function GetMac(const id: IDerObjectIdentifier): IMac; overload;
+      static; inline;
+    class function GetMac(const algorithm: string): IMac; overload; static;
+
+    class function GetAlgorithmName(const oid: IDerObjectIdentifier): string;
+      static; inline;
+
+    class function CalculateMac(const algorithm: String;
+      const cp: ICipherParameters; input: TCryptoLibByteArray)
+      : TCryptoLibByteArray; static; inline;
+
+    class function DoFinal(const mac: IMac): TCryptoLibByteArray; overload;
+      static; inline;
+
+    class function DoFinal(const mac: IMac; input: TCryptoLibByteArray)
+      : TCryptoLibByteArray; overload; static; inline;
+
+    class procedure Boot(); static;
+
+  end;
+
+implementation
+
+{ TMacUtilities }
+
+class procedure TMacUtilities.Boot;
+begin
+  Falgorithms := TDictionary<string, string>.Create();
+
+  TIanaObjectIdentifiers.Boot;
+
+  Falgorithms.Add(TIanaObjectIdentifiers.HmacMD5.id, 'HMAC-MD5');
+  Falgorithms.Add(TIanaObjectIdentifiers.HmacRipeMD160.id, 'HMAC-RIPEMD160');
+  Falgorithms.Add(TIanaObjectIdentifiers.HmacSha1.id, 'HMAC-SHA1');
+  Falgorithms.Add(TIanaObjectIdentifiers.HmacTiger.id, 'HMAC-TIGER');
+
+  TPkcsObjectIdentifiers.Boot;
+
+  Falgorithms.Add(TPkcsObjectIdentifiers.IdHmacWithSha1.id, 'HMAC-SHA1');
+  Falgorithms.Add(TPkcsObjectIdentifiers.IdHmacWithSha224.id, 'HMAC-SHA224');
+  Falgorithms.Add(TPkcsObjectIdentifiers.IdHmacWithSha256.id, 'HMAC-SHA256');
+  Falgorithms.Add(TPkcsObjectIdentifiers.IdHmacWithSha384.id, 'HMAC-SHA384');
+  Falgorithms.Add(TPkcsObjectIdentifiers.IdHmacWithSha512.id, 'HMAC-SHA512');
+
+  TNistObjectIdentifiers.Boot;
+
+  Falgorithms.Add(TNistObjectIdentifiers.IdHMacWithSha3_224.id,
+    'HMAC-SHA3-224');
+  Falgorithms.Add(TNistObjectIdentifiers.IdHMacWithSha3_256.id,
+    'HMAC-SHA3-256');
+  Falgorithms.Add(TNistObjectIdentifiers.IdHMacWithSha3_384.id,
+    'HMAC-SHA3-384');
+  Falgorithms.Add(TNistObjectIdentifiers.IdHMacWithSha3_512.id,
+    'HMAC-SHA3-512');
+
+  TRosstandartObjectIdentifiers.Boot;
+
+  Falgorithms.Add(TRosstandartObjectIdentifiers.id_tc26_hmac_gost_3411_12_256.
+    id, 'HMAC-GOST3411-2012-256');
+  Falgorithms.Add(TRosstandartObjectIdentifiers.id_tc26_hmac_gost_3411_12_512.
+    id, 'HMAC-GOST3411-2012-512');
+end;
+
+class function TMacUtilities.GetMac(const algorithm: string): IMac;
+var
+  upper, mechanism, digestName: string;
+  HighPoint: Int32;
+begin
+  upper := UpperCase(algorithm);
+
+  if not Falgorithms.TryGetValue(upper, mechanism) then
+  begin
+    mechanism := upper;
+  end;
+
+  if TStringUtils.BeginsWith(mechanism, 'HMAC', True) then
+  begin
+{$IFDEF DELPHIXE3_UP}
+    HighPoint := System.High(mechanism);
+{$ELSE}
+    HighPoint := System.Length(mechanism);
+{$ENDIF DELPHIXE3_UP}
+    if ((TStringUtils.BeginsWith(mechanism, 'HMAC-', True)) or
+      (TStringUtils.BeginsWith(mechanism, 'HMAC/', True))) then
+    begin
+      digestName := System.Copy(mechanism, 6, HighPoint - 5);
+    end
+    else
+    begin
+      digestName := System.Copy(mechanism, 5, HighPoint - 4);
+    end;
+
+    result := THMac.Create(TDigestUtilities.GetDigest(digestName));
+    Exit;
+  end;
+
+  raise ESecurityUtilityCryptoLibException.CreateResFmt(@SUnRecognizedMac,
+    [mechanism]);
+end;
+
+class function TMacUtilities.DoFinal(const mac: IMac;
+  input: TCryptoLibByteArray): TCryptoLibByteArray;
+begin
+  mac.BlockUpdate(input, 0, System.Length(input));
+  result := DoFinal(mac);
+end;
+
+class function TMacUtilities.DoFinal(const mac: IMac): TCryptoLibByteArray;
+begin
+  System.SetLength(result, mac.GetMacSize());
+  mac.DoFinal(result, 0);
+end;
+
+class function TMacUtilities.CalculateMac(const algorithm: String;
+  const cp: ICipherParameters; input: TCryptoLibByteArray): TCryptoLibByteArray;
+var
+  mac: IMac;
+begin
+  mac := GetMac(algorithm);
+  mac.Init(cp);
+  mac.BlockUpdate(input, 0, System.Length(input));
+  result := DoFinal(mac);
+end;
+
+class constructor TMacUtilities.CreateMacUtilities;
+begin
+  TMacUtilities.Boot;
+end;
+
+class destructor TMacUtilities.DestroyMacUtilities;
+begin
+  Falgorithms.Free;
+end;
+
+class function TMacUtilities.GetMac(const id: IDerObjectIdentifier): IMac;
+begin
+  result := GetMac(id.id);
+end;
+
+class function TMacUtilities.GetAlgorithmName
+  (const oid: IDerObjectIdentifier): string;
+begin
+  Falgorithms.TryGetValue(oid.id, result);
+end;
+
+end.