Browse Source

Merge branch 'master' into travis

Ugochukwu Mmaduekwe 7 years ago
parent
commit
03ee900b7f
100 changed files with 7171 additions and 512 deletions
  1. 17 1
      CryptoLib.Samples/Delphi.Samples/UsageSamples.dpr
  2. 2 2
      CryptoLib.Samples/src/UsageExamples.pas
  3. 24 3
      CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.dpr
  4. 30 6
      CryptoLib.Tests/FreePascal.Tests/CryptoLib.Tests.lpi
  5. 7 1
      CryptoLib.Tests/FreePascal.Tests/CryptoLib.lpr
  6. 39 8
      CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.Tests.lpi
  7. 11 5
      CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.lpr
  8. 4 0
      CryptoLib.Tests/src/Asn1/Asn1SequenceParserTests.pas
  9. 4 0
      CryptoLib.Tests/src/Asn1/DerApplicationSpecificTests.pas
  10. 0 1
      CryptoLib.Tests/src/Asn1/EqualsAndHashCodeTests.pas
  11. 4 6
      CryptoLib.Tests/src/Asn1/OIDTests.pas
  12. 0 4
      CryptoLib.Tests/src/Crypto/AESSICTests.pas
  13. 4 0
      CryptoLib.Tests/src/Crypto/AESTestVectors.pas
  14. 0 3
      CryptoLib.Tests/src/Crypto/AESTests.pas
  15. 1 2
      CryptoLib.Tests/src/Crypto/BlockCipherVectorTests.pas
  16. 1979 0
      CryptoLib.Tests/src/Crypto/DSATests.pas
  17. 428 0
      CryptoLib.Tests/src/Crypto/DeterministicDsaTests.pas
  18. 0 1
      CryptoLib.Tests/src/Crypto/DigestRandomNumberTests.pas
  19. 0 2
      CryptoLib.Tests/src/Crypto/HMacTests.pas
  20. 343 0
      CryptoLib.Tests/src/Crypto/HkdfGeneratorTests.pas
  21. 2 4
      CryptoLib.Tests/src/Crypto/MD5HMacTests.pas
  22. 293 0
      CryptoLib.Tests/src/Crypto/PaddingTests.pas
  23. 14 16
      CryptoLib.Tests/src/Crypto/Pkcs5Tests.pas
  24. 3 9
      CryptoLib.Tests/src/Math/BigIntegerTests.pas
  25. 0 1
      CryptoLib.Tests/src/Math/EC/Custom/Sec/SecP384R1FieldTests.pas
  26. 1 6
      CryptoLib.Tests/src/Math/EC/FixedPointTests.pas
  27. 3 4
      CryptoLib.Tests/src/Math/ECAlgorithmsTests.pas
  28. 677 0
      CryptoLib.Tests/src/Math/ECIESTests.pas
  29. 477 0
      CryptoLib.Tests/src/Math/ECNRTests.pas
  30. 31 15
      CryptoLib.Tests/src/Math/ECPointTests.pas
  31. 275 0
      CryptoLib.Tests/src/Math/IESCipherTests.pas
  32. 17 5
      CryptoLib.Tests/src/Others/ECDsa5Tests.pas
  33. 1 5
      CryptoLib.Tests/src/Others/ECSchnorrTests.pas
  34. 18 7
      CryptoLib.Tests/src/Others/ECTests.pas
  35. 3 1
      CryptoLib.Tests/src/Others/NamedCurveTests.pas
  36. 9 7
      CryptoLib.Tests/src/Others/SignerUtilitiesTests.pas
  37. 0 5
      CryptoLib.Tests/src/Security/SecureRandomTests.pas
  38. 4 4
      CryptoLib.Tests/src/Utils/ClpFixedSecureRandom.pas
  39. 0 7
      CryptoLib.Tests/src/Utils/ClpIFixedSecureRandom.pas
  40. 1 1
      CryptoLib/src/Asn1/ClpAsn1Set.pas
  41. 0 8
      CryptoLib/src/Asn1/ClpDerGeneralString.pas
  42. 1 5
      CryptoLib/src/Asn1/ClpDerGraphicString.pas
  43. 0 8
      CryptoLib/src/Asn1/ClpDerIA5String.pas
  44. 1 2
      CryptoLib/src/Asn1/ClpDerInteger.pas
  45. 0 8
      CryptoLib/src/Asn1/ClpDerNumericString.pas
  46. 2 3
      CryptoLib/src/Asn1/ClpDerOctetString.pas
  47. 7 15
      CryptoLib/src/Asn1/ClpDerPrintableString.pas
  48. 0 8
      CryptoLib/src/Asn1/ClpDerT61String.pas
  49. 0 12
      CryptoLib/src/Asn1/ClpDerUtf8String.pas
  50. 1 5
      CryptoLib/src/Asn1/ClpDerVideotexString.pas
  51. 0 8
      CryptoLib/src/Asn1/ClpDerVisibleString.pas
  52. 69 15
      CryptoLib/src/Asn1/Nist/ClpNistObjectIdentifiers.pas
  53. 142 0
      CryptoLib/src/Asn1/X509/ClpDsaParameter.pas
  54. 2 2
      CryptoLib/src/Asn1/X9/ClpECNamedCurveTable.pas
  55. 48 36
      CryptoLib/src/Asn1/X9/ClpX9Curve.pas
  56. 9 9
      CryptoLib/src/Asn1/X9/ClpX9ECParameters.pas
  57. 6 5
      CryptoLib/src/Asn1/X9/ClpX9FieldElement.pas
  58. 1 1
      CryptoLib/src/Asn1/X9/ClpX9FieldID.pas
  59. 21 6
      CryptoLib/src/Crypto/Agreement/ClpECDHBasicAgreement.pas
  60. 16 6
      CryptoLib/src/Crypto/Agreement/ClpECDHCBasicAgreement.pas
  61. 7 20
      CryptoLib/src/Crypto/ClpEphemeralKeyPair.pas
  62. 56 36
      CryptoLib/src/Crypto/ClpIESCipher.pas
  63. 29 2
      CryptoLib/src/Crypto/ClpKeyEncoder.pas
  64. 1 1
      CryptoLib/src/Crypto/Engines/ClpIESEngine.pas
  65. 1 1
      CryptoLib/src/Crypto/Engines/ClpPascalCoinIESEngine.pas
  66. 618 0
      CryptoLib/src/Crypto/Generators/ClpDSAParametersGenerator.pas
  67. 5 8
      CryptoLib/src/Crypto/Generators/ClpEphemeralKeyPairGenerator.pas
  68. 233 0
      CryptoLib/src/Crypto/Generators/ClpHkdfBytesGenerator.pas
  69. 5 6
      CryptoLib/src/Crypto/Generators/ClpPbeParametersGenerator.pas
  70. 1 2
      CryptoLib/src/Crypto/Modes/ClpSicBlockCipher.pas
  71. 1 0
      CryptoLib/src/Crypto/Paddings/ClpX923Padding.pas
  72. 146 0
      CryptoLib/src/Crypto/Parameters/ClpDsaParameterGenerationParameters.pas
  73. 1 1
      CryptoLib/src/Crypto/Parameters/ClpDsaPublicKeyParameters.pas
  74. 78 21
      CryptoLib/src/Crypto/Parameters/ClpECDomainParameters.pas
  75. 1 2
      CryptoLib/src/Crypto/Parameters/ClpECKeyParameters.pas
  76. 9 20
      CryptoLib/src/Crypto/Parameters/ClpECPublicKeyParameters.pas
  77. 203 0
      CryptoLib/src/Crypto/Parameters/ClpHkdfParameters.pas
  78. 2 2
      CryptoLib/src/Crypto/Parameters/ClpIESParameters.pas
  79. 112 33
      CryptoLib/src/Crypto/Parameters/ClpIESWithCipherParameters.pas
  80. 2 1
      CryptoLib/src/Crypto/Signers/ClpECSchnorrSigner.pas
  81. 224 0
      CryptoLib/src/Crypto/Signers/ClpHMacDsaKCalculator.pas
  82. 2 2
      CryptoLib/src/Crypto/Signers/ClpRandomDsaKCalculator.pas
  83. 100 0
      CryptoLib/src/Interfaces/ClpIDSAParametersGenerator.pas
  84. 2 1
      CryptoLib/src/Interfaces/ClpIDsaKCalculator.pas
  85. 45 0
      CryptoLib/src/Interfaces/ClpIDsaParameter.pas
  86. 49 0
      CryptoLib/src/Interfaces/ClpIDsaParameterGenerationParameters.pas
  87. 3 0
      CryptoLib/src/Interfaces/ClpIDsaPrivateKeyParameters.pas
  88. 4 1
      CryptoLib/src/Interfaces/ClpIECDomainParameters.pas
  89. 17 2
      CryptoLib/src/Interfaces/ClpIECFieldElement.pas
  90. 13 33
      CryptoLib/src/Interfaces/ClpIECInterface.pas
  91. 1 1
      CryptoLib/src/Interfaces/ClpIECSchnorrBSISigner.pas
  92. 1 1
      CryptoLib/src/Interfaces/ClpIFilterStream.pas
  93. 0 2
      CryptoLib/src/Interfaces/ClpIFixedPointCombMultiplier.pas
  94. 1 6
      CryptoLib/src/Interfaces/ClpIFixedPointPreCompInfo.pas
  95. 0 1
      CryptoLib/src/Interfaces/ClpIGF2Polynomial.pas
  96. 0 1
      CryptoLib/src/Interfaces/ClpIGenericPolynomialExtensionField.pas
  97. 1 1
      CryptoLib/src/Interfaces/ClpIHMac.pas
  98. 39 0
      CryptoLib/src/Interfaces/ClpIHMacDsaKCalculator.pas
  99. 35 0
      CryptoLib/src/Interfaces/ClpIHkdfBytesGenerator.pas
  100. 71 0
      CryptoLib/src/Interfaces/ClpIHkdfParameters.pas

+ 17 - 1
CryptoLib.Samples/Delphi.Samples/UsageSamples.dpr

@@ -324,6 +324,7 @@ uses
   ClpEphemeralKeyPairGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpEphemeralKeyPairGenerator.pas',
   ClpIEphemeralKeyPairGenerator in '..\..\CryptoLib\src\Interfaces\ClpIEphemeralKeyPairGenerator.pas',
   ClpKeyEncoder in '..\..\CryptoLib\src\Crypto\ClpKeyEncoder.pas',
+  ClpIKeyEncoder in '..\..\CryptoLib\src\Interfaces\ClpIKeyEncoder.pas',
   ClpIESCipher in '..\..\CryptoLib\src\Crypto\ClpIESCipher.pas',
   ClpIIESCipher in '..\..\CryptoLib\src\Interfaces\ClpIIESCipher.pas',
   ClpECIESPublicKeyParser in '..\..\CryptoLib\src\Crypto\Parsers\ClpECIESPublicKeyParser.pas',
@@ -394,7 +395,22 @@ uses
   ClpIDsaSigner in '..\..\CryptoLib\src\Interfaces\ClpIDsaSigner.pas',
   ClpDigest in '..\..\CryptoLib\src\Crypto\Digests\ClpDigest.pas',
   ClpECDHCBasicAgreement in '..\..\CryptoLib\src\Crypto\Agreement\ClpECDHCBasicAgreement.pas',
-  ClpIECDHCBasicAgreement in '..\..\CryptoLib\src\Interfaces\ClpIECDHCBasicAgreement.pas';
+  ClpIECDHCBasicAgreement in '..\..\CryptoLib\src\Interfaces\ClpIECDHCBasicAgreement.pas',
+  ClpHMacDsaKCalculator in '..\..\CryptoLib\src\Crypto\Signers\ClpHMacDsaKCalculator.pas',
+  ClpIHMacDsaKCalculator in '..\..\CryptoLib\src\Interfaces\ClpIHMacDsaKCalculator.pas',
+  ClpHkdfBytesGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpHkdfBytesGenerator.pas',
+  ClpIHkdfBytesGenerator in '..\..\CryptoLib\src\Interfaces\ClpIHkdfBytesGenerator.pas',
+  ClpHkdfParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpHkdfParameters.pas',
+  ClpIHkdfParameters in '..\..\CryptoLib\src\Interfaces\ClpIHkdfParameters.pas',
+  ClpDsaParameterGenerationParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpDsaParameterGenerationParameters.pas',
+  ClpIDsaParameterGenerationParameters in '..\..\CryptoLib\src\Interfaces\ClpIDsaParameterGenerationParameters.pas',
+  ClpValidityPrecompInfo in '..\..\CryptoLib\src\Math\EC\ClpValidityPrecompInfo.pas',
+  ClpIValidityPrecompInfo in '..\..\CryptoLib\src\Interfaces\ClpIValidityPrecompInfo.pas',
+  ClpDsaParametersGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpDsaParametersGenerator.pas',
+  ClpIDsaParametersGenerator in '..\..\CryptoLib\src\Interfaces\ClpIDsaParametersGenerator.pas',
+  ClpDsaParameter in '..\..\CryptoLib\src\Asn1\X509\ClpDsaParameter.pas',
+  ClpIDsaParameter in '..\..\CryptoLib\src\Interfaces\ClpIDsaParameter.pas',
+  ClpIPreCompCallBack in '..\..\CryptoLib\src\Interfaces\ClpIPreCompCallBack.pas';
 
 begin
   try

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

@@ -727,8 +727,8 @@ begin
   // from a point or not in the EphemeralKeyPairGenerator
   UsePointCompression := True; // for compatibility
 
-  Result := TIESWithCipherParameters.Create(Derivation, Encoding, IVBytes,
-    MacKeySizeInBits, CipherKeySizeInBits, UsePointCompression);
+  Result := TIESWithCipherParameters.Create(Derivation, Encoding,
+    MacKeySizeInBits, CipherKeySizeInBits, IVBytes, UsePointCompression);
 end;
 
 class procedure TUsageExamples.GetPublicKeyFromPrivateKey;

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

@@ -356,6 +356,7 @@ uses
   ClpEphemeralKeyPairGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpEphemeralKeyPairGenerator.pas',
   ClpIEphemeralKeyPairGenerator in '..\..\CryptoLib\src\Interfaces\ClpIEphemeralKeyPairGenerator.pas',
   ClpKeyEncoder in '..\..\CryptoLib\src\Crypto\ClpKeyEncoder.pas',
+  ClpIKeyEncoder in '..\..\CryptoLib\src\Interfaces\ClpIKeyEncoder.pas',
   ClpIESCipher in '..\..\CryptoLib\src\Crypto\ClpIESCipher.pas',
   ClpIIESCipher in '..\..\CryptoLib\src\Interfaces\ClpIIESCipher.pas',
   ClpECIESPublicKeyParser in '..\..\CryptoLib\src\Crypto\Parsers\ClpECIESPublicKeyParser.pas',
@@ -366,7 +367,7 @@ uses
   ClpIIESEngine in '..\..\CryptoLib\src\Interfaces\ClpIIESEngine.pas',
   ClpPascalCoinIESEngine in '..\..\CryptoLib\src\Crypto\Engines\ClpPascalCoinIESEngine.pas',
   ClpIPascalCoinIESEngine in '..\..\CryptoLib\src\Interfaces\ClpIPascalCoinIESEngine.pas',
-  IESCipherTests in '..\src\Crypto\IESCipherTests.pas',
+  IESCipherTests in '..\src\Math\IESCipherTests.pas',
   ClpPascalCoinECIESKdfBytesGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpPascalCoinECIESKdfBytesGenerator.pas',
   ClpIPascalCoinECIESKdfBytesGenerator in '..\..\CryptoLib\src\Interfaces\ClpIPascalCoinECIESKdfBytesGenerator.pas',
   ClpISO10126d2Padding in '..\..\CryptoLib\src\Crypto\Paddings\ClpISO10126d2Padding.pas',
@@ -432,7 +433,28 @@ uses
   ClpIDsaSigner in '..\..\CryptoLib\src\Interfaces\ClpIDsaSigner.pas',
   ClpDigest in '..\..\CryptoLib\src\Crypto\Digests\ClpDigest.pas',
   ClpECDHCBasicAgreement in '..\..\CryptoLib\src\Crypto\Agreement\ClpECDHCBasicAgreement.pas',
-  ClpIECDHCBasicAgreement in '..\..\CryptoLib\src\Interfaces\ClpIECDHCBasicAgreement.pas';
+  ClpIECDHCBasicAgreement in '..\..\CryptoLib\src\Interfaces\ClpIECDHCBasicAgreement.pas',
+  ClpHMacDsaKCalculator in '..\..\CryptoLib\src\Crypto\Signers\ClpHMacDsaKCalculator.pas',
+  ClpIHMacDsaKCalculator in '..\..\CryptoLib\src\Interfaces\ClpIHMacDsaKCalculator.pas',
+  ClpHkdfBytesGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpHkdfBytesGenerator.pas',
+  ClpIHkdfBytesGenerator in '..\..\CryptoLib\src\Interfaces\ClpIHkdfBytesGenerator.pas',
+  ClpHkdfParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpHkdfParameters.pas',
+  ClpIHkdfParameters in '..\..\CryptoLib\src\Interfaces\ClpIHkdfParameters.pas',
+  ClpDsaParameterGenerationParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpDsaParameterGenerationParameters.pas',
+  ClpIDsaParameterGenerationParameters in '..\..\CryptoLib\src\Interfaces\ClpIDsaParameterGenerationParameters.pas',
+  ClpValidityPrecompInfo in '..\..\CryptoLib\src\Math\EC\ClpValidityPrecompInfo.pas',
+  ClpIValidityPrecompInfo in '..\..\CryptoLib\src\Interfaces\ClpIValidityPrecompInfo.pas',
+  HkdfGeneratorTests in '..\src\Crypto\HkdfGeneratorTests.pas',
+  ECIESTests in '..\src\Math\ECIESTests.pas',
+  ECNRTests in '..\src\Math\ECNRTests.pas',
+  PaddingTests in '..\src\Crypto\PaddingTests.pas',
+  ClpDsaParametersGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpDsaParametersGenerator.pas',
+  ClpIDsaParametersGenerator in '..\..\CryptoLib\src\Interfaces\ClpIDsaParametersGenerator.pas',
+  DSATests in '..\src\Crypto\DSATests.pas',
+  ClpDsaParameter in '..\..\CryptoLib\src\Asn1\X509\ClpDsaParameter.pas',
+  ClpIDsaParameter in '..\..\CryptoLib\src\Interfaces\ClpIDsaParameter.pas',
+  ClpIPreCompCallBack in '..\..\CryptoLib\src\Interfaces\ClpIPreCompCallBack.pas',
+  DeterministicDsaTests in '..\src\Crypto\DeterministicDsaTests.pas';
 
 begin
 
@@ -442,5 +464,4 @@ begin
   else
     GUITestRunner.RunRegisteredTests;
 
-
 end.

+ 30 - 6
CryptoLib.Tests/FreePascal.Tests/CryptoLib.Tests.lpi

@@ -36,7 +36,7 @@
         <PackageName Value="FCL"/>
       </Item4>
     </RequiredPackages>
-    <Units Count="27">
+    <Units Count="33">
       <Unit0>
         <Filename Value="CryptoLib.lpr"/>
         <IsPartOfProject Value="True"/>
@@ -127,25 +127,49 @@
         <IsPartOfProject Value="True"/>
       </Unit21>
       <Unit22>
-        <Filename Value="..\src\Crypto\IESCipherTests.pas"/>
+        <Filename Value="..\src\Crypto\AESSICTests.pas"/>
         <IsPartOfProject Value="True"/>
       </Unit22>
       <Unit23>
-        <Filename Value="..\src\Crypto\AESSICTests.pas"/>
+        <Filename Value="..\src\Crypto\HMacTests.pas"/>
         <IsPartOfProject Value="True"/>
       </Unit23>
       <Unit24>
-        <Filename Value="..\src\Crypto\HMacTests.pas"/>
+        <Filename Value="..\src\Crypto\MD5HMacTests.pas"/>
         <IsPartOfProject Value="True"/>
       </Unit24>
       <Unit25>
-        <Filename Value="..\src\Crypto\MD5HMacTests.pas"/>
+        <Filename Value="..\src\Crypto\Pkcs5Tests.pas"/>
         <IsPartOfProject Value="True"/>
       </Unit25>
       <Unit26>
-        <Filename Value="..\src\Crypto\Pkcs5Tests.pas"/>
+        <Filename Value="..\src\Crypto\HkdfGeneratorTests.pas"/>
         <IsPartOfProject Value="True"/>
       </Unit26>
+      <Unit27>
+        <Filename Value="..\src\Math\ECIESTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit27>
+      <Unit28>
+        <Filename Value="..\src\Math\IESCipherTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit28>
+      <Unit29>
+        <Filename Value="..\src\Math\ECNRTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit29>
+      <Unit30>
+        <Filename Value="..\src\Crypto\PaddingTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit30>
+      <Unit31>
+        <Filename Value="..\src\Crypto\DeterministicDsaTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit31>
+      <Unit32>
+        <Filename Value="..\src\Crypto\DSATests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit32>
     </Units>
   </ProjectOptions>
   <CompilerOptions>

+ 7 - 1
CryptoLib.Tests/FreePascal.Tests/CryptoLib.lpr

@@ -25,11 +25,17 @@ uses
   AESTests,
   BlockCipherVectorTests,
   AESTestVectors,
-  IESCipherTests,
   AESSICTests,
+  IESCipherTests,
   MD5HMacTests,
   HMacTests,
   Pkcs5Tests,
+  HkdfGeneratorTests,
+  ECIESTests,
+  ECNRTests,
+  PaddingTests,
+  DSATests,
+  DeterministicDsaTests,
   ClpFixedSecureRandom,
   ClpIFixedSecureRandom;
 

+ 39 - 8
CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.Tests.lpi

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <CONFIG>
   <ProjectOptions>
-    <Version Value="10"/>
+    <Version Value="11"/>
     <PathDelim Value="\"/>
     <General>
       <SessionStorage Value="InProjectDir"/>
@@ -18,9 +18,16 @@
     </PublishOptions>
     <RunParams>
       <local>
-        <FormatVersion Value="1"/>
         <CommandLineParams Value="--format=plain --all --progress"/>
       </local>
+      <FormatVersion Value="2"/>
+      <Modes Count="1">
+        <Mode0 Name="default">
+          <local>
+            <CommandLineParams Value="--format=plain --all --progress"/>
+          </local>
+        </Mode0>
+      </Modes>
     </RunParams>
     <RequiredPackages Count="2">
       <Item1>
@@ -30,7 +37,7 @@
         <PackageName Value="FCL"/>
       </Item2>
     </RequiredPackages>
-    <Units Count="27">
+    <Units Count="33">
       <Unit0>
         <Filename Value="CryptoLibConsole.lpr"/>
         <IsPartOfProject Value="True"/>
@@ -120,25 +127,49 @@
         <IsPartOfProject Value="True"/>
       </Unit21>
       <Unit22>
-        <Filename Value="..\src\Crypto\IESCipherTests.pas"/>
+        <Filename Value="..\src\Crypto\AESSICTests.pas"/>
         <IsPartOfProject Value="True"/>
       </Unit22>
       <Unit23>
-        <Filename Value="..\src\Crypto\AESSICTests.pas"/>
+        <Filename Value="..\src\Crypto\HMacTests.pas"/>
         <IsPartOfProject Value="True"/>
       </Unit23>
       <Unit24>
-        <Filename Value="..\src\Crypto\HMacTests.pas"/>
+        <Filename Value="..\src\Crypto\MD5HMacTests.pas"/>
         <IsPartOfProject Value="True"/>
       </Unit24>
       <Unit25>
-        <Filename Value="..\src\Crypto\MD5HMacTests.pas"/>
+        <Filename Value="..\src\Crypto\Pkcs5Tests.pas"/>
         <IsPartOfProject Value="True"/>
       </Unit25>
       <Unit26>
-        <Filename Value="..\src\Crypto\Pkcs5Tests.pas"/>
+        <Filename Value="..\src\Crypto\HkdfGeneratorTests.pas"/>
         <IsPartOfProject Value="True"/>
       </Unit26>
+      <Unit27>
+        <Filename Value="..\src\Math\ECIESTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit27>
+      <Unit28>
+        <Filename Value="..\src\Math\ECNRTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit28>
+      <Unit29>
+        <Filename Value="..\src\Math\IESCipherTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit29>
+      <Unit30>
+        <Filename Value="..\src\Crypto\PaddingTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit30>
+      <Unit31>
+        <Filename Value="..\src\Crypto\DeterministicDsaTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit31>
+      <Unit32>
+        <Filename Value="..\src\Crypto\DSATests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit32>
     </Units>
   </ProjectOptions>
   <CompilerOptions>

+ 11 - 5
CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.lpr

@@ -23,11 +23,17 @@ uses
   AESTests, // pass x64, pass arm
   BlockCipherVectorTests, // pass x64, pass arm
   AESTestVectors,
-  IESCipherTests, // pass x64, pass arm
-  AESSICTests, // pass x64, pass arm
-  MD5HMacTests, // pass x64, pass arm
- // HMacTests, // pass arm, x64 stalling
-  Pkcs5Tests, // pass x64, pass arm
+  AESSICTests,
+  IESCipherTests,
+  MD5HMacTests,
+  HMacTests,
+  Pkcs5Tests,
+  HkdfGeneratorTests,
+  ECIESTests,
+  ECNRTests,
+  PaddingTests,
+  DSATests,
+  DeterministicDsaTests,
   ClpFixedSecureRandom,
   ClpIFixedSecureRandom;
 

+ 4 - 0
CryptoLib.Tests/src/Asn1/Asn1SequenceParserTests.pas

@@ -19,6 +19,10 @@ unit Asn1SequenceParserTests;
 
 interface
 
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
 uses
   Classes,
   SysUtils,

+ 4 - 0
CryptoLib.Tests/src/Asn1/DerApplicationSpecificTests.pas

@@ -19,6 +19,10 @@ unit DerApplicationSpecificTests;
 
 interface
 
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
 uses
   Classes,
   SysUtils,

+ 0 - 1
CryptoLib.Tests/src/Asn1/EqualsAndHashCodeTests.pas

@@ -22,7 +22,6 @@ interface
 {$IFDEF FPC}
 {$MODE DELPHI}
 {$ENDIF FPC}
-{$HINTS OFF}
 
 uses
   Classes,

+ 4 - 6
CryptoLib.Tests/src/Asn1/OIDTests.pas

@@ -21,7 +21,6 @@ interface
 
 {$IFDEF FPC}
 {$MODE DELPHI}
-{$NOTES OFF}
 {$ENDIF FPC}
 
 uses
@@ -34,6 +33,7 @@ uses
   TestFramework,
 {$ENDIF FPC}
   ClpHex,
+  ClpArrayUtils,
   ClpCryptoLibTypes,
   ClpAsn1Object,
   ClpDerObjectIdentifier,
@@ -87,10 +87,8 @@ begin
 end;
 
 procedure TTestOID.constructorMethod;
-var
-  temp: IDerObjectIdentifier;
 begin
-  temp := TDerObjectIdentifier.Create(Foid);
+  TDerObjectIdentifier.Create(Foid);
 end;
 
 procedure TTestOID.invalidOidCheck;
@@ -133,8 +131,8 @@ begin
 
   CheckEquals(true, o.Equals(encO), 'object comparison failed');
 
-  CheckEquals(true, CompareMem(bytes, enc, System.Length(enc) *
-    System.SizeOf(Byte)), 'bytearray comparison failed');
+  CheckEquals(true, TArrayUtils.AreEqual(bytes, enc),
+    'bytearray comparison failed');
 end;
 
 procedure TTestOID.SetUp;

+ 0 - 4
CryptoLib.Tests/src/Crypto/AESSICTests.pas

@@ -22,7 +22,6 @@ interface
 {$IFDEF FPC}
 {$MODE DELPHI}
 {$ENDIF FPC}
-{$HINTS OFF}
 
 uses
   SysUtils,
@@ -32,13 +31,10 @@ uses
 {$ELSE}
   TestFramework,
 {$ENDIF FPC}
-  ClpKeyParameter,
   ClpIKeyParameter,
   ClpParametersWithIV,
   ClpIParametersWithIV,
   ClpIBufferedCipher,
-  ClpICipherKeyGenerator,
-  ClpICipherParameters,
   ClpGeneratorUtilities,
   ClpParameterUtilities,
   ClpCipherUtilities,

+ 4 - 0
CryptoLib.Tests/src/Crypto/AESTestVectors.pas

@@ -19,6 +19,10 @@ unit AESTestVectors;
 
 interface
 
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
 uses
   ClpCryptoLibTypes;
 

+ 0 - 3
CryptoLib.Tests/src/Crypto/AESTests.pas

@@ -22,7 +22,6 @@ interface
 {$IFDEF FPC}
 {$MODE DELPHI}
 {$ENDIF FPC}
-{$HINTS OFF}
 
 uses
   SysUtils,
@@ -35,7 +34,6 @@ uses
   AESTestVectors,
   ClpAesEngine,
   ClpIAesEngine,
-  ClpKeyParameter,
   ClpIKeyParameter,
   ClpParametersWithIV,
   ClpIParametersWithIV,
@@ -105,7 +103,6 @@ procedure TTestAES.doAESTest(const cipher: IBufferedCipher;
   const param: ICipherParameters; const input, output: String;
   withpadding: Boolean);
 var
-  len1, len2: Int32;
   LInput, LOutput, EncryptionResult, DecryptionResult: TBytes;
 begin
   LInput := THex.Decode(input);

+ 1 - 2
CryptoLib.Tests/src/Crypto/BlockCipherVectorTests.pas

@@ -22,7 +22,6 @@ interface
 {$IFDEF FPC}
 {$MODE DELPHI}
 {$ENDIF FPC}
-{$HINTS OFF}
 
 uses
   SysUtils,
@@ -86,7 +85,7 @@ procedure TTestBlockCipherVector.doBlockCipherVectorTest
 var
   cipher: IBufferedBlockCipher;
   len1, len2: Int32;
-  LKey, LInput, LOutput, outBytes: TBytes;
+  LInput, LOutput, outBytes: TBytes;
 begin
   LInput := THex.Decode(input);
   LOutput := THex.Decode(output);

+ 1979 - 0
CryptoLib.Tests/src/Crypto/DSATests.pas

@@ -0,0 +1,1979 @@
+{ *********************************************************************************** }
+{ *                              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 DSATests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+uses
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpISigner,
+  ClpIDsaSigner,
+  ClpDsaSigner,
+  ClpIDsaParameters,
+  ClpDsaParameters,
+  ClpIECInterface,
+  ClpDsaParameter,
+  ClpIDsaParameter,
+  ClpECCurve,
+  ClpECDomainParameters,
+  ClpIECDomainParameters,
+  ClpIDerObjectIdentifier,
+  ClpDsaParametersGenerator,
+  ClpIDsaParametersGenerator,
+  ClpIDsaValidationParameters,
+  ClpIDsaKeyPairGenerator,
+  ClpDsaKeyPairGenerator,
+  ClpIDsaPublicKeyParameters,
+  ClpDsaPublicKeyParameters,
+  ClpDsaPrivateKeyParameters,
+  ClpIDsaPrivateKeyParameters,
+  ClpIDsaKeyGenerationParameters,
+  ClpDsaKeyGenerationParameters,
+  ClpDsaParameterGenerationParameters,
+  ClpIDsaParameterGenerationParameters,
+  ClpIAsymmetricCipherKeyPairGenerator,
+  ClpIAsymmetricCipherKeyPair,
+  ClpIAsymmetricKeyParameter,
+  ClpECPrivateKeyParameters,
+  ClpIECPrivateKeyParameters,
+  ClpECPublicKeyParameters,
+  ClpIECPublicKeyParameters,
+  ClpParametersWithRandom,
+  ClpIParametersWithRandom,
+  ClpSignerUtilities,
+  ClpDigestUtilities,
+  ClpGeneratorUtilities,
+  ClpTeleTrusTObjectIdentifiers,
+  ClpX9ObjectIdentifiers,
+  ClpECKeyGenerationParameters,
+  ClpIECKeyGenerationParameters,
+  ClpHex,
+  ClpBigInteger,
+  ClpArrayUtils,
+  ClpIDerInteger,
+  ClpIAsn1Sequence,
+  ClpAsn1Object,
+  ClpDSADigestSigner,
+  ClpIDSADigestSigner,
+  ClpISecureRandom,
+  ClpSecureRandom,
+  ClpFixedSecureRandom,
+  ClpIFixedSecureRandom,
+  ClpCryptoLibTypes;
+
+type
+  IDSATestSecureRandom = interface(IFixedSecureRandom)
+    ['{EE74B77E-4383-4C78-98FD-572482A5CAC3}']
+  end;
+
+type
+  TDSATestSecureRandom = class(TFixedSecureRandom, IDSATestSecureRandom)
+
+  strict private
+    Ffirst: Boolean;
+
+  public
+    constructor Create(value: TCryptoLibByteArray);
+
+    procedure NextBytes(bytes: TCryptoLibByteArray); override;
+
+  end;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  /// <summary>
+  /// Test based on FIPS 186-2, Appendix 5, an example of DSA, and FIPS 168-3 test vectors.
+  /// </summary>
+  TTestDSA = class(TCryptoLibTestCase)
+
+  private
+
+    procedure DoDSA2Test1();
+    procedure DoDSA2Test2();
+    procedure DoDSA2Test3();
+    procedure DoDSA2Test4();
+    procedure DoTestDSASHA3(size: Int32; const s: TBigInteger);
+    procedure DoTestECDsa239BitBinary(const algorithm: String;
+      const oid: IDerObjectIdentifier);
+
+    procedure DoCheckMessage(const sgr: ISigner;
+      const sKey: IECPrivateKeyParameters; const vKey: IECPublicKeyParameters;
+      &message, sig: TCryptoLibByteArray);
+
+    procedure DoTestKeyGeneration(keysize: Int32);
+    procedure DoTestBadStrength(strength: Int32);
+
+    function DoDerDecode(encoding: TCryptoLibByteArray)
+      : TCryptoLibGenericArray<TBigInteger>;
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+
+    procedure TestDSA;
+    procedure TestNONEwithDSA;
+    procedure TestNONEwithECDSA239bitPrime;
+    procedure TestECDsa239BitBinaryRipeMD160;
+    procedure TestECDsa239BitBinarySha1;
+    procedure TestECDsa239BitBinarySha224;
+    procedure TestECDsa239BitBinarySha256;
+    procedure TestECDsa239BitBinarySha384;
+    procedure TestECDsa239BitBinarySha512;
+    procedure TestGeneration;
+    procedure TestDsa2Parameters;
+    procedure TestKeyGenerationAll;
+    procedure TestParameters;
+
+    /// <summary>
+    /// <para>
+    /// X9.62 - 1998, J.3.2, Page 155, ECDSA over the field <c>Fp</c>
+    /// </para>
+    /// <para>
+    /// <c>an example with 239 bit prime</c>
+    /// </para>
+    /// </summary>
+    procedure TestECDsa239BitPrime;
+
+    /// <summary>
+    /// <para>
+    /// X9.62 - 1998, J.2.1, Page 100, ECDSA over the field F2m
+    /// </para>
+    /// <para>
+    /// an example with 191 bit binary field
+    /// </para>
+    /// </summary>
+    procedure TestECDsa239BitBinary;
+
+  end;
+
+implementation
+
+{ TTestDSA }
+
+procedure TTestDSA.DoCheckMessage(const sgr: ISigner;
+  const sKey: IECPrivateKeyParameters; const vKey: IECPublicKeyParameters;
+  &message, sig: TCryptoLibByteArray);
+var
+  kData, sigBytes: TCryptoLibByteArray;
+  k: ISecureRandom;
+begin
+
+  kData := TBigInteger.Create
+    ('700000017569056646655505781757157107570501575775705779575555657156756655')
+    .ToByteArrayUnsigned;
+
+  k := TFixedSecureRandom.From(TCryptoLibMatrixByteArray.Create(kData));
+
+  sgr.Init(true, TParametersWithRandom.Create(sKey, k)
+    as IParametersWithRandom);
+
+  sgr.BlockUpdate(&message, 0, System.Length(&message));
+
+  sigBytes := sgr.GenerateSignature();
+
+  if (not TArrayUtils.AreEqual(sigBytes, sig)) then
+  begin
+    Fail(String(TEncoding.UTF8.GetString(&message)) + ' signature incorrect');
+  end;
+
+  sgr.Init(false, vKey);
+
+  sgr.BlockUpdate(&message, 0, System.Length(&message));
+
+  if (not(sgr.VerifySignature(sigBytes))) then
+  begin
+    Fail(String(TEncoding.UTF8.GetString(&message)) + ' verification failed');
+  end;
+end;
+
+function TTestDSA.DoDerDecode(encoding: TCryptoLibByteArray)
+  : TCryptoLibGenericArray<TBigInteger>;
+var
+  s: IAsn1Sequence;
+begin
+  s := TAsn1Object.FromByteArray(encoding) as IAsn1Sequence;
+
+  result := TCryptoLibGenericArray<TBigInteger>.Create
+    ((s[0] as IDerInteger).value, (s[1] as IDerInteger).value);
+end;
+
+procedure TTestDSA.DoTestBadStrength(strength: Int32);
+var
+  rand: ISecureRandom;
+  pGen: IDsaParametersGenerator;
+begin
+  try
+
+    rand := TSecureRandom.Create();
+    pGen := TDsaParametersGenerator.Create();
+    pGen.Init(strength, 80, rand);
+    Fail('illegal parameter ' + IntToStr(strength) + ' check failed.');
+
+  except
+    on e: EArgumentCryptoLibException do
+    begin
+      // expected
+    end;
+
+  end;
+end;
+
+procedure TTestDSA.DoDSA2Test1;
+var
+  seed, msg: TCryptoLibByteArray;
+  pGen: IDsaParametersGenerator;
+  params: IDSAParameters;
+  pv: IDSAValidationParameters;
+  kpGen: IDSAKeyPairGenerator;
+  kp: IAsymmetricCipherKeyPair;
+  pub: IDSAPublicKeyParameters;
+  priv: IDSAPrivateKeyParameters;
+  signer: IDSASigner;
+  sig: TCryptoLibGenericArray<TBigInteger>;
+begin
+  seed := THex.Decode('ED8BEE8D1CB89229D2903CBF0E51EE7377F48698');
+
+  pGen := TDsaParametersGenerator.Create();
+
+  pGen.Init(TDSAParameterGenerationParameters.Create(1024, 160, 80,
+    TDSATestSecureRandom.Create(seed)) as IDSAParameterGenerationParameters);
+
+  params := pGen.GenerateParameters();
+
+  pv := params.getValidationParameters();
+
+  if (pv.GetCounter() <> 5) then
+  begin
+    Fail('counter incorrect');
+  end;
+
+  if (not TArrayUtils.AreEqual(seed, pv.seed)) then
+  begin
+    Fail('seed incorrect');
+  end;
+
+  if (not(params.Q.Equals(TBigInteger.Create
+    ('E950511EAB424B9A19A2AEB4E159B7844C589C4F', 16)))) then
+  begin
+    Fail('Q incorrect');
+  end;
+
+  if (not(params.p.Equals(TBigInteger.Create('E0A67598CD1B763B' +
+    'C98C8ABB333E5DDA0CD3AA0E5E1FB5BA8A7B4EABC10BA338' +
+    'FAE06DD4B90FDA70D7CF0CB0C638BE3341BEC0AF8A7330A3' +
+    '307DED2299A0EE606DF035177A239C34A912C202AA5F83B9' +
+    'C4A7CF0235B5316BFC6EFB9A248411258B30B839AF172440' +
+    'F32563056CB67A861158DDD90E6A894C72A5BBEF9E286C6B', 16)))) then
+  begin
+    Fail('P incorrect');
+  end;
+
+  if (not(params.G.Equals(TBigInteger.Create('D29D5121B0423C27' +
+    '69AB21843E5A3240FF19CACC792264E3BB6BE4F78EDD1B15' +
+    'C4DFF7F1D905431F0AB16790E1F773B5CE01C804E509066A' +
+    '9919F5195F4ABC58189FD9FF987389CB5BEDF21B4DAB4F8B' +
+    '76A055FFE2770988FE2EC2DE11AD92219F0B351869AC24DA' +
+    '3D7BA87011A701CE8EE7BFE49486ED4527B7186CA4610A75', 16)))) then
+  begin
+    Fail('G incorrect');
+  end;
+
+  kpGen := TDSAKeyPairGenerator.Create();
+
+  kpGen.Init(TDSAKeyGenerationParameters.Create(TFixedSecureRandom.Create
+    (TCryptoLibGenericArray<ISource>.Create
+    (TFixedSecureRandom.TBigIntegerSource.Create(TBigInteger.Create
+    ('D0EC4E50BB290A42E9E355C73D8809345DE2E139', 16).ToByteArrayUnsigned))),
+    params) as IDSAKeyGenerationParameters);
+
+  kp := kpGen.GenerateKeyPair();
+
+  pub := kp.Public as IDSAPublicKeyParameters;
+  priv := kp.Private as IDSAPrivateKeyParameters;
+
+  if (not(pub.Y.Equals(TBigInteger.Create('25282217F5730501' +
+    'DD8DBA3EDFCF349AAFFEC20921128D70FAC44110332201BB' +
+    'A3F10986140CBB97C726938060473C8EC97B4731DB004293' +
+    'B5E730363609DF9780F8D883D8C4D41DED6A2F1E1BBBDC97' +
+    '9E1B9D6D3C940301F4E978D65B19041FCF1E8B518F5C0576' +
+    'C770FE5A7A485D8329EE2914A2DE1B5DA4A6128CEAB70F79', 16)))) then
+  begin
+    Fail('Y value incorrect');
+  end;
+
+  if (not(priv.X.Equals(TBigInteger.Create
+    ('D0EC4E50BB290A42E9E355C73D8809345DE2E139', 16)))) then
+  begin
+    Fail('X value incorrect');
+  end;
+
+  signer := TDSASigner.Create();
+
+  signer.Init(true, TParametersWithRandom.Create(kp.Private,
+    TFixedSecureRandom.Create(TCryptoLibGenericArray<ISource>.Create
+    (TFixedSecureRandom.TBigIntegerSource.Create
+    ('349C55648DCF992F3F33E8026CFAC87C1D2BA075'),
+    TFixedSecureRandom.TData.Create(THex.Decode('01020304')))))
+    as IParametersWithRandom);
+
+  msg := THex.Decode('A9993E364706816ABA3E25717850C26C9CD0D89D');
+
+  sig := signer.GenerateSignature(msg);
+
+  if (not(sig[0].Equals(TBigInteger.Create
+    ('636155AC9A4633B4665D179F9E4117DF68601F34', 16)))) then
+  begin
+    Fail('R value incorrect');
+  end;
+
+  if (not(sig[1].Equals(TBigInteger.Create
+    ('6C540B02D9D4852F89DF8CFC99963204F4347704', 16)))) then
+  begin
+    Fail('S value incorrect');
+  end;
+
+  signer.Init(false, kp.Public);
+
+  if (not(signer.VerifySignature(msg, sig[0], sig[1]))) then
+  begin
+    Fail('signature not verified');
+  end;
+end;
+
+procedure TTestDSA.DoDSA2Test2;
+var
+  seed, msg: TCryptoLibByteArray;
+  pGen: IDsaParametersGenerator;
+  params: IDSAParameters;
+  pv: IDSAValidationParameters;
+  kpGen: IDSAKeyPairGenerator;
+  kp: IAsymmetricCipherKeyPair;
+  pub: IDSAPublicKeyParameters;
+  priv: IDSAPrivateKeyParameters;
+  signer: IDSASigner;
+  sig: TCryptoLibGenericArray<TBigInteger>;
+begin
+  seed := THex.Decode
+    ('5AFCC1EFFC079A9CCA6ECA86D6E3CC3B18642D9BE1CC6207C84002A9');
+
+  pGen := TDsaParametersGenerator.Create(TDigestUtilities.GetDigest('SHA-224'));
+
+  pGen.Init(TDSAParameterGenerationParameters.Create(2048, 224, 80,
+    TDSATestSecureRandom.Create(seed)) as IDSAParameterGenerationParameters);
+
+  params := pGen.GenerateParameters();
+
+  pv := params.getValidationParameters();
+
+  if (pv.GetCounter() <> 21) then
+  begin
+    Fail('counter incorrect');
+  end;
+
+  if (not TArrayUtils.AreEqual(seed, pv.seed)) then
+  begin
+    Fail('seed incorrect');
+  end;
+
+  if (not(params.Q.Equals(TBigInteger.Create
+    ('90EAF4D1AF0708B1B612FF35E0A2997EB9E9D263C9CE659528945C0D', 16)))) then
+  begin
+    Fail('Q incorrect');
+  end;
+
+  if (not(params.p.Equals(TBigInteger.Create('C196BA05AC29E1F9C3C72D56DFFC6154'
+    + 'A033F1477AC88EC37F09BE6C5BB95F51C296DD20D1A28A06' +
+    '7CCC4D4316A4BD1DCA55ED1066D438C35AEBAABF57E7DAE4' +
+    '28782A95ECA1C143DB701FD48533A3C18F0FE23557EA7AE6' +
+    '19ECACC7E0B51652A8776D02A425567DED36EABD90CA33A1' +
+    'E8D988F0BBB92D02D1D20290113BB562CE1FC856EEB7CDD9' +
+    '2D33EEA6F410859B179E7E789A8F75F645FAE2E136D252BF' +
+    'FAFF89528945C1ABE705A38DBC2D364AADE99BE0D0AAD82E' +
+    '5320121496DC65B3930E38047294FF877831A16D5228418D' +
+    'E8AB275D7D75651CEFED65F78AFC3EA7FE4D79B35F62A040' +
+    '2A1117599ADAC7B269A59F353CF450E6982D3B1702D9CA83', 16)))) then
+  begin
+    Fail('P incorrect');
+  end;
+
+  if (not(params.G.Equals(TBigInteger.Create('A59A749A11242C58C894E9E5A91804E8'
+    + 'FA0AC64B56288F8D47D51B1EDC4D65444FECA0111D78F35F' +
+    'C9FDD4CB1F1B79A3BA9CBEE83A3F811012503C8117F98E50' +
+    '48B089E387AF6949BF8784EBD9EF45876F2E6A5A495BE64B' +
+    '6E770409494B7FEE1DBB1E4B2BC2A53D4F893D418B715959' +
+    '2E4FFFDF6969E91D770DAEBD0B5CB14C00AD68EC7DC1E574' +
+    '5EA55C706C4A1C5C88964E34D09DEB753AD418C1AD0F4FDF' +
+    'D049A955E5D78491C0B7A2F1575A008CCD727AB376DB6E69' +
+    '5515B05BD412F5B8C2F4C77EE10DA48ABD53F5DD498927EE' +
+    '7B692BBBCDA2FB23A516C5B4533D73980B2A3B60E384ED20' +
+    '0AE21B40D273651AD6060C13D97FD69AA13C5611A51B9085', 16)))) then
+  begin
+    Fail('G incorrect');
+  end;
+
+  kpGen := TDSAKeyPairGenerator.Create();
+
+  kpGen.Init(TDSAKeyGenerationParameters.Create(TFixedSecureRandom.Create
+    (TCryptoLibGenericArray<ISource>.Create(TFixedSecureRandom.TData.Create
+    (THex.Decode('00D0F09ED3E2568F6CADF9224117DA2AEC5A4300E009DE1366023E17')))),
+    params) as IDSAKeyGenerationParameters);
+
+  kp := kpGen.GenerateKeyPair();
+
+  pub := kp.Public as IDSAPublicKeyParameters;
+  priv := kp.Private as IDSAPrivateKeyParameters;
+
+  if (not(pub.Y.Equals(TBigInteger.Create('70035C9A3B225B258F16741F3941FBF0' +
+    '6F3D056CD7BD864604CBB5EE9DD85304EE8E8E4ABD5E9032' +
+    '11DDF25CE149075510ACE166970AFDC7DF552B7244F342FA' +
+    '02F7A621405B754909D757F97290E1FE5036E904CF593446' +
+    '0C046D95659821E1597ED9F2B1F0E20863A6BBD0CE74DACB' +
+    'A5D8C68A90B29C2157CDEDB82EC12B81EE3068F9BF5F7F34' +
+    '6ECA41ED174CCCD7D154FA4F42F80FFE1BF46AE9D8125DEB' +
+    '5B4BA08A72BDD86596DBEDDC9550FDD650C58F5AE5133509' +
+    'A702F79A31ECB490F7A3C5581631F7C5BE4FF7F9E9F27FA3' +
+    '90E47347AD1183509FED6FCF198BA9A71AB3335B4F38BE8D' +
+    '15496A00B6DC2263E20A5F6B662320A3A1EC033AA61E3B68', 16)))) then
+  begin
+    Fail('Y value incorrect');
+  end;
+
+  if (not(priv.X.Equals(TBigInteger.Create
+    ('00D0F09ED3E2568F6CADF9224117DA2AEC5A4300E009DE1366023E17', 16)))) then
+  begin
+    Fail('X value incorrect');
+  end;
+
+  signer := TDSASigner.Create();
+
+  signer.Init(true, TParametersWithRandom.Create(kp.Private,
+    TFixedSecureRandom.Create(TCryptoLibGenericArray<ISource>.Create
+    (TFixedSecureRandom.TBigIntegerSource.Create
+    ('735959CC4463B8B440E407EECA8A473BF6A6D1FE657546F67D401F05'),
+    TFixedSecureRandom.TData.Create(THex.Decode('01020304')))))
+    as IParametersWithRandom);
+
+  msg := THex.Decode
+    ('23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7');
+
+  sig := signer.GenerateSignature(msg);
+
+  if (not(sig[0].Equals(TBigInteger.Create
+    ('4400138D05F9639CAF54A583CAAF25D2B76D0C3EAD752CE17DBC85FE', 16)))) then
+  begin
+    Fail('R value incorrect');
+  end;
+
+  if (not(sig[1].Equals(TBigInteger.Create
+    ('874D4F12CB13B61732D398445698CFA9D92381D938AA57EE2C9327B3', 16)))) then
+  begin
+    Fail('S value incorrect');
+  end;
+
+  signer.Init(false, kp.Public);
+
+  if (not(signer.VerifySignature(msg, sig[0], sig[1]))) then
+  begin
+    Fail('signature not verified');
+  end;
+end;
+
+procedure TTestDSA.DoDSA2Test3;
+var
+  seed, msg: TCryptoLibByteArray;
+  pGen: IDsaParametersGenerator;
+  params: IDSAParameters;
+  pv: IDSAValidationParameters;
+  kpGen: IDSAKeyPairGenerator;
+  kp: IAsymmetricCipherKeyPair;
+  pub: IDSAPublicKeyParameters;
+  priv: IDSAPrivateKeyParameters;
+  signer: IDSASigner;
+  sig: TCryptoLibGenericArray<TBigInteger>;
+begin
+  seed := THex.Decode
+    ('4783081972865EA95D43318AB2EAF9C61A2FC7BBF1B772A09017BDF5A58F4FF0');
+
+  pGen := TDsaParametersGenerator.Create(TDigestUtilities.GetDigest('SHA-256'));
+
+  pGen.Init(TDSAParameterGenerationParameters.Create(2048, 256, 80,
+    TDSATestSecureRandom.Create(seed)) as IDSAParameterGenerationParameters);
+
+  params := pGen.GenerateParameters();
+
+  pv := params.getValidationParameters();
+
+  if (pv.GetCounter() <> 12) then
+  begin
+    Fail('counter incorrect');
+  end;
+
+  if (not TArrayUtils.AreEqual(seed, pv.seed)) then
+  begin
+    Fail('seed incorrect');
+  end;
+
+  if (not(params.Q.Equals(TBigInteger.Create
+    ('C24ED361870B61E0D367F008F99F8A1F75525889C89DB1B673C45AF5867CB467', 16))))
+  then
+  begin
+    Fail('Q incorrect');
+  end;
+
+  if (not(params.p.Equals(TBigInteger.Create('F56C2A7D366E3EBDEAA1891FD2A0D099'
+    + '436438A673FED4D75F594959CFFEBCA7BE0FC72E4FE67D91' +
+    'D801CBA0693AC4ED9E411B41D19E2FD1699C4390AD27D94C' +
+    '69C0B143F1DC88932CFE2310C886412047BD9B1C7A67F8A2' +
+    '5909132627F51A0C866877E672E555342BDF9355347DBD43' +
+    'B47156B2C20BAD9D2B071BC2FDCF9757F75C168C5D9FC431' +
+    '31BE162A0756D1BDEC2CA0EB0E3B018A8B38D3EF2487782A' +
+    'EB9FBF99D8B30499C55E4F61E5C7DCEE2A2BB55BD7F75FCD' +
+    'F00E48F2E8356BDB59D86114028F67B8E07B127744778AFF' +
+    '1CF1399A4D679D92FDE7D941C5C85C5D7BFF91BA69F9489D' +
+    '531D1EBFA727CFDA651390F8021719FA9F7216CEB177BD75', 16)))) then
+  begin
+    Fail('P incorrect');
+  end;
+
+  if (not(params.G.Equals(TBigInteger.Create('8DC6CC814CAE4A1C05A3E186A6FE27EA'
+    + 'BA8CDB133FDCE14A963A92E809790CBA096EAA26140550C1' +
+    '29FA2B98C16E84236AA33BF919CD6F587E048C52666576DB' +
+    '6E925C6CBE9B9EC5C16020F9A44C9F1C8F7A8E611C1F6EC2' +
+    '513EA6AA0B8D0F72FED73CA37DF240DB57BBB27431D61869' +
+    '7B9E771B0B301D5DF05955425061A30DC6D33BB6D2A32BD0' +
+    'A75A0A71D2184F506372ABF84A56AEEEA8EB693BF29A6403' +
+    '45FA1298A16E85421B2208D00068A5A42915F82CF0B858C8' +
+    'FA39D43D704B6927E0B2F916304E86FB6A1B487F07D8139E' +
+    '428BB096C6D67A76EC0B8D4EF274B8A2CF556D279AD267CC' +
+    'EF5AF477AFED029F485B5597739F5D0240F67C2D948A6279', 16)))) then
+  begin
+    Fail('G incorrect');
+  end;
+
+  kpGen := TDSAKeyPairGenerator.Create();
+
+  kpGen.Init(TDSAKeyGenerationParameters.Create(TFixedSecureRandom.Create
+    (TCryptoLibGenericArray<ISource>.Create(TFixedSecureRandom.TData.Create
+    (THex.Decode
+    ('0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C')))),
+    params) as IDSAKeyGenerationParameters);
+
+  kp := kpGen.GenerateKeyPair();
+
+  pub := kp.Public as IDSAPublicKeyParameters;
+  priv := kp.Private as IDSAPrivateKeyParameters;
+
+  if (not(pub.Y.Equals(TBigInteger.Create('2828003D7C747199143C370FDD07A286' +
+    '1524514ACC57F63F80C38C2087C6B795B62DE1C224BF8D1D' +
+    '1424E60CE3F5AE3F76C754A2464AF292286D873A7A30B7EA' +
+    'CBBC75AAFDE7191D9157598CDB0B60E0C5AA3F6EBE425500' +
+    'C611957DBF5ED35490714A42811FDCDEB19AF2AB30BEADFF' +
+    '2907931CEE7F3B55532CFFAEB371F84F01347630EB227A41' +
+    '9B1F3F558BC8A509D64A765D8987D493B007C4412C297CAF' +
+    '41566E26FAEE475137EC781A0DC088A26C8804A98C23140E' +
+    '7C936281864B99571EE95C416AA38CEEBB41FDBFF1EB1D1D' +
+    'C97B63CE1355257627C8B0FD840DDB20ED35BE92F08C49AE' +
+    'A5613957D7E5C7A6D5A5834B4CB069E0831753ECF65BA02B', 16)))) then
+  begin
+    Fail('Y value incorrect');
+  end;
+
+  if (not(priv.X.Equals(TBigInteger.Create
+    ('0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C', 16))))
+  then
+  begin
+    Fail('X value incorrect');
+  end;
+
+  signer := TDSASigner.Create();
+
+  signer.Init(true, TParametersWithRandom.Create(kp.Private,
+    TFixedSecureRandom.Create(TCryptoLibGenericArray<ISource>.Create
+    (TFixedSecureRandom.TBigIntegerSource.Create
+    ('0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C'),
+    TFixedSecureRandom.TData.Create(THex.Decode('01020304')))))
+    as IParametersWithRandom);
+
+  msg := THex.Decode
+    ('BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD');
+
+  sig := signer.GenerateSignature(msg);
+
+  if (not(sig[0].Equals(TBigInteger.Create
+    ('315C875DCD4850E948B8AC42824E9483A32D5BA5ABE0681B9B9448D444F2BE3C', 16))))
+  then
+  begin
+    Fail('R value incorrect');
+  end;
+
+  if (not(sig[1].Equals(TBigInteger.Create
+    ('89718D12E54A8D9ED066E4A55F7ED5A2229CD23B9A3CEE78F83ED6AA61F6BCB9', 16))))
+  then
+  begin
+    Fail('S value incorrect');
+  end;
+
+  signer.Init(false, kp.Public);
+
+  if (not(signer.VerifySignature(msg, sig[0], sig[1]))) then
+  begin
+    Fail('signature not verified');
+  end;
+end;
+
+procedure TTestDSA.DoDSA2Test4;
+var
+  seed, msg: TCryptoLibByteArray;
+  pGen: IDsaParametersGenerator;
+  params: IDSAParameters;
+  pv: IDSAValidationParameters;
+  kpGen: IDSAKeyPairGenerator;
+  kp: IAsymmetricCipherKeyPair;
+  pub: IDSAPublicKeyParameters;
+  priv: IDSAPrivateKeyParameters;
+  signer: IDSASigner;
+  sig: TCryptoLibGenericArray<TBigInteger>;
+begin
+  seed := THex.Decode
+    ('193AFCA7C1E77B3C1ECC618C81322E47B8B8B997C9C83515C59CC446C2D9BD47');
+
+  pGen := TDsaParametersGenerator.Create(TDigestUtilities.GetDigest('SHA-256'));
+
+  pGen.Init(TDSAParameterGenerationParameters.Create(3072, 256, 80,
+    TDSATestSecureRandom.Create(seed)) as IDSAParameterGenerationParameters);
+
+  params := pGen.GenerateParameters();
+
+  pv := params.getValidationParameters();
+
+  if (pv.GetCounter() <> 20) then
+  begin
+    Fail('counter incorrect');
+  end;
+
+  if (not TArrayUtils.AreEqual(seed, pv.seed)) then
+  begin
+    Fail('seed incorrect');
+  end;
+
+  if (not(params.Q.Equals(TBigInteger.Create
+    ('CFA0478A54717B08CE64805B76E5B14249A77A4838469DF7F7DC987EFCCFB11D', 16))))
+  then
+  begin
+    Fail('Q incorrect');
+  end;
+
+  if (not(params.p.Equals(TBigInteger.Create
+    ('90066455B5CFC38F9CAA4A48B4281F292C260FEEF01FD610' +
+    '37E56258A7795A1C7AD46076982CE6BB956936C6AB4DCFE0' +
+    '5E6784586940CA544B9B2140E1EB523F009D20A7E7880E4E' +
+    '5BFA690F1B9004A27811CD9904AF70420EEFD6EA11EF7DA1' +
+    '29F58835FF56B89FAA637BC9AC2EFAAB903402229F491D8D' +
+    '3485261CD068699B6BA58A1DDBBEF6DB51E8FE34E8A78E54' +
+    '2D7BA351C21EA8D8F1D29F5D5D15939487E27F4416B0CA63' +
+    '2C59EFD1B1EB66511A5A0FBF615B766C5862D0BD8A3FE7A0' +
+    'E0DA0FB2FE1FCB19E8F9996A8EA0FCCDE538175238FC8B0E' +
+    'E6F29AF7F642773EBE8CD5402415A01451A840476B2FCEB0' +
+    'E388D30D4B376C37FE401C2A2C2F941DAD179C540C1C8CE0' +
+    '30D460C4D983BE9AB0B20F69144C1AE13F9383EA1C08504F' +
+    'B0BF321503EFE43488310DD8DC77EC5B8349B8BFE97C2C56' +
+    '0EA878DE87C11E3D597F1FEA742D73EEC7F37BE43949EF1A' +
+    '0D15C3F3E3FC0A8335617055AC91328EC22B50FC15B941D3' +
+    'D1624CD88BC25F3E941FDDC6200689581BFEC416B4B2CB73', 16)))) then
+  begin
+    Fail('P incorrect');
+  end;
+
+  if (not(params.G.Equals(TBigInteger.Create
+    ('5E5CBA992E0A680D885EB903AEA78E4A45A469103D448EDE' +
+    '3B7ACCC54D521E37F84A4BDD5B06B0970CC2D2BBB715F7B8' +
+    '2846F9A0C393914C792E6A923E2117AB805276A975AADB52' +
+    '61D91673EA9AAFFEECBFA6183DFCB5D3B7332AA19275AFA1' +
+    'F8EC0B60FB6F66CC23AE4870791D5982AAD1AA9485FD8F4A' +
+    '60126FEB2CF05DB8A7F0F09B3397F3937F2E90B9E5B9C9B6' +
+    'EFEF642BC48351C46FB171B9BFA9EF17A961CE96C7E7A7CC' +
+    '3D3D03DFAD1078BA21DA425198F07D2481622BCE45969D9C' +
+    '4D6063D72AB7A0F08B2F49A7CC6AF335E08C4720E31476B6' +
+    '7299E231F8BD90B39AC3AE3BE0C6B6CACEF8289A2E2873D5' +
+    '8E51E029CAFBD55E6841489AB66B5B4B9BA6E2F784660896' +
+    'AFF387D92844CCB8B69475496DE19DA2E58259B090489AC8' +
+    'E62363CDF82CFD8EF2A427ABCD65750B506F56DDE3B98856' +
+    '7A88126B914D7828E2B63A6D7ED0747EC59E0E0A23CE7D8A' +
+    '74C1D2C2A7AFB6A29799620F00E11C33787F7DED3B30E1A2' +
+    '2D09F1FBDA1ABBBFBF25CAE05A13F812E34563F99410E73B', 16)))) then
+  begin
+    Fail('G incorrect');
+  end;
+
+  kpGen := TDSAKeyPairGenerator.Create();
+
+  kpGen.Init(TDSAKeyGenerationParameters.Create(TFixedSecureRandom.Create
+    (TCryptoLibGenericArray<ISource>.Create(TFixedSecureRandom.TData.Create
+    (THex.Decode
+    ('3ABC1587297CE7B9EA1AD6651CF2BC4D7F92ED25CABC8553F567D1B40EBB8764')))
+    ), params));
+
+  kp := kpGen.GenerateKeyPair();
+
+  pub := kp.Public as IDSAPublicKeyParameters;
+  priv := kp.Private as IDSAPrivateKeyParameters;
+
+  if (not(pub.Y.Equals(TBigInteger.Create
+    ('8B891C8692D3DE875879390F2698B26FBECCA6B075535DCE' +
+    '6B0C862577F9FA0DEF6074E7A7624121224A595896ABD4CD' +
+    'A56B2CEFB942E025D2A4282FFAA98A48CDB47E1A6FCB5CFB' +
+    '393EF35AF9DF913102BB303C2B5C36C3F8FC04ED7B8B69FE' +
+    'FE0CF3E1FC05CFA713B3435B2656E913BA8874AEA9F93600' +
+    '6AEB448BCD005D18EC3562A33D04CF25C8D3D69844343442' +
+    'FA3DB7DE618C5E2DA064573E61E6D5581BFB694A23AC87FD' +
+    '5B52D62E954E1376DB8DDB524FFC0D469DF978792EE44173' +
+    '8E5DB05A7DC43E94C11A2E7A4FBE383071FA36D2A7EC8A93' +
+    '88FE1C4F79888A99D3B6105697C2556B79BB4D7E781CEBB3' +
+    'D4866AD825A5E830846072289FDBC941FA679CA82F5F78B7' +
+    '461B2404DB883D215F4E0676CF5493950AC5591697BFEA8D' +
+    '1EE6EC016B89BA51CAFB5F9C84C989FA117375E94578F28B' +
+    'E0B34CE0545DA46266FD77F62D8F2CEE92AB77012AFEBC11' +
+    '008985A821CD2D978C7E6FE7499D1AAF8DE632C21BB48CA5' +
+    'CBF9F31098FD3FD3854C49A65D9201744AACE540354974F9', 16)))) then
+  begin
+    Fail('Y value incorrect');
+  end;
+
+  if (not(priv.X.Equals(TBigInteger.Create
+    ('3ABC1587297CE7B9EA1AD6651CF2BC4D7F92ED25CABC8553F567D1B40EBB8764', 16))))
+  then
+  begin
+    Fail('X value incorrect');
+  end;
+
+  signer := TDSASigner.Create();
+
+  signer.Init(true, TParametersWithRandom.Create(kp.Private,
+    TFixedSecureRandom.Create(TCryptoLibGenericArray<ISource>.Create
+    (TFixedSecureRandom.TBigIntegerSource.Create
+    ('A6902C1E6E3943C5628061588A8B007BCCEA91DBF12915483F04B24AB0678BEE'),
+    TFixedSecureRandom.TData.Create(THex.Decode('01020304')))))
+    as IParametersWithRandom);
+
+  msg := THex.Decode
+    ('BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD');
+
+  sig := signer.GenerateSignature(msg);
+
+  if (not(sig[0].Equals(TBigInteger.Create
+    ('5F184E645A38BE8FB4A6871B6503A9D12924C7ABE04B71410066C2ECA6E3BE3E', 16))))
+  then
+  begin
+    Fail('R value incorrect');
+  end;
+
+  if (not(sig[1].Equals(TBigInteger.Create
+    ('91EB0C7BA3D4B9B60B825C3D9F2CADA8A2C9D7723267B033CBCDCF8803DB9C18', 16))))
+  then
+  begin
+    Fail('S value incorrect');
+  end;
+
+  signer.Init(false, kp.Public);
+
+  if (not(signer.VerifySignature(msg, sig[0], sig[1]))) then
+  begin
+    Fail('signature not verified');
+  end;
+end;
+
+procedure TTestDSA.DoTestDSASHA3(size: Int32; const s: TBigInteger);
+var
+  dsaParams: IDSAParameters;
+  X, Y, r: TBigInteger;
+  priKey: IDSAPrivateKeyParameters;
+  pubKey: IDSAPublicKeyParameters;
+  k: ISecureRandom;
+  M, encSig: TCryptoLibByteArray;
+  dsa: IDSADigestSigner;
+  RS: TCryptoLibGenericArray<TBigInteger>;
+begin
+  dsaParams := TDSAParameters.Create
+    (TBigInteger.Create('F56C2A7D366E3EBDEAA1891FD2A0D099' +
+    '436438A673FED4D75F594959CFFEBCA7BE0FC72E4FE67D91' +
+    'D801CBA0693AC4ED9E411B41D19E2FD1699C4390AD27D94C' +
+    '69C0B143F1DC88932CFE2310C886412047BD9B1C7A67F8A2' +
+    '5909132627F51A0C866877E672E555342BDF9355347DBD43' +
+    'B47156B2C20BAD9D2B071BC2FDCF9757F75C168C5D9FC431' +
+    '31BE162A0756D1BDEC2CA0EB0E3B018A8B38D3EF2487782A' +
+    'EB9FBF99D8B30499C55E4F61E5C7DCEE2A2BB55BD7F75FCD' +
+    'F00E48F2E8356BDB59D86114028F67B8E07B127744778AFF' +
+    '1CF1399A4D679D92FDE7D941C5C85C5D7BFF91BA69F9489D' +
+    '531D1EBFA727CFDA651390F8021719FA9F7216CEB177BD75', 16),
+    TBigInteger.Create
+    ('C24ED361870B61E0D367F008F99F8A1F75525889C89DB1B673C45AF5867CB467', 16),
+    TBigInteger.Create('8DC6CC814CAE4A1C05A3E186A6FE27EA' +
+    'BA8CDB133FDCE14A963A92E809790CBA096EAA26140550C1' +
+    '29FA2B98C16E84236AA33BF919CD6F587E048C52666576DB' +
+    '6E925C6CBE9B9EC5C16020F9A44C9F1C8F7A8E611C1F6EC2' +
+    '513EA6AA0B8D0F72FED73CA37DF240DB57BBB27431D61869' +
+    '7B9E771B0B301D5DF05955425061A30DC6D33BB6D2A32BD0' +
+    'A75A0A71D2184F506372ABF84A56AEEEA8EB693BF29A6403' +
+    '45FA1298A16E85421B2208D00068A5A42915F82CF0B858C8' +
+    'FA39D43D704B6927E0B2F916304E86FB6A1B487F07D8139E' +
+    '428BB096C6D67A76EC0B8D4EF274B8A2CF556D279AD267CC' +
+    'EF5AF477AFED029F485B5597739F5D0240F67C2D948A6279', 16));
+
+  X := TBigInteger.Create
+    ('0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C', 16);
+
+  Y := TBigInteger.Create('2828003D7C747199143C370FDD07A286' +
+    '1524514ACC57F63F80C38C2087C6B795B62DE1C224BF8D1D' +
+    '1424E60CE3F5AE3F76C754A2464AF292286D873A7A30B7EA' +
+    'CBBC75AAFDE7191D9157598CDB0B60E0C5AA3F6EBE425500' +
+    'C611957DBF5ED35490714A42811FDCDEB19AF2AB30BEADFF' +
+    '2907931CEE7F3B55532CFFAEB371F84F01347630EB227A41' +
+    '9B1F3F558BC8A509D64A765D8987D493B007C4412C297CAF' +
+    '41566E26FAEE475137EC781A0DC088A26C8804A98C23140E' +
+    '7C936281864B99571EE95C416AA38CEEBB41FDBFF1EB1D1D' +
+    'C97B63CE1355257627C8B0FD840DDB20ED35BE92F08C49AE' +
+    'A5613957D7E5C7A6D5A5834B4CB069E0831753ECF65BA02B', 16);
+
+  priKey := TDSAPrivateKeyParameters.Create(X, dsaParams);
+
+  k := TFixedSecureRandom.Create(TCryptoLibGenericArray<ISource>.Create
+    (TFixedSecureRandom.TBigIntegerSource.Create(TBigInteger.Create
+    ('72546832179840998877302529996971396893172522460793442785601695562409154906335')
+    .ToByteArrayUnsigned), TFixedSecureRandom.TData.Create
+    (THex.Decode('01020304'))));
+
+  M := THex.Decode
+    ('1BD4ED430B0F384B4E8D458EFF1A8A553286D7AC21CB2F6806172EF5F94A06AD');
+
+  dsa := TDSADigestSigner.Create(TDSASigner.Create() as IDSASigner,
+    TDigestUtilities.GetDigest('SHA3-' + IntToStr(size)));
+
+  dsa.Init(true, TParametersWithRandom.Create(priKey, k)
+    as IParametersWithRandom);
+
+  dsa.BlockUpdate(M, 0, System.Length(M));
+
+  encSig := dsa.GenerateSignature();
+
+  RS := DoDerDecode(encSig);
+
+  r := TBigInteger.Create
+    ('4864074fe30e6601268ee663440e4d9b703f62673419864e91e9edb0338ce510', 16);
+
+  if (not r.Equals(RS[0])) then
+  begin
+    Fail('r component wrong.' + sLineBreak + ' expecting: ' + r.toString(16) +
+      sLineBreak + ' got      : ' + RS[0].toString(16));
+  end;
+
+  if (not s.Equals(RS[1])) then
+  begin
+    Fail('s component wrong.' + sLineBreak + ' expecting: ' + s.toString(16) +
+      sLineBreak + ' got      : ' + RS[1].toString(16));
+  end;
+
+  // Verify the signature
+  pubKey := TDSAPublicKeyParameters.Create(Y, dsaParams);
+
+  dsa.Init(false, pubKey);
+
+  dsa.BlockUpdate(M, 0, System.Length(M));
+
+  if (not(dsa.VerifySignature(encSig))) then
+  begin
+    Fail('signature fails');
+  end;
+end;
+
+procedure TTestDSA.DoTestECDsa239BitBinary(const algorithm: String;
+  const oid: IDerObjectIdentifier);
+var
+  kData, &message, sigBytes: TCryptoLibByteArray;
+  k: ISecureRandom;
+  curve: IECCurve;
+  parameters: IECDomainParameters;
+  sgr: ISigner;
+  sKey, vKey: IAsymmetricKeyParameter;
+begin
+
+  kData := TBigInteger.Create
+    ('171278725565216523967285789236956265265265235675811949404040041670216363')
+    .ToByteArrayUnsigned;
+
+  k := TFixedSecureRandom.From(TCryptoLibMatrixByteArray.Create(kData));
+
+  curve := TF2mCurve.Create(239, // m
+    36, // k
+    TBigInteger.Create
+    ('32010857077C5431123A46B808906756F543423E8D27877578125778AC76', 16), // a
+    TBigInteger.Create
+    ('790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16', 16), // b
+    TBigInteger.Create
+    ('2000000000000000000000000000000F4D42FFE1492A4993F1CAD666E447', 16),
+    TBigInteger.Four);
+
+  parameters := TECDomainParameters.Create(curve,
+    curve.DecodePoint(THex.Decode
+    ('0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305')
+    ), // G
+    TBigInteger.Create
+    ('220855883097298041197912187592864814557886993776713230936715041207411783'),
+    // n
+    TBigInteger.ValueOf(4)); // h
+
+  sKey := TECPrivateKeyParameters.Create('ECDSA',
+    TBigInteger.Create
+    ('145642755521911534651321230007534120304391871461646461466464667494947990'),
+    // d
+    parameters);
+
+  vKey := TECPublicKeyParameters.Create('ECDSA',
+    curve.DecodePoint(THex.Decode
+    ('045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5')
+    ), // Q
+    parameters);
+
+  sgr := TSignerUtilities.GetSigner(algorithm);
+
+  sgr.Init(true, TParametersWithRandom.Create(sKey, k)
+    as IParametersWithRandom);
+
+  &message := TEncoding.ASCII.GetBytes('abc');
+
+  sgr.BlockUpdate(&message, 0, System.Length(&message));
+
+  sigBytes := sgr.GenerateSignature();
+
+  sgr := TSignerUtilities.GetSigner(oid.Id);
+
+  sgr.Init(false, vKey);
+
+  sgr.BlockUpdate(&message, 0, System.Length(&message));
+
+  if (not(sgr.VerifySignature(sigBytes))) then
+  begin
+    Fail('239 Bit ' + algorithm + ' verification failed');
+  end;
+
+end;
+
+procedure TTestDSA.DoTestKeyGeneration(keysize: Int32);
+var
+  rand: ISecureRandom;
+  generator: IDSAKeyPairGenerator;
+  dsapGen: IDsaParametersGenerator;
+  p: IAsymmetricCipherKeyPair;
+  params: IDSAParameters;
+  priv: IDSAPrivateKeyParameters;
+  qsize: Int32;
+begin
+  rand := TSecureRandom.Create();
+  generator := TGeneratorUtilities.GetKeyPairGenerator('DSA')
+    as IDSAKeyPairGenerator;
+
+  // The NIST standard does not fully specify the size of q that
+  // must be used for a given key size. Hence there are differences.
+  // For example if keysize = 2048, then OpenSSL uses 256 bit q's by default,
+  // but the SUN provider uses 224 bits. Both are acceptable sizes.
+  // The tests below simply asserts that the size of q does not decrease the
+  // overall security of the DSA.
+
+  // Also We Check the length of the private key.
+  // For example GPG4Browsers or the KJUR library derived from it use
+  // q.BitCount instead of q.BitLength to determine the size of the private key
+  // and hence would generate keys that are much too small.
+  case keysize of
+    1024:
+      begin
+        dsapGen := TDsaParametersGenerator.Create(); // SHA-1 Default
+        dsapGen.Init(TDSAParameterGenerationParameters.Create(keysize, 160, 80,
+          rand) as IDSAParameterGenerationParameters);
+
+        params := dsapGen.GenerateParameters();
+
+        generator.Init(TDSAKeyGenerationParameters.Create(rand, params)
+          as IDSAKeyGenerationParameters);
+
+        p := generator.GenerateKeyPair();
+
+        priv := p.Private as IDSAPrivateKeyParameters;
+        params := priv.parameters;
+
+        CheckTrue(keysize = params.p.BitLength, 'keysize mismatch');
+        qsize := params.Q.BitLength;
+
+        CheckTrue(qsize = 160, 'Invalid qsize for 1024 bit key: ' +
+          IntToStr(qsize));
+
+        CheckTrue(priv.X.BitLength >= (qsize - 32), 'privkey error');
+      end;
+
+    2048:
+      begin
+        dsapGen := TDsaParametersGenerator.Create
+          (TDigestUtilities.GetDigest('SHA-224'));
+        dsapGen.Init(TDSAParameterGenerationParameters.Create(keysize, 224, 80,
+          rand) as IDSAParameterGenerationParameters);
+
+        params := dsapGen.GenerateParameters();
+
+        generator.Init(TDSAKeyGenerationParameters.Create(rand, params)
+          as IDSAKeyGenerationParameters);
+
+        p := generator.GenerateKeyPair();
+
+        priv := p.Private as IDSAPrivateKeyParameters;
+        params := priv.parameters;
+
+        CheckTrue(keysize = params.p.BitLength, 'keysize mismatch');
+
+        qsize := params.Q.BitLength;
+        CheckTrue(qsize = 224, 'Invalid qsize for 2048 bit key: ' +
+          IntToStr(qsize));
+
+        CheckTrue(priv.X.BitLength >= (qsize - 32), 'privkey error');
+        //
+        // .....
+        //
+        dsapGen := TDsaParametersGenerator.Create
+          (TDigestUtilities.GetDigest('SHA-256'));
+        dsapGen.Init(TDSAParameterGenerationParameters.Create(keysize, 256, 80,
+          rand) as IDSAParameterGenerationParameters);
+
+        params := dsapGen.GenerateParameters();
+
+        generator.Init(TDSAKeyGenerationParameters.Create(rand, params)
+          as IDSAKeyGenerationParameters);
+
+        p := generator.GenerateKeyPair();
+
+        priv := p.Private as IDSAPrivateKeyParameters;
+        params := priv.parameters;
+
+        CheckTrue(keysize = params.p.BitLength, 'keysize mismatch');
+
+        qsize := params.Q.BitLength;
+        CheckTrue(qsize = 256, 'Invalid qsize for 2048 bit key: ' +
+          IntToStr(qsize));
+
+        CheckTrue(priv.X.BitLength >= (qsize - 32), 'privkey error');
+      end;
+
+    3072:
+      begin
+
+        dsapGen := TDsaParametersGenerator.Create
+          (TDigestUtilities.GetDigest('SHA-256'));
+        dsapGen.Init(TDSAParameterGenerationParameters.Create(keysize, 256, 80,
+          rand) as IDSAParameterGenerationParameters);
+
+        params := dsapGen.GenerateParameters();
+
+        generator.Init(TDSAKeyGenerationParameters.Create(rand, params)
+          as IDSAKeyGenerationParameters);
+
+        p := generator.GenerateKeyPair();
+
+        priv := p.Private as IDSAPrivateKeyParameters;
+        params := priv.parameters;
+
+        CheckTrue(keysize = params.p.BitLength, 'keysize mismatch');
+
+        qsize := params.Q.BitLength;
+        CheckTrue(qsize = 256, 'Invalid qsize for 3072 bit key: ' +
+          IntToStr(qsize));
+
+        CheckTrue(priv.X.BitLength >= (qsize - 32), 'privkey error');
+      end
+
+  else
+    begin
+      Fail('Invalid key size: ' + IntToStr(keysize));
+    end;
+
+  end;
+
+end;
+
+procedure TTestDSA.SetUp;
+begin
+  inherited;
+
+end;
+
+procedure TTestDSA.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestDSA.TestDSA;
+var
+  k1, k2, keyData, &message: TCryptoLibByteArray;
+  sig: TCryptoLibGenericArray<TBigInteger>;
+  random, keyRandom: ISecureRandom;
+  pValue, qValue, r, s: TBigInteger;
+  pGen: IDsaParametersGenerator;
+  params: IDSAParameters;
+  pValid: IDSAValidationParameters;
+  dsaKeyGen: IDSAKeyPairGenerator;
+  genParam: IDSAKeyGenerationParameters;
+  pair: IAsymmetricCipherKeyPair;
+  param: IParametersWithRandom;
+  dsa: IDSASigner;
+begin
+  k1 := THex.Decode('d5014e4b60ef2ba8b6211b4062ba3224e0427dd3');
+  k2 := THex.Decode
+    ('345e8d05c075c3a508df729a1685690e68fcfb8c8117847e89063bca1f85d968fd281540b6e13bd1af989a1fbf17e06462bf511f9d0b140fb48ac1b1baa5bded');
+
+  random := TFixedSecureRandom.Create(TCryptoLibGenericArray<ISource>.Create
+    (TFixedSecureRandom.TData.Create(k1), TFixedSecureRandom.TData.Create(k2)));
+
+  keyData := THex.Decode('b5014e4b60ef2ba8b6211b4062ba3224e0427dd3');
+
+  keyRandom := TFixedSecureRandom.Create
+    (TCryptoLibGenericArray<ISource>.Create(TFixedSecureRandom.TData.Create
+    (keyData), TFixedSecureRandom.TData.Create(keyData),
+    TFixedSecureRandom.TData.Create(THex.Decode('01020304'))));
+
+  pValue := TBigInteger.Create
+    ('8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291',
+    16);
+  qValue := TBigInteger.Create('c773218c737ec8ee993b4f2ded30f48edace915f', 16);
+
+  r := TBigInteger.Create('68076202252361894315274692543577577550894681403');
+  s := TBigInteger.Create('1089214853334067536215539335472893651470583479365');
+  pGen := TDsaParametersGenerator.Create();
+
+  pGen.Init(512, 80, random);
+
+  params := pGen.GenerateParameters();
+  pValid := params.ValidationParameters;
+
+  if (pValid.GetCounter() <> 105) then
+  begin
+    Fail('Counter wrong');
+  end;
+
+  if ((not(pValue.Equals(params.p))) or (not(qValue.Equals(params.Q)))) then
+  begin
+    Fail('p or q wrong');
+  end;
+
+  dsaKeyGen := TDSAKeyPairGenerator.Create();
+  genParam := TDSAKeyGenerationParameters.Create(keyRandom, params);
+
+  dsaKeyGen.Init(genParam);
+
+  pair := dsaKeyGen.GenerateKeyPair();
+
+  param := TParametersWithRandom.Create(pair.Private, keyRandom);
+
+  dsa := TDSASigner.Create();
+
+  dsa.Init(true, param);
+
+  &message := TBigInteger.Create
+    ('968236873715988614170569073515315707566766479517').ToByteArrayUnsigned;
+  sig := dsa.GenerateSignature(&message);
+
+  if (not(r.Equals(sig[0]))) then
+  begin
+    Fail('r component wrong. expected ' + r.toString + ' but got ' +
+      sig[0].toString);
+  end;
+
+  if (not(s.Equals(sig[1]))) then
+  begin
+    Fail('s component wrong. expected ' + s.toString + ' but got ' +
+      sig[1].toString);
+  end;
+
+  dsa.Init(false, pair.Public);
+
+  if (not(dsa.VerifySignature(&message, sig[0], sig[1]))) then
+  begin
+    Fail('verification fails');
+  end;
+
+  DoDSA2Test1();
+  DoDSA2Test2();
+  DoDSA2Test3();
+  DoDSA2Test4();
+
+  DoTestDSASHA3(224,
+    TBigInteger.Create
+    ('613202af2a7f77e02b11b5c3a5311cf6b412192bc0032aac3ec127faebfc6bd0', 16));
+  DoTestDSASHA3(256,
+    TBigInteger.Create
+    ('2450755c5e15a691b121bc833b97864e34a61ee025ecec89289c949c1858091e', 16));
+  DoTestDSASHA3(384,
+    TBigInteger.Create
+    ('7aad97c0b71bb1e1a6483b6948a03bbe952e4780b0cee699a11731f90d84ddd1', 16));
+  DoTestDSASHA3(512,
+    TBigInteger.Create
+    ('725ad64d923c668e64e7c3898b5efde484cab49ce7f98c2885d2a13a9e355ad4', 16));
+end;
+
+procedure TTestDSA.TestDsa2Parameters;
+var
+  seed, encodeParams, encodeParams_2, data, sigBytes: TCryptoLibByteArray;
+  a: IDsaParametersGenerator;
+  dsaP: IDSAParameters;
+  G: IAsymmetricCipherKeyPairGenerator;
+  p: IAsymmetricCipherKeyPair;
+  sKey: IDSAPrivateKeyParameters;
+  vKey: IDSAPublicKeyParameters;
+  p2: IDSAParameters;
+  s: ISigner;
+begin
+  seed := THex.Decode
+    ('4783081972865EA95D43318AB2EAF9C61A2FC7BBF1B772A09017BDF5A58F4FF0');
+
+  a := TDsaParametersGenerator.Create(TDigestUtilities.GetDigest('SHA-256'));
+  a.Init(TDSAParameterGenerationParameters.Create(2048, 256, 80,
+    TDSATestSecureRandom.Create(seed) as ISecureRandom)
+    as IDSAParameterGenerationParameters);
+
+  dsaP := a.GenerateParameters();
+
+  if (not(dsaP.Q.Equals(TBigInteger.Create
+    ('C24ED361870B61E0D367F008F99F8A1F75525889C89DB1B673C45AF5867CB467', 16))))
+  then
+  begin
+    Fail('Q incorrect');
+  end;
+
+  if (not(dsaP.p.Equals(TBigInteger.Create('F56C2A7D366E3EBDEAA1891FD2A0D099' +
+    '436438A673FED4D75F594959CFFEBCA7BE0FC72E4FE67D91' +
+    'D801CBA0693AC4ED9E411B41D19E2FD1699C4390AD27D94C' +
+    '69C0B143F1DC88932CFE2310C886412047BD9B1C7A67F8A2' +
+    '5909132627F51A0C866877E672E555342BDF9355347DBD43' +
+    'B47156B2C20BAD9D2B071BC2FDCF9757F75C168C5D9FC431' +
+    '31BE162A0756D1BDEC2CA0EB0E3B018A8B38D3EF2487782A' +
+    'EB9FBF99D8B30499C55E4F61E5C7DCEE2A2BB55BD7F75FCD' +
+    'F00E48F2E8356BDB59D86114028F67B8E07B127744778AFF' +
+    '1CF1399A4D679D92FDE7D941C5C85C5D7BFF91BA69F9489D' +
+    '531D1EBFA727CFDA651390F8021719FA9F7216CEB177BD75', 16)))) then
+  begin
+    Fail('P incorrect');
+  end;
+
+  if (not(dsaP.G.Equals(TBigInteger.Create('8DC6CC814CAE4A1C05A3E186A6FE27EA' +
+    'BA8CDB133FDCE14A963A92E809790CBA096EAA26140550C1' +
+    '29FA2B98C16E84236AA33BF919CD6F587E048C52666576DB' +
+    '6E925C6CBE9B9EC5C16020F9A44C9F1C8F7A8E611C1F6EC2' +
+    '513EA6AA0B8D0F72FED73CA37DF240DB57BBB27431D61869' +
+    '7B9E771B0B301D5DF05955425061A30DC6D33BB6D2A32BD0' +
+    'A75A0A71D2184F506372ABF84A56AEEEA8EB693BF29A6403' +
+    '45FA1298A16E85421B2208D00068A5A42915F82CF0B858C8' +
+    'FA39D43D704B6927E0B2F916304E86FB6A1B487F07D8139E' +
+    '428BB096C6D67A76EC0B8D4EF274B8A2CF556D279AD267CC' +
+    'EF5AF477AFED029F485B5597739F5D0240F67C2D948A6279', 16)))) then
+  begin
+    Fail('G incorrect');
+  end;
+
+  G := TGeneratorUtilities.GetKeyPairGenerator('DSA');
+
+  G.Init(TDSAKeyGenerationParameters.Create(TFixedSecureRandom.From
+    (TCryptoLibMatrixByteArray.Create(THex.Decode
+    ('0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C'))),
+    dsaP) as IDSAKeyGenerationParameters);
+
+  p := G.GenerateKeyPair();
+
+  sKey := p.Private as IDSAPrivateKeyParameters;
+  vKey := p.Public as IDSAPublicKeyParameters;
+
+  if (not(vKey.Y.Equals(TBigInteger.Create('2828003D7C747199143C370FDD07A286' +
+    '1524514ACC57F63F80C38C2087C6B795B62DE1C224BF8D1D' +
+    '1424E60CE3F5AE3F76C754A2464AF292286D873A7A30B7EA' +
+    'CBBC75AAFDE7191D9157598CDB0B60E0C5AA3F6EBE425500' +
+    'C611957DBF5ED35490714A42811FDCDEB19AF2AB30BEADFF' +
+    '2907931CEE7F3B55532CFFAEB371F84F01347630EB227A41' +
+    '9B1F3F558BC8A509D64A765D8987D493B007C4412C297CAF' +
+    '41566E26FAEE475137EC781A0DC088A26C8804A98C23140E' +
+    '7C936281864B99571EE95C416AA38CEEBB41FDBFF1EB1D1D' +
+    'C97B63CE1355257627C8B0FD840DDB20ED35BE92F08C49AE' +
+    'A5613957D7E5C7A6D5A5834B4CB069E0831753ECF65BA02B', 16)))) then
+  begin
+    Fail('Y value incorrect');
+  end;
+
+  if (not sKey.X.Equals(TBigInteger.Create
+    ('0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C', 16)))
+  then
+  begin
+    Fail('X value incorrect');
+  end;
+
+  encodeParams := TDsaParameter.Create(dsaP.p, dsaP.Q, dsaP.G).GetDerEncoded();
+
+  p2 := TDSAParameters.Create(dsaP.p, dsaP.Q, dsaP.G);
+
+  encodeParams_2 := TDsaParameter.Create(p2.p, p2.Q, p2.G).GetDerEncoded();
+
+  if (not TArrayUtils.AreEqual(encodeParams, encodeParams_2)) then
+  begin
+    Fail('encode/decode parameters failed');
+  end;
+
+  s := TSignerUtilities.GetSigner('DSA');
+  data := TCryptoLibByteArray.Create(1, 2, 3, 4, 5, 6, 7, 8, 9, 0);
+
+  s.Init(true, sKey);
+
+  s.BlockUpdate(data, 0, System.Length(data));
+
+  sigBytes := s.GenerateSignature();
+
+  s := TSignerUtilities.GetSigner('DSA');
+
+  s.Init(false, vKey);
+
+  s.BlockUpdate(data, 0, System.Length(data));
+
+  if (not(s.VerifySignature(sigBytes))) then
+  begin
+    Fail('DSA verification failed');
+  end;
+end;
+
+procedure TTestDSA.TestECDsa239BitPrime;
+var
+  r, s: TBigInteger;
+  kData, &message, sigBytes: TCryptoLibByteArray;
+  k: ISecureRandom;
+  curve: IECCurve;
+  spec: IECDomainParameters;
+  priKey: IECPrivateKeyParameters;
+  pubKey: IECPublicKeyParameters;
+  sgr: ISigner;
+  sKey, vKey: IAsymmetricKeyParameter;
+  sig: TCryptoLibGenericArray<TBigInteger>;
+begin
+
+  r := TBigInteger.Create
+    ('308636143175167811492622547300668018854959378758531778147462058306432176');
+  s := TBigInteger.Create
+    ('323813553209797357708078776831250505931891051755007842781978505179448783');
+
+  kData := TBigInteger.Create
+    ('700000017569056646655505781757157107570501575775705779575555657156756655')
+    .ToByteArrayUnsigned;
+
+  k := TFixedSecureRandom.From(TCryptoLibMatrixByteArray.Create(kData));
+
+  curve := TFpCurve.Create
+    (TBigInteger.Create
+    ('883423532389192164791648750360308885314476597252960362792450860609699839'),
+    // q
+    TBigInteger.Create
+    ('7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc', 16), // a
+    TBigInteger.Create
+    ('6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a', 16), // b
+    TBigInteger.Create
+    ('7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b', 16),
+    TBigInteger.One);
+
+  spec := TECDomainParameters.Create(curve,
+    curve.DecodePoint(THex.Decode
+    ('020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf')), // G
+    TBigInteger.Create
+    ('883423532389192164791648750360308884807550341691627752275345424702807307')
+    ); // n
+
+  priKey := TECPrivateKeyParameters.Create('ECDSA',
+    TBigInteger.Create
+    ('876300101507107567501066130761671078357010671067781776716671676178726717'),
+    // d
+    spec);
+
+  pubKey := TECPublicKeyParameters.Create('ECDSA',
+    curve.DecodePoint(THex.Decode
+    ('025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70')), // Q
+    spec);
+
+  sgr := TSignerUtilities.GetSigner('ECDSA');
+
+  // KeyFactory f = KeyFactory.GetInstance('ECDSA');
+  // PrivateKey sKey = f.generatePrivate(priKey);
+  // PublicKey vKey = f.generatePublic(pubKey);
+  sKey := priKey;
+  vKey := pubKey;
+
+  sgr.Init(true, TParametersWithRandom.Create(sKey, k)
+    as IParametersWithRandom);
+
+  &message := TEncoding.ASCII.GetBytes('abc');
+
+  sgr.BlockUpdate(&message, 0, System.Length(&message));
+
+  sigBytes := sgr.GenerateSignature();
+
+  sgr.Init(false, vKey);
+
+  sgr.BlockUpdate(&message, 0, System.Length(&message));
+
+  if (not(sgr.VerifySignature(sigBytes))) then
+  begin
+    Fail('239 Bit EC verification failed');
+  end;
+
+  sig := DoDerDecode(sigBytes);
+
+  if (not(r.Equals(sig[0]))) then
+  begin
+    Fail('r component wrong.' + sLineBreak + ' expecting: ' + r.toString +
+      sLineBreak + ' got      : ' + sig[0].toString);
+  end;
+
+  if (not(s.Equals(sig[1]))) then
+  begin
+    Fail('s component wrong.' + sLineBreak + ' expecting: ' + s.toString +
+      sLineBreak + ' got      : ' + sig[1].toString);
+  end;
+
+end;
+
+procedure TTestDSA.TestGeneration;
+var
+  s: ISigner;
+  data, sigBytes: TCryptoLibByteArray;
+  rand: ISecureRandom;
+  G: IAsymmetricCipherKeyPairGenerator;
+  pGen: IDsaParametersGenerator;
+  p: IAsymmetricCipherKeyPair;
+  sKey, vKey: IAsymmetricKeyParameter;
+  curve: IECCurve;
+  ecSpec: IECDomainParameters;
+begin
+
+  // test exception
+  //
+
+  DoTestBadStrength(513);
+  DoTestBadStrength(510);
+  DoTestBadStrength(1025);
+
+  s := TSignerUtilities.GetSigner('DSA');
+  data := TCryptoLibByteArray.Create(1, 2, 3, 4, 5, 6, 7, 8, 9, 0);
+  rand := TSecureRandom.Create();
+
+  G := TGeneratorUtilities.GetKeyPairGenerator('DSA');
+
+  pGen := TDsaParametersGenerator.Create();
+  pGen.Init(512, 80, rand);
+
+  G.Init(TDSAKeyGenerationParameters.Create(rand, pGen.GenerateParameters())
+    as IDSAKeyGenerationParameters);
+
+  p := G.GenerateKeyPair();
+
+  sKey := p.Private;
+  vKey := p.Public;
+
+  s.Init(true, sKey);
+
+  s.BlockUpdate(data, 0, System.Length(data));
+
+  sigBytes := s.GenerateSignature();
+
+  s := TSignerUtilities.GetSigner('DSA');
+
+  s.Init(false, vKey);
+
+  s.BlockUpdate(data, 0, System.Length(data));
+
+  if (not(s.VerifySignature(sigBytes))) then
+  begin
+    Fail('DSA verification failed');
+  end;
+
+  //
+  // ECDSA Fp generation test
+  //
+  s := TSignerUtilities.GetSigner('ECDSA');
+
+  curve := TFpCurve.Create
+    (TBigInteger.Create
+    ('883423532389192164791648750360308885314476597252960362792450860609699839'),
+    // q
+    TBigInteger.Create
+    ('7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc', 16), // a
+    TBigInteger.Create
+    ('6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a', 16), // b
+    TBigInteger.Create
+    ('7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b', 16),
+    TBigInteger.One);
+
+  ecSpec := TECDomainParameters.Create(curve,
+    curve.DecodePoint(THex.Decode
+    ('020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf')), // G
+    TBigInteger.Create
+    ('883423532389192164791648750360308884807550341691627752275345424702807307')
+    ); // n
+
+  G := TGeneratorUtilities.GetKeyPairGenerator('ECDSA');
+  G.Init(TECKeyGenerationParameters.Create(ecSpec, rand)
+    as IECKeyGenerationParameters);
+
+  p := G.GenerateKeyPair();
+
+  sKey := p.Private;
+  vKey := p.Public;
+
+  s.Init(true, sKey);
+
+  s.BlockUpdate(data, 0, System.Length(data));
+
+  sigBytes := s.GenerateSignature();
+
+  s := TSignerUtilities.GetSigner('ECDSA');
+
+  s.Init(false, vKey);
+
+  s.BlockUpdate(data, 0, System.Length(data));
+
+  if (not(s.VerifySignature(sigBytes))) then
+  begin
+    Fail('ECDSA verification failed');
+  end;
+
+  //
+  // ECDSA F2m generation test
+  //
+  s := TSignerUtilities.GetSigner('ECDSA');
+
+  curve := TF2mCurve.Create(239, // m
+    36, // k
+    TBigInteger.Create
+    ('32010857077C5431123A46B808906756F543423E8D27877578125778AC76', 16), // a
+    TBigInteger.Create
+    ('790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16', 16), // b
+    TBigInteger.Create
+    ('2000000000000000000000000000000F4D42FFE1492A4993F1CAD666E447', 16),
+    TBigInteger.Four);
+
+  ecSpec := TECDomainParameters.Create(curve,
+    curve.DecodePoint(THex.Decode
+    ('0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305')
+    ), // G
+    TBigInteger.Create
+    ('220855883097298041197912187592864814557886993776713230936715041207411783'),
+    // n
+    TBigInteger.ValueOf(4)); // h
+
+  G := TGeneratorUtilities.GetKeyPairGenerator('ECDSA');
+  G.Init(TECKeyGenerationParameters.Create(ecSpec, rand)
+    as IECKeyGenerationParameters);
+
+  p := G.GenerateKeyPair();
+
+  sKey := p.Private;
+  vKey := p.Public;
+
+  s.Init(true, sKey);
+
+  s.BlockUpdate(data, 0, System.Length(data));
+
+  sigBytes := s.GenerateSignature();
+
+  s := TSignerUtilities.GetSigner('ECDSA');
+
+  s.Init(false, vKey);
+
+  s.BlockUpdate(data, 0, System.Length(data));
+
+  if (not(s.VerifySignature(sigBytes))) then
+  begin
+    Fail('ECDSA verification failed');
+  end;
+end;
+
+procedure TTestDSA.TestKeyGenerationAll;
+begin
+  DoTestKeyGeneration(1024);
+  DoTestKeyGeneration(2048);
+  DoTestKeyGeneration(3072);
+end;
+
+procedure TTestDSA.TestECDsa239BitBinary;
+var
+  r, s: TBigInteger;
+  kData, &message, sigBytes: TCryptoLibByteArray;
+  k: ISecureRandom;
+  curve: IECCurve;
+  parameters: IECDomainParameters;
+  sKey: IECPrivateKeyParameters;
+  vKey: IECPublicKeyParameters;
+  sgr: ISigner;
+  sig: TCryptoLibGenericArray<TBigInteger>;
+begin
+
+  r := TBigInteger.Create
+    ('21596333210419611985018340039034612628818151486841789642455876922391552');
+  s := TBigInteger.Create
+    ('197030374000731686738334997654997227052849804072198819102649413465737174');
+
+  kData := TBigInteger.Create
+    ('171278725565216523967285789236956265265265235675811949404040041670216363')
+    .ToByteArrayUnsigned;
+
+  k := TFixedSecureRandom.From(TCryptoLibMatrixByteArray.Create(kData));
+
+  curve := TF2mCurve.Create(239, // m
+    36, // k
+    TBigInteger.Create
+    ('32010857077C5431123A46B808906756F543423E8D27877578125778AC76', 16), // a
+    TBigInteger.Create
+    ('790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16', 16), // b
+    TBigInteger.Create
+    ('2000000000000000000000000000000F4D42FFE1492A4993F1CAD666E447', 16),
+    TBigInteger.Four);
+
+  parameters := TECDomainParameters.Create(curve,
+    curve.DecodePoint(THex.Decode
+    ('0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305')
+    ), // G
+    TBigInteger.Create
+    ('220855883097298041197912187592864814557886993776713230936715041207411783'),
+    // n
+    TBigInteger.Four); // h
+
+  sKey := TECPrivateKeyParameters.Create('ECDSA',
+    TBigInteger.Create
+    ('145642755521911534651321230007534120304391871461646461466464667494947990'),
+    // d
+    parameters);
+
+  vKey := TECPublicKeyParameters.Create('ECDSA',
+    curve.DecodePoint(THex.Decode
+    ('045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5')
+    ), // Q
+    parameters);
+
+  sgr := TSignerUtilities.GetSigner('ECDSA');
+
+  sgr.Init(true, TParametersWithRandom.Create(sKey, k)
+    as IParametersWithRandom);
+
+  &message := TEncoding.ASCII.GetBytes('abc');
+
+  sgr.BlockUpdate(&message, 0, System.Length(&message));
+
+  sigBytes := sgr.GenerateSignature();
+
+  sgr.Init(false, vKey);
+
+  sgr.BlockUpdate(&message, 0, System.Length(&message));
+
+  if (not(sgr.VerifySignature(sigBytes))) then
+  begin
+    Fail('239 Bit EC verification failed');
+  end;
+
+  sig := DoDerDecode(sigBytes);
+
+  if (not(r.Equals(sig[0]))) then
+  begin
+    Fail('r component wrong.' + sLineBreak + ' expecting: ' + r.toString +
+      sLineBreak + ' got      : ' + sig[0].toString);
+  end;
+
+  if (not(s.Equals(sig[1]))) then
+  begin
+    Fail('s component wrong.' + sLineBreak + ' expecting: ' + s.toString +
+      sLineBreak + ' got      : ' + sig[1].toString);
+  end;
+
+end;
+
+procedure TTestDSA.TestECDsa239BitBinaryRipeMD160;
+begin
+  DoTestECDsa239BitBinary('RIPEMD160withECDSA',
+    TTeleTrusTObjectIdentifiers.ECSignWithRipeMD160);
+end;
+
+procedure TTestDSA.TestECDsa239BitBinarySha1;
+begin
+  DoTestECDsa239BitBinary('SHA1withECDSA',
+    TTeleTrusTObjectIdentifiers.ECSignWithSha1);
+end;
+
+procedure TTestDSA.TestECDsa239BitBinarySha224;
+begin
+  DoTestECDsa239BitBinary('SHA224withECDSA',
+    TX9ObjectIdentifiers.ECDsaWithSha224);
+end;
+
+procedure TTestDSA.TestECDsa239BitBinarySha256;
+begin
+  DoTestECDsa239BitBinary('SHA256withECDSA',
+    TX9ObjectIdentifiers.ECDsaWithSha256);
+end;
+
+procedure TTestDSA.TestECDsa239BitBinarySha384;
+begin
+  DoTestECDsa239BitBinary('SHA384withECDSA',
+    TX9ObjectIdentifiers.ECDsaWithSha384);
+end;
+
+procedure TTestDSA.TestECDsa239BitBinarySha512;
+begin
+  DoTestECDsa239BitBinary('SHA512withECDSA',
+    TX9ObjectIdentifiers.ECDsaWithSha512);
+end;
+
+procedure TTestDSA.TestNONEwithDSA;
+var
+  dummySha1, sigBytes: TCryptoLibByteArray;
+  rand: ISecureRandom;
+  pGen: IDsaParametersGenerator;
+  G: IAsymmetricCipherKeyPairGenerator;
+  kp: IAsymmetricCipherKeyPair;
+  sig: ISigner;
+  signer: IDSASigner;
+  RS: TCryptoLibGenericArray<TBigInteger>;
+begin
+  dummySha1 := THex.Decode('01020304050607080910111213141516');
+
+  rand := TSecureRandom.Create();
+
+  pGen := TDsaParametersGenerator.Create();
+  pGen.Init(512, 80, rand);
+
+  G := TGeneratorUtilities.GetKeyPairGenerator('DSA');
+  G.Init(TDSAKeyGenerationParameters.Create(rand, pGen.GenerateParameters())
+    as IDSAKeyGenerationParameters);
+
+  kp := G.GenerateKeyPair();
+
+  sig := TSignerUtilities.GetSigner('NONEwithDSA');
+  sig.Init(true, kp.Private);
+  sig.BlockUpdate(dummySha1, 0, System.Length(dummySha1));
+  sigBytes := sig.GenerateSignature();
+
+  sig.Init(false, kp.Public);
+  sig.BlockUpdate(dummySha1, 0, System.Length(dummySha1));
+  sig.VerifySignature(sigBytes);
+
+  // reset test
+
+  sig.BlockUpdate(dummySha1, 0, System.Length(dummySha1));
+
+  if (not(sig.VerifySignature(sigBytes))) then
+  begin
+    Fail('NONEwithDSA failed to reset');
+  end;
+
+  // lightweight test
+  signer := TDSASigner.Create();
+  signer.Init(false, kp.Public);
+  RS := DoDerDecode(sigBytes);
+
+  if (not(signer.VerifySignature(dummySha1, RS[0], RS[1]))) then
+  begin
+    Fail('NONEwithDSA not really NONE!');
+  end;
+end;
+
+procedure TTestDSA.TestNONEwithECDSA239bitPrime;
+var
+  &message, sig: TCryptoLibByteArray;
+  curve: IECCurve;
+  spec: IECDomainParameters;
+  priKey: IECPrivateKeyParameters;
+  pubKey: IECPublicKeyParameters;
+  sgr: ISigner;
+begin
+
+  curve := TFpCurve.Create
+    (TBigInteger.Create
+    ('883423532389192164791648750360308885314476597252960362792450860609699839'),
+    // q
+    TBigInteger.Create
+    ('7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc', 16), // a
+    TBigInteger.Create
+    ('6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a', 16), // b
+    TBigInteger.Create
+    ('7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b', 16),
+    TBigInteger.One);
+
+  spec := TECDomainParameters.Create(curve,
+    curve.DecodePoint(THex.Decode
+    ('020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf')), // G
+    TBigInteger.Create
+    ('883423532389192164791648750360308884807550341691627752275345424702807307')
+    ); // n
+
+  priKey := TECPrivateKeyParameters.Create('ECDSA',
+    TBigInteger.Create
+    ('876300101507107567501066130761671078357010671067781776716671676178726717'),
+    // d
+    spec);
+
+  pubKey := TECPublicKeyParameters.Create('ECDSA',
+    curve.DecodePoint(THex.Decode
+    ('025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70')), // Q
+    spec);
+
+  sgr := TSignerUtilities.GetSigner('NONEwithECDSA');
+
+  &message := TEncoding.UTF8.GetBytes('abc');
+  sig := THex.Decode
+    ('3040021e2cb7f36803ebb9c427c58d8265f11fc5084747133078fc279de874fbecb0021e64cb19604be06c57e761b3de5518f71de0f6e0cd2df677cec8a6ffcb690d');
+
+  DoCheckMessage(sgr, priKey, pubKey, &message, sig);
+
+  &message := TEncoding.UTF8.GetBytes('abcdefghijklmnopqrstuvwxyz');
+  sig := THex.Decode
+    ('3040021e2cb7f36803ebb9c427c58d8265f11fc5084747133078fc279de874fbecb0021e43fd65b3363d76aabef8630572257dbb67c82818ad9fad31256539b1b02c');
+
+  DoCheckMessage(sgr, priKey, pubKey, &message, sig);
+
+  &message := TEncoding.UTF8.GetBytes
+    ('a very very long message gauranteed to cause an overflow');
+  sig := THex.Decode
+    ('3040021e2cb7f36803ebb9c427c58d8265f11fc5084747133078fc279de874fbecb0021e7d5be84b22937a1691859a3c6fe45ed30b108574431d01b34025825ec17a');
+
+  DoCheckMessage(sgr, priKey, pubKey, &message, sig);
+
+end;
+
+procedure TTestDSA.TestParameters;
+var
+  random: ISecureRandom;
+  a: IDsaParametersGenerator;
+  p: IDSAParameters;
+  encodeParams, encodeParams_2, data, sigBytes: TCryptoLibByteArray;
+  dsaP: IDsaParameter;
+  p2: IDSAParameters;
+  G: IAsymmetricCipherKeyPairGenerator;
+  pair: IAsymmetricCipherKeyPair;
+  sKey, vKey: IAsymmetricKeyParameter;
+  s: ISigner;
+begin
+  random := TFixedSecureRandom.From
+    (TCryptoLibMatrixByteArray.Create
+    (THex.Decode('d5014e4b60ef2ba8b6211b4062ba3224e0427dd3'),
+    THex.Decode
+    ('345e8d05c075c3a508df729a1685690e68fcfb8c8117847e89063bca1f85d968fd281540b6e13bd1af989a1fbf17e06462bf511f9d0b140fb48ac1b1baa5bded'))
+    );
+
+  a := TDsaParametersGenerator.Create();
+  a.Init(512, 20, random);
+
+  p := a.GenerateParameters();
+
+  encodeParams := TDsaParameter.Create(p.p, p.Q, p.G).GetDerEncoded();
+
+  dsaP := TDsaParameter.GetInstance(TAsn1Object.FromByteArray(encodeParams)
+    as TAsn1Object);
+  p2 := TDSAParameters.Create(dsaP.p, dsaP.Q, dsaP.G);
+
+  // a and a2 should be equivalent!
+  encodeParams_2 := TDsaParameter.Create(p2.p, p2.Q, p2.G).GetDerEncoded();
+
+  if (not TArrayUtils.AreEqual(encodeParams, encodeParams_2)) then
+  begin
+    Fail('encode/Decode parameters failed');
+  end;
+
+  G := TGeneratorUtilities.GetKeyPairGenerator('DSA');
+
+  G.Init(TDSAKeyGenerationParameters.Create(TSecureRandom.Create()
+    as ISecureRandom, p) as IDSAKeyGenerationParameters);
+
+  pair := G.GenerateKeyPair();
+
+  sKey := pair.Private;
+  vKey := pair.Public;
+
+  s := TSignerUtilities.GetSigner('DSA');
+  data := TBytes.Create(1, 2, 3, 4, 5, 6, 7, 8, 9, 0);
+
+  s.Init(true, sKey);
+
+  s.BlockUpdate(data, 0, System.Length(data));
+
+  sigBytes := s.GenerateSignature();
+
+  s := TSignerUtilities.GetSigner('DSA');
+
+  s.Init(false, vKey);
+
+  s.BlockUpdate(data, 0, System.Length(data));
+
+  if (not(s.VerifySignature(sigBytes))) then
+  begin
+    Fail('dsa verification failed');
+  end;
+end;
+
+{ TDSATestSecureRandom }
+
+constructor TDSATestSecureRandom.Create(value: TCryptoLibByteArray);
+begin
+  Inherited Create(System.Copy(value));
+  Ffirst := true;
+end;
+
+procedure TDSATestSecureRandom.NextBytes(bytes: TCryptoLibByteArray);
+begin
+  if (Ffirst) then
+  begin
+    Inherited NextBytes(bytes);
+    Ffirst := false;
+  end
+  else
+  begin
+    bytes[System.Length(bytes) - 1] := 2;
+  end;
+
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestDSA);
+{$ELSE}
+  RegisterTest(TTestDSA.Suite);
+{$ENDIF FPC}
+
+end.

+ 428 - 0
CryptoLib.Tests/src/Crypto/DeterministicDsaTests.pas

@@ -0,0 +1,428 @@
+{ *********************************************************************************** }
+{ *                              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 DeterministicDsaTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+uses
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpIDsa,
+  ClpIDigest,
+  ClpDsaSigner,
+  ClpIDsaSigner,
+  ClpECDsaSigner,
+  ClpIECDsaSigner,
+  ClpIDsaParameters,
+  ClpDsaParameters,
+  ClpHMacDsaKCalculator,
+  ClpIHMacDsaKCalculator,
+  ClpICipherParameters,
+  ClpIX9ECParameters,
+  ClpIECPrivateKeyParameters,
+  ClpECPrivateKeyParameters,
+  ClpIDsaPrivateKeyParameters,
+  ClpDsaPrivateKeyParameters,
+  ClpIECDomainParameters,
+  ClpECDomainParameters,
+  ClpBigInteger,
+  ClpDigestUtilities,
+  ClpSecNamedCurves,
+  ClpHex,
+  ClpCryptoLibTypes;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  /// <summary>
+  /// Tests are taken from RFC 6979 - "Deterministic Usage of the Digital
+  /// Signature Algorithm (DSA) and Elliptic Curve Digital Signature
+  /// Algorithm (ECDSA)".
+  /// </summary>
+  TTestDeterministicDsa = class(TCryptoLibTestCase)
+
+  private
+  var
+    FSAMPLE, FTEST: TCryptoLibByteArray;
+
+    // test vectors from appendix in RFC 6979
+    procedure DoTestHMacDeterministic;
+    procedure DoTestECHMacDeterministic;
+
+    procedure DoTestHMacDetDsaSample(const digest: IDigest;
+      const privKey: IDsaPrivateKeyParameters; const r, s: TBigInteger);
+
+    procedure DoTestHMacDetDsaTest(const digest: IDigest;
+      const privKey: IDsaPrivateKeyParameters; const r, s: TBigInteger);
+
+    procedure DoTestHMacDetECDsaSample(const digest: IDigest;
+      const privKey: IECPrivateKeyParameters; const r, s: TBigInteger);
+
+    procedure DoTestHMacDetECDsaTest(const digest: IDigest;
+      const privKey: IECPrivateKeyParameters; const r, s: TBigInteger);
+
+    procedure DoTestHMacDetECDsa(const detSigner: IDsa; const digest: IDigest;
+      data: TCryptoLibByteArray; const privKey: ICipherParameters;
+      const r, s: TBigInteger);
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+
+    procedure TestDsaDeterministic;
+
+  end;
+
+implementation
+
+{ TTestDeterministicDsa }
+
+procedure TTestDeterministicDsa.DoTestECHMacDeterministic;
+var
+  x9ECParameters: IX9ECParameters;
+  ecDomainParameters: IECDomainParameters;
+  privKey: IECPrivateKeyParameters;
+begin
+  x9ECParameters := TSecNamedCurves.GetByName('secp521r1');
+  ecDomainParameters := TECDomainParameters.Create(x9ECParameters.Curve,
+    x9ECParameters.G, x9ECParameters.N);
+
+  privKey := TECPrivateKeyParameters.Create
+    (TBigInteger.Create
+    ('0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75C' +
+    'AA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83' + '538',
+    16), ecDomainParameters);
+
+  DoTestHMacDetECDsaSample(TDigestUtilities.GetDigest('SHA-1'), privKey,
+    TBigInteger.Create
+    ('0343B6EC45728975EA5CBA6659BBB6062A5FF89EEA58BE3C80B619F322C87910' +
+    'FE092F7D45BB0F8EEE01ED3F20BABEC079D202AE677B243AB40B5431D497C55D' + '75D',
+    16), TBigInteger.Create
+    ('0E7B0E675A9B24413D448B8CC119D2BF7B2D2DF032741C096634D6D65D0DBE3D' +
+    '5694625FB9E8104D3B842C1B0E2D0B98BEA19341E8676AEF66AE4EBA3D5475D5' +
+    'D16', 16));
+  DoTestHMacDetECDsaSample(TDigestUtilities.GetDigest('SHA-224'), privKey,
+    TBigInteger.Create
+    ('1776331CFCDF927D666E032E00CF776187BC9FDD8E69D0DABB4109FFE1B5E2A3' +
+    '0715F4CC923A4A5E94D2503E9ACFED92857B7F31D7152E0F8C00C15FF3D87E2E' + 'D2E',
+    16), TBigInteger.Create
+    ('050CB5265417FE2320BBB5A122B8E1A32BD699089851128E360E620A30C7E17B' +
+    'A41A666AF126CE100E5799B153B60528D5300D08489CA9178FB610A2006C254B' +
+    '41F', 16));
+  DoTestHMacDetECDsaSample(TDigestUtilities.GetDigest('SHA-256'), privKey,
+    TBigInteger.Create
+    ('1511BB4D675114FE266FC4372B87682BAECC01D3CC62CF2303C92B3526012659' +
+    'D16876E25C7C1E57648F23B73564D67F61C6F14D527D54972810421E7D87589E' + '1A7',
+    16), TBigInteger.Create
+    ('04A171143A83163D6DF460AAF61522695F207A58B95C0644D87E52AA1A347916' +
+    'E4F7A72930B1BC06DBE22CE3F58264AFD23704CBB63B29B931F7DE6C9D949A7E' +
+    'CFC', 16));
+  DoTestHMacDetECDsaSample(TDigestUtilities.GetDigest('SHA-384'), privKey,
+    TBigInteger.Create
+    ('1EA842A0E17D2DE4F92C15315C63DDF72685C18195C2BB95E572B9C5136CA4B4' +
+    'B576AD712A52BE9730627D16054BA40CC0B8D3FF035B12AE75168397F5D50C67' + '451',
+    16), TBigInteger.Create
+    ('1F21A3CEE066E1961025FB048BD5FE2B7924D0CD797BABE0A83B66F1E35EEAF5' +
+    'FDE143FA85DC394A7DEE766523393784484BDF3E00114A1C857CDE1AA203DB65' +
+    'D61', 16));
+  DoTestHMacDetECDsaSample(TDigestUtilities.GetDigest('SHA-512'), privKey,
+    TBigInteger.Create
+    ('0C328FAFCBD79DD77850370C46325D987CB525569FB63C5D3BC53950E6D4C5F1' +
+    '74E25A1EE9017B5D450606ADD152B534931D7D4E8455CC91F9B15BF05EC36E37' + '7FA',
+    16), TBigInteger.Create
+    ('0617CCE7CF5064806C467F678D3B4080D6F1CC50AF26CA209417308281B68AF2' +
+    '82623EAA63E5B5C0723D8B8C37FF0777B1A20F8CCB1DCCC43997F1EE0E44DA4A' +
+    '67A', 16));
+
+  DoTestHMacDetECDsaTest(TDigestUtilities.GetDigest('SHA-1'), privKey,
+    TBigInteger.Create
+    ('13BAD9F29ABE20DE37EBEB823C252CA0F63361284015A3BF430A46AAA80B87B0' +
+    '693F0694BD88AFE4E661FC33B094CD3B7963BED5A727ED8BD6A3A202ABE009D0' + '367',
+    16), TBigInteger.Create
+    ('1E9BB81FF7944CA409AD138DBBEE228E1AFCC0C890FC78EC8604639CB0DBDC90' +
+    'F717A99EAD9D272855D00162EE9527567DD6A92CBD629805C0445282BBC91679' +
+    '7FF', 16));
+  DoTestHMacDetECDsaTest(TDigestUtilities.GetDigest('SHA-224'), privKey,
+    TBigInteger.Create
+    ('1C7ED902E123E6815546065A2C4AF977B22AA8EADDB68B2C1110E7EA44D42086' +
+    'BFE4A34B67DDC0E17E96536E358219B23A706C6A6E16BA77B65E1C595D43CAE1' + '7FB',
+    16), TBigInteger.Create
+    ('177336676304FCB343CE028B38E7B4FBA76C1C1B277DA18CAD2A8478B2A9A9F5' +
+    'BEC0F3BA04F35DB3E4263569EC6AADE8C92746E4C82F8299AE1B8F1739F8FD51' +
+    '9A4', 16));
+  DoTestHMacDetECDsaTest(TDigestUtilities.GetDigest('SHA-256'), privKey,
+    TBigInteger.Create
+    ('00E871C4A14F993C6C7369501900C4BC1E9C7B0B4BA44E04868B30B41D807104' +
+    '2EB28C4C250411D0CE08CD197E4188EA4876F279F90B3D8D74A3C76E6F1E4656' + 'AA8',
+    16), TBigInteger.Create
+    ('0CD52DBAA33B063C3A6CD8058A1FB0A46A4754B034FCC644766CA14DA8CA5CA9' +
+    'FDE00E88C1AD60CCBA759025299079D7A427EC3CC5B619BFBC828E7769BCD694' +
+    'E86', 16));
+  DoTestHMacDetECDsaTest(TDigestUtilities.GetDigest('SHA-384'), privKey,
+    TBigInteger.Create
+    ('14BEE21A18B6D8B3C93FAB08D43E739707953244FDBE924FA926D76669E7AC8C' +
+    '89DF62ED8975C2D8397A65A49DCC09F6B0AC62272741924D479354D74FF60755' + '78C',
+    16), TBigInteger.Create
+    ('133330865C067A0EAF72362A65E2D7BC4E461E8C8995C3B6226A21BD1AA78F0E' +
+    'D94FE536A0DCA35534F0CD1510C41525D163FE9D74D134881E35141ED5E8E95B' +
+    '979', 16));
+  DoTestHMacDetECDsaTest(TDigestUtilities.GetDigest('SHA-512'), privKey,
+    TBigInteger.Create
+    ('13E99020ABF5CEE7525D16B69B229652AB6BDF2AFFCAEF38773B4B7D08725F10' +
+    'CDB93482FDCC54EDCEE91ECA4166B2A7C6265EF0CE2BD7051B7CEF945BABD47E' + 'E6D',
+    16), TBigInteger.Create
+    ('1FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78' +
+    'A19CA69EFF5C57400E3B3A0AD66CE0978214D13BAF4E9AC60752F7B155E2DE4D' +
+    'CE3', 16));
+end;
+
+procedure TTestDeterministicDsa.DoTestHMacDetDsaSample(const digest: IDigest;
+  const privKey: IDsaPrivateKeyParameters; const r, s: TBigInteger);
+begin
+  DoTestHMacDetECDsa(TDsaSigner.Create(THMacDsaKCalculator.Create(digest)
+    as IHMacDsaKCalculator) as IDsaSigner, digest, FSAMPLE, privKey, r, s);
+end;
+
+procedure TTestDeterministicDsa.DoTestHMacDetDsaTest(const digest: IDigest;
+  const privKey: IDsaPrivateKeyParameters; const r, s: TBigInteger);
+begin
+  DoTestHMacDetECDsa(TDsaSigner.Create(THMacDsaKCalculator.Create(digest)
+    as IHMacDsaKCalculator) as IDsaSigner, digest, FTEST, privKey, r, s);
+end;
+
+procedure TTestDeterministicDsa.DoTestHMacDetECDsa(const detSigner: IDsa;
+  const digest: IDigest; data: TCryptoLibByteArray;
+  const privKey: ICipherParameters; const r, s: TBigInteger);
+var
+  m: TCryptoLibByteArray;
+  rs: TCryptoLibGenericArray<TBigInteger>;
+begin
+  System.SetLength(m, digest.GetDigestSize());
+
+  digest.BlockUpdate(data, 0, System.Length(data));
+
+  digest.DoFinal(m, 0);
+
+  detSigner.Init(true, privKey);
+
+  rs := detSigner.GenerateSignature(m);
+
+  if (not r.Equals(rs[0])) then
+  begin
+    Fail('r value wrong');
+  end;
+  if (not s.Equals(rs[1])) then
+  begin
+    Fail('s value wrong');
+  end;
+end;
+
+procedure TTestDeterministicDsa.DoTestHMacDetECDsaSample(const digest: IDigest;
+  const privKey: IECPrivateKeyParameters; const r, s: TBigInteger);
+begin
+  DoTestHMacDetECDsa(TECDsaSigner.Create(THMacDsaKCalculator.Create(digest)
+    as IHMacDsaKCalculator) as IECDsaSigner, digest, FSAMPLE, privKey, r, s);
+end;
+
+procedure TTestDeterministicDsa.DoTestHMacDetECDsaTest(const digest: IDigest;
+  const privKey: IECPrivateKeyParameters; const r, s: TBigInteger);
+begin
+  DoTestHMacDetECDsa(TECDsaSigner.Create(THMacDsaKCalculator.Create(digest)
+    as IHMacDsaKCalculator) as IECDsaSigner, digest, FTEST, privKey, r, s);
+end;
+
+procedure TTestDeterministicDsa.DoTestHMacDeterministic;
+var
+  dsaParameters: IDsaParameters;
+  privKey: IDsaPrivateKeyParameters;
+begin
+  dsaParameters := TDsaParameters.Create
+    (TBigInteger.Create
+    ('86F5CA03DCFEB225063FF830A0C769B9DD9D6153AD91D7CE27F787C43278B447' +
+    'E6533B86B18BED6E8A48B784A14C252C5BE0DBF60B86D6385BD2F12FB763ED88' +
+    '73ABFD3F5BA2E0A8C0A59082EAC056935E529DAF7C610467899C77ADEDFC846C' +
+    '881870B7B19B2B58F9BE0521A17002E3BDD6B86685EE90B3D9A1B02B782B1779', 16),
+    TBigInteger.Create('996F967F6C8E388D9E28D01E205FBA957A5698B1', 16),
+    TBigInteger.Create
+    ('07B0F92546150B62514BB771E2A0C0CE387F03BDA6C56B505209FF25FD3C133D' +
+    '89BBCD97E904E09114D9A7DEFDEADFC9078EA544D2E401AEECC40BB9FBBF78FD' +
+    '87995A10A1C27CB7789B594BA7EFB5C4326A9FE59A070E136DB77175464ADCA4' +
+    '17BE5DCE2F40D10A46A3A3943F26AB7FD9C0398FF8C76EE0A56826A8A88F1DBD', 16));
+
+  privKey := TDsaPrivateKeyParameters.Create
+    (TBigInteger.Create('411602CB19A6CCC34494D79D98EF1E7ED5AF25F7', 16),
+    dsaParameters);
+
+  DoTestHMacDetDsaSample(TDigestUtilities.GetDigest('SHA-1'), privKey,
+    TBigInteger.Create('2E1A0C2562B2912CAAF89186FB0F42001585DA55', 16),
+    TBigInteger.Create('29EFB6B0AFF2D7A68EB70CA313022253B9A88DF5', 16));
+  DoTestHMacDetDsaSample(TDigestUtilities.GetDigest('SHA-224'), privKey,
+    TBigInteger.Create('4BC3B686AEA70145856814A6F1BB53346F02101E', 16),
+    TBigInteger.Create('410697B92295D994D21EDD2F4ADA85566F6F94C1', 16));
+  DoTestHMacDetDsaSample(TDigestUtilities.GetDigest('SHA-256'), privKey,
+    TBigInteger.Create('81F2F5850BE5BC123C43F71A3033E9384611C545', 16),
+    TBigInteger.Create('4CDD914B65EB6C66A8AAAD27299BEE6B035F5E89', 16));
+  DoTestHMacDetDsaSample(TDigestUtilities.GetDigest('SHA-384'), privKey,
+    TBigInteger.Create('07F2108557EE0E3921BC1774F1CA9B410B4CE65A', 16),
+    TBigInteger.Create('54DF70456C86FAC10FAB47C1949AB83F2C6F7595', 16));
+  DoTestHMacDetDsaSample(TDigestUtilities.GetDigest('SHA-512'), privKey,
+    TBigInteger.Create('16C3491F9B8C3FBBDD5E7A7B667057F0D8EE8E1B', 16),
+    TBigInteger.Create('02C36A127A7B89EDBB72E4FFBC71DABC7D4FC69C', 16));
+
+  DoTestHMacDetDsaTest(TDigestUtilities.GetDigest('SHA-1'), privKey,
+    TBigInteger.Create('42AB2052FD43E123F0607F115052A67DCD9C5C77', 16),
+    TBigInteger.Create('183916B0230D45B9931491D4C6B0BD2FB4AAF088', 16));
+  DoTestHMacDetDsaTest(TDigestUtilities.GetDigest('SHA-224'), privKey,
+    TBigInteger.Create('6868E9964E36C1689F6037F91F28D5F2C30610F2', 16),
+    TBigInteger.Create('49CEC3ACDC83018C5BD2674ECAAD35B8CD22940F', 16));
+  DoTestHMacDetDsaTest(TDigestUtilities.GetDigest('SHA-256'), privKey,
+    TBigInteger.Create('22518C127299B0F6FDC9872B282B9E70D0790812', 16),
+    TBigInteger.Create('6837EC18F150D55DE95B5E29BE7AF5D01E4FE160', 16));
+  DoTestHMacDetDsaTest(TDigestUtilities.GetDigest('SHA-384'), privKey,
+    TBigInteger.Create('854CF929B58D73C3CBFDC421E8D5430CD6DB5E66', 16),
+    TBigInteger.Create('91D0E0F53E22F898D158380676A871A157CDA622', 16));
+  DoTestHMacDetDsaTest(TDigestUtilities.GetDigest('SHA-512'), privKey,
+    TBigInteger.Create('8EA47E475BA8AC6F2D821DA3BD212D11A3DEB9A0', 16),
+    TBigInteger.Create('7C670C7AD72B6C050C109E1790008097125433E8', 16));
+
+  dsaParameters := TDsaParameters.Create
+    (TBigInteger.Create
+    ('9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48' +
+    'C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757264E5A1A44F' +
+    'FE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5' +
+    'B3CC4D9BE341104AD4A80AD6C94E005F4B993E14F091EB51743BF33050C38DE2' +
+    '35567E1B34C3D6A5C0CEAA1A0F368213C3D19843D0B4B09DCB9FC72D39C8DE41' +
+    'F1BF14D4BB4563CA28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE' +
+    '92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6F71125A7456FEA15' +
+    '3E433256A2261C6A06ED3693797E7995FAD5AABBCFBE3EDA2741E375404AE25B', 16),
+    TBigInteger.Create
+    ('F2C3119374CE76C9356990B465374A17F23F9ED35089BD969F61C6DDE9998C1F', 16),
+    TBigInteger.Create
+    ('5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E24809670716C613' +
+    'D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D1AA58C4328A06C4' +
+    '6A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A338661D10461C0D135472' +
+    '085057F3494309FFA73C611F78B32ADBB5740C361C9F35BE90997DB2014E2EF5' +
+    'AA61782F52ABEB8BD6432C4DD097BC5423B285DAFB60DC364E8161F4A2A35ACA' +
+    '3A10B1C4D203CC76A470A33AFDCBDD92959859ABD8B56E1725252D78EAC66E71' +
+    'BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0' +
+    'DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7', 16));
+
+  privKey := TDsaPrivateKeyParameters.Create
+    (TBigInteger.Create
+    ('69C7548C21D0DFEA6B9A51C9EAD4E27C33D3B3F180316E5BCAB92C933F0E4DBC', 16),
+    dsaParameters);
+
+  DoTestHMacDetDsaSample(TDigestUtilities.GetDigest('SHA-1'), privKey,
+    TBigInteger.Create
+    ('3A1B2DBD7489D6ED7E608FD036C83AF396E290DBD602408E8677DAABD6E7445A', 16),
+    TBigInteger.Create
+    ('D26FCBA19FA3E3058FFC02CA1596CDBB6E0D20CB37B06054F7E36DED0CDBBCCF', 16));
+  DoTestHMacDetDsaSample(TDigestUtilities.GetDigest('SHA-224'), privKey,
+    TBigInteger.Create
+    ('DC9F4DEADA8D8FF588E98FED0AB690FFCE858DC8C79376450EB6B76C24537E2C', 16),
+    TBigInteger.Create
+    ('A65A9C3BC7BABE286B195D5DA68616DA8D47FA0097F36DD19F517327DC848CEC', 16));
+  DoTestHMacDetDsaSample(TDigestUtilities.GetDigest('SHA-256'), privKey,
+    TBigInteger.Create
+    ('EACE8BDBBE353C432A795D9EC556C6D021F7A03F42C36E9BC87E4AC7932CC809', 16),
+    TBigInteger.Create
+    ('7081E175455F9247B812B74583E9E94F9EA79BD640DC962533B0680793A38D53', 16));
+  DoTestHMacDetDsaSample(TDigestUtilities.GetDigest('SHA-384'), privKey,
+    TBigInteger.Create
+    ('B2DA945E91858834FD9BF616EBAC151EDBC4B45D27D0DD4A7F6A22739F45C00B', 16),
+    TBigInteger.Create
+    ('19048B63D9FD6BCA1D9BAE3664E1BCB97F7276C306130969F63F38FA8319021B', 16));
+  DoTestHMacDetDsaSample(TDigestUtilities.GetDigest('SHA-512'), privKey,
+    TBigInteger.Create
+    ('2016ED092DC5FB669B8EFB3D1F31A91EECB199879BE0CF78F02BA062CB4C942E', 16),
+    TBigInteger.Create
+    ('D0C76F84B5F091E141572A639A4FB8C230807EEA7D55C8A154A224400AFF2351', 16));
+
+  DoTestHMacDetDsaTest(TDigestUtilities.GetDigest('SHA-1'), privKey,
+    TBigInteger.Create
+    ('C18270A93CFC6063F57A4DFA86024F700D980E4CF4E2CB65A504397273D98EA0', 16),
+    TBigInteger.Create
+    ('414F22E5F31A8B6D33295C7539C1C1BA3A6160D7D68D50AC0D3A5BEAC2884FAA', 16));
+  DoTestHMacDetDsaTest(TDigestUtilities.GetDigest('SHA-224'), privKey,
+    TBigInteger.Create
+    ('272ABA31572F6CC55E30BF616B7A265312018DD325BE031BE0CC82AA17870EA3', 16),
+    TBigInteger.Create
+    ('E9CC286A52CCE201586722D36D1E917EB96A4EBDB47932F9576AC645B3A60806', 16));
+  DoTestHMacDetDsaTest(TDigestUtilities.GetDigest('SHA-256'), privKey,
+    TBigInteger.Create
+    ('8190012A1969F9957D56FCCAAD223186F423398D58EF5B3CEFD5A4146A4476F0', 16),
+    TBigInteger.Create
+    ('7452A53F7075D417B4B013B278D1BB8BBD21863F5E7B1CEE679CF2188E1AB19E', 16));
+  DoTestHMacDetDsaTest(TDigestUtilities.GetDigest('SHA-384'), privKey,
+    TBigInteger.Create
+    ('239E66DDBE8F8C230A3D071D601B6FFBDFB5901F94D444C6AF56F732BEB954BE', 16),
+    TBigInteger.Create
+    ('6BD737513D5E72FE85D1C750E0F73921FE299B945AAD1C802F15C26A43D34961', 16));
+  DoTestHMacDetDsaTest(TDigestUtilities.GetDigest('SHA-512'), privKey,
+    TBigInteger.Create
+    ('89EC4BB1400ECCFF8E7D9AA515CD1DE7803F2DAFF09693EE7FD1353E90A68307', 16),
+    TBigInteger.Create
+    ('C9F0BDABCC0D880BB137A994CC7F3980CE91CC10FAF529FC46565B15CEA854E1', 16));
+
+end;
+
+procedure TTestDeterministicDsa.SetUp;
+begin
+  inherited;
+  FSAMPLE := THex.Decode('73616d706c65'); // "sample"
+  FTEST := THex.Decode('74657374'); // "test"
+end;
+
+procedure TTestDeterministicDsa.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestDeterministicDsa.TestDsaDeterministic;
+begin
+  DoTestHMacDeterministic();
+  DoTestECHMacDeterministic();
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestDeterministicDsa);
+{$ELSE}
+  RegisterTest(TTestDeterministicDsa.Suite);
+{$ENDIF FPC}
+
+end.

+ 0 - 1
CryptoLib.Tests/src/Crypto/DigestRandomNumberTests.pas

@@ -22,7 +22,6 @@ interface
 {$IFDEF FPC}
 {$MODE DELPHI}
 {$ENDIF FPC}
-{$HINTS OFF}
 
 uses
   Classes,

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

@@ -22,7 +22,6 @@ interface
 {$IFDEF FPC}
 {$MODE DELPHI}
 {$ENDIF FPC}
-{$HINTS OFF}
 
 uses
   SysUtils,
@@ -34,7 +33,6 @@ uses
 {$ENDIF FPC}
   ClpKeyParameter,
   ClpIKeyParameter,
-  ClpHMac,
   ClpIMac,
   ClpICipherKeyGenerator,
   ClpDigestUtilities,

+ 343 - 0
CryptoLib.Tests/src/Crypto/HkdfGeneratorTests.pas

@@ -0,0 +1,343 @@
+{ *********************************************************************************** }
+{ *                              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 HkdfGeneratorTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+uses
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpHex,
+  ClpIDigest,
+  ClpDigestUtilities,
+  ClpArrayUtils,
+  ClpHkdfParameters,
+  ClpIHkdfParameters,
+  ClpHkdfBytesGenerator,
+  ClpIHkdfBytesGenerator,
+  ClpCryptoLibTypes;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  /// <summary>
+  /// HKDF tests - vectors from RFC 5869, + 2 more, 101 and 102
+  /// </summary>
+  TTestHkdfGenerator = class(TCryptoLibTestCase)
+  private
+
+    procedure CompareOkm(test: Int32;
+      calculatedOkm, testOkm: TCryptoLibByteArray);
+    procedure DoTestHKDF();
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+
+    procedure TestHkdfGenerator;
+
+  end;
+
+implementation
+
+{ TTestHkdfGenerator }
+
+procedure TTestHkdfGenerator.CompareOkm(test: Int32;
+  calculatedOkm, testOkm: TCryptoLibByteArray);
+begin
+  if (not TArrayUtils.AreEqual(calculatedOkm, testOkm)) then
+  begin
+    Fail('HKDF failed generator test ' + IntToStr(test));
+  end;
+end;
+
+procedure TTestHkdfGenerator.DoTestHKDF;
+var
+  hash: IDigest;
+  ikm, salt, info, okm: TBytes;
+  l, zeros, i: Int32;
+  parameters: IHkdfParameters;
+  hkdf: IHkdfBytesGenerator;
+begin
+  // === A.1. Test Case 1 - Basic test case with SHA-256 ===
+
+  hash := TDigestUtilities.GetDigest('SHA-256');
+  ikm := THex.Decode('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b');
+  salt := THex.Decode('000102030405060708090a0b0c');
+  info := THex.Decode('f0f1f2f3f4f5f6f7f8f9');
+  l := 42;
+  System.SetLength(okm, l);
+
+  parameters := THkdfParameters.Create(ikm, salt, info);
+
+  hkdf := THkdfBytesGenerator.Create(hash);
+  hkdf.Init(parameters);
+  hkdf.GenerateBytes(okm, 0, l);
+
+  CompareOkm(1, okm, THex.Decode('3cb25f25faacd57a90434f64d0362f2a' +
+    '2d2d0a90cf1a5a4c5db02d56ecc4c5bf' + '34007208d5b887185865'));
+
+
+  // === A.2. Test Case 2 - Test with SHA-256 and longer inputs/outputs
+  // ===
+
+  hash := TDigestUtilities.GetDigest('SHA-256');
+  ikm := THex.Decode('000102030405060708090a0b0c0d0e0f' +
+    '101112131415161718191a1b1c1d1e1f' + '202122232425262728292a2b2c2d2e2f' +
+    '303132333435363738393a3b3c3d3e3f' + '404142434445464748494a4b4c4d4e4f');
+  salt := THex.Decode('606162636465666768696a6b6c6d6e6f' +
+    '707172737475767778797a7b7c7d7e7f' + '808182838485868788898a8b8c8d8e8f' +
+    '909192939495969798999a9b9c9d9e9f' + 'a0a1a2a3a4a5a6a7a8a9aaabacadaeaf');
+  info := THex.Decode('b0b1b2b3b4b5b6b7b8b9babbbcbdbebf' +
+    'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf' + 'd0d1d2d3d4d5d6d7d8d9dadbdcdddedf' +
+    'e0e1e2e3e4e5e6e7e8e9eaebecedeeef' + 'f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff');
+  l := 82;
+  System.SetLength(okm, l);
+
+  parameters := THkdfParameters.Create(ikm, salt, info);
+
+  hkdf := THkdfBytesGenerator.Create(hash);
+  hkdf.Init(parameters);
+  hkdf.GenerateBytes(okm, 0, l);
+
+  CompareOkm(2, okm, THex.Decode('b11e398dc80327a1c8e7f78c596a4934' +
+    '4f012eda2d4efad8a050cc4c19afa97c' + '59045a99cac7827271cb41c65e590e09' +
+    'da3275600c2f09b8367793a9aca3db71' + 'cc30c58179ec3e87c14c01d5c1f3434f'
+    + '1d87'));
+
+
+
+  // === A.3. Test Case 3 - Test with SHA-256 and zero-length
+  // salt/info ===
+
+  // setting salt to an empty byte array means that the salt is set to
+  // HashLen zero valued bytes
+  // setting info to Nil generates an empty byte array as info
+  // structure
+
+  hash := TDigestUtilities.GetDigest('SHA-256');
+  ikm := THex.Decode('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b');
+  System.SetLength(salt, 0);
+  info := Nil;
+  l := 42;
+  System.SetLength(okm, l);
+
+  parameters := THkdfParameters.Create(ikm, salt, info);
+
+  hkdf := THkdfBytesGenerator.Create(hash);
+  hkdf.Init(parameters);
+  hkdf.GenerateBytes(okm, 0, l);
+
+  CompareOkm(3, okm, THex.Decode('8da4e775a563c18f715f802a063c5a31' +
+    'b8a11f5c5ee1879ec3454e5f3c738d2d' + '9d201395faa4b61a96c8'));
+
+
+
+  // === A.4. Test Case 4 - Basic test case with SHA-1 ===
+
+  hash := TDigestUtilities.GetDigest('SHA-1');
+  ikm := THex.Decode('0b0b0b0b0b0b0b0b0b0b0b');
+  salt := THex.Decode('000102030405060708090a0b0c');
+  info := THex.Decode('f0f1f2f3f4f5f6f7f8f9');
+  l := 42;
+  System.SetLength(okm, l);
+
+  parameters := THkdfParameters.Create(ikm, salt, info);
+
+  hkdf := THkdfBytesGenerator.Create(hash);
+  hkdf.Init(parameters);
+  hkdf.GenerateBytes(okm, 0, l);
+
+  CompareOkm(4, okm, THex.Decode('085a01ea1b10f36933068b56efa5ad81' +
+    'a4f14b822f5b091568a9cdd4f155fda2' + 'c22e422478d305f3f896'));
+
+
+  // === A.5. Test Case 5 - Test with SHA-1 and longer inputs/outputs ===
+
+  hash := TDigestUtilities.GetDigest('SHA-1');
+  ikm := THex.Decode('000102030405060708090a0b0c0d0e0f' +
+    '101112131415161718191a1b1c1d1e1f' + '202122232425262728292a2b2c2d2e2f' +
+    '303132333435363738393a3b3c3d3e3f' + '404142434445464748494a4b4c4d4e4f');
+  salt := THex.Decode('606162636465666768696a6b6c6d6e6f' +
+    '707172737475767778797a7b7c7d7e7f' + '808182838485868788898a8b8c8d8e8f' +
+    '909192939495969798999a9b9c9d9e9f' + 'a0a1a2a3a4a5a6a7a8a9aaabacadaeaf');
+  info := THex.Decode('b0b1b2b3b4b5b6b7b8b9babbbcbdbebf' +
+    'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf' + 'd0d1d2d3d4d5d6d7d8d9dadbdcdddedf' +
+    'e0e1e2e3e4e5e6e7e8e9eaebecedeeef' + 'f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff');
+  l := 82;
+  System.SetLength(okm, l);
+
+  parameters := THkdfParameters.Create(ikm, salt, info);
+
+  hkdf := THkdfBytesGenerator.Create(hash);
+  hkdf.Init(parameters);
+  hkdf.GenerateBytes(okm, 0, l);
+
+  CompareOkm(5, okm, THex.Decode('0bd770a74d1160f7c9f12cd5912a06eb' +
+    'ff6adcae899d92191fe4305673ba2ffe' + '8fa3f1a4e5ad79f3f334b3b202b2173c' +
+    '486ea37ce3d397ed034c7f9dfeb15c5e' + '927336d0441f4c4300e2cff0d0900b52'
+    + 'd3b4'));
+
+
+
+  // === A.6. Test Case 6 - Test with SHA-1 and zero-length salt/info
+  // ===
+
+  // setting salt to Nil should generate a new salt of HashLen zero
+  // valued bytes
+
+  hash := TDigestUtilities.GetDigest('SHA-1');
+  ikm := THex.Decode('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b');
+  salt := Nil;
+  System.SetLength(info, 0);
+  l := 42;
+  System.SetLength(okm, l);
+
+  parameters := THkdfParameters.Create(ikm, salt, info);
+
+  hkdf := THkdfBytesGenerator.Create(hash);
+  hkdf.Init(parameters);
+  hkdf.GenerateBytes(okm, 0, l);
+
+  CompareOkm(6, okm, THex.Decode('0ac1af7002b3d761d1e55298da9d0506' +
+    'b9ae52057220a306e07b6b87e8df21d0' + 'ea00033de03984d34918'));
+
+
+
+  // === A.7. Test Case 7 - Test with SHA-1, salt not provided,
+  // zero-length info ===
+  // (salt defaults to HashLen zero octets)
+
+  // this test is identical to test 6 in all ways bar the IKM value
+
+  hash := TDigestUtilities.GetDigest('SHA-1');
+  ikm := THex.Decode('0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c');
+  salt := Nil;
+  System.SetLength(info, 0);
+  l := 42;
+  System.SetLength(okm, l);
+
+  parameters := THkdfParameters.Create(ikm, salt, info);
+
+  hkdf := THkdfBytesGenerator.Create(hash);
+  hkdf.Init(parameters);
+  hkdf.GenerateBytes(okm, 0, l);
+
+  CompareOkm(7, okm, THex.Decode('2c91117204d745f3500d636a62f64f0a' +
+    'b3bae548aa53d423b0d1f27ebba6f5e5' + '673a081d70cce7acfc48'));
+
+
+
+  // === A.101. Additional Test Case - Test with SHA-1, skipping extract
+  // zero-length info ===
+  // (salt defaults to HashLen zero octets)
+
+  // this test is identical to test 7 in all ways bar the IKM value
+  // which is set to the PRK value
+
+  hash := TDigestUtilities.GetDigest('SHA-1');
+  ikm := THex.Decode('2adccada18779e7c2077ad2eb19d3f3e731385dd');
+  System.SetLength(info, 0);
+  l := 42;
+  System.SetLength(okm, l);
+
+  parameters := THkdfParameters.SkipExtractParameters(ikm, info);
+
+  hkdf := THkdfBytesGenerator.Create(hash);
+  hkdf.Init(parameters);
+  hkdf.GenerateBytes(okm, 0, l);
+
+  CompareOkm(101, okm, THex.Decode('2c91117204d745f3500d636a62f64f0a' +
+    'b3bae548aa53d423b0d1f27ebba6f5e5' + '673a081d70cce7acfc48'));
+
+  // === A.102. Additional Test Case - Test with SHA-1, maximum output ===
+  // (salt defaults to HashLen zero octets)
+
+  // this test is identical to test 7 in all ways bar the IKM value
+
+  hash := TDigestUtilities.GetDigest('SHA-1');
+  ikm := THex.Decode('2adccada18779e7c2077ad2eb19d3f3e731385dd');
+  System.SetLength(info, 0);
+  l := 255 * hash.GetDigestSize();
+  System.SetLength(okm, l);
+
+  parameters := THkdfParameters.SkipExtractParameters(ikm, info);
+
+  hkdf := THkdfBytesGenerator.Create(hash);
+  hkdf.Init(parameters);
+  hkdf.GenerateBytes(okm, 0, l);
+
+  zeros := 0;
+  for i := 0 to System.Pred(hash.GetDigestSize()) do
+  begin
+    if (okm[i] = 0) then
+    begin
+      System.Inc(zeros);
+    end;
+  end;
+
+  if (zeros = hash.GetDigestSize()) then
+  begin
+    Fail('HKDF failed generator test ' + IntToStr(102));
+  end;
+
+end;
+
+procedure TTestHkdfGenerator.SetUp;
+begin
+  inherited;
+
+end;
+
+procedure TTestHkdfGenerator.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestHkdfGenerator.TestHkdfGenerator;
+begin
+  DoTestHKDF();
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestHkdfGenerator);
+{$ELSE}
+  RegisterTest(TTestHkdfGenerator.Suite);
+{$ENDIF FPC}
+
+end.

+ 2 - 4
CryptoLib.Tests/src/Crypto/MD5HMacTests.pas

@@ -22,7 +22,6 @@ interface
 {$IFDEF FPC}
 {$MODE DELPHI}
 {$ENDIF FPC}
-{$HINTS OFF}
 
 uses
   SysUtils,
@@ -33,7 +32,6 @@ uses
   TestFramework,
 {$ENDIF FPC}
   ClpKeyParameter,
-  ClpIKeyParameter,
   ClpHMac,
   ClpIMac,
   ClpDigestUtilities,
@@ -112,7 +110,7 @@ begin
 
   for i := 0 to System.Pred(System.Length(Fmessages)) do
   begin
-    m := TEncoding.ASCII.GetBytes(Fmessages[i]);
+    m := TEncoding.ASCII.GetBytes(UnicodeString(Fmessages[i]));
     if (TStringUtils.BeginsWith(Fmessages[i], '0x', True)) then
     begin
       m := THex.Decode(System.Copy(Fmessages[i], 3,
@@ -130,7 +128,7 @@ begin
 
   // test reset
   vector := 0; // vector used for test
-  m2 := TEncoding.ASCII.GetBytes(Fmessages[vector]);
+  m2 := TEncoding.ASCII.GetBytes(UnicodeString(Fmessages[vector]));
 
   if (TStringUtils.BeginsWith(Fmessages[vector], '0x', True)) then
   begin

+ 293 - 0
CryptoLib.Tests/src/Crypto/PaddingTests.pas

@@ -0,0 +1,293 @@
+{ *********************************************************************************** }
+{ *                              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 PaddingTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+uses
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpSecureRandom,
+  ClpISecureRandom,
+  ClpKeyParameter,
+  ClpIKeyParameter,
+  ClpIBlockCipherPadding,
+  ClpAESEngine,
+  ClpIAesEngine,
+  ClpTTBCPadding,
+  ClpITBCPadding,
+  ClpPkcs7Padding,
+  ClpIPkcs7Padding,
+  ClpX923Padding,
+  ClpIX923Padding,
+  ClpISO7816d4Padding,
+  ClpIISO7816d4Padding,
+  ClpZeroBytePadding,
+  ClpIZeroBytePadding,
+  ClpISO10126d2Padding,
+  ClpIISO10126d2Padding,
+  ClpPaddedBufferedBlockCipher,
+  ClpIPaddedBufferedBlockCipher,
+  ClpHex,
+  ClpArrayUtils,
+  ClpCryptoLibTypes;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  /// <summary>
+  /// Padding tests.
+  /// </summary>
+  TTestPadding = class(TCryptoLibTestCase)
+  private
+
+    procedure DoBlockCheck(const cipher: IPaddedBufferedBlockCipher;
+      const padding: IBlockCipherPadding; const key: IKeyParameter;
+      data: TCryptoLibByteArray);
+    procedure DoTestPadding(const padding: IBlockCipherPadding;
+      const rand: ISecureRandom; ffVector, ZeroVector: TCryptoLibByteArray);
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+
+  published
+
+    procedure TestOutputSizes();
+    procedure TestPadding();
+
+  end;
+
+implementation
+
+{ TTestPadding }
+
+procedure TTestPadding.DoBlockCheck(const cipher: IPaddedBufferedBlockCipher;
+  const padding: IBlockCipherPadding; const key: IKeyParameter;
+  data: TCryptoLibByteArray);
+var
+  &out, dec: TBytes;
+  len, decLen: Int32;
+begin
+  System.SetLength(&out, System.Length(data) + 16);
+  System.SetLength(dec, System.Length(data));
+
+  try
+
+    cipher.Init(true, key);
+
+    len := cipher.ProcessBytes(data, 0, System.Length(data), &out, 0);
+
+    len := len + cipher.doFinal(&out, len);
+
+    cipher.Init(false, key);
+
+    decLen := cipher.ProcessBytes(&out, 0, len, dec, 0);
+
+    // decLen := decLen + cipher.doFinal(dec, decLen);
+    cipher.doFinal(dec, decLen);
+
+    if (not TArrayUtils.AreEqual(data, dec)) then
+    begin
+      Fail('failed to decrypt - i = ' + IntToStr(System.Length(data)) +
+        ', padding = ' + padding.PaddingName);
+    end;
+
+  except
+    on e: ECryptoLibException do
+    begin
+      Fail('Exception - ' + e.ToString());
+    end;
+
+  end;
+
+end;
+
+procedure TTestPadding.SetUp;
+begin
+  inherited;
+
+end;
+
+procedure TTestPadding.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestPadding.TestOutputSizes;
+var
+  bc: IPaddedBufferedBlockCipher;
+  key: IKeyParameter;
+  i: Int32;
+begin
+  bc := TPaddedBufferedBlockCipher.Create(TAESEngine.Create() as IAESEngine,
+    TPKCS7Padding.Create() as IPKCS7Padding);
+  key := TKeyParameter.Create(THex.decode('001122334455667788990A0B0C0D0E0F'));
+
+  for i := 0 to (bc.GetBlockSize * 2) do
+  begin
+    bc.Init(true, key);
+    if (bc.GetUpdateOutputSize(i) < 0) then
+    begin
+      Fail('Padded cipher encrypt negative update output size for input size ' +
+        IntToStr(i));
+    end;
+    if (bc.GetOutputSize(i) < 0) then
+    begin
+      Fail('Padded cipher encrypt negative output size for input size ' +
+        IntToStr(i));
+    end;
+
+    bc.Init(false, key);
+    if (bc.GetUpdateOutputSize(i) < 0) then
+    begin
+      Fail('Padded cipher decrypt negative update output size for input size ' +
+        IntToStr(i));
+    end;
+    if (bc.GetOutputSize(i) < 0) then
+    begin
+      Fail('Padded cipher decrypt negative output size for input size ' +
+        IntToStr(i));
+    end;
+  end;
+
+end;
+
+procedure TTestPadding.TestPadding;
+var
+  rand: ISecureRandom;
+  padder: IPKCS7Padding;
+  temp: TBytes;
+begin
+  rand := TSecureRandom.GetInstance('SHA256PRNG');
+
+  DoTestPadding(TPKCS7Padding.Create() as IPKCS7Padding, rand,
+    THex.decode('ffffff0505050505'), THex.decode('0000000004040404'));
+
+  padder := TPKCS7Padding.Create();
+  try
+
+    System.SetLength(temp, 8);
+    padder.PadCount(temp);
+
+    Fail('invalid padding not detected');
+
+  except
+    on e: EInvalidCipherTextCryptoLibException do
+    begin
+      if (not(e.Message = 'Pad Block Corrupted')) then
+      begin
+        Fail('wrong exception for corrupt padding: ' + e.Message);
+      end;
+    end;
+
+  end;
+
+  DoTestPadding(TISO10126d2Padding.Create() as IISO10126d2Padding, rand,
+    Nil, Nil);
+
+  DoTestPadding(TX923Padding.Create() as IX923Padding, rand, Nil, Nil);
+
+  DoTestPadding(TTBCPadding.Create() as ITBCPadding, rand,
+    THex.decode('ffffff0000000000'), THex.decode('00000000ffffffff'));
+
+  DoTestPadding(TZeroBytePadding.Create() as IZeroBytePadding, rand,
+    THex.decode('ffffff0000000000'), Nil);
+
+  DoTestPadding(TISO7816d4Padding.Create() as IISO7816d4Padding, rand,
+    THex.decode('ffffff8000000000'), THex.decode('0000000080000000'));
+
+  TestOutputSizes();
+end;
+
+procedure TTestPadding.DoTestPadding(const padding: IBlockCipherPadding;
+  const rand: ISecureRandom; ffVector, ZeroVector: TCryptoLibByteArray);
+var
+  cipher: IPaddedBufferedBlockCipher;
+  key: IKeyParameter;
+  data: TBytes;
+  i: Int32;
+begin
+  cipher := TPaddedBufferedBlockCipher.Create(TAESEngine.Create()
+    as IAESEngine, padding);
+  key := TKeyParameter.Create(THex.decode('001122334455667788990A0B0C0D0E0F'));
+
+  //
+  // ff test
+  //
+  data := TBytes.Create($FF, $FF, $FF, $0, $0, $0, $0, $0);
+
+  if (ffVector <> Nil) then
+  begin
+    padding.addPadding(data, 3);
+
+    if (not TArrayUtils.AreEqual(data, ffVector)) then
+    begin
+      Fail('failed ff test for ' + padding.PaddingName);
+    end;
+  end;
+
+  //
+  // zero test
+  //
+  if (ZeroVector <> Nil) then
+  begin
+    System.FillChar(data[0], 8 * System.SizeOf(Byte), Byte(0));
+    padding.addPadding(data, 4);
+
+    if (not TArrayUtils.AreEqual(data, ZeroVector)) then
+    begin
+      Fail('failed zero test for ' + padding.PaddingName);
+    end;
+  end;
+
+  for i := 1 to System.Pred(200) do
+  begin
+    System.SetLength(data, i);
+    rand.NextBytes(data);
+    DoBlockCheck(cipher, padding, key, data);
+  end;
+
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestPadding);
+{$ELSE}
+  RegisterTest(TTestPadding.Suite);
+{$ENDIF FPC}
+
+end.

+ 14 - 16
CryptoLib.Tests/src/Crypto/Pkcs5Tests.pas

@@ -22,7 +22,6 @@ interface
 {$IFDEF FPC}
 {$MODE DELPHI}
 {$ENDIF FPC}
-{$HINTS OFF}
 
 uses
   SysUtils,
@@ -32,7 +31,6 @@ uses
 {$ELSE}
   TestFramework,
 {$ENDIF FPC}
-  ClpKeyParameter,
   ClpIKeyParameter,
   ClpPkcs5S2ParametersGenerator,
   ClpIPkcs5S2ParametersGenerator,
@@ -102,7 +100,7 @@ begin
   SaltBytes := THex.Decode('1234567878563412');
 
   PasswordString := 'password';
-  PasswordBytes := TEncoding.UTF8.GetBytes(PasswordString);
+  PasswordBytes := TEncoding.UTF8.GetBytes(UnicodeString(PasswordString));
   generator := TPkcs5S2ParametersGenerator.Create
     (TDigestUtilities.GetDigest('SHA-1'));
 
@@ -116,7 +114,7 @@ begin
 
   PasswordString :=
     'All n-entities must communicate with other n-entities via n-1 entiteeheehees';
-  PasswordBytes := TEncoding.UTF8.GetBytes(PasswordString);
+  PasswordBytes := TEncoding.UTF8.GetBytes(UnicodeString(PasswordString));
 
   generator.Init(PasswordBytes, SaltBytes, 500);
 
@@ -142,10 +140,10 @@ begin
     (TDigestUtilities.GetDigest('SHA-1'));
 
   PasswordString := 'password';
-  PasswordBytes := TEncoding.UTF8.GetBytes(PasswordString);
+  PasswordBytes := TEncoding.UTF8.GetBytes(UnicodeString(PasswordString));
 
   SaltString := 'salt';
-  SaltBytes := TEncoding.UTF8.GetBytes(SaltString);
+  SaltBytes := TEncoding.UTF8.GetBytes(UnicodeString(SaltString));
 
   // 1
 
@@ -220,10 +218,10 @@ begin
   // 5
 
   PasswordString := 'passwordPASSWORDpassword';
-  PasswordBytes := TEncoding.UTF8.GetBytes(PasswordString);
+  PasswordBytes := TEncoding.UTF8.GetBytes(UnicodeString(PasswordString));
 
   SaltString := 'saltSALTsaltSALTsaltSALTsaltSALTsalt';
-  SaltBytes := TEncoding.UTF8.GetBytes(SaltString);
+  SaltBytes := TEncoding.UTF8.GetBytes(UnicodeString(SaltString));
 
   iteration_count := 4096;
 
@@ -245,10 +243,10 @@ begin
 
   PasswordString := 'pass' + Char(0) + 'word';
   // Char(0) represents #0 (null char)
-  PasswordBytes := TEncoding.UTF8.GetBytes(PasswordString);
+  PasswordBytes := TEncoding.UTF8.GetBytes(UnicodeString(PasswordString));
 
   SaltString := 'sa' + Char(0) + 'lt'; // Char(0) represents #0 (null char)
-  SaltBytes := TEncoding.UTF8.GetBytes(SaltString);
+  SaltBytes := TEncoding.UTF8.GetBytes(UnicodeString(SaltString));
 
   iteration_count := 4096;
 
@@ -281,10 +279,10 @@ begin
     (TDigestUtilities.GetDigest('SHA-256'));
 
   PasswordString := 'password';
-  PasswordBytes := TEncoding.UTF8.GetBytes(PasswordString);
+  PasswordBytes := TEncoding.UTF8.GetBytes(UnicodeString(PasswordString));
 
   SaltString := 'salt';
-  SaltBytes := TEncoding.UTF8.GetBytes(SaltString);
+  SaltBytes := TEncoding.UTF8.GetBytes(UnicodeString(SaltString));
 
   // 1
 
@@ -363,10 +361,10 @@ begin
   // 5
 
   PasswordString := 'passwordPASSWORDpassword';
-  PasswordBytes := TEncoding.UTF8.GetBytes(PasswordString);
+  PasswordBytes := TEncoding.UTF8.GetBytes(UnicodeString(PasswordString));
 
   SaltString := 'saltSALTsaltSALTsaltSALTsaltSALTsalt';
-  SaltBytes := TEncoding.UTF8.GetBytes(SaltString);
+  SaltBytes := TEncoding.UTF8.GetBytes(UnicodeString(SaltString));
 
   iteration_count := 4096;
 
@@ -390,10 +388,10 @@ begin
 
   PasswordString := 'pass' + Char(0) + 'word';
   // Char(0) represents #0 (null char)
-  PasswordBytes := TEncoding.UTF8.GetBytes(PasswordString);
+  PasswordBytes := TEncoding.UTF8.GetBytes(UnicodeString(PasswordString));
 
   SaltString := 'sa' + Char(0) + 'lt'; // Char(0) represents #0 (null char)
-  SaltBytes := TEncoding.UTF8.GetBytes(SaltString);
+  SaltBytes := TEncoding.UTF8.GetBytes(UnicodeString(SaltString));
 
   iteration_count := 4096;
 

+ 3 - 9
CryptoLib.Tests/src/Math/BigIntegerTests.pas

@@ -21,11 +21,6 @@ interface
 
 {$IFDEF FPC}
 {$MODE DELPHI}
-// Disable Overflow and RangeChecks.
-{$OVERFLOWCHECKS OFF}
-{$RANGECHECKS OFF}
-{$HINTS OFF}
-{$NOTES OFF}
 {$ENDIF FPC}
 
 uses
@@ -179,7 +174,7 @@ begin
     for j := -10 to 10 do
     begin
 
-      CheckEqualsBigInteger(val(i + j), val(i).Add(val(j)),
+      CheckEqualsBigInteger(val(Int64(i) + Int64(j)), val(i).Add(val(j)),
         Format('Problem: %d.Add(%d) should be %d', [i, j, (i + j)]));
 
     end;
@@ -867,10 +862,9 @@ end;
 
 procedure TTestBigInteger.TestMonoBug81857;
 var
-  b, exp, &Mod, expected, manual: TBigInteger;
+  b, &Mod, expected, manual: TBigInteger;
 begin
   b := TBigInteger.Create('18446744073709551616');
-  exp := TBigInteger.Two;
   &Mod := TBigInteger.Create('48112959837082048697');
   expected := TBigInteger.Create('4970597831480284165');
 
@@ -1192,7 +1186,7 @@ begin
   begin
     for j := -10 to 10 do
     begin
-      CheckEqualsBigInteger(val(i - j), val(i).Subtract(val(j)),
+      CheckEqualsBigInteger(val(Int64(i) - Int64(j)), val(i).Subtract(val(j)),
         Format('Problem: %d.Subtract(%d) should be %d', [i, j, (i - j)]));
     end;
 

+ 0 - 1
CryptoLib.Tests/src/Math/EC/Custom/Sec/SecP384R1FieldTests.pas

@@ -22,7 +22,6 @@ interface
 {$IFDEF FPC}
 {$MODE DELPHI}
 {$ENDIF FPC}
-{$HINTS OFF}
 
 uses
   Classes,

+ 1 - 6
CryptoLib.Tests/src/Math/EC/FixedPointTests.pas

@@ -21,7 +21,6 @@ interface
 
 {$IFDEF FPC}
 {$MODE DELPHI}
-{$WARNINGS OFF}
 {$ENDIF FPC}
 
 uses
@@ -40,7 +39,6 @@ uses
   ClpFixedPointCombMultiplier,
   ClpIFixedPointCombMultiplier,
   ClpECAlgorithms,
-  ClpX9ECParameters,
   ClpIX9ECParameters,
   ClpCryptoLibTypes;
 
@@ -107,10 +105,7 @@ begin
     try
       for s in tempList do
       begin
-        if not tempDict.ContainsKey(s) then // make sure they are unique
-        begin
-          tempDict.Add(s, s);
-        end;
+        tempDict.AddOrSetValue(s, s); // make sure they are unique
       end;
       names := tempDict.Values.ToArray; // save unique instances to array
     finally

+ 3 - 4
CryptoLib.Tests/src/Math/ECAlgorithmsTests.pas

@@ -22,6 +22,8 @@ interface
 {$IFDEF FPC}
 {$MODE DELPHI}
 {$WARNINGS OFF}
+{$NOTES OFF}
+{$HINTS OFF}
 {$ENDIF FPC}
 
 uses
@@ -246,10 +248,7 @@ begin
       try
         for s in tempList do
         begin
-          if not tempDict.ContainsKey(s) then // make sure they are unique
-          begin
-            tempDict.Add(s, s);
-          end;
+          tempDict.AddOrSetValue(s, s); // make sure they are unique
         end;
         names := tempDict.Values.ToArray; // save unique instances to array
       finally

+ 677 - 0
CryptoLib.Tests/src/Math/ECIESTests.pas

@@ -0,0 +1,677 @@
+{ *********************************************************************************** }
+{ *                              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 ECIESTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+uses
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpECCurve,
+  ClpIECInterface,
+  ClpIHMac,
+  ClpHMac,
+  ClpIESEngine,
+  ClpIIESEngine,
+  ClpICipherParameters,
+  ClpIECDHBasicAgreement,
+  ClpECDHBasicAgreement,
+  ClpParametersWithIV,
+  ClpKDF2BytesGenerator,
+  ClpIKDF2BytesGenerator,
+  ClpIAsymmetricCipherKeyPair,
+  ClpAsymmetricCipherKeyPair,
+  ClpECKeyPairGenerator,
+  ClpIECKeyPairGenerator,
+  ClpECKeyGenerationParameters,
+  ClpIECKeyGenerationParameters,
+  ClpECPrivateKeyParameters,
+  ClpIECPrivateKeyParameters,
+  ClpECPublicKeyParameters,
+  ClpIECPublicKeyParameters,
+  ClpSecureRandom,
+  ClpISecureRandom,
+  ClpIKeyGenerationParameters,
+  ClpECDomainParameters,
+  ClpIECDomainParameters,
+  ClpIESParameters,
+  ClpIBufferedBlockCipher,
+  ClpPaddedBufferedBlockCipher,
+  ClpIESWithCipherParameters,
+  ClpEphemeralKeyPairGenerator,
+  ClpIEphemeralKeyPairGenerator,
+  ClpECIESPublicKeyParser,
+  ClpIECIESPublicKeyParser,
+  ClpCBCBlockCipher,
+  ClpICBCBlockCipher,
+  ClpKeyEncoder,
+  ClpIKeyEncoder,
+  ClpAESEngine,
+  ClpIAesEngine,
+  ClpHex,
+  ClpArrayUtils,
+  ClpBigInteger,
+  ClpDigestUtilities,
+  ClpCryptoLibTypes;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  /// <summary>
+  /// test for ECIES - Elliptic Curve Integrated Encryption Scheme
+  /// </summary>
+  TTestECIES = class(TCryptoLibTestCase)
+  private
+  var
+    FAES_IV: TBytes;
+
+    procedure DoStaticTest(iv: TBytes);
+    procedure DoShortTest();
+    procedure DoTest(const p1, p2: IAsymmetricCipherKeyPair);
+    procedure DoEphemeralTest(iv: TBytes; usePointCompression: Boolean);
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+
+    procedure TestECIES;
+
+  end;
+
+implementation
+
+{ TTestECIES }
+
+procedure TTestECIES.DoEphemeralTest(iv: TBytes; usePointCompression: Boolean);
+var
+  n: TBigInteger;
+  curve: IFpCurve;
+  params: IECDomainParameters;
+  priKey: IECPrivateKeyParameters;
+  pubKey: IECPublicKeyParameters;
+  p1: IAsymmetricCipherKeyPair;
+  p: ICipherParameters;
+  i1, i2: IIESEngine;
+  d, e, &message, out1, out2: TBytes;
+  gen: IECKeyPairGenerator;
+  ephKeyGen: IEphemeralKeyPairGenerator;
+  c1, c2: IBufferedBlockCipher;
+begin
+  n := TBigInteger.Create
+    ('6277101735386680763835789423176059013767194773182842284081');
+
+  curve := TFpCurve.Create
+    (TBigInteger.Create
+    ('6277101735386680763835789423207666416083908700390324961279'), // q
+    TBigInteger.Create('fffffffffffffffffffffffffffffffefffffffffffffffc', 16),
+    // a
+    TBigInteger.Create('64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1', 16),
+    // b
+    n, TBigInteger.One);
+
+  params := TECDomainParameters.Create(curve,
+    curve.DecodePoint(THex.Decode
+    ('03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012')), // G
+    n);
+
+  priKey := TECPrivateKeyParameters.Create
+    (TBigInteger.Create
+    ('651056770906015076056810763456358567190100156695615665659'), // d
+    params);
+
+  pubKey := TECPublicKeyParameters.Create
+    (curve.DecodePoint(THex.Decode
+    ('0262b12d60690cdcf330babab6e69763b471f994dd702d16a5')), // Q
+    params);
+
+  p1 := TAsymmetricCipherKeyPair.Create(pubKey, priKey);
+
+
+  // Generate the ephemeral key pair
+
+  gen := TECKeyPairGenerator.Create();
+  gen.Init(TECKeyGenerationParameters.Create(params, TSecureRandom.Create()
+    as ISecureRandom) as IECKeyGenerationParameters);
+
+  ephKeyGen := TEphemeralKeyPairGenerator.Create(gen,
+    TKeyEncoder.Create(usePointCompression) as IKeyEncoder);
+
+  //
+  // stream test
+  //
+  i1 := TIESEngine.Create(TECDHBasicAgreement.Create() as IECDHBasicAgreement,
+    TKDF2BytesGenerator.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IKDF2BytesGenerator, THMac.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IHMac);
+
+  i2 := TIESEngine.Create(TECDHBasicAgreement.Create() as IECDHBasicAgreement,
+    TKDF2BytesGenerator.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IKDF2BytesGenerator, THMac.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IHMac);
+
+  d := TBytes.Create(1, 2, 3, 4, 5, 6, 7, 8);
+  e := TBytes.Create(8, 7, 6, 5, 4, 3, 2, 1);
+  p := TIESParameters.Create(d, e, 64);
+
+  i1.Init(p1.Public, p, ephKeyGen);
+  i2.Init(p1.Private, p, TECIESPublicKeyParser.Create(params)
+    as IECIESPublicKeyParser);
+
+  &message := THex.Decode('1234567890abcdef');
+
+  out1 := i1.processBlock(&message, 0, System.Length(&message));
+  out2 := i2.processBlock(out1, 0, System.Length(out1));
+
+  if (not TArrayUtils.AreEqual(out2, &message)) then
+  begin
+    Fail('stream cipher test failed');
+  end;
+
+  //
+  // AES with CBC
+  //
+
+  c1 := TPaddedBufferedBlockCipher.Create
+    (TCBCBlockCipher.Create(TAesEngine.Create() as IAesEngine)
+    as ICBCBlockCipher);
+
+  c2 := TPaddedBufferedBlockCipher.Create
+    (TCBCBlockCipher.Create(TAesEngine.Create() as IAesEngine)
+    as ICBCBlockCipher);
+
+  i1 := TIESEngine.Create(TECDHBasicAgreement.Create() as IECDHBasicAgreement,
+    TKDF2BytesGenerator.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IKDF2BytesGenerator, THMac.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IHMac, c1);
+
+  i2 := TIESEngine.Create(TECDHBasicAgreement.Create() as IECDHBasicAgreement,
+    TKDF2BytesGenerator.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IKDF2BytesGenerator, THMac.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IHMac, c2);
+
+  d := TBytes.Create(1, 2, 3, 4, 5, 6, 7, 8);
+  e := TBytes.Create(8, 7, 6, 5, 4, 3, 2, 1);
+  p := TIESWithCipherParameters.Create(d, e, 64, 128);
+
+  if (iv <> Nil) then
+  begin
+    p := TParametersWithIV.Create(p, iv);
+  end;
+
+  i1.Init(p1.Public, p, ephKeyGen);
+  i2.Init(p1.Private, p, TECIESPublicKeyParser.Create(params)
+    as IECIESPublicKeyParser);
+
+  &message := THex.Decode('1234567890abcdef');
+
+  out1 := i1.processBlock(&message, 0, System.Length(&message));
+
+  out2 := i2.processBlock(out1, 0, System.Length(out1));
+
+  if (not TArrayUtils.AreEqual(out2, &message)) then
+  begin
+    Fail('AES cipher test failed');
+  end;
+end;
+
+procedure TTestECIES.DoShortTest();
+var
+  n: TBigInteger;
+  curve: IFpCurve;
+  params: IECDomainParameters;
+  priKey: IECPrivateKeyParameters;
+  pubKey: IECPublicKeyParameters;
+  p1, p2: IAsymmetricCipherKeyPair;
+  p: ICipherParameters;
+  i1, i2: IIESEngine;
+  d, e, &message, out1, out2: TBytes;
+  gen: IECKeyPairGenerator;
+  ephKeyGen: IEphemeralKeyPairGenerator;
+begin
+  n := TBigInteger.Create
+    ('6277101735386680763835789423176059013767194773182842284081');
+
+  curve := TFpCurve.Create
+    (TBigInteger.Create
+    ('6277101735386680763835789423207666416083908700390324961279'), // q
+    TBigInteger.Create('fffffffffffffffffffffffffffffffefffffffffffffffc', 16),
+    // a
+    TBigInteger.Create('64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1', 16),
+    // b
+    n, TBigInteger.One);
+
+  params := TECDomainParameters.Create(curve,
+    curve.DecodePoint(THex.Decode
+    ('03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012')), // G
+    n);
+
+  priKey := TECPrivateKeyParameters.Create
+    (TBigInteger.Create
+    ('651056770906015076056810763456358567190100156695615665659'), // d
+    params);
+
+  pubKey := TECPublicKeyParameters.Create
+    (curve.DecodePoint(THex.Decode
+    ('0262b12d60690cdcf330babab6e69763b471f994dd702d16a5')), // Q
+    params);
+
+  p1 := TAsymmetricCipherKeyPair.Create(pubKey, priKey);
+  p2 := TAsymmetricCipherKeyPair.Create(pubKey, priKey);
+
+  //
+  // stream test - V 0
+  //
+  i1 := TIESEngine.Create(TECDHBasicAgreement.Create() as IECDHBasicAgreement,
+    TKDF2BytesGenerator.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IKDF2BytesGenerator, THMac.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IHMac);
+
+  i2 := TIESEngine.Create(TECDHBasicAgreement.Create() as IECDHBasicAgreement,
+    TKDF2BytesGenerator.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IKDF2BytesGenerator, THMac.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IHMac);
+
+  d := TBytes.Create(1, 2, 3, 4, 5, 6, 7, 8);
+  e := TBytes.Create(8, 7, 6, 5, 4, 3, 2, 1);
+  p := TIESParameters.Create(d, e, 64);
+
+  i1.Init(true, p1.Private, p2.Public, p);
+  i2.Init(false, p2.getPrivate, p1.getPublic, p);
+
+  &message := Nil;
+
+  out1 := i1.processBlock(&message, 0, System.Length(&message));
+  out2 := i2.processBlock(out1, 0, System.Length(out1));
+
+  if (not TArrayUtils.AreEqual(out2, &message)) then
+  begin
+    Fail('stream cipher test failed');
+  end;
+
+  out2 := i2.processBlock(out1, 0, System.Length(out1));
+
+  try
+
+    i2.processBlock(out1, 0, System.Length(out1) - 1);
+    Fail('Expected EInvalidCipherTextCryptoLibException');
+
+  except
+    on e: EInvalidCipherTextCryptoLibException do
+    begin
+      if (e.Message <>
+        'Length of Input Must be Greater than the MAC and V Combined') then
+      begin
+        Fail('Wrong Exception Message');
+      end;
+
+    end;
+
+  end;
+
+
+  // with ephemeral key pair
+
+  // Generate the ephemeral key pair
+
+  gen := TECKeyPairGenerator.Create();
+  gen.Init(TECKeyGenerationParameters.Create(params, TSecureRandom.Create()
+    as ISecureRandom) as IECKeyGenerationParameters);
+
+  ephKeyGen := TEphemeralKeyPairGenerator.Create(gen, TKeyEncoder.Create(false)
+    as IKeyEncoder);
+
+  i1.Init(p2.Public, p, ephKeyGen);
+  i2.Init(p2.Private, p, TECIESPublicKeyParser.Create(params)
+    as IECIESPublicKeyParser);
+
+  out1 := i1.processBlock(&message, 0, System.Length(&message));
+  out2 := i2.processBlock(out1, 0, System.Length(out1));
+
+  if (not TArrayUtils.AreEqual(out2, &message)) then
+  begin
+    Fail('V cipher test failed');
+  end;
+
+  try
+
+    i2.processBlock(out1, 0, System.Length(out1) - 1);
+    Fail('Expected EInvalidCipherTextCryptoLibException');
+
+  except
+    on e: EInvalidCipherTextCryptoLibException do
+    begin
+      if (e.Message <>
+        'Length of Input Must be Greater than the MAC and V Combined') then
+      begin
+        Fail('Wrong Exception Message');
+      end;
+
+    end;
+
+  end;
+
+end;
+
+procedure TTestECIES.DoStaticTest(iv: TBytes);
+var
+  n: TBigInteger;
+  curve: IFpCurve;
+  params: IECDomainParameters;
+  priKey: IECPrivateKeyParameters;
+  pubKey: IECPublicKeyParameters;
+  p1, p2: IAsymmetricCipherKeyPair;
+  p: ICipherParameters;
+  i1, i2: IIESEngine;
+  d, e, &message, out1, out2, compareValue: TBytes;
+  c1, c2: IBufferedBlockCipher;
+begin
+  n := TBigInteger.Create
+    ('6277101735386680763835789423176059013767194773182842284081');
+
+  curve := TFpCurve.Create
+    (TBigInteger.Create
+    ('6277101735386680763835789423207666416083908700390324961279'), // q
+    TBigInteger.Create('fffffffffffffffffffffffffffffffefffffffffffffffc', 16),
+    // a
+    TBigInteger.Create('64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1', 16),
+    // b
+    n, TBigInteger.One);
+
+  params := TECDomainParameters.Create(curve,
+    curve.DecodePoint(THex.Decode
+    ('03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012')), // G
+    n, TBigInteger.One);
+
+  priKey := TECPrivateKeyParameters.Create
+    (TBigInteger.Create
+    ('651056770906015076056810763456358567190100156695615665659'), // d
+    params);
+
+  pubKey := TECPublicKeyParameters.Create
+    (curve.DecodePoint(THex.Decode
+    ('0262b12d60690cdcf330babab6e69763b471f994dd702d16a5')), // Q
+    params);
+
+  p1 := TAsymmetricCipherKeyPair.Create(pubKey, priKey);
+  p2 := TAsymmetricCipherKeyPair.Create(pubKey, priKey);
+
+  //
+  // stream test
+  //
+  i1 := TIESEngine.Create(TECDHBasicAgreement.Create() as IECDHBasicAgreement,
+    TKDF2BytesGenerator.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IKDF2BytesGenerator, THMac.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IHMac);
+
+  i2 := TIESEngine.Create(TECDHBasicAgreement.Create() as IECDHBasicAgreement,
+    TKDF2BytesGenerator.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IKDF2BytesGenerator, THMac.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IHMac);
+
+  d := TBytes.Create(1, 2, 3, 4, 5, 6, 7, 8);
+  e := TBytes.Create(8, 7, 6, 5, 4, 3, 2, 1);
+  p := TIESParameters.Create(d, e, 64);
+
+  i1.Init(true, p1.Private, p2.Public, p);
+  i2.Init(false, p2.getPrivate, p1.getPublic, p);
+
+  &message := THex.Decode('1234567890abcdef');
+
+  out1 := i1.processBlock(&message, 0, System.Length(&message));
+
+  if (not TArrayUtils.AreEqual(out1,
+    THex.Decode('468d89877e8238802403ec4cb6b329faeccfa6f3a730f2cdb3c0a8e8')))
+  then
+  begin
+    Fail('stream cipher test failed on enc');
+  end;
+
+  out2 := i2.processBlock(out1, 0, System.Length(out1));
+
+  if (not TArrayUtils.AreEqual(out2, &message)) then
+  begin
+    Fail('stream cipher test failed');
+  end;
+
+  //
+  // AES with CBC
+  //
+
+  c1 := TPaddedBufferedBlockCipher.Create
+    (TCBCBlockCipher.Create(TAesEngine.Create() as IAesEngine)
+    as ICBCBlockCipher);
+
+  c2 := TPaddedBufferedBlockCipher.Create
+    (TCBCBlockCipher.Create(TAesEngine.Create() as IAesEngine)
+    as ICBCBlockCipher);
+
+  i1 := TIESEngine.Create(TECDHBasicAgreement.Create() as IECDHBasicAgreement,
+    TKDF2BytesGenerator.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IKDF2BytesGenerator, THMac.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IHMac, c1);
+
+  i2 := TIESEngine.Create(TECDHBasicAgreement.Create() as IECDHBasicAgreement,
+    TKDF2BytesGenerator.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IKDF2BytesGenerator, THMac.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IHMac, c2);
+
+  d := TBytes.Create(1, 2, 3, 4, 5, 6, 7, 8);
+  e := TBytes.Create(8, 7, 6, 5, 4, 3, 2, 1);
+  p := TIESWithCipherParameters.Create(d, e, 64, 128);
+
+  if (iv <> Nil) then
+  begin
+    p := TParametersWithIV.Create(p, iv);
+  end;
+
+  i1.Init(true, p1.Private, p2.Public, p);
+  i2.Init(false, p2.Private, p1.Public, p);
+
+  &message := THex.Decode('1234567890abcdef');
+
+  out1 := i1.processBlock(&message, 0, System.Length(&message));
+
+  if iv = Nil then
+  begin
+    compareValue := THex.Decode
+      ('33578c27c3c044a535d42b9fe77003c3c4c9a74b987adac5c21c920b4b878debdefdff1e');
+  end
+  else
+  begin
+    compareValue := THex.Decode
+      ('cae615459828884e5444a33a0271d763a8ca8affc60b8551a5fb2cc362409c0226e225e0');
+  end;
+
+  if (not TArrayUtils.AreEqual(out1, compareValue)) then
+  begin
+    Fail('AES cipher test failed on enc');
+  end;
+
+  out2 := i2.processBlock(out1, 0, System.Length(out1));
+
+  if (not TArrayUtils.AreEqual(out2, &message)) then
+  begin
+    Fail('AES cipher test failed');
+  end;
+
+end;
+
+procedure TTestECIES.DoTest(const p1, p2: IAsymmetricCipherKeyPair);
+var
+  p: ICipherParameters;
+  i1, i2: IIESEngine;
+  d, e, &message, out1, out2: TBytes;
+  c1, c2: IBufferedBlockCipher;
+begin
+  //
+  // stream test
+  //
+  i1 := TIESEngine.Create(TECDHBasicAgreement.Create() as IECDHBasicAgreement,
+    TKDF2BytesGenerator.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IKDF2BytesGenerator, THMac.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IHMac);
+
+  i2 := TIESEngine.Create(TECDHBasicAgreement.Create() as IECDHBasicAgreement,
+    TKDF2BytesGenerator.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IKDF2BytesGenerator, THMac.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IHMac);
+
+  d := TBytes.Create(1, 2, 3, 4, 5, 6, 7, 8);
+  e := TBytes.Create(8, 7, 6, 5, 4, 3, 2, 1);
+  p := TIESParameters.Create(d, e, 64);
+
+  i1.Init(true, p1.Private, p2.Public, p);
+  i2.Init(false, p2.getPrivate, p1.getPublic, p);
+
+  &message := THex.Decode('1234567890abcdef');
+
+  out1 := i1.processBlock(&message, 0, System.Length(&message));
+
+  out2 := i2.processBlock(out1, 0, System.Length(out1));
+
+  if (not TArrayUtils.AreEqual(out2, &message)) then
+  begin
+    Fail('stream cipher test failed');
+  end;
+
+  //
+  // AES with CBC
+  //
+
+  c1 := TPaddedBufferedBlockCipher.Create
+    (TCBCBlockCipher.Create(TAesEngine.Create() as IAesEngine)
+    as ICBCBlockCipher);
+
+  c2 := TPaddedBufferedBlockCipher.Create
+    (TCBCBlockCipher.Create(TAesEngine.Create() as IAesEngine)
+    as ICBCBlockCipher);
+
+  i1 := TIESEngine.Create(TECDHBasicAgreement.Create() as IECDHBasicAgreement,
+    TKDF2BytesGenerator.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IKDF2BytesGenerator, THMac.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IHMac, c1);
+
+  i2 := TIESEngine.Create(TECDHBasicAgreement.Create() as IECDHBasicAgreement,
+    TKDF2BytesGenerator.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IKDF2BytesGenerator, THMac.Create(TDigestUtilities.GetDigest('SHA-1'))
+    as IHMac, c2);
+
+  d := TBytes.Create(1, 2, 3, 4, 5, 6, 7, 8);
+  e := TBytes.Create(8, 7, 6, 5, 4, 3, 2, 1);
+  p := TIESWithCipherParameters.Create(d, e, 64, 128);
+
+  i1.Init(true, p1.Private, p2.Public, p);
+  i2.Init(false, p2.Private, p1.Public, p);
+
+  &message := THex.Decode('1234567890abcdef');
+
+  out1 := i1.processBlock(&message, 0, System.Length(&message));
+
+  out2 := i2.processBlock(out1, 0, System.Length(out1));
+
+  if (not TArrayUtils.AreEqual(out2, &message)) then
+  begin
+    Fail('AES cipher test failed');
+  end;
+end;
+
+procedure TTestECIES.SetUp;
+begin
+  inherited;
+  FAES_IV := THex.Decode('000102030405060708090a0b0c0d0e0f');
+end;
+
+procedure TTestECIES.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestECIES.TestECIES;
+var
+  n: TBigInteger;
+  curve: IFpCurve;
+  params: IECDomainParameters;
+  eGen: IECKeyPairGenerator;
+  gParam: IKeyGenerationParameters;
+  p1, p2: IAsymmetricCipherKeyPair;
+begin
+  DoStaticTest(Nil);
+  DoStaticTest(FAES_IV);
+  DoShortTest();
+
+  n := TBigInteger.Create
+    ('6277101735386680763835789423176059013767194773182842284081');
+
+  curve := TFpCurve.Create
+    (TBigInteger.Create
+    ('6277101735386680763835789423207666416083908700390324961279'), // q
+    TBigInteger.Create('fffffffffffffffffffffffffffffffefffffffffffffffc', 16),
+    // a
+    TBigInteger.Create('64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1', 16),
+    // b
+    n, TBigInteger.One);
+
+  params := TECDomainParameters.Create(curve,
+    curve.DecodePoint(THex.Decode
+    ('03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012')), // G
+    n, TBigInteger.One);
+
+  eGen := TECKeyPairGenerator.Create();
+  gParam := TECKeyGenerationParameters.Create(params, TSecureRandom.Create()
+    as ISecureRandom);
+
+  eGen.Init(gParam);
+
+  p1 := eGen.generateKeyPair();
+  p2 := eGen.generateKeyPair();
+
+  DoTest(p1, p2);
+
+  DoEphemeralTest(Nil, false);
+  DoEphemeralTest(Nil, true);
+  DoEphemeralTest(FAES_IV, false);
+  DoEphemeralTest(FAES_IV, true);
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestECIES);
+{$ELSE}
+  RegisterTest(TTestECIES.Suite);
+{$ENDIF FPC}
+
+end.

+ 477 - 0
CryptoLib.Tests/src/Math/ECNRTests.pas

@@ -0,0 +1,477 @@
+{ *********************************************************************************** }
+{ *                              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 ECNRTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+uses
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpIECInterface,
+  ClpECCurve,
+  ClpECNRSigner,
+  ClpIECNRSigner,
+  ClpECDomainParameters,
+  ClpIECDomainParameters,
+  ClpECPrivateKeyParameters,
+  ClpIECPrivateKeyParameters,
+  ClpECPublicKeyParameters,
+  ClpIECPublicKeyParameters,
+  ClpISigner,
+  ClpAsn1Object,
+  ClpParametersWithRandom,
+  ClpIParametersWithRandom,
+  ClpIAsn1Sequence,
+  ClpSecureRandom,
+  ClpISecureRandom,
+  ClpFixedSecureRandom,
+  ClpIDerInteger,
+  ClpHex,
+  ClpDigestUtilities,
+  ClpSignerUtilities,
+  ClpBigInteger,
+  ClpCryptoLibTypes;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  /// <summary>
+  /// ECNR tests.
+  /// </summary>
+  TTestECNR = class(TCryptoLibTestCase)
+  private
+
+    procedure DoCheckSignature(size: Int32; const sKey: IECPrivateKeyParameters;
+      const vKey: IECPublicKeyParameters; const sgr: ISigner;
+      const k: ISecureRandom; &message: TCryptoLibByteArray;
+      const r, s: TBigInteger);
+
+    function DoDerDecode(encoding: TCryptoLibByteArray)
+      : TCryptoLibGenericArray<TBigInteger>;
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+
+    /// <summary>
+    /// a basic regression test with 239 bit prime
+    /// </summary>
+    procedure TestECNR239bitPrime;
+
+    /// <summary>
+    /// <para>
+    /// X9.62 - 1998,
+    /// </para>
+    /// <para>
+    /// <br />J.3.2, Page 155, ECDSA over the field <c>Fp</c>
+    /// </para>
+    /// <para>
+    /// <br />an example with 239 bit prime
+    /// </para>
+    /// </summary>
+    procedure TestECNR239bitPrimeSHA1; // Prime239v1
+
+    /// <summary>
+    /// <para>
+    /// 9.62 - 1998,
+    /// </para>
+    /// <para>
+    /// Page 104-105, ECDSA over the field <c>Fp</c>
+    /// </para>
+    /// <para>
+    /// <c>an example with 192 bit prime</c>
+    /// </para>
+    /// </summary>
+    procedure TestECNR192bitPrimeSHA1; // Prime192v1
+
+    /// <summary>
+    /// <para>
+    /// SEC 2: Recommended Elliptic Curve Domain Parameters - September
+    /// 2000,
+    /// </para>
+    /// <para>
+    /// Page 17-19, Recommended 521-bit Elliptic Curve Domain Parameters
+    /// over <c>Fp</c>
+    /// </para>
+    /// <para>
+    /// <c>an ECC example with a 521 bit prime and a 512 bit hash</c>
+    /// </para>
+    /// </summary>
+    procedure TestECNR521bitPrimeSHA512; // SecP521r1
+
+  end;
+
+implementation
+
+{ TTestECNR }
+
+procedure TTestECNR.DoCheckSignature(size: Int32;
+  const sKey: IECPrivateKeyParameters; const vKey: IECPublicKeyParameters;
+  const sgr: ISigner; const k: ISecureRandom; &message: TCryptoLibByteArray;
+  const r, s: TBigInteger);
+var
+  sigBytes: TBytes;
+  sig: TCryptoLibGenericArray<TBigInteger>;
+begin
+  sgr.Init(true, TParametersWithRandom.Create(sKey, k)
+    as IParametersWithRandom);
+
+  sgr.BlockUpdate(&message, 0, System.Length(&message));
+
+  sigBytes := sgr.GenerateSignature();
+
+  sgr.Init(false, vKey);
+
+  sgr.BlockUpdate(&message, 0, System.Length(&message));
+
+  if (not(sgr.VerifySignature(sigBytes))) then
+  begin
+    Fail(IntToStr(size) + ' bit EC verification failed');
+  end;
+
+  sig := DoDerDecode(sigBytes);
+
+  if (not(r.Equals(sig[0]))) then
+  begin
+    Fail(IntToStr(size) + 'bit' + ': r component wrong.' + sLineBreak +
+      ' expecting: ' + r.ToString() + sLineBreak + ' got      : ' +
+      sig[0].ToString());
+  end;
+
+  if (not(s.Equals(sig[1]))) then
+  begin
+    Fail(IntToStr(size) + 'bit' + ': s component wrong.' + sLineBreak +
+      ' expecting: ' + s.ToString() + sLineBreak + ' got      : ' +
+      sig[1].ToString());
+  end;
+end;
+
+function TTestECNR.DoDerDecode(encoding: TCryptoLibByteArray)
+  : TCryptoLibGenericArray<TBigInteger>;
+var
+  s: IAsn1Sequence;
+begin
+  s := TAsn1Object.FromByteArray(encoding) as IAsn1Sequence;
+
+  result := TCryptoLibGenericArray<TBigInteger>.Create
+    ((s[0] as IDerInteger).Value, (s[1] as IDerInteger).Value);
+end;
+
+procedure TTestECNR.SetUp;
+begin
+  inherited;
+
+end;
+
+procedure TTestECNR.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestECNR.TestECNR192bitPrimeSHA1;
+var
+  r, s: TBigInteger;
+  kData, &message: TBytes;
+  k: ISecureRandom;
+  curve: IFpCurve;
+  parameters: IECDomainParameters;
+  priKey: IECPrivateKeyParameters;
+  pubKey: IECPublicKeyParameters;
+  sgr: ISigner;
+begin
+  r := TBigInteger.Create
+    ('2474388605162950674935076940284692598330235697454145648371');
+  s := TBigInteger.Create
+    ('2997192822503471356158280167065034437828486078932532073836');
+
+  kData := TBigInteger.Create
+    ('dcc5d1f1020906df2782360d36b2de7a17ece37d503784af', 16)
+    .ToByteArrayUnsigned();
+  k := TFixedSecureRandom.From(TCryptoLibMatrixByteArray.Create(kData));
+
+  curve := TFpCurve.Create
+    (TBigInteger.Create
+    ('6277101735386680763835789423207666416083908700390324961279'),
+    // q (or p)
+    TBigInteger.Create('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC', 16),
+    // a
+    TBigInteger.Create('64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1', 16),
+    // b
+    TBigInteger.Create
+    ('6277101735386680763835789423176059013767194773182842284081'),
+    TBigInteger.One);
+
+  parameters := TECDomainParameters.Create(curve,
+    curve.DecodePoint(THex.Decode
+    ('03188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012')), // G
+    TBigInteger.Create
+    ('6277101735386680763835789423176059013767194773182842284081')
+    // n
+    );
+
+  priKey := TECPrivateKeyParameters.Create
+    (TBigInteger.Create
+    ('651056770906015076056810763456358567190100156695615665659'),
+    // d
+    parameters);
+
+  pubKey := TECPublicKeyParameters.Create
+    (curve.DecodePoint(THex.Decode
+    ('0262B12D60690CDCF330BABAB6E69763B471F994DD702D16A5')), // Q
+    parameters);
+
+  sgr := TSignerUtilities.GetSigner('SHA1withECNR');
+  &message := TEncoding.UTF8.GetBytes('abc');
+
+  DoCheckSignature(192, priKey, pubKey, sgr, k, &message, r, s);
+end;
+
+procedure TTestECNR.TestECNR239bitPrime;
+var
+  r, s, n: TBigInteger;
+  kData, &message: TBytes;
+  k: ISecureRandom;
+  curve: IFpCurve;
+  parameters: IECDomainParameters;
+  priKey: IECPrivateKeyParameters;
+  pubKey: IECPublicKeyParameters;
+  ecnr: IECNRSigner;
+  param: IParametersWithRandom;
+  sig: TCryptoLibGenericArray<TBigInteger>;
+begin
+  r := TBigInteger.Create
+    ('308636143175167811492623515537541734843573549327605293463169625072911693');
+  s := TBigInteger.Create
+    ('852401710738814635664888632022555967400445256405412579597015412971797143');
+
+  kData := TBigInteger.Create
+    ('700000017569056646655505781757157107570501575775705779575555657156756655')
+    .ToByteArrayUnsigned();
+  k := TFixedSecureRandom.From(TCryptoLibMatrixByteArray.Create(kData));
+
+  n := TBigInteger.Create
+    ('883423532389192164791648750360308884807550341691627752275345424702807307');
+
+  curve := TFpCurve.Create
+    (TBigInteger.Create
+    ('883423532389192164791648750360308885314476597252960362792450860609699839'),
+    // q
+    TBigInteger.Create
+    ('7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc', 16), // a
+    TBigInteger.Create
+    ('6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a', 16), // b
+    TBigInteger.Create
+    ('7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b', 16),
+    TBigInteger.One);
+
+  parameters := TECDomainParameters.Create(curve,
+    curve.DecodePoint(THex.Decode
+    ('020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf')), // G
+    n, TBigInteger.One);
+
+  priKey := TECPrivateKeyParameters.Create
+    (TBigInteger.Create
+    ('876300101507107567501066130761671078357010671067781776716671676178726717'),
+    // d
+    parameters);
+
+  ecnr := TECNRSigner.Create();
+  param := TParametersWithRandom.Create(priKey, k);
+
+  ecnr.Init(true, param);
+
+  &message := TBigInteger.Create
+    ('968236873715988614170569073515315707566766479517').ToByteArray();
+  sig := ecnr.GenerateSignature(&message);
+
+  if (not(r.Equals(sig[0]))) then
+  begin
+    Fail('r component wrong. ' + r.ToString + ' expected but ' + sig[0].ToString
+      + ' gotten');
+  end;
+
+  if (not(s.Equals(sig[1]))) then
+  begin
+    Fail('s component wrong. ' + s.ToString + ' expected but ' + sig[1].ToString
+      + ' gotten');
+  end;
+
+  // Verify the signature
+  pubKey := TECPublicKeyParameters.Create
+    (curve.DecodePoint(THex.Decode
+    ('025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70')), // Q
+    parameters);
+
+  ecnr.Init(false, pubKey);
+  if (not(ecnr.VerifySignature(&message, sig[0], sig[1]))) then
+  begin
+    Fail('signature fails');
+  end;
+end;
+
+procedure TTestECNR.TestECNR239bitPrimeSHA1;
+var
+  r, s: TBigInteger;
+  kData, &message: TBytes;
+  k: ISecureRandom;
+  curve: IFpCurve;
+  parameters: IECDomainParameters;
+  priKey: IECPrivateKeyParameters;
+  pubKey: IECPublicKeyParameters;
+  sgr: ISigner;
+begin
+  r := TBigInteger.Create
+    ('308636143175167811492623515537541734843573549327605293463169625072911693');
+  s := TBigInteger.Create
+    ('852401710738814635664888632022555967400445256405412579597015412971797143');
+
+  kData := TBigInteger.Create
+    ('700000017569056646655505781757157107570501575775705779575555657156756655')
+    .ToByteArrayUnsigned();
+  k := TFixedSecureRandom.From(TCryptoLibMatrixByteArray.Create(kData));
+
+  curve := TFpCurve.Create
+    (TBigInteger.Create
+    ('883423532389192164791648750360308885314476597252960362792450860609699839'),
+    // q
+    TBigInteger.Create
+    ('7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc', 16), // a
+    TBigInteger.Create
+    ('6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a', 16), // b
+    TBigInteger.Create
+    ('7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b', 16),
+    TBigInteger.One);
+
+  parameters := TECDomainParameters.Create(curve,
+    curve.DecodePoint(THex.Decode
+    ('020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf')), // G
+    TBigInteger.Create
+    ('883423532389192164791648750360308884807550341691627752275345424702807307'),
+    // n
+    TBigInteger.One);
+
+  priKey := TECPrivateKeyParameters.Create
+    (TBigInteger.Create
+    ('876300101507107567501066130761671078357010671067781776716671676178726717'),
+    // d
+    parameters);
+
+  pubKey := TECPublicKeyParameters.Create
+    (curve.DecodePoint(THex.Decode
+    ('025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70')), // Q
+    parameters);
+
+  sgr := TSignerUtilities.GetSigner('SHA1withECNR');
+  &message := TEncoding.UTF8.GetBytes('abc');
+
+  DoCheckSignature(239, priKey, pubKey, sgr, k, &message, r, s);
+end;
+
+procedure TTestECNR.TestECNR521bitPrimeSHA512;
+var
+  r, s: TBigInteger;
+  kData, &message: TBytes;
+  k: ISecureRandom;
+  curve: IFpCurve;
+  parameters: IECDomainParameters;
+  priKey: IECPrivateKeyParameters;
+  pubKey: IECPublicKeyParameters;
+  sgr: ISigner;
+begin
+  r := TBigInteger.Create
+    ('1820641608112320695747745915744708800944302281118541146383656165330049339564439316345159057453301092391897040509935100825960342573871340486684575368150970954');
+  s := TBigInteger.Create
+    ('6358277176448326821136601602749690343031826490505780896013143436153111780706227024847359990383467115737705919410755190867632280059161174165591324242446800763');
+
+  kData := TBigInteger.Create
+    ('cdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
+    16).ToByteArrayUnsigned();
+  k := TFixedSecureRandom.From(TCryptoLibMatrixByteArray.Create(kData));
+
+  curve := TFpCurve.Create
+    (TBigInteger.Create
+    ('6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151'),
+    // q (or p)
+    TBigInteger.Create
+    ('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC',
+    16),
+    // a
+    TBigInteger.Create
+    ('0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00',
+    16), // b
+    TBigInteger.Create(1,
+    THex.Decode
+    ('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409')
+    ), TBigInteger.One);
+  // b
+
+  parameters := TECDomainParameters.Create(curve,
+    curve.DecodePoint(THex.Decode
+    ('0200C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66')
+    ), // G
+    TBigInteger.Create
+    ('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409',
+    16)
+    // n
+    );
+
+  priKey := TECPrivateKeyParameters.Create
+    (TBigInteger.Create
+    ('5769183828869504557786041598510887460263120754767955773309066354712783118202294874205844512909370791582896372147797293913785865682804434049019366394746072023'),
+    // d
+    parameters);
+
+  pubKey := TECPublicKeyParameters.Create
+    (curve.DecodePoint(THex.Decode
+    ('02006BFDD2C9278B63C92D6624F151C9D7A822CC75BD983B17D25D74C26740380022D3D8FAF304781E416175EADF4ED6E2B47142D2454A7AC7801DD803CF44A4D1F0AC')
+    ), // Q
+    parameters);
+
+  sgr := TSignerUtilities.GetSigner('SHA512withECNR');
+  &message := TEncoding.UTF8.GetBytes('abc');
+
+  DoCheckSignature(521, priKey, pubKey, sgr, k, &message, r, s);
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestECNR);
+{$ELSE}
+  RegisterTest(TTestECNR.Suite);
+{$ENDIF FPC}
+
+end.

+ 31 - 15
CryptoLib.Tests/src/Math/ECPointTests.pas

@@ -21,7 +21,6 @@ interface
 
 {$IFDEF FPC}
 {$MODE DELPHI}
-{$WARNINGS OFF}
 {$ENDIF FPC}
 
 uses
@@ -201,6 +200,8 @@ type
 
     procedure ImplSqrtTest(const c: IECCurve);
 
+    procedure ImplValidityTest(const c: IECCurve; const g: IECPoint);
+
     procedure ImplAddSubtractMultiplyTwiceEncodingTestAllCoords
       (const x9ECParameters: IX9ECParameters);
 
@@ -320,13 +321,13 @@ procedure TTestECPoint.ImplAddSubtractMultiplyTwiceEncodingTestAllCoords
   (const x9ECParameters: IX9ECParameters);
 var
   n, b: TBigInteger;
-  G, sg, q: IECPoint;
+  g, sg, q: IECPoint;
   c, sc: IECCurve;
   coords: TCryptoLibInt32Array;
   i, coord: Int32;
 begin
   n := x9ECParameters.n;
-  G := x9ECParameters.G;
+  g := x9ECParameters.g;
   c := x9ECParameters.curve;
 
   coords := TECCurve.GetAllCoordinateSystems();
@@ -337,12 +338,12 @@ begin
     if (c.SupportsCoordinateSystem(coord)) then
     begin
       sc := c;
-      sg := G;
+      sg := g;
 
       if (sc.CoordinateSystem <> coord) then
       begin
         sc := c.Configure().SetCoordinateSystem(coord).CreateCurve();
-        sg := sc.ImportPoint(G);
+        sg := sc.ImportPoint(g);
       end;
 
       // The generator is multiplied by random b to get random q
@@ -353,6 +354,7 @@ begin
       ImplAddSubtractMultiplyTwiceEncodingTest(sc, q, n);
 
       ImplSqrtTest(sc);
+      ImplValidityTest(sc, sg);
     end;
     System.Inc(i);
   end;
@@ -508,6 +510,25 @@ begin
   AssertPointsEqual('Add same point incorrect', p[3], p[0].Add(p[0]));
 end;
 
+procedure TTestECPoint.ImplValidityTest(const c: IECCurve; const g: IECPoint);
+var
+  h: TBigInteger;
+  order2, bad: IECPoint;
+begin
+  CheckTrue(g.IsValid());
+
+  h := c.getCofactor();
+  if ((h.IsInitialized) and (h.CompareTo(TBigInteger.One) > 0)) then
+  begin
+    if (TECAlgorithms.IsF2mCurve(c)) then
+    begin
+      order2 := c.CreatePoint(TBigInteger.Zero, c.b.Sqrt().ToBigInteger());
+      bad := g.Add(order2);
+      CheckFalse(bad.IsValid());
+    end;
+  end;
+end;
+
 procedure TTestECPoint.SetUp;
 begin
   inherited;
@@ -573,10 +594,7 @@ begin
     try
       for s in tempList do
       begin
-        if not tempDict.ContainsKey(s) then // make sure they are unique
-        begin
-          tempDict.Add(s, s);
-        end;
+        tempDict.AddOrSetValue(s, s); // make sure they are unique
       end;
       uniqNames := tempDict.Values.ToArray; // save unique instances to array
     finally
@@ -645,11 +663,9 @@ begin
 end;
 
 procedure TTestECPoint.TestPointCreationConsistency;
-var
-  bad: IECPoint;
 begin
   try
-    bad := FpInstance.Fcurve.CreatePoint(TBigInteger.ValueOf(12),
+    FpInstance.Fcurve.CreatePoint(TBigInteger.ValueOf(12),
       Default (TBigInteger));
     Fail('expected EArgumentCryptoLibException');
   except
@@ -661,7 +677,7 @@ begin
   end;
 
   try
-    bad := FpInstance.Fcurve.CreatePoint(Default (TBigInteger),
+    FpInstance.Fcurve.CreatePoint(Default (TBigInteger),
       TBigInteger.ValueOf(12));
     Fail('expected EArgumentCryptoLibException');
   except
@@ -673,7 +689,7 @@ begin
   end;
 
   try
-    bad := FpInstance.Fcurve.CreatePoint(TBigInteger.Create('1011'),
+    FpInstance.Fcurve.CreatePoint(TBigInteger.Create('1011'),
       Default (TBigInteger));
     Fail('expected EArgumentCryptoLibException');
   except
@@ -685,7 +701,7 @@ begin
   end;
 
   try
-    bad := FpInstance.Fcurve.CreatePoint(Default (TBigInteger),
+    FpInstance.Fcurve.CreatePoint(Default (TBigInteger),
       TBigInteger.Create('1011'));
     Fail('expected EArgumentCryptoLibException');
   except

+ 275 - 0
CryptoLib.Tests/src/Math/IESCipherTests.pas

@@ -0,0 +1,275 @@
+{ *********************************************************************************** }
+{ *                              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 IESCipherTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+uses
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpIMac,
+  ClpAesEngine,
+  ClpIAesEngine,
+  ClpIAsymmetricCipherKeyPairGenerator,
+  ClpGeneratorUtilities,
+  ClpIESWithCipherParameters,
+  ClpIIESWithCipherParameters,
+  // ClpKeyParameter,
+  // ClpIKeyParameter,
+  // ClpParametersWithIV,
+  // ClpIParametersWithIV,
+  ClpIBufferedBlockCipher,
+  // ClpParameterUtilities,
+  // ClpCipherUtilities,
+  ClpCbcBlockCipher,
+  ClpICbcBlockCipher,
+  ClpPaddedBufferedBlockCipher,
+  ClpECDHBasicAgreement,
+  ClpIECDHBasicAgreement,
+  ClpIESEngine,
+  ClpIIESEngine,
+  ClpPkcs7Padding,
+  ClpIPkcs7Padding,
+  // ClpZeroBytePadding,
+  // ClpIZeroBytePadding,
+  ClpKdf2BytesGenerator,
+  ClpIKdf2BytesGenerator,
+  ClpIX9ECParameters,
+  ClpSecNamedCurves,
+  ClpIECDomainParameters,
+  ClpECDomainParameters,
+  ClpECKeyGenerationParameters,
+  ClpSecureRandom,
+  ClpISecureRandom,
+  ClpIAsymmetricCipherKeyPair,
+  ClpIECPublicKeyParameters,
+  ClpIECPrivateKeyParameters,
+  ClpIIESCipher,
+  ClpIESCipher,
+  ClpHex,
+  ClpDigestUtilities,
+  ClpMacUtilities,
+  ClpArrayUtils;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  TTestIESCipher = class(TCryptoLibTestCase)
+  private
+
+    function GetECIESAES256CBCEngine: IIESEngine;
+    function GetECKeyPair: IAsymmetricCipherKeyPair;
+    function GetIESWithCipherParameters: IIESWithCipherParameters;
+
+    procedure doIESCipher_Encryption_Decryption_TestWithIV
+      (const KeyPair: IAsymmetricCipherKeyPair;
+      const param: IIESWithCipherParameters; const Random: ISecureRandom;
+      const PlainText: String);
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+
+    procedure TestIESCipher_Random_Values_Encryption_Decryption_AES256_CBC_PKCS7PADDING;
+
+  end;
+
+implementation
+
+{ TTestIESCipher }
+
+procedure TTestIESCipher.doIESCipher_Encryption_Decryption_TestWithIV
+  (const KeyPair: IAsymmetricCipherKeyPair;
+  const param: IIESWithCipherParameters; const Random: ISecureRandom;
+  const PlainText: String);
+var
+  PlainTextBytes, CipherTextBytes, DecryptionResultBytes: TBytes;
+  CipherEncrypt, CipherDecrypt: IIESCipher;
+begin
+  PlainTextBytes := TEncoding.UTF8.GetBytes(UnicodeString(PlainText));
+  // Encryption
+  CipherEncrypt := TIESCipher.Create(GetECIESAES256CBCEngine);
+  CipherEncrypt.Init(True, KeyPair.Public as IECPublicKeyParameters,
+    param, Random);
+  CipherTextBytes := CipherEncrypt.DoFinal(PlainTextBytes);
+
+  // Decryption
+  CipherDecrypt := TIESCipher.Create(GetECIESAES256CBCEngine);
+  CipherDecrypt.Init(False, KeyPair.Private as IECPrivateKeyParameters,
+    param, Random);
+  DecryptionResultBytes := CipherDecrypt.DoFinal(CipherTextBytes);
+
+  if (not TArrayUtils.AreEqual(PlainTextBytes, DecryptionResultBytes)) then
+  begin
+    Fail(Format('Decryption Failed - Expected %s but got %s',
+      [THex.Encode(PlainTextBytes), THex.Encode(DecryptionResultBytes)]));
+  end;
+end;
+
+function TTestIESCipher.GetECIESAES256CBCEngine: IIESEngine;
+var
+  Cipher: IBufferedBlockCipher;
+  AesEngine: IAesEngine;
+  blockCipher: ICbcBlockCipher;
+  ECDHBasicAgreementInstance: IECDHBasicAgreement;
+  KDFInstance: IKdf2BytesGenerator;
+  DigestMACInstance: IMac;
+
+begin
+  // // Set up IES Cipher Engine
+
+  ECDHBasicAgreementInstance := TECDHBasicAgreement.Create();
+
+  KDFInstance := TKdf2BytesGenerator.Create
+    (TDigestUtilities.GetDigest('SHA-256'));
+
+  DigestMACInstance := TMacUtilities.GetMac('HMAC-SHA-256');
+
+  // Method 1: Set Up Block Cipher
+  // Cipher := TCipherUtilities.GetCipher('AES/CBC/PKCS7PADDING') as IBufferedBlockCipher;
+
+  // Method 2: Set Up Block Cipher
+  AesEngine := TAesEngine.Create(); // AES Engine
+
+  blockCipher := TCbcBlockCipher.Create(AesEngine); // CBC
+
+  Cipher := TPaddedBufferedBlockCipher.Create(blockCipher,
+    TPkcs7Padding.Create() as IPkcs7Padding); // Pkcs7Padding
+
+  // Cipher := TPaddedBufferedBlockCipher.Create(blockCipher,
+  // TZeroBytePadding.Create() as IZeroBytePadding); // ZeroBytePadding
+
+  result := TIESEngine.Create(ECDHBasicAgreementInstance, KDFInstance,
+    DigestMACInstance, Cipher);
+end;
+
+function TTestIESCipher.GetECKeyPair: IAsymmetricCipherKeyPair;
+var
+  CurveName: string;
+  KeyPairGeneratorInstance: IAsymmetricCipherKeyPairGenerator;
+  RandomInstance: ISecureRandom;
+  Lcurve: IX9ECParameters;
+  ecSpec: IECDomainParameters;
+begin
+  // Set Up EC Key Pair
+
+  CurveName := 'secp256k1';
+  Lcurve := TSecNamedCurves.GetByName(CurveName);
+  KeyPairGeneratorInstance := TGeneratorUtilities.GetKeyPairGenerator('ECDSA');
+  ecSpec := TECDomainParameters.Create(Lcurve.Curve, Lcurve.G, Lcurve.N,
+    Lcurve.H, Lcurve.GetSeed);
+  RandomInstance := TSecureRandom.Create();
+  KeyPairGeneratorInstance.Init(TECKeyGenerationParameters.Create(ecSpec,
+    RandomInstance));
+  result := KeyPairGeneratorInstance.GenerateKeyPair();
+end;
+
+function TTestIESCipher.GetIESWithCipherParameters: IIESWithCipherParameters;
+var
+  Derivation, Encoding, IVBytes: TBytes;
+  MacKeySizeInBits, CipherKeySizeInBits: Int32;
+  UsePointCompression: Boolean;
+begin
+  // Setup IES With Cipher Parameters
+
+  // The derivation and encoding vectors are used when initialising the KDF and MAC.
+  // They're optional but if used then they need to be known by the other user so that
+  // they can decrypt the ciphertext and verify the MAC correctly. The security is based
+  // on the shared secret coming from the (static-ephemeral) ECDH key agreement.
+  Derivation := Nil;
+
+  Encoding := Nil;
+
+  System.SetLength(IVBytes, 16); // using Zero Initialized IV for ease
+
+  MacKeySizeInBits := 32 * 8; // Since we are using SHA2_256 for MAC
+
+  CipherKeySizeInBits := 32 * 8; // Since we are using AES256 for Cipher
+
+  // whether to use point compression when deriving the octets string
+  // from a point or not in the EphemeralKeyPairGenerator
+  UsePointCompression := False;
+
+  result := TIESWithCipherParameters.Create(Derivation, Encoding,
+    MacKeySizeInBits, CipherKeySizeInBits, IVBytes, UsePointCompression);
+
+end;
+
+procedure TTestIESCipher.SetUp;
+begin
+  inherited;
+end;
+
+procedure TTestIESCipher.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestIESCipher.
+  TestIESCipher_Random_Values_Encryption_Decryption_AES256_CBC_PKCS7PADDING;
+var
+  RandomInstance: ISecureRandom;
+  PlainText: string;
+  I: Int32;
+  RandomBytes: TBytes;
+begin
+  RandomInstance := TSecureRandom.Create();
+  I := 0;
+  while I <= 10 do
+  begin
+    System.SetLength(RandomBytes, Byte(RandomInstance.NextInt32));
+    RandomInstance.NextBytes(RandomBytes);
+    PlainText := THex.Encode(RandomBytes);
+
+    // Call IESCipher Encryption and Decryption Method
+
+    doIESCipher_Encryption_Decryption_TestWithIV(GetECKeyPair,
+      GetIESWithCipherParameters, RandomInstance, PlainText);
+
+    System.Inc(I);
+  end;
+
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestIESCipher);
+{$ELSE}
+  RegisterTest(TTestIESCipher.Suite);
+{$ENDIF FPC}
+
+end.

+ 17 - 5
CryptoLib.Tests/src/Others/ECDsa5Tests.pas

@@ -133,8 +133,11 @@ begin
     ('6277101735386680763835789423207666416083908700390324961279'), // q
     TBigInteger.Create('fffffffffffffffffffffffffffffffefffffffffffffffc', 16),
     // a
-    TBigInteger.Create('64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1', 16));
-  // b
+    TBigInteger.Create('64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1', 16),
+    // b
+    TBigInteger.Create
+    ('6277101735386680763835789423176059013767194773182842284081'),
+    TBigInteger.One);
 
   p := curve.DecodePoint
     (THex.Decode('03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012'));
@@ -183,7 +186,10 @@ begin
     TBigInteger.Create
     ('32010857077C5431123A46B808906756F543423E8D27877578125778AC76', 16), // a
     TBigInteger.Create
-    ('790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16', 16)); // b
+    ('790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16', 16), // b
+    TBigInteger.Create
+    ('2000000000000000000000000000000F4D42FFE1492A4993F1CAD666E447', 16),
+    TBigInteger.Four);
 
   parameters := TECDomainParameters.Create(curve,
     curve.DecodePoint(THex.Decode
@@ -271,7 +277,10 @@ begin
     TBigInteger.Create
     ('7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc', 16), // a
     TBigInteger.Create
-    ('6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a', 16)); // b
+    ('6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a', 16), // b
+    TBigInteger.Create
+    ('7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b', 16),
+    TBigInteger.One);
 
   spec := TECDomainParameters.Create(curve,
 
@@ -356,7 +365,10 @@ begin
     TBigInteger.Create
     ('7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc', 16), // a
     TBigInteger.Create
-    ('6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a', 16)); // b
+    ('6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a', 16), // b
+    TBigInteger.Create
+    ('7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b', 16),
+    TBigInteger.One);
 
   ecSpec := TECDomainParameters.Create(curve,
     curve.DecodePoint(THex.Decode

+ 1 - 5
CryptoLib.Tests/src/Others/ECSchnorrTests.pas

@@ -35,9 +35,6 @@ uses
   ClpSecureRandom,
   ClpISecureRandom,
   ClpFixedSecureRandom,
-  ClpIFixedSecureRandom,
-  ClpECSchnorrSigner,
-  ClpIECSchnorrSigner,
   ClpISigner,
   ClpECPublicKeyParameters,
   ClpIECPublicKeyParameters,
@@ -57,8 +54,7 @@ uses
   ClpSecNamedCurves,
   ClpCryptoLibTypes,
   ClpBigInteger,
-  ClpSignerUtilities,
-  ClpBigIntegers;
+  ClpSignerUtilities;
 
 type
 

+ 18 - 7
CryptoLib.Tests/src/Others/ECTests.pas

@@ -151,8 +151,11 @@ begin
     ('6277101735386680763835789423207666416083908700390324961279'), // q
     TBigInteger.Create('fffffffffffffffffffffffffffffffefffffffffffffffc', 16),
     // a
-    TBigInteger.Create('64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1', 16));
-  // b
+    TBigInteger.Create('64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1', 16),
+    // b
+    TBigInteger.Create
+    ('6277101735386680763835789423176059013767194773182842284081'),
+    TBigInteger.One);
 
   p := curve.DecodePoint
     (THex.Decode('03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012'))
@@ -172,7 +175,7 @@ begin
     Fail('y uncompressed incorrectly');
   end;
 
-  encoding := p.GetEncoded();
+  encoding := p.GetEncoded(true);
 
   if (not TArrayUtils.AreEqual(encoding,
     THex.Decode('03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012'))) then
@@ -209,8 +212,10 @@ begin
     9, // k
     TBigInteger.Create('2866537B676752636A68F56554E12640276B649EF7526267', 16),
     // a
-    TBigInteger.Create('2E45EF571F00786F67B0081B9495A3D95462F5DE0AA185EC', 16));
-  // b
+    TBigInteger.Create('2E45EF571F00786F67B0081B9495A3D95462F5DE0AA185EC', 16),
+    // b
+    TBigInteger.Create('40000000000000000000000004A20E90C39067C893BBB9A5', 16),
+    TBigInteger.Two);
 
   parameters := TECDomainParameters.Create(curve,
     curve.DecodePoint(THex.Decode
@@ -373,7 +378,10 @@ begin
     TBigInteger.Create
     ('32010857077C5431123A46B808906756F543423E8D27877578125778AC76', 16), // a
     TBigInteger.Create
-    ('790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16', 16)); // b
+    ('790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16', 16), // b
+    TBigInteger.Create
+    ('2000000000000000000000000000000F4D42FFE1492A4993F1CAD666E447', 16),
+    TBigInteger.Four);
 
   parameters := TECDomainParameters.Create(curve,
     curve.DecodePoint(THex.Decode
@@ -455,7 +463,10 @@ begin
     TBigInteger.Create
     ('32010857077C5431123A46B808906756F543423E8D27877578125778AC76', 16), // a
     TBigInteger.Create
-    ('790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16', 16)); // b
+    ('790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16', 16), // b
+    TBigInteger.Create
+    ('2000000000000000000000000000000F4D42FFE1492A4993F1CAD666E447', 16),
+    TBigInteger.Four);
 
   parameters := TECDomainParameters.Create(curve,
     curve.DecodePoint(THex.Decode

+ 3 - 1
CryptoLib.Tests/src/Others/NamedCurveTests.pas

@@ -19,7 +19,9 @@ unit NamedCurveTests;
 
 interface
 
-{$HINTS OFF}
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
 
 uses
   Classes,

+ 9 - 7
CryptoLib.Tests/src/Others/SignerUtilitiesTests.pas

@@ -19,10 +19,13 @@ unit SignerUtilitiesTests;
 
 interface
 
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
 uses
   Classes,
   SysUtils,
-  ClpHex,
 {$IFDEF FPC}
   fpcunit,
   testregistry,
@@ -116,15 +119,14 @@ begin
     TBigInteger.Create
     ('7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc', 16), // a
     TBigInteger.Create
-    ('6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a', 16)); // b
+    ('6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a', 16), // b
+    FECParraN, FECParraH);
 
   FecDomain := TECDomainParameters.Create(Fcurve,
-    TFpPoint.Create(Fcurve, Fcurve.FromBigInteger(FECParraGX),
-    Fcurve.FromBigInteger(FECParraGY)) as IFpPoint, FECParraN);
+    Fcurve.ValidatePoint(FECParraGX, FECParraGY), FECParraN, FECParraH);
 
-  FecPub := TECPublicKeyParameters.Create(TFpPoint.Create(Fcurve,
-    Fcurve.FromBigInteger(FECPubQX), Fcurve.FromBigInteger(FECPubQY))
-    as IFpPoint, FecDomain);
+  FecPub := TECPublicKeyParameters.Create(Fcurve.ValidatePoint(FECPubQX,
+    FECPubQY), FecDomain);
 
   FecPriv := TECPrivateKeyParameters.Create(FECPrivD, FecDomain);
 

+ 0 - 5
CryptoLib.Tests/src/Security/SecureRandomTests.pas

@@ -21,11 +21,6 @@ interface
 
 {$IFDEF FPC}
 {$MODE DELPHI}
-// Disable Overflow and RangeChecks.
-{$OVERFLOWCHECKS OFF}
-{$RANGECHECKS OFF}
-{$HINTS OFF}
-{$NOTES OFF}
 {$ENDIF FPC}
 
 uses

+ 4 - 4
CryptoLib.Tests/src/Utils/ClpFixedSecureRandom.pas

@@ -21,7 +21,6 @@ interface
 
 {$IFDEF FPC}
 {$MODE DELPHI}
-{$WARNINGS OFF}
 {$ENDIF FPC}
 
 uses
@@ -276,9 +275,6 @@ begin
         System.Inc(i);
       end;
 
-      System.SetLength(F_data, bOut.Size);
-      bOut.Position := 0;
-      bOut.Read(F_data[0], bOut.Size);
     end
     else
     begin
@@ -286,6 +282,10 @@ begin
         (@SUnRecognizedImplementation);
     end;
 
+    System.SetLength(F_data, bOut.Size);
+    bOut.Position := 0;
+    bOut.Read(F_data[0], bOut.Size);
+
   finally
     bOut.Free;
 

+ 0 - 7
CryptoLib.Tests/src/Utils/ClpIFixedSecureRandom.pas

@@ -21,7 +21,6 @@ interface
 
 {$IFDEF FPC}
 {$MODE DELPHI}
-{$WARNINGS OFF}
 {$ENDIF FPC}
 
 uses
@@ -34,18 +33,12 @@ type
 
     function GetIsExhausted: Boolean;
 
-    function GenerateSeed(numBytes: Int32): TCryptoLibByteArray;
-
-    procedure NextBytes(buf: TCryptoLibByteArray); overload;
-    procedure NextBytes(buf: TCryptoLibByteArray; off, len: Int32); overload;
-
     property IsExhausted: Boolean read GetIsExhausted;
 
   end;
 
   IRandomChecker = interface(ISecureRandom)
     ['{EFC0D597-00E4-4DAE-8529-E14C9FE50B41}']
-    procedure NextBytes(bytes: TCryptoLibByteArray);
   end;
 
   ISource = interface(IInterface)

+ 1 - 1
CryptoLib/src/Asn1/ClpAsn1Set.pas

@@ -450,7 +450,7 @@ begin
           else
           begin
             temp := F_set[index];
-            // review being picky for copy
+            // Review being picky for copy
             // temp := System.Copy(F_set.List, Index, 1)[0];
             F_set[index] := F_set[index + 1];
             F_set[index + 1] := temp;

+ 0 - 8
CryptoLib/src/Asn1/ClpDerGeneralString.pas

@@ -81,11 +81,7 @@ end;
 
 function TDerGeneralString.GetOctets: TCryptoLibByteArray;
 begin
-{$IFDEF FPC}
   result := TEncoding.ASCII.GetBytes(UnicodeString(Str));
-{$ELSE}
-  result := TEncoding.ASCII.GetBytes(Str);
-{$ENDIF FPC}
 end;
 
 function TDerGeneralString.Asn1Equals(const asn1Object: IAsn1Object): Boolean;
@@ -104,11 +100,7 @@ end;
 
 constructor TDerGeneralString.Create(Str: TCryptoLibByteArray);
 begin
-{$IFDEF FPC}
   Create(String(TEncoding.ASCII.GetString(Str)));
-{$ELSE}
-  Create(TEncoding.ASCII.GetString(Str));
-{$ENDIF FPC}
 end;
 
 constructor TDerGeneralString.Create(const Str: String);

+ 1 - 5
CryptoLib/src/Asn1/ClpDerGraphicString.pas

@@ -192,11 +192,7 @@ end;
 
 function TDerGraphicString.GetString: String;
 begin
-{$IFDEF FPC}
-  result := String(TEncoding.ASCII.GetString(mString)); // encoding.default
-{$ELSE}
-  result := TEncoding.ASCII.GetString(mString); // encoding.default
-{$ENDIF FPC}
+  result := String(TEncoding.ASCII.GetString(mString));
 end;
 
 end.

+ 0 - 8
CryptoLib/src/Asn1/ClpDerIA5String.pas

@@ -140,11 +140,7 @@ end;
 
 function TDerIA5String.GetOctets: TCryptoLibByteArray;
 begin
-{$IFDEF FPC}
   result := TEncoding.ASCII.GetBytes(UnicodeString(Str));
-{$ELSE}
-  result := TEncoding.ASCII.GetBytes(Str);
-{$ENDIF FPC}
 end;
 
 class function TDerIA5String.IsIA5String(const Str: String): Boolean;
@@ -184,11 +180,7 @@ end;
 
 constructor TDerIA5String.Create(Str: TCryptoLibByteArray);
 begin
-{$IFDEF FPC}
   Create(String(TEncoding.ASCII.GetString(Str)), false);
-{$ELSE}
-  Create(TEncoding.ASCII.GetString(Str), false);
-{$ENDIF FPC}
 end;
 
 constructor TDerIA5String.Create(const Str: String);

+ 1 - 2
CryptoLib/src/Asn1/ClpDerInteger.pas

@@ -73,8 +73,7 @@ type
     // * @exception ArgumentException if the object cannot be converted.
     // */
 
-    class function GetInstance(obj: TObject): IDerInteger; overload;
-      static; inline;
+    class function GetInstance(obj: TObject): IDerInteger; overload; static;
 
     // /**
     // * return an Integer from a tagged object.

+ 0 - 8
CryptoLib/src/Asn1/ClpDerNumericString.pas

@@ -142,11 +142,7 @@ end;
 
 function TDerNumericString.GetOctets: TCryptoLibByteArray;
 begin
-{$IFDEF FPC}
   result := TEncoding.ASCII.GetBytes(UnicodeString(Str));
-{$ELSE}
-  result := TEncoding.ASCII.GetBytes(Str);
-{$ENDIF FPC}
 end;
 
 class function TDerNumericString.IsNumericString(const Str: String): Boolean;
@@ -183,11 +179,7 @@ end;
 
 constructor TDerNumericString.Create(Str: TCryptoLibByteArray);
 begin
-{$IFDEF FPC}
   Create(String(TEncoding.ASCII.GetString(Str)), false);
-{$ELSE}
-  Create(TEncoding.ASCII.GetString(Str), false);
-{$ENDIF FPC}
 end;
 
 constructor TDerNumericString.Create(const Str: String);

+ 2 - 3
CryptoLib/src/Asn1/ClpDerOctetString.pas

@@ -40,9 +40,8 @@ type
     destructor Destroy(); override;
 
     procedure Encode(const derOut: IDerOutputStream); overload; override;
-    class procedure Encode(derOut: TDerOutputStream;
-      bytes: TCryptoLibByteArray; offset, length: Int32); reintroduce; overload;
-      static; inline;
+    class procedure Encode(derOut: TDerOutputStream; bytes: TCryptoLibByteArray;
+      offset, length: Int32); reintroduce; overload; static; inline;
 
   end;
 

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

@@ -137,6 +137,11 @@ implementation
 
 { TDerPrintableString }
 
+function TDerPrintableString.GetStr: String;
+begin
+  result := FStr;
+end;
+
 function TDerPrintableString.GetString: String;
 begin
   result := Str;
@@ -144,11 +149,7 @@ end;
 
 function TDerPrintableString.GetOctets: TCryptoLibByteArray;
 begin
-{$IFDEF FPC}
   result := TEncoding.ASCII.GetBytes(UnicodeString(Str));
-{$ELSE}
-  result := TEncoding.ASCII.GetBytes(Str);
-{$ENDIF FPC}
 end;
 
 class function TDerPrintableString.IsPrintableString(const Str: String)
@@ -171,8 +172,8 @@ begin
       continue;
     end;
 
-    case IndexStr({$IFDEF FPC}UnicodeString{$ENDIF FPC}(ch), [''' ''', '\', '(', ')', '+', '-', '.', ':', '=', '?',
-      '/', ',']) of
+    case IndexStr(UnicodeString(ch), [''' ''', '\', '(', ')', '+', '-', '.',
+      ':', '=', '?', '/', ',']) of
       0 .. 11:
         begin
           continue;
@@ -202,11 +203,7 @@ end;
 
 constructor TDerPrintableString.Create(Str: TCryptoLibByteArray);
 begin
-{$IFDEF FPC}
   Create(String(TEncoding.ASCII.GetString(Str)), false);
-{$ELSE}
-  Create(TEncoding.ASCII.GetString(Str), false);
-{$ENDIF FPC}
 end;
 
 constructor TDerPrintableString.Create(const Str: String);
@@ -264,9 +261,4 @@ begin
     (TAsn1OctetString.GetInstance(o as TAsn1Object).GetOctets());
 end;
 
-function TDerPrintableString.GetStr: String;
-begin
-  result := FStr;
-end;
-
 end.

+ 0 - 8
CryptoLib/src/Asn1/ClpDerT61String.pas

@@ -113,11 +113,7 @@ end;
 
 function TDerT61String.GetOctets: TCryptoLibByteArray;
 begin
-{$IFDEF FPC}
   result := TEncoding.ASCII.GetBytes(UnicodeString(Str));
-{$ELSE}
-  result := TEncoding.ASCII.GetBytes(Str);
-{$ENDIF FPC}
 end;
 
 function TDerT61String.Asn1Equals(const asn1Object: IAsn1Object): Boolean;
@@ -136,11 +132,7 @@ end;
 
 constructor TDerT61String.Create(Str: TCryptoLibByteArray);
 begin
-{$IFDEF FPC}
   Create(String(TEncoding.ASCII.GetString(Str)));
-{$ELSE}
-  Create(TEncoding.ASCII.GetString(Str));
-{$ENDIF FPC}
 end;
 
 constructor TDerT61String.Create(const Str: String);

+ 0 - 12
CryptoLib/src/Asn1/ClpDerUtf8String.pas

@@ -113,11 +113,7 @@ end;
 
 function TDerUtf8String.GetOctets: TCryptoLibByteArray;
 begin
-{$IFDEF FPC}
   result := TEncoding.ASCII.GetBytes(UnicodeString(Str));
-{$ELSE}
-  result := TEncoding.ASCII.GetBytes(Str);
-{$ENDIF FPC}
 end;
 
 function TDerUtf8String.Asn1Equals(const asn1Object: IAsn1Object): Boolean;
@@ -136,11 +132,7 @@ end;
 
 constructor TDerUtf8String.Create(Str: TCryptoLibByteArray);
 begin
-{$IFDEF FPC}
   Create(String(TEncoding.UTF8.GetString(Str)));
-{$ELSE}
-  Create(TEncoding.UTF8.GetString(Str));
-{$ENDIF FPC}
 end;
 
 constructor TDerUtf8String.Create(const Str: String);
@@ -156,12 +148,8 @@ end;
 
 procedure TDerUtf8String.Encode(const derOut: IDerOutputStream);
 begin
-{$IFDEF FPC}
   derOut.WriteEncoded(TAsn1Tags.Utf8String,
     TEncoding.UTF8.GetBytes(UnicodeString(Str)));
-{$ELSE}
-  derOut.WriteEncoded(TAsn1Tags.Utf8String, TEncoding.UTF8.GetBytes(Str));
-{$ENDIF FPC}
 end;
 
 class function TDerUtf8String.GetInstance(obj: TObject): IDerUtf8String;

+ 1 - 5
CryptoLib/src/Asn1/ClpDerVideotexString.pas

@@ -192,11 +192,7 @@ end;
 
 function TDerVideotexString.GetString: String;
 begin
-{$IFDEF FPC}
-  result := String(TEncoding.ASCII.GetString(mString)); // encoding.default
-{$ELSE}
-  result := TEncoding.ASCII.GetString(mString); // encoding.default
-{$ENDIF FPC}
+  result := String(TEncoding.ASCII.GetString(mString));
 end;
 
 end.

+ 0 - 8
CryptoLib/src/Asn1/ClpDerVisibleString.pas

@@ -115,11 +115,7 @@ end;
 
 function TDerVisibleString.GetOctets: TCryptoLibByteArray;
 begin
-{$IFDEF FPC}
   result := TEncoding.ASCII.GetBytes(UnicodeString(Str));
-{$ELSE}
-  result := TEncoding.ASCII.GetBytes(Str);
-{$ENDIF FPC}
 end;
 
 function TDerVisibleString.Asn1Equals(const asn1Object: IAsn1Object): Boolean;
@@ -143,11 +139,7 @@ end;
 
 constructor TDerVisibleString.Create(Str: TCryptoLibByteArray);
 begin
-{$IFDEF FPC}
   Create(String(TEncoding.ASCII.GetString(Str)));
-{$ELSE}
-  Create(TEncoding.ASCII.GetString(Str));
-{$ENDIF FPC}
 end;
 
 constructor TDerVisibleString.Create(const Str: String);

+ 69 - 15
CryptoLib/src/Asn1/Nist/ClpNistObjectIdentifiers.pas

@@ -32,18 +32,21 @@ type
 
     class var
 
-      FNistAlgorithm, FHashAlgs, FIdSha256, FIdSha384, FIdSha512, FIdSha224,
-      FIdSha512_224, FIdSha512_256, FIdSha3_224, FIdSha3_256, FIdSha3_384,
-      FIdSha3_512, FIdHMacWithSha3_224, FIdHMacWithSha3_256,
+      FNistAlgorithm, FHashAlgs, FSigAlgs, 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, FIdDsaWithSha2, FDsaWithSha224, FDsaWithSha256,
       FDsaWithSha384, FDsaWithSha512, FIdDsaWithSha3_224, FIdDsaWithSha3_256,
-      FIdDsaWithSha3_384, FIdDsaWithSha3_512: IDerObjectIdentifier;
+      FIdDsaWithSha3_384, FIdDsaWithSha3_512, FIdECDsaWithSha3_224,
+      FIdECDsaWithSha3_256, FIdECDsaWithSha3_384, FIdECDsaWithSha3_512
+      : IDerObjectIdentifier;
 
     class function GetNistAlgorithm: IDerObjectIdentifier; static; inline;
     class function GetHashAlgs: IDerObjectIdentifier; static; inline;
+    class function GetSigAlgs: IDerObjectIdentifier; static; inline;
 
     class function GetIdSha224: IDerObjectIdentifier; static; inline;
     class function GetIdSha256: IDerObjectIdentifier; static; inline;
@@ -87,6 +90,11 @@ type
     class function GetIdDsaWithSha3_384: IDerObjectIdentifier; static; inline;
     class function GetIdDsaWithSha3_512: IDerObjectIdentifier; static; inline;
 
+    class function GetIdECDsaWithSha3_224: IDerObjectIdentifier; static; inline;
+    class function GetIdECDsaWithSha3_256: IDerObjectIdentifier; static; inline;
+    class function GetIdECDsaWithSha3_384: IDerObjectIdentifier; static; inline;
+    class function GetIdECDsaWithSha3_512: IDerObjectIdentifier; static; inline;
+
     class constructor NistObjectIdentifiers();
 
   public
@@ -100,6 +108,7 @@ type
     //
     class property NistAlgorithm: IDerObjectIdentifier read GetNistAlgorithm;
     class property HashAlgs: IDerObjectIdentifier read GetHashAlgs;
+    class property SigAlgs: IDerObjectIdentifier read GetSigAlgs;
 
     class property IdSha256: IDerObjectIdentifier read GetIdSha256;
     class property IdSha384: IDerObjectIdentifier read GetIdSha384;
@@ -151,6 +160,15 @@ type
     class property IdDsaWithSha3_512: IDerObjectIdentifier
       read GetIdDsaWithSha3_512;
 
+    class property IdECDsaWithSha3_224: IDerObjectIdentifier
+      read GetIdECDsaWithSha3_224;
+    class property IdECDsaWithSha3_256: IDerObjectIdentifier
+      read GetIdECDsaWithSha3_256;
+    class property IdECDsaWithSha3_384: IDerObjectIdentifier
+      read GetIdECDsaWithSha3_384;
+    class property IdECDsaWithSha3_512: IDerObjectIdentifier
+      read GetIdECDsaWithSha3_512;
+
     class procedure Boot(); static;
 
   end;
@@ -352,11 +370,40 @@ begin
   result := FIdDsaWithSha3_512;
 end;
 
+class function TNistObjectIdentifiers.GetIdECDsaWithSha3_224
+  : IDerObjectIdentifier;
+begin
+  result := FIdECDsaWithSha3_224;
+end;
+
+class function TNistObjectIdentifiers.GetIdECDsaWithSha3_256
+  : IDerObjectIdentifier;
+begin
+  result := FIdECDsaWithSha3_256;
+end;
+
+class function TNistObjectIdentifiers.GetIdECDsaWithSha3_384
+  : IDerObjectIdentifier;
+begin
+  result := FIdECDsaWithSha3_384;
+end;
+
+class function TNistObjectIdentifiers.GetIdECDsaWithSha3_512
+  : IDerObjectIdentifier;
+begin
+  result := FIdECDsaWithSha3_512;
+end;
+
 class function TNistObjectIdentifiers.GetNistAlgorithm: IDerObjectIdentifier;
 begin
   result := FNistAlgorithm;
 end;
 
+class function TNistObjectIdentifiers.GetSigAlgs: IDerObjectIdentifier;
+begin
+  result := FSigAlgs;
+end;
+
 class constructor TNistObjectIdentifiers.NistObjectIdentifiers;
 begin
   TNistObjectIdentifiers.Boot;
@@ -401,17 +448,24 @@ begin
   //
   // signatures
   //
-  FIdDsaWithSha2 := TDerObjectIdentifier.Create(NistAlgorithm.id + '.3');
-
-  FDsaWithSha224 := TDerObjectIdentifier.Create(IdDsaWithSha2.id + '.1');
-  FDsaWithSha256 := TDerObjectIdentifier.Create(IdDsaWithSha2.id + '.2');
-  FDsaWithSha384 := TDerObjectIdentifier.Create(IdDsaWithSha2.id + '.3');
-  FDsaWithSha512 := TDerObjectIdentifier.Create(IdDsaWithSha2.id + '.4');
-
-  FIdDsaWithSha3_224 := TDerObjectIdentifier.Create(IdDsaWithSha2.id + '.5');
-  FIdDsaWithSha3_256 := TDerObjectIdentifier.Create(IdDsaWithSha2.id + '.6');
-  FIdDsaWithSha3_384 := TDerObjectIdentifier.Create(IdDsaWithSha2.id + '.7');
-  FIdDsaWithSha3_512 := TDerObjectIdentifier.Create(IdDsaWithSha2.id + '.8');
+  FSigAlgs := NistAlgorithm.Branch('3');
+  FIdDsaWithSha2 := SigAlgs;
+
+  FDsaWithSha224 := TDerObjectIdentifier.Create(SigAlgs.id + '.1');
+  FDsaWithSha256 := TDerObjectIdentifier.Create(SigAlgs.id + '.2');
+  FDsaWithSha384 := TDerObjectIdentifier.Create(SigAlgs.id + '.3');
+  FDsaWithSha512 := TDerObjectIdentifier.Create(SigAlgs.id + '.4');
+
+  FIdDsaWithSha3_224 := TDerObjectIdentifier.Create(SigAlgs.id + '.5');
+  FIdDsaWithSha3_256 := TDerObjectIdentifier.Create(SigAlgs.id + '.6');
+  FIdDsaWithSha3_384 := TDerObjectIdentifier.Create(SigAlgs.id + '.7');
+  FIdDsaWithSha3_512 := TDerObjectIdentifier.Create(SigAlgs.id + '.8');
+
+  // ECDSA with SHA-3
+  FIdECDsaWithSha3_224 := TDerObjectIdentifier.Create(SigAlgs.id + '.9');
+  FIdECDsaWithSha3_256 := TDerObjectIdentifier.Create(SigAlgs.id + '.10');
+  FIdECDsaWithSha3_384 := TDerObjectIdentifier.Create(SigAlgs.id + '.11');
+  FIdECDsaWithSha3_512 := TDerObjectIdentifier.Create(SigAlgs.id + '.12');
 
 end;
 

+ 142 - 0
CryptoLib/src/Asn1/X509/ClpDsaParameter.pas

@@ -0,0 +1,142 @@
+{ *********************************************************************************** }
+{ *                              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 ClpDsaParameter;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIDsaParameter,
+  ClpDerInteger,
+  ClpIDerInteger,
+  ClpDerSequence,
+  ClpIProxiedInterface,
+  ClpAsn1Sequence,
+  ClpIAsn1Sequence,
+  ClpIAsn1TaggedObject,
+  ClpBigInteger,
+  ClpAsn1Encodable,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SBadSequenceSize = 'Bad Sequence Size "seq": %d';
+  SInvalidDsaParameter = 'Invalid DsaParameter: %s';
+
+type
+  TDsaParameter = class(TAsn1Encodable, IDsaParameter)
+
+  strict private
+  var
+    Fp, Fq, Fg: IDerInteger;
+
+    function GetG: TBigInteger; inline;
+    function GetP: TBigInteger; inline;
+    function GetQ: TBigInteger; inline;
+
+    constructor Create(const seq: IAsn1Sequence); overload;
+
+  public
+    constructor Create(const p, q, g: TBigInteger); overload;
+
+    function ToAsn1Object(): IAsn1Object; override;
+
+    property p: TBigInteger read GetP;
+    property q: TBigInteger read GetQ;
+    property g: TBigInteger read GetG;
+
+    class function GetInstance(const obj: IAsn1TaggedObject;
+      explicitly: Boolean): IDsaParameter; overload; static; inline;
+
+    class function GetInstance(obj: TObject): IDsaParameter; overload;
+      static; inline;
+
+  end;
+
+implementation
+
+{ TDsaParameter }
+
+function TDsaParameter.GetP: TBigInteger;
+begin
+  result := Fp.PositiveValue;
+end;
+
+function TDsaParameter.GetQ: TBigInteger;
+begin
+  result := Fq.PositiveValue;
+end;
+
+function TDsaParameter.GetG: TBigInteger;
+begin
+  result := Fg.PositiveValue;
+end;
+
+function TDsaParameter.ToAsn1Object: IAsn1Object;
+begin
+  result := TDerSequence.Create([Fp, Fq, Fg]);
+end;
+
+constructor TDsaParameter.Create(const seq: IAsn1Sequence);
+begin
+  Inherited Create();
+  if (seq.Count <> 3) then
+  begin
+    raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize,
+      [seq.Count]);
+  end;
+
+  Fp := TDerInteger.GetInstance(seq[0] as TAsn1Encodable);
+  Fq := TDerInteger.GetInstance(seq[1] as TAsn1Encodable);
+  Fg := TDerInteger.GetInstance(seq[2] as TAsn1Encodable);
+end;
+
+constructor TDsaParameter.Create(const p, q, g: TBigInteger);
+begin
+  Inherited Create();
+  Fp := TDerInteger.Create(p);
+  Fq := TDerInteger.Create(q);
+  Fg := TDerInteger.Create(g);
+end;
+
+class function TDsaParameter.GetInstance(obj: TObject): IDsaParameter;
+begin
+  if ((obj = Nil) or (obj is TDsaParameter)) then
+  begin
+    result := obj as TDsaParameter;
+    Exit;
+  end;
+
+  if (obj is TAsn1Sequence) then
+  begin
+    result := TDsaParameter.Create(obj as TAsn1Sequence);
+    Exit;
+  end;
+
+  raise EArgumentCryptoLibException.CreateResFmt(@SInvalidDsaParameter,
+    [obj.ToString]);
+end;
+
+class function TDsaParameter.GetInstance(const obj: IAsn1TaggedObject;
+  explicitly: Boolean): IDsaParameter;
+begin
+  result := GetInstance(TAsn1Sequence.GetInstance(obj, explicitly)
+    as TAsn1Sequence);
+end;
+
+end.

+ 2 - 2
CryptoLib/src/Asn1/X9/ClpECNamedCurveTable.pas

@@ -26,9 +26,9 @@ uses
   ClpCryptoLibTypes,
   // ClpX962NamedCurves,
   // ClpECGost3410NamedCurves,
- // ClpX9ECParameters,
+  // ClpX9ECParameters,
   ClpSecNamedCurves,
- // ClpIECDomainParameters,
+  // ClpIECDomainParameters,
   ClpIDerObjectIdentifier,
   ClpIX9ECParameters;
 

+ 48 - 36
CryptoLib/src/Asn1/X9/ClpX9Curve.pas

@@ -35,6 +35,7 @@ uses
   ClpIX9FieldElement,
   ClpIAsn1OctetString,
   ClpECAlgorithms,
+  ClpAsn1OctetString,
   ClpAsn1EncodableVector,
   ClpIAsn1EncodableVector,
   ClpX9ObjectIdentifiers,
@@ -71,8 +72,11 @@ type
     constructor Create(const curve: IECCurve); overload;
     constructor Create(const curve: IECCurve;
       seed: TCryptoLibByteArray); overload;
+    constructor Create(const fieldID: IX9FieldID; const seq: IAsn1Sequence);
+      overload; deprecated 'Use constructor including order/cofactor';
+
     constructor Create(const fieldID: IX9FieldID;
-      const seq: IAsn1Sequence); overload;
+      const order, cofactor: TBigInteger; const seq: IAsn1Sequence); overload;
 
     function GetSeed(): TCryptoLibByteArray; inline;
 
@@ -131,9 +135,14 @@ end;
 
 constructor TX9Curve.Create(const fieldID: IX9FieldID;
   const seq: IAsn1Sequence);
+begin
+  Create(fieldID, Default (TBigInteger), Default (TBigInteger), seq);
+end;
+
+constructor TX9Curve.Create(const fieldID: IX9FieldID;
+  const order, cofactor: TBigInteger; const seq: IAsn1Sequence);
 var
-  q: TBigInteger;
-  x9A, x9B: IX9FieldElement;
+  p, A, B: TBigInteger;
   parameters: IDerSequence;
   representation: IDerObjectIdentifier;
   pentanomial: IDerSequence;
@@ -153,43 +162,46 @@ begin
 
   if (FfieldIdentifier.Equals(TX9ObjectIdentifiers.PrimeField)) then
   begin
-    q := (fieldID.parameters as IDerInteger).Value;
-    x9A := TX9FieldElement.Create(q, seq[0] as IAsn1OctetString);
-    x9B := TX9FieldElement.Create(q, seq[1] as IAsn1OctetString);
-    Fcurve := TFpCurve.Create(q, x9A.Value.ToBigInteger(),
-      x9B.Value.ToBigInteger());
+    p := (fieldID.parameters as IDerInteger).Value;
+    A := TBigInteger.Create(1,
+      TAsn1OctetString.GetInstance(seq[0] as TAsn1Encodable).GetOctets());
+    B := TBigInteger.Create(1,
+      TAsn1OctetString.GetInstance(seq[1] as TAsn1Encodable).GetOctets());
+    Fcurve := TFpCurve.Create(p, A, B, order, cofactor);
   end
-  else
+  else if (FfieldIdentifier.Equals(TX9ObjectIdentifiers.CharacteristicTwoField))
+  then
   begin
-    if (FfieldIdentifier.Equals(TX9ObjectIdentifiers.CharacteristicTwoField))
-    then
+    // Characteristic two field
+    parameters := fieldID.parameters as IDerSequence;
+    m := (parameters[0] as IDerInteger).Value.Int32Value;
+    representation := parameters[1] as IDerObjectIdentifier;
+
+    k2 := 0;
+    k3 := 0;
+    if (representation.Equals(TX9ObjectIdentifiers.TPBasis)) then
     begin
-      // Characteristic two field
-      parameters := fieldID.parameters as IDerSequence;
-      m := (parameters[0] as IDerInteger).Value.Int32Value;
-      representation := parameters[1] as IDerObjectIdentifier;
-
-      k2 := 0;
-      k3 := 0;
-      if (representation.Equals(TX9ObjectIdentifiers.TPBasis)) then
-      begin
-        // Trinomial basis representation
-        k1 := (parameters[2] as IDerInteger).Value.Int32Value;
-      end
-      else
-      begin
-        // Pentanomial basis representation
-        pentanomial := parameters[2] as IDerSequence;
-        k1 := (pentanomial[0] as IDerInteger).Value.Int32Value;
-        k2 := (pentanomial[1] as IDerInteger).Value.Int32Value;
-        k3 := (pentanomial[2] as IDerInteger).Value.Int32Value;
-      end;
-      x9A := TX9FieldElement.Create(m, k1, k2, k3, seq[0] as IAsn1OctetString);
-      x9B := TX9FieldElement.Create(m, k1, k2, k3, seq[1] as IAsn1OctetString);
-      // TODO Is it possible to get the order (n) and cofactor(h) too?
-      Fcurve := TF2mCurve.Create(m, k1, k2, k3, x9A.Value.ToBigInteger(),
-        x9B.Value.ToBigInteger());
+      // Trinomial basis representation
+      k1 := (parameters[2] as IDerInteger).Value.Int32Value;
+    end
+    else
+    begin
+      // Pentanomial basis representation
+      pentanomial := parameters[2] as IDerSequence;
+      k1 := (pentanomial[0] as IDerInteger).Value.Int32Value;
+      k2 := (pentanomial[1] as IDerInteger).Value.Int32Value;
+      k3 := (pentanomial[2] as IDerInteger).Value.Int32Value;
     end;
+    A := TBigInteger.Create(1,
+      TAsn1OctetString.GetInstance(seq[0] as TAsn1Encodable).GetOctets());
+    B := TBigInteger.Create(1,
+      TAsn1OctetString.GetInstance(seq[1] as TAsn1Encodable).GetOctets());
+
+    Fcurve := TF2mCurve.Create(m, k1, k2, k3, A, B, order, cofactor);
+  end
+  else
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SNotImplementedECCurve);
   end;
 
   if (seq.Count = 3) then

+ 9 - 9
CryptoLib/src/Asn1/X9/ClpX9ECParameters.pas

@@ -158,8 +158,15 @@ begin
     raise EArgumentCryptoLibException.CreateRes(@SBadVersion);
   end;
 
-  x9c := TX9Curve.Create(TX9FieldID.GetInstance(seq[1] as TAsn1Sequence),
-    TAsn1Sequence.GetInstance(seq[2] as TAsn1Sequence));
+  Fn := (seq[4] as IDerInteger).Value;
+
+  if (seq.Count = 6) then
+  begin
+    Fh := (seq[5] as IDerInteger).Value;
+  end;
+
+  x9c := TX9Curve.Create(TX9FieldID.GetInstance(seq[1] as TAsn1Sequence), Fn,
+    Fh, TAsn1Sequence.GetInstance(seq[2] as TAsn1Sequence));
 
   Fcurve := x9c.curve;
   p := seq[3] as TAsn1Sequence;
@@ -174,14 +181,7 @@ begin
     Fg := TX9ECPoint.Create(curve, p as TAsn1OctetString);
   end;
 
-  Fn := (seq[4] as IDerInteger).Value;
   Fseed := x9c.GetSeed();
-
-  if (seq.Count = 6) then
-  begin
-
-    Fh := (seq[5] as IDerInteger).Value;
-  end;
 end;
 
 constructor TX9ECParameters.Create(const curve: IECCurve; const g: IX9ECPoint;

+ 6 - 5
CryptoLib/src/Asn1/X9/ClpX9FieldElement.pas

@@ -48,10 +48,10 @@ type
 
   public
     constructor Create(const f: IECFieldElement); overload;
-    constructor Create(const p: TBigInteger;
-      const s: IAsn1OctetString); overload;
-    constructor Create(m, k1, k2, k3: Int32;
-      const s: IAsn1OctetString); overload;
+    constructor Create(const p: TBigInteger; const s: IAsn1OctetString);
+      overload; deprecated 'Will be removed';
+    constructor Create(m, k1, k2, k3: Int32; const s: IAsn1OctetString);
+      overload; deprecated 'Will be removed';
 
     // /**
     // * Produce an object suitable for an Asn1OutputStream.
@@ -83,7 +83,8 @@ implementation
 constructor TX9FieldElement.Create(const p: TBigInteger;
   const s: IAsn1OctetString);
 begin
-  Create(TFpFieldElement.Create(p, TBigInteger.Create(1, s.GetOctets())))
+  Create(TFpFieldElement.Create(p, TBigInteger.Create(1, s.GetOctets()))
+    as IFpFieldElement)
 end;
 
 constructor TX9FieldElement.Create(const f: IECFieldElement);

+ 1 - 1
CryptoLib/src/Asn1/X9/ClpX9FieldID.pas

@@ -133,7 +133,7 @@ end;
 constructor TX9FieldID.Create(const seq: IAsn1Sequence);
 begin
   Inherited Create();
-  Fid := TDerObjectIdentifier.GetInstance(seq[0] as TAsn1Sequence);
+  Fid := TDerObjectIdentifier.GetInstance(seq[0] as TAsn1Encodable);
   Fparameters := seq[1].ToAsn1Object();
 end;
 

+ 21 - 6
CryptoLib/src/Crypto/Agreement/ClpECDHBasicAgreement.pas

@@ -24,7 +24,9 @@ interface
 uses
   SysUtils,
   ClpBigInteger,
+  ClpECAlgorithms,
   ClpICipherParameters,
+  ClpIECDomainParameters,
   ClpIECInterface,
   ClpIBasicAgreement,
   ClpIECDHBasicAgreement,
@@ -86,25 +88,38 @@ function TECDHBasicAgreement.CalculateAgreement(const pubKey: ICipherParameters)
   : TBigInteger;
 var
   pub: IECPublicKeyParameters;
-  P, pubPoint: IECPoint;
+  params: IECDomainParameters;
+  P, Q: IECPoint;
+  d, h: TBigInteger;
 begin
   pub := pubKey as IECPublicKeyParameters;
-  if (not(pub.parameters.Equals(FprivKey.parameters))) then
+  params := FprivKey.parameters;
+  if (not(params.Equals(pub.parameters))) then
   begin
     raise EInvalidOperationCryptoLibException.CreateRes(@SWrongDomainParameter);
 
   end;
+
+  d := FprivKey.d;
   // Always perform calculations on the exact curve specified by our private key's parameters
 
-  pubPoint := FprivKey.parameters.Curve.decodePoint(pub.Q.GetEncoded(False));
-  if (pubPoint.IsInfinity) then
+  Q := TECAlgorithms.CleanPoint(params.Curve, pub.Q);
+
+  if (Q.IsInfinity) then
   begin
     raise EInvalidOperationCryptoLibException.CreateRes
       (@SInfinityInvalidPublicKey);
   end;
 
-  // P := pub.Q.Multiply(FprivKey.D).Normalize();
-  P := pubPoint.Multiply(FprivKey.D).Normalize();
+  h := params.h;
+
+  if (not(h.Equals(TBigInteger.One))) then
+  begin
+    d := params.HInv.Multiply(d).&Mod(params.N);
+    Q := TECAlgorithms.ReferenceMultiply(Q, h);
+  end;
+
+  P := Q.Multiply(d).Normalize();
 
   if (P.IsInfinity) then
   begin

+ 16 - 6
CryptoLib/src/Crypto/Agreement/ClpECDHCBasicAgreement.pas

@@ -24,6 +24,7 @@ interface
 uses
   SysUtils,
   ClpBigInteger,
+  ClpECAlgorithms,
   ClpICipherParameters,
   ClpIECInterface,
   ClpIBasicAgreement,
@@ -37,6 +38,7 @@ uses
 resourcestring
   SWrongDomainParameter = 'ECDHC Public Key has Wrong Domain Parameters';
   SInvalidAgreementValue = 'Infinity is not a Valid Agreement Value for ECDHC';
+  SInfinityInvalidPublicKey = 'Infinity is not a Valid Public Key for ECDHC';
 
 type
   /// <summary>
@@ -91,21 +93,29 @@ function TECDHCBasicAgreement.CalculateAgreement(const pubKey
   : ICipherParameters): TBigInteger;
 var
   pub: IECPublicKeyParameters;
-  parameters: IECDomainParameters;
+  params: IECDomainParameters;
   hd: TBigInteger;
-  P: IECPoint;
+  P, pubPoint: IECPoint;
 begin
   pub := pubKey as IECPublicKeyParameters;
-  parameters := pub.parameters;
-  if (not(parameters.Equals(FprivKey.parameters))) then
+  params := FprivKey.parameters;
+  if (not(params.Equals(pub.parameters))) then
   begin
     raise EInvalidOperationCryptoLibException.CreateRes(@SWrongDomainParameter);
 
   end;
 
-  hd := parameters.H.Multiply(FprivKey.D).&Mod(parameters.N);
+  hd := params.H.Multiply(FprivKey.D).&Mod(params.N);
 
-  P := pub.Q.Multiply(hd).Normalize();
+  // Always perform calculations on the exact curve specified by our private key's parameters
+  pubPoint := TECAlgorithms.CleanPoint(params.Curve, pub.Q);
+  if (pubPoint.IsInfinity) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes
+      (@SInfinityInvalidPublicKey);
+  end;
+
+  P := pubPoint.Multiply(hd).Normalize();
 
   if (P.IsInfinity) then
   begin

+ 7 - 20
CryptoLib/src/Crypto/ClpEphemeralKeyPair.pas

@@ -24,29 +24,25 @@ interface
 uses
   ClpIEphemeralKeyPair,
   ClpIAsymmetricCipherKeyPair,
-  ClpKeyEncoder,
+  ClpIKeyEncoder,
   ClpCryptoLibTypes;
 
-resourcestring
-  SParameterFunctionCannotBeNil = 'Parameter Function Cannot be Nil.';
-
 type
   TEphemeralKeyPair = class sealed(TInterfacedObject, IEphemeralKeyPair)
 
   strict private
 
     FkeyPair: IAsymmetricCipherKeyPair;
-    FUsePointCompression: Boolean;
-    FpublicKeyEncoder: TKeyEncoder;
+    FpublicKeyEncoder: IKeyEncoder;
 
   public
 
     function getKeyPair(): IAsymmetricCipherKeyPair; inline;
 
-    function getEncodedPublicKey(): TCryptoLibByteArray; inline;
+    function GetEncodedPublicKey: TCryptoLibByteArray; inline;
 
     constructor Create(const keyPair: IAsymmetricCipherKeyPair;
-      usePointCompression: Boolean; const publicKeyEncoder: TKeyEncoder);
+      const publicKeyEncoder: IKeyEncoder);
 
   end;
 
@@ -55,25 +51,16 @@ implementation
 { TEphemeralKeyPair }
 
 constructor TEphemeralKeyPair.Create(const keyPair: IAsymmetricCipherKeyPair;
-  usePointCompression: Boolean; const publicKeyEncoder: TKeyEncoder);
+  const publicKeyEncoder: IKeyEncoder);
 begin
   Inherited Create();
   FkeyPair := keyPair;
-  FUsePointCompression := usePointCompression;
   FpublicKeyEncoder := publicKeyEncoder;
 end;
 
-function TEphemeralKeyPair.getEncodedPublicKey: TCryptoLibByteArray;
+function TEphemeralKeyPair.GetEncodedPublicKey: TCryptoLibByteArray;
 begin
-  if Assigned(FpublicKeyEncoder) then
-  begin
-    result := FpublicKeyEncoder(FkeyPair.Public, FUsePointCompression);
-  end
-  else
-  begin
-    raise EArgumentNilCryptoLibException.CreateRes
-      (@SParameterFunctionCannotBeNil);
-  end;
+  result := FpublicKeyEncoder.GetEncoded(FkeyPair.Public);
 end;
 
 function TEphemeralKeyPair.getKeyPair: IAsymmetricCipherKeyPair;

+ 56 - 36
CryptoLib/src/Crypto/ClpIESCipher.pas

@@ -41,8 +41,9 @@ uses
   ClpEphemeralKeyPairGenerator,
   ClpIEphemeralKeyPairGenerator,
   ClpParametersWithIV,
-  ClpIECPublicKeyParameters,
   ClpIIESCipher,
+  ClpKeyEncoder,
+  ClpIKeyEncoder,
   ClpISecureRandom,
   ClpSecureRandom,
   ClpCryptoLibTypes;
@@ -52,29 +53,30 @@ resourcestring
     'Must be Passed Recipient''s Public EC Key for Encryption';
   SInvalidPrivateKey =
     'Must be Passed Recipient''s Private EC Key for Decryption';
-  SIESWithCipherParametersCannotBeNil = 'IESWithCipherParameters Cannot Be Nil';
+  SIESCipherParameterNil = 'IES Cipher Parameters Cannot Be Nil';
   SUnableToProcessBlock = 'Unable to Process Block. "%s"';
+  SIESCipherParameterError = 'IES Cipher Parameter Error';
+  SNonceInvalidLength = 'NONCE in IES Parameters Needs to be "%s" Bytes Long';
 
 type
   TIESCipher = class sealed(TInterfacedObject, IIESCipher)
 
   strict private
   var
+    FivLength: Int32;
     FEngine: IIESEngine;
     FForEncryption: Boolean;
     FBuffer: TMemoryStream;
-    FIESWithCipherParameters: IIESWithCipherParameters;
+    FIESCipherParameters: IIESWithCipherParameters;
     Fkey: IAsymmetricKeyParameter;
     FRandom: ISecureRandom;
 
     function Aggregate: TCryptoLibByteArray; inline;
 
-    function KeyEncoder(const keyParameter: IAsymmetricKeyParameter;
-      UsePointCompression: Boolean): TCryptoLibByteArray; inline;
-
   public
     procedure Init(ForEncryption: Boolean; const Key: ICipherParameters;
-      const params: IIESWithCipherParameters; const Random: ISecureRandom);
+      const IESCipherParameters: IIESWithCipherParameters;
+      const Random: ISecureRandom);
 
     procedure ProcessBytes(input: TCryptoLibByteArray); overload;
     procedure ProcessBytes(input: TCryptoLibByteArray;
@@ -88,7 +90,8 @@ type
     function DoFinal(input: TCryptoLibByteArray; inputOffset, inputLen: Int32;
       output: TCryptoLibByteArray; outputOffset: Int32): Int32; overload;
 
-    constructor Create(const Engine: IIESEngine);
+    constructor Create(const Engine: IIESEngine); overload;
+    constructor Create(const Engine: IIESEngine; ivLength: Int32); overload;
     destructor Destroy(); override;
 
   end;
@@ -97,13 +100,6 @@ implementation
 
 { TIESCipher }
 
-function TIESCipher.KeyEncoder(const keyParameter: IAsymmetricKeyParameter;
-  UsePointCompression: Boolean): TCryptoLibByteArray;
-begin
-  Result := (keyParameter as IECPublicKeyParameters)
-    .Q.GetEncoded(UsePointCompression);
-end;
-
 function TIESCipher.Aggregate: TCryptoLibByteArray;
 begin
   FBuffer.Position := 0;
@@ -112,9 +108,15 @@ begin
 end;
 
 constructor TIESCipher.Create(const Engine: IIESEngine);
+begin
+  Create(Engine, 0);
+end;
+
+constructor TIESCipher.Create(const Engine: IIESEngine; ivLength: Int32);
 begin
   Inherited Create();
   FEngine := Engine;
+  FivLength := ivLength;
   FBuffer := TMemoryStream.Create();
 end;
 
@@ -137,16 +139,14 @@ begin
   FBuffer.Clear;
   FBuffer.SetSize(0);
 
-  // Copy parameters for use in IESEngine
-  params := TIESWithCipherParameters.Create
-    (FIESWithCipherParameters.GetDerivationV,
-    FIESWithCipherParameters.GetEncodingV, FIESWithCipherParameters.Nonce,
-    FIESWithCipherParameters.MacKeySize, FIESWithCipherParameters.CipherKeySize,
-    FIESWithCipherParameters.PointCompression);
+  // Convert parameters for use in IESEngine
+  params := TIESWithCipherParameters.Create(FIESCipherParameters.GetDerivationV,
+    FIESCipherParameters.GetEncodingV, FIESCipherParameters.MacKeySize,
+    FIESCipherParameters.CipherKeySize);
 
-  if (FIESWithCipherParameters.Nonce <> Nil) then
+  if (FIESCipherParameters.Nonce <> Nil) then
   begin
-    params := TParametersWithIV.Create(params, FIESWithCipherParameters.Nonce);
+    params := TParametersWithIV.Create(params, FIESCipherParameters.Nonce);
   end;
   ecParams := (Fkey as IECKeyParameters).Parameters;
 
@@ -157,10 +157,10 @@ begin
     gen.Init(TECKeyGenerationParameters.Create(ecParams, FRandom)
       as IECKeyGenerationParameters);
 
-    UsePointCompression := FIESWithCipherParameters.PointCompression;
+    UsePointCompression := FIESCipherParameters.PointCompression;
 
-    kGen := TEphemeralKeyPairGenerator.Create(gen, UsePointCompression,
-      KeyEncoder);
+    kGen := TEphemeralKeyPairGenerator.Create(gen,
+      TKeyEncoder.Create(UsePointCompression) as IKeyEncoder);
 
     // Encrypt the buffer
 
@@ -222,12 +222,40 @@ begin
 end;
 
 procedure TIESCipher.Init(ForEncryption: Boolean; const Key: ICipherParameters;
-  const params: IIESWithCipherParameters; const Random: ISecureRandom);
+  const IESCipherParameters: IIESWithCipherParameters;
+  const Random: ISecureRandom);
 var
   LKey: ICipherParameters;
+  Nonce: TCryptoLibByteArray;
 begin
+
   FForEncryption := ForEncryption;
+
+  if (IESCipherParameters = Nil) then
+  begin
+    raise EArgumentNilCryptoLibException.CreateRes(@SIESCipherParameterNil);
+  end
+  else if (Supports(IESCipherParameters, IIESWithCipherParameters)) then
+  begin
+    FIESCipherParameters := IESCipherParameters as IIESWithCipherParameters;
+  end
+  else
+  begin
+    raise EInvalidParameterCryptoLibException.CreateRes
+      (@SIESCipherParameterError);
+  end;
+
+  Nonce := FIESCipherParameters.Nonce;
+
+  if ((FivLength <> 0) and ((Nonce = Nil) or (System.length(Nonce) <>
+    FivLength))) then
+  begin
+    raise EInvalidParameterCryptoLibException.CreateResFmt(@SNonceInvalidLength,
+      [FivLength]);
+  end;
+
   LKey := Key;
+
   // Parse the recipient's key
   if ForEncryption then
   begin
@@ -252,15 +280,7 @@ begin
     end;
 
   end;
-  if params = Nil then
-  begin
-    raise EArgumentNilCryptoLibException.CreateRes
-      (@SIESWithCipherParametersCannotBeNil);
-  end
-  else
-  begin
-    FIESWithCipherParameters := params;
-  end;
+
   FRandom := Random;
   FBuffer.Clear;
   FBuffer.SetSize(0);

+ 29 - 2
CryptoLib/src/Crypto/ClpKeyEncoder.pas

@@ -23,12 +23,39 @@ interface
 
 uses
   ClpIAsymmetricKeyParameter,
+  ClpIECPublicKeyParameters,
+  ClpIKeyEncoder,
   ClpCryptoLibTypes;
 
 type
-  TKeyEncoder = function(const keyParameter: IAsymmetricKeyParameter;
-    UsePointCompression: Boolean): TCryptoLibByteArray of Object;
+  TKeyEncoder = class(TInterfacedObject, IKeyEncoder)
+
+  strict private
+  var
+    FUsePointCompression: Boolean;
+
+  public
+    constructor Create(usePointCompression: Boolean);
+    function GetEncoded(const keyParameter: IAsymmetricKeyParameter)
+      : TCryptoLibByteArray;
+
+  end;
 
 implementation
 
+{ TKeyEncoder }
+
+constructor TKeyEncoder.Create(usePointCompression: Boolean);
+begin
+  Inherited Create();
+  FUsePointCompression := usePointCompression;
+end;
+
+function TKeyEncoder.GetEncoded(const keyParameter: IAsymmetricKeyParameter)
+  : TCryptoLibByteArray;
+begin
+  Result := (keyParameter as IECPublicKeyParameters)
+    .Q.GetEncoded(FUsePointCompression);
+end;
+
 end.

+ 1 - 1
CryptoLib/src/Crypto/Engines/ClpIESEngine.pas

@@ -52,7 +52,7 @@ resourcestring
   SErrorRecoveringEphemeralPublicKey =
     'Unable to Recover Ephemeral Public Key: "%s"';
   SInvalidCipherTextLength =
-    'Length of Input Must be Greater than the MAC and V combined';
+    'Length of Input Must be Greater than the MAC and V Combined';
   SInvalidMAC = 'Invalid MAC';
 
 type

+ 1 - 1
CryptoLib/src/Crypto/Engines/ClpPascalCoinIESEngine.pas

@@ -46,7 +46,7 @@ resourcestring
   SErrorRecoveringEphemeralPublicKey =
     'Unable to Recover Ephemeral Public Key: "%s"';
   SInvalidCipherTextLength =
-    'Length of Input Must be Greater than the MAC and V combined';
+    'Length of Input Must be Greater than the MAC and V Combined';
   SInvalidMAC = 'Invalid MAC';
   SCipherCannotbeNilInThisMode = 'Cipher Cannot be Nil in This Mode.';
 

+ 618 - 0
CryptoLib/src/Crypto/Generators/ClpDSAParametersGenerator.pas

@@ -0,0 +1,618 @@
+{ *********************************************************************************** }
+{ *                              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 ClpDsaParametersGenerator;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Math,
+  SysUtils,
+  HlpSHA1,
+  ClpIDigest,
+  ClpISecureRandom,
+  ClpDsaParameters,
+  ClpIDsaParameters,
+  ClpDsaValidationParameters,
+  ClpIDsaValidationParameters,
+  ClpIDsaParametersGenerator,
+  ClpIDsaParameterGenerationParameters,
+  ClpHex,
+  ClpDigestUtilities,
+  ClpBigInteger,
+  ClpBigIntegers,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SInvalidLValue =
+    'L Values Must be Between 1024 and 3072 and a Multiple of 1024';
+  SInvalidNValueForSpecifiedL = 'N Must be " %d " for L = " %d "';
+  SInvalidNValueForSpecifiedL_Two = 'N Must be " %d " or " %d " for L = " %d "';
+  SDigestOutputSizeTooSmallForN =
+    'Digest Output Size Too Small for Value of N Which is " %d "';
+  SUnsupportedDigest =
+    'Can Only Use SHA-1 For Generating FIPS 186-2 Parameters';
+  SInvalidDsaKeyStrength =
+    'Size Must Be From %d - %d and a multiple of %d, "%d"';
+
+type
+
+  /// <summary>
+  /// Generate suitable parameters for DSA, in line with FIPS 186-2, or FIPS
+  /// 186-3.
+  /// </summary>
+  TDsaParametersGenerator = class(TInterfacedObject, IDsaParametersGenerator)
+
+  strict private
+    Fdigest: IDigest;
+    FL, FN, Fcertainty, Fiterations, FusageIndex: Int32;
+    Frandom: ISecureRandom;
+    Fuse186_3: Boolean;
+
+    function IsProbablePrime(const x: TBigInteger): Boolean; inline;
+
+    function GenerateParameters_FIPS186_2(): IDsaParameters;
+
+    /// <summary>
+    /// generate suitable parameters for DSA, in line with <i>FIPS 186-3 A.1
+    /// Generation of the FFC Primes p and q</i>
+    /// </summary>
+    function GenerateParameters_FIPS186_3(): IDsaParameters;
+
+    class function IsValidDsaStrength(strength: Int32): Boolean; static; inline;
+
+    class function GetDefaultN(L: Int32): Int32; static; inline;
+    class function GetMinimumIterations(L: Int32): Int32; static; inline;
+    class procedure Hash(const d: IDigest; input, output: TCryptoLibByteArray;
+      outputPos: Int32); static; inline;
+
+    class procedure Inc(buf: TCryptoLibByteArray); static; inline;
+
+    class function CalculateGenerator_FIPS186_2(const p, q: TBigInteger;
+      const r: ISecureRandom): TBigInteger; static; inline;
+
+    class function CalculateGenerator_FIPS186_3_Unverifiable(const p,
+      q: TBigInteger; const r: ISecureRandom): TBigInteger; static; inline;
+
+    class function CalculateGenerator_FIPS186_3_Verifiable(const d: IDigest;
+      const p, q: TBigInteger; seed: TCryptoLibByteArray; index: Int32)
+      : TBigInteger; static; inline;
+
+  public
+    constructor Create(); overload;
+    constructor Create(const digest: IDigest); overload;
+
+    /// <summary>
+    /// initialise the key generator.
+    /// </summary>
+    /// <param name="size">
+    /// size of the key (range 2^512 -&amp;gt; 2^1024 - 64 bit increments)
+    /// </param>
+    /// <param name="certainty">
+    /// measure of robustness of prime (for FIPS 186-2 compliance this should
+    /// be at least 80).
+    /// </param>
+    /// <param name="random">
+    /// random byte source.
+    /// </param>
+    procedure Init(size, certainty: Int32;
+      const random: ISecureRandom); overload;
+
+    /// <summary>
+    /// initialise the key generator.
+    /// </summary>
+    /// <param name="size">
+    /// size of the key (range 2^512 -&amp;gt; 2^1024 - 64 bit increments)
+    /// </param>
+    /// <param name="certainty">
+    /// measure of robustness of prime (for FIPS 186-2 compliance this should
+    /// be at least 80).
+    /// </param>
+    /// <param name="iterations">
+    /// iterations
+    /// </param>
+    /// <param name="random">
+    /// random byte source.
+    /// </param>
+    procedure Init(size, certainty, iterations: Int32;
+      const random: ISecureRandom); overload;
+
+    /// <summary>
+    /// <para>
+    /// Initialise the key generator for DSA 2.
+    /// </para>
+    /// <para>
+    /// Use this init method if you need to generate parameters for DSA 2
+    /// keys.
+    /// </para>
+    /// </summary>
+    /// <param name="params">
+    /// DSA 2 key generation parameters.
+    /// </param>
+    procedure Init(const params: IDsaParameterGenerationParameters); overload;
+
+    /// <summary>
+    /// <para>
+    /// which generates the p and g values from the given parameters,
+    /// returning the DSAParameters object.
+    /// </para>
+    /// <para>
+    /// Note: can take a while...
+    /// </para>
+    /// </summary>
+    /// <returns>
+    /// a generated DSA parameters object.
+    /// </returns>
+    function GenerateParameters(): IDsaParameters; inline;
+
+  end;
+
+implementation
+
+{ TDsaParametersGenerator }
+
+function TDsaParametersGenerator.IsProbablePrime(const x: TBigInteger): Boolean;
+begin
+  result := x.IsProbablePrime(Fcertainty);
+end;
+
+class function TDsaParametersGenerator.IsValidDsaStrength
+  (strength: Int32): Boolean;
+begin
+  // result := (strength >= 512) and (strength <= 1024) and ((strength mod 64) = 0);
+  result := (strength >= 512) and (strength <= 1024) and
+    ((strength and 63) = 0);
+end;
+
+class function TDsaParametersGenerator.GetDefaultN(L: Int32): Int32;
+begin
+  if L > 1024 then
+  begin
+    result := 256
+  end
+  else
+  begin
+    result := 160;
+  end;
+end;
+
+class function TDsaParametersGenerator.GetMinimumIterations(L: Int32): Int32;
+begin
+  // Values based on FIPS 186-4 C.3 Table C.1
+  if L <= 1024 then
+  begin
+    result := 40;
+  end
+  else
+  begin
+    result := (48 + 8 * ((L - 1) div 1024))
+  end;
+end;
+
+class procedure TDsaParametersGenerator.Hash(const d: IDigest;
+  input, output: TCryptoLibByteArray; outputPos: Int32);
+begin
+  d.BlockUpdate(input, 0, System.Length(input));
+  d.DoFinal(output, outputPos);
+end;
+
+class procedure TDsaParametersGenerator.Inc(buf: TCryptoLibByteArray);
+var
+  i: Int32;
+  b: Byte;
+begin
+  i := System.Length(buf) - 1;
+  while i >= 0 do
+  begin
+    b := Byte((buf[i] + 1) and $FF);
+    buf[i] := b;
+
+    if (b <> 0) then
+    begin
+      break;
+    end;
+    System.Dec(i);
+  end;
+end;
+
+constructor TDsaParametersGenerator.Create;
+begin
+  Create(TDigestUtilities.GetDigest('SHA-1'));
+end;
+
+class function TDsaParametersGenerator.CalculateGenerator_FIPS186_2(const p,
+  q: TBigInteger; const r: ISecureRandom): TBigInteger;
+var
+  e, pSub2, h, g: TBigInteger;
+begin
+  result := Default (TBigInteger);
+  e := p.subtract(TBigInteger.One).Divide(q);
+  pSub2 := p.subtract(TBigInteger.Two);
+
+  while True do
+  begin
+    h := TBigIntegers.CreateRandomInRange(TBigInteger.Two, pSub2, r);
+    g := h.ModPow(e, p);
+    if (g.BitLength > 1) then
+    begin
+      result := g;
+      Exit;
+    end;
+  end;
+end;
+
+class function TDsaParametersGenerator.CalculateGenerator_FIPS186_3_Unverifiable
+  (const p, q: TBigInteger; const r: ISecureRandom): TBigInteger;
+begin
+  result := CalculateGenerator_FIPS186_2(p, q, r);
+end;
+
+class function TDsaParametersGenerator.CalculateGenerator_FIPS186_3_Verifiable
+  (const d: IDigest; const p, q: TBigInteger; seed: TCryptoLibByteArray;
+  index: Int32): TBigInteger;
+var
+  e, W, g: TBigInteger;
+  ggen, U, smallw: TCryptoLibByteArray;
+  count: Int32;
+begin
+  // A.2.3 Verifiable Canonical Generation of the Generator g
+  e := p.subtract(TBigInteger.One).Divide(q);
+  ggen := THex.Decode('6767656E');
+
+  // 7. U = domain_parameter_seed || "ggen" || index || count.
+  System.SetLength(U, System.Length(seed) + System.Length(ggen) + 1 + 2);
+  System.Move(seed[0], U[0], System.Length(seed) * System.SizeOf(Byte));
+  System.Move(ggen[0], U[System.Length(seed)], System.Length(ggen) *
+    System.SizeOf(Byte));
+  U[System.Length(U) - 3] := Byte(index);
+
+  System.SetLength(smallw, d.GetDigestSize());
+
+  count := 1;
+  while count < (1 shl 16) do
+  begin
+    Inc(U);
+    Hash(d, U, smallw, 0);
+    W := TBigInteger.Create(1, smallw);
+    g := W.ModPow(e, p);
+    if (g.CompareTo(TBigInteger.Two) >= 0) then
+    begin
+      result := g;
+      Exit;
+    end;
+    System.Inc(count);
+  end;
+
+  result := Default (TBigInteger);
+end;
+
+function TDsaParametersGenerator.GenerateParameters_FIPS186_2: IDsaParameters;
+var
+  seed, part1, part2, U, W, offset: TCryptoLibByteArray;
+  n, i, counter, k, remaining: Int32;
+  q, x, c, p, g: TBigInteger;
+begin
+  result := Nil;
+  System.SetLength(seed, 20);
+  System.SetLength(part1, 20);
+  System.SetLength(part2, 20);
+  System.SetLength(U, 20);
+  n := (FL - 1) div 160;
+  System.SetLength(W, FL div 8);
+
+  if (not {$IFDEF FPC} (Supports(Fdigest.GetUnderlyingIHash, TSHA1))
+{$ELSE} (Fdigest.GetUnderlyingIHash is TSHA1) {$ENDIF FPC}) then
+  begin
+    raise EInvalidParameterCryptoLibException.CreateRes(@SUnsupportedDigest);
+  end;
+
+  while True do
+  begin
+    Frandom.NextBytes(seed);
+
+    Hash(Fdigest, seed, part1, 0);
+    System.Move(seed[0], part2[0], System.Length(seed) * System.SizeOf(Byte));
+    Inc(part2);
+    Hash(Fdigest, part2, part2, 0);
+
+    i := 0;
+    while i <> System.Length(U) do
+    begin
+      U[i] := Byte(part1[i] xor part2[i]);
+      System.Inc(i);
+    end;
+
+    U[0] := U[0] or Byte($80);
+    U[19] := U[19] or Byte($01);
+
+    q := TBigInteger.Create(1, U);
+
+    if (not IsProbablePrime(q)) then
+    begin
+      continue;
+    end;
+
+    offset := System.Copy(seed);
+    Inc(offset);
+    counter := 0;
+    while counter < 4096 do
+    begin
+
+      k := 1;
+      while k <= n do
+      begin
+        Inc(offset);
+        Hash(Fdigest, offset, W, System.Length(W) - (k * System.Length(part1)));
+        System.Inc(k);
+      end;
+
+      remaining := System.Length(W) - (n * System.Length(part1));
+      Inc(offset);
+      Hash(Fdigest, offset, part1, 0);
+      System.Move(part1[System.Length(part1) - remaining], W[0], remaining);
+
+      W[0] := W[0] or Byte($80);
+
+      x := TBigInteger.Create(1, W);
+
+      c := x.&Mod(q.ShiftLeft(1));
+
+      p := x.subtract(c.subtract(TBigInteger.One));
+
+      if (p.BitLength <> FL) then
+      begin
+        System.Inc(counter);
+        continue;
+      end;
+
+      if (IsProbablePrime(p)) then
+      begin
+        g := CalculateGenerator_FIPS186_2(p, q, Frandom);
+
+        result := TDsaParameters.Create(p, q, g,
+          TDsaValidationParameters.Create(seed, counter)
+          as IDsaValidationParameters);
+        Exit;
+      end;
+
+      System.Inc(counter);
+    end;
+  end;
+end;
+
+function TDsaParametersGenerator.GenerateParameters_FIPS186_3: IDsaParameters;
+var
+  d: IDigest;
+  outlen, seedlen, n, { b, } counterLimit, counter, j, remaining: Int32;
+  seed, W, output, offset: TCryptoLibByteArray;
+  U, q, x, c, p, g: TBigInteger;
+begin
+  result := Nil;
+  // A.1.1.2 Generation of the Probable Primes p and q Using an Approved Hash Function
+  // TODO FIXME This should be configurable (digest size in bits must be >= N)
+  d := Fdigest;
+  outlen := d.GetDigestSize() * 8;
+
+  // 1. Check that the (L, N) pair is in the list of acceptable (L, N pairs) (see Section 4.2). If
+  // the pair is not in the list, then return INVALID.
+  // Note: checked at initialisation
+
+  // 2. If (seedlen < N), then return INVALID.
+  // TODO FIXME This should be configurable (must be >= N)
+  seedlen := FN;
+  System.SetLength(seed, seedlen div 8);
+
+  // 3. n = ceiling(L / outlen) - 1.
+  n := (FL - 1) div outlen;
+
+  // 4. b = L - 1 - (n * outlen).
+  // b := (FL - 1) mod outlen;
+
+  System.SetLength(W, FL div 8);
+
+  System.SetLength(output, d.GetDigestSize());
+
+  while True do
+  begin
+    // 5. Get an arbitrary sequence of seedlen bits as the domain_parameter_seed.
+    Frandom.NextBytes(seed);
+
+    // 6. U = Hash (domain_parameter_seed) mod 2^(N–1).
+    Hash(d, seed, output, 0);
+
+    U := TBigInteger.Create(1, output).&Mod(TBigInteger.One.ShiftLeft(FN - 1));
+
+    // 7. q = 2^(N–1) + U + 1 – ( U mod 2).
+    q := U.SetBit(0).SetBit(FN - 1);
+
+    // 8. Test whether or not q is prime as specified in Appendix C.3.
+    if (not IsProbablePrime(q)) then
+    begin
+      // 9. If q is not a prime, then go to step 5.
+      continue;
+    end;
+
+    // 10. offset = 1.
+    // Note: 'offset' value managed incrementally
+    offset := System.Copy(seed);
+
+    // 11. For counter = 0 to (4L – 1) do
+    counterLimit := 4 * FL;
+    counter := 0;
+    while counter < counterLimit do
+    begin
+      // 11.1 For j = 0 to n do
+      // Vj = Hash ((domain_parameter_seed + offset + j) mod 2^seedlen).
+      // 11.2 W = V0 + (V1 * 2^outlen) + ... + (V^(n–1) * 2^((n–1) * outlen)) + ((Vn mod 2^b) * 2^(n * outlen)).
+
+      j := 1;
+      while j <= n do
+      begin
+        Inc(offset);
+        Hash(d, offset, W, System.Length(W) - (j * System.Length(output)));
+        System.Inc(j);
+      end;
+
+      remaining := System.Length(W) - (n * System.Length(output));
+      Inc(offset);
+      Hash(d, offset, output, 0);
+      System.Move(output[System.Length(output) - remaining], W[0], remaining);
+
+      // 11.3 X = W + 2^(L–1). Comment: 0 ≤ W < 2^(L–1); hence, 2^(L–1) ≤ X < 2^L.
+      W[0] := W[0] or Byte($80);
+
+      x := TBigInteger.Create(1, W);
+
+      // 11.4 c = X mod 2q.
+      c := x.&Mod(q.ShiftLeft(1));
+
+      // 11.5 p = X - (c - 1). Comment: p ≡ 1 (mod 2q).
+      p := x.subtract(c.subtract(TBigInteger.One));
+
+      // 11.6 If (p < 2^(L-1)), then go to step 11.9
+      if (p.BitLength <> FL) then
+      begin
+        System.Inc(counter);
+        continue;
+      end;
+
+      // 11.7 Test whether or not p is prime as specified in Appendix C.3.
+      if (IsProbablePrime(p)) then
+      begin
+        // 11.8 If p is determined to be prime, then return VALID and the values of p, q and
+        // (optionally) the values of domain_parameter_seed and counter.
+        if (FusageIndex >= 0) then
+        begin
+          g := CalculateGenerator_FIPS186_3_Verifiable(d, p, q, seed,
+            FusageIndex);
+          if (g.IsInitialized) then
+          begin
+            result := TDsaParameters.Create(p, q, g,
+              TDsaValidationParameters.Create(seed, counter, FusageIndex)
+              as IDsaValidationParameters);
+            Exit;
+          end;
+        end;
+
+        g := CalculateGenerator_FIPS186_3_Unverifiable(p, q, Frandom);
+
+        result := TDsaParameters.Create(p, q, g,
+          TDsaValidationParameters.Create(seed, counter)
+          as IDsaValidationParameters);
+        Exit;
+      end;
+
+      // 11.9 offset = offset + n + 1.      Comment: Increment offset; then, as part of
+      // the loop in step 11, increment counter; if
+      // counter < 4L, repeat steps 11.1 through 11.8.
+      // Note: 'offset' value already incremented in inner loop
+      System.Inc(counter);
+    end;
+    // 12. Go to step 5.
+  end;
+
+end;
+
+function TDsaParametersGenerator.GenerateParameters: IDsaParameters;
+begin
+  if Fuse186_3 then
+  begin
+    result := GenerateParameters_FIPS186_3()
+  end
+  else
+  begin
+    result := GenerateParameters_FIPS186_2();
+  end;
+end;
+
+constructor TDsaParametersGenerator.Create(const digest: IDigest);
+begin
+  Inherited Create();
+  Fdigest := digest;
+end;
+
+procedure TDsaParametersGenerator.Init(size, certainty: Int32;
+  const random: ISecureRandom);
+begin
+  Init(size, certainty, Max(GetMinimumIterations(size),
+    (certainty + 1) div 2), random);
+end;
+
+procedure TDsaParametersGenerator.Init(size, certainty, iterations: Int32;
+  const random: ISecureRandom);
+begin
+  if (not IsValidDsaStrength(size)) then
+  begin
+    raise EArgumentCryptoLibException.CreateResFmt(@SInvalidDsaKeyStrength,
+      [512, 1024, 64, size]);
+  end;
+  FL := size;
+  FN := GetDefaultN(size);
+  Fcertainty := certainty;
+  Fiterations := iterations;
+  Frandom := random;
+  Fuse186_3 := false;
+  FusageIndex := -1;
+end;
+
+procedure TDsaParametersGenerator.Init(const params
+  : IDsaParameterGenerationParameters);
+var
+  L, n: Int32;
+begin
+  L := params.L;
+  n := params.n;
+
+  // if (((L < 1024) or (L > 3072)) or ((L mod 1024) <> 0))
+  if (((L < 1024) or (L > 3072)) or ((L and 1023) <> 0)) then
+  begin
+    raise EInvalidParameterCryptoLibException.CreateRes(@SInvalidLValue);
+  end
+  else if ((L = 1024) and (n <> 160)) then
+  begin
+    raise EInvalidParameterCryptoLibException.CreateResFmt
+      (@SInvalidNValueForSpecifiedL, [160, 1024]);
+  end
+  else if ((L = 2048) and ((n <> 224) and (n <> 256))) then
+  begin
+    raise EInvalidParameterCryptoLibException.CreateResFmt
+      (@SInvalidNValueForSpecifiedL_Two, [224, 256, 2048]);
+  end
+  else if ((L = 3072) and (n <> 256)) then
+  begin
+    raise EInvalidParameterCryptoLibException.CreateResFmt
+      (@SInvalidNValueForSpecifiedL, [256, 3072]);
+  end;
+
+  if ((Fdigest.GetDigestSize * 8) < n) then
+  begin
+    raise EInvalidParameterCryptoLibException.CreateResFmt
+      (@SDigestOutputSizeTooSmallForN, [n]);
+  end;
+
+  FL := L;
+  FN := n;
+  Fcertainty := params.certainty;
+  Fiterations := Max(GetMinimumIterations(L), (Fcertainty + 1) div 2);
+  Frandom := params.random;
+  Fuse186_3 := True;
+  FusageIndex := params.UsageIndex;
+end;
+
+end.

+ 5 - 8
CryptoLib/src/Crypto/Generators/ClpEphemeralKeyPairGenerator.pas

@@ -27,7 +27,7 @@ uses
   ClpIEphemeralKeyPairGenerator,
   ClpIAsymmetricCipherKeyPair,
   ClpIAsymmetricCipherKeyPairGenerator,
-  ClpKeyEncoder;
+  ClpIKeyEncoder;
 
 type
   TEphemeralKeyPairGenerator = class sealed(TInterfacedObject,
@@ -35,13 +35,12 @@ type
 
   strict private
     Fgen: IAsymmetricCipherKeyPairGenerator;
-    FUsePointCompression: Boolean;
-    FkeyEncoder: TKeyEncoder;
+    FkeyEncoder: IKeyEncoder;
 
   public
     function Generate(): IEphemeralKeyPair; inline;
     constructor Create(const gen: IAsymmetricCipherKeyPairGenerator;
-      UsePointCompression: Boolean; const keyEncoder: TKeyEncoder);
+      const keyEncoder: IKeyEncoder);
   end;
 
 implementation
@@ -49,12 +48,10 @@ implementation
 { TEphemeralKeyPairGenerator }
 
 constructor TEphemeralKeyPairGenerator.Create
-  (const gen: IAsymmetricCipherKeyPairGenerator; UsePointCompression: Boolean;
-  const keyEncoder: TKeyEncoder);
+  (const gen: IAsymmetricCipherKeyPairGenerator; const keyEncoder: IKeyEncoder);
 begin
   Inherited Create();
   Fgen := gen;
-  FUsePointCompression := UsePointCompression;
   FkeyEncoder := keyEncoder;
 end;
 
@@ -64,7 +61,7 @@ var
 begin
   eph := Fgen.generateKeyPair();
   // Encode the ephemeral public key
-  result := TEphemeralKeyPair.Create(eph, FUsePointCompression, FkeyEncoder);
+  result := TEphemeralKeyPair.Create(eph, FkeyEncoder);
 end;
 
 end.

+ 233 - 0
CryptoLib/src/Crypto/Generators/ClpHkdfBytesGenerator.pas

@@ -0,0 +1,233 @@
+{ *********************************************************************************** }
+{ *                              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 ClpHkdfBytesGenerator;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Math,
+  SysUtils,
+  ClpHMac,
+  ClpIHMac,
+  ClpIDigest,
+  ClpKeyParameter,
+  ClpIKeyParameter,
+  ClpIHkdfParameters,
+  ClpIHkdfBytesGenerator,
+  ClpIDerivationFunction,
+  ClpIDerivationParameters,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SSizeTooBigHKDF = 'HKDF Cannot Generate More Than 255 Blocks of HashLen Size';
+  SSizeTooBigHKDF2 = 'HKDF May Only Be Used For 255 * HashLen Bytes of Output';
+  SInvalidParameterHKDF =
+    'HKDF Parameters Required For "HkdfBytesGenerator", "parameters"';
+
+type
+
+  /// <summary>
+  /// HMAC-based Extract-and-Expand Key Derivation Function (HKDF)
+  /// implemented <br />according to IETF RFC 5869, May 2010 as specified by
+  /// H. Krawczyk, IBM <br />Research &amp;amp; P. Eronen, Nokia. It uses a
+  /// HMac internally to compute the OKM <br />(output keying material) and
+  /// is likely to have better security properties <br />than KDF's based on
+  /// just a hash function.
+  /// </summary>
+  THkdfBytesGenerator = class(TInterfacedObject, IDerivationFunction,
+    IHkdfBytesGenerator)
+
+  strict private
+  var
+    FhMacHash: IHMac;
+    FhashLen, FgeneratedBytes: Int32;
+    Finfo, FcurrentT: TCryptoLibByteArray;
+
+  strict private
+
+    /// <summary>
+    /// Performs the extract part of the key derivation function.
+    /// </summary>
+    /// <param name="salt">
+    /// the salt to use
+    /// </param>
+    /// <param name="ikm">
+    /// the input keying material
+    /// </param>
+    /// <returns>
+    /// the PRK as KeyParameter
+    /// </returns>
+    function Extract(salt, ikm: TCryptoLibByteArray): IKeyParameter;
+
+    /// <summary>
+    /// Performs the expand part of the key derivation function, using
+    /// currentT <br />as input and output buffer.
+    /// </summary>
+    /// <exception cref="EDataLengthCryptoLibException">
+    /// if the total number of bytes generated is larger than the one
+    /// specified by RFC 5869 (255 * HashLen)
+    /// </exception>
+    procedure ExpandNext();
+
+  strict protected
+    function GetDigest: IDigest; virtual;
+
+  public
+
+    /// <summary>
+    /// Creates a HKDFBytesGenerator based on the given hash function.
+    /// </summary>
+    /// <param name="hash">
+    /// the digest to be used as the source of generatedBytes bytes
+    /// </param>
+    constructor Create(const hash: IDigest);
+
+    procedure Init(const parameters: IDerivationParameters); virtual;
+
+    function GenerateBytes(output: TCryptoLibByteArray; outOff, len: Int32)
+      : Int32; virtual;
+
+    property Digest: IDigest read GetDigest;
+
+  end;
+
+implementation
+
+{ THkdfBytesGenerator }
+
+constructor THkdfBytesGenerator.Create(const hash: IDigest);
+begin
+  Inherited Create();
+  FhMacHash := THMac.Create(hash);
+  FhashLen := hash.GetDigestSize();
+end;
+
+procedure THkdfBytesGenerator.ExpandNext;
+var
+  n: Int32;
+begin
+  n := (FgeneratedBytes div FhashLen) + 1;
+  if (n >= 256) then
+  begin
+    raise EDataLengthCryptoLibException.CreateRes(@SSizeTooBigHKDF);
+  end;
+  // special case for T(0): T(0) is empty, so no update
+  if (FgeneratedBytes <> 0) then
+  begin
+    FhMacHash.BlockUpdate(FcurrentT, 0, FhashLen);
+  end;
+  FhMacHash.BlockUpdate(Finfo, 0, System.Length(Finfo));
+  FhMacHash.Update(Byte(n));
+  FhMacHash.DoFinal(FcurrentT, 0);
+end;
+
+function THkdfBytesGenerator.Extract(salt, ikm: TCryptoLibByteArray)
+  : IKeyParameter;
+var
+  temp, prk: TCryptoLibByteArray;
+begin
+  if (salt = Nil) then
+  begin
+    System.SetLength(temp, FhashLen);
+    // TODO check if hashLen is indeed same as HMAC size
+    FhMacHash.Init(TKeyParameter.Create(temp) as IKeyParameter);
+  end
+  else
+  begin
+    FhMacHash.Init(TKeyParameter.Create(salt) as IKeyParameter);
+  end;
+
+  FhMacHash.BlockUpdate(ikm, 0, System.Length(ikm));
+
+  System.SetLength(prk, FhashLen);
+  FhMacHash.DoFinal(prk, 0);
+  result := TKeyParameter.Create(prk);
+end;
+
+function THkdfBytesGenerator.GenerateBytes(output: TCryptoLibByteArray;
+  outOff, len: Int32): Int32;
+var
+  toGenerate, posInT, leftInT, toCopy: Int32;
+begin
+  if ((FgeneratedBytes + len) > (255 * FhashLen)) then
+  begin
+    raise EDataLengthCryptoLibException.CreateRes(@SSizeTooBigHKDF2);
+  end;
+
+  if (FgeneratedBytes mod FhashLen = 0) then
+  begin
+    ExpandNext();
+  end;
+
+  // copy what is left in the currentT (1..hash
+  toGenerate := len;
+  posInT := FgeneratedBytes mod FhashLen;
+  leftInT := FhashLen - (FgeneratedBytes mod FhashLen);
+  toCopy := Min(leftInT, toGenerate);
+  System.Move(FcurrentT[posInT], output[outOff], toCopy);
+  FgeneratedBytes := FgeneratedBytes + toCopy;
+  toGenerate := toGenerate - toCopy;
+  outOff := outOff + toCopy;
+
+  while (toGenerate > 0) do
+  begin
+    ExpandNext();
+    toCopy := Min(FhashLen, toGenerate);
+    System.Move(FcurrentT[0], output[outOff], toCopy);
+    FgeneratedBytes := FgeneratedBytes + toCopy;
+    toGenerate := toGenerate - toCopy;
+    outOff := outOff + toCopy;
+  end;
+
+  result := len;
+end;
+
+function THkdfBytesGenerator.GetDigest: IDigest;
+begin
+  result := FhMacHash.GetUnderlyingDigest();
+end;
+
+procedure THkdfBytesGenerator.Init(const parameters: IDerivationParameters);
+var
+  hkdfParameters: IHkdfParameters;
+begin
+  if (not Supports(parameters, IHkdfParameters, hkdfParameters)) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SInvalidParameterHKDF);
+  end;
+
+  if (hkdfParameters.SkipExtract) then
+  begin
+    // use IKM directly as PRK
+    FhMacHash.Init(TKeyParameter.Create(hkdfParameters.GetIkm())
+      as IKeyParameter);
+  end
+  else
+  begin
+    FhMacHash.Init(Extract(hkdfParameters.GetSalt(), hkdfParameters.GetIkm()));
+  end;
+
+  Finfo := hkdfParameters.GetInfo();
+
+  FgeneratedBytes := 0;
+  System.SetLength(FcurrentT, FhashLen);
+end;
+
+end.

+ 5 - 6
CryptoLib/src/Crypto/Generators/ClpPbeParametersGenerator.pas

@@ -92,8 +92,8 @@ type
     /// <returns>
     /// a parameters object representing a key.
     /// </returns>
-    function GenerateDerivedParameters(const algorithm: String;
-      keySize: Int32): ICipherParameters; overload; virtual; abstract;
+    function GenerateDerivedParameters(const algorithm: String; keySize: Int32)
+      : ICipherParameters; overload; virtual; abstract;
 
     /// <summary>
     /// Generate derived parameters for a key of length keySize and iv
@@ -112,8 +112,7 @@ type
     /// a parameters object representing a key and an iv.
     /// </returns>
     function GenerateDerivedParameters(const algorithm: String;
-      keySize, ivSize: Int32): ICipherParameters; overload;
-      virtual; abstract;
+      keySize, ivSize: Int32): ICipherParameters; overload; virtual; abstract;
 
     /// <summary>
     /// Generate derived parameters for a key of length keySize,
@@ -125,8 +124,8 @@ type
     /// <returns>
     /// a parameters object representing a key.
     /// </returns>
-    function GenerateDerivedMacParameters(keySize: Int32)
-      : ICipherParameters; virtual; abstract;
+    function GenerateDerivedMacParameters(keySize: Int32): ICipherParameters;
+      virtual; abstract;
 
   end;
 

+ 1 - 2
CryptoLib/src/Crypto/Modes/ClpSicBlockCipher.pas

@@ -172,8 +172,7 @@ procedure TSicBlockCipher.Reset;
 begin
   System.FillChar(Fcounter[0], System.Length(Fcounter) *
     System.SizeOf(Byte), Byte(0));
-  System.Move(FIV[0], Fcounter[0], System.Length(FIV) *
-    System.SizeOf(Byte));
+  System.Move(FIV[0], Fcounter[0], System.Length(FIV) * System.SizeOf(Byte));
 
   Fcipher.Reset();
 

+ 1 - 0
CryptoLib/src/Crypto/Paddings/ClpX923Padding.pas

@@ -118,6 +118,7 @@ begin
     System.Inc(inOff);
   end;
 
+  input[inOff] := code;
   result := code;
 end;
 

+ 146 - 0
CryptoLib/src/Crypto/Parameters/ClpDsaParameterGenerationParameters.pas

@@ -0,0 +1,146 @@
+{ *********************************************************************************** }
+{ *                              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 ClpDsaParameterGenerationParameters;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpISecureRandom,
+  ClpIDsaParameterGenerationParameters;
+
+type
+  TDsaParameterGenerationParameters = class(TInterfacedObject,
+    IDsaParameterGenerationParameters)
+
+  strict private
+  var
+    Fl, Fn, Fcertainty, FusageIndex: Int32;
+    Frandom: ISecureRandom;
+
+  strict protected
+
+    function GetL: Int32; virtual;
+    function GetN: Int32; virtual;
+    function GetCertainty: Int32; virtual;
+    function GetUsageIndex: Int32; virtual;
+    function GetRandom: ISecureRandom; virtual;
+
+  public
+
+    const
+    DigitalSignatureUsage = Int32(1);
+    KeyEstablishmentUsage = Int32(2);
+
+    /// <summary>
+    /// Construct without a usage index, this will do a random construction
+    /// of G.
+    /// </summary>
+    /// <param name="L">
+    /// desired length of prime P in bits (the effective key size).
+    /// </param>
+    /// <param name="N">
+    /// desired length of prime Q in bits.
+    /// </param>
+    /// <param name="certainty">
+    /// certainty level for prime number generation.
+    /// </param>
+    /// <param name="random">
+    /// the source of randomness to use.
+    /// </param>
+    constructor Create(L, N, certainty: Int32;
+      const random: ISecureRandom); overload;
+
+    /// <summary>
+    /// Construct without a usage index, this will do a random construction
+    /// of G.
+    /// </summary>
+    /// <param name="L">
+    /// desired length of prime P in bits (the effective key size).
+    /// </param>
+    /// <param name="N">
+    /// desired length of prime Q in bits.
+    /// </param>
+    /// <param name="certainty">
+    /// certainty level for prime number generation.
+    /// </param>
+    /// <param name="random">
+    /// the source of randomness to use.
+    /// </param>
+    /// <param name="usageIndex">
+    /// a valid usage index.
+    /// </param>
+    constructor Create(L, N, certainty: Int32; const random: ISecureRandom;
+      usageIndex: Int32); overload;
+
+    property L: Int32 read GetL;
+    property N: Int32 read GetN;
+    property usageIndex: Int32 read GetUsageIndex;
+    property certainty: Int32 read GetCertainty;
+    property random: ISecureRandom read GetRandom;
+
+  end;
+
+implementation
+
+{ TDsaParameterGenerationParameters }
+
+constructor TDsaParameterGenerationParameters.Create(L, N, certainty: Int32;
+  const random: ISecureRandom);
+begin
+  Create(L, N, certainty, random, -1);
+end;
+
+constructor TDsaParameterGenerationParameters.Create(L, N, certainty: Int32;
+  const random: ISecureRandom; usageIndex: Int32);
+begin
+  Inherited Create();
+  Fl := L;
+  Fn := N;
+  Fcertainty := certainty;
+  Frandom := random;
+  FusageIndex := usageIndex;
+end;
+
+function TDsaParameterGenerationParameters.GetL: Int32;
+begin
+  result := Fl;
+end;
+
+function TDsaParameterGenerationParameters.GetN: Int32;
+begin
+  result := Fn;
+end;
+
+function TDsaParameterGenerationParameters.GetCertainty: Int32;
+begin
+  result := Fcertainty;
+end;
+
+function TDsaParameterGenerationParameters.GetUsageIndex: Int32;
+begin
+  result := FusageIndex;
+end;
+
+function TDsaParameterGenerationParameters.GetRandom: ISecureRandom;
+begin
+  result := Frandom;
+end;
+
+end.

+ 1 - 1
CryptoLib/src/Crypto/Parameters/ClpDsaPublicKeyParameters.pas

@@ -98,7 +98,7 @@ function TDsaPublicKeyParameters.Equals(const other
 begin
   if other = Nil then
   begin
-    result := False;
+    result := false;
     Exit;
   end;
   if ((Self as IDsaPublicKeyParameters) = other) then

+ 78 - 21
CryptoLib/src/Crypto/Parameters/ClpECDomainParameters.pas

@@ -22,7 +22,9 @@ unit ClpECDomainParameters;
 interface
 
 uses
+  SyncObjs,
   ClpBigInteger,
+  ClpECAlgorithms,
   ClpIECInterface,
   ClpCryptoLibTypes,
   ClpIECDomainParameters;
@@ -31,26 +33,41 @@ resourcestring
   SCurveNil = 'Curve Cannot be Nil';
   SGNil = 'G Cannot be Nil';
   SBigIntegerNotInitialized = 'BigInteger Not Initialized "%s"';
+  SQNil = 'Q Cannot be Nil';
+  SQInfinity = 'Point at Infinity "Q"';
+  SQPointNotOnCurve = 'Point Not on Curve "Q"';
 
 type
 
   TECDomainParameters = class sealed(TInterfacedObject, IECDomainParameters)
 
   strict private
+
+    class var
+
+      FLock: TCriticalSection;
+
   var
     Fcurve: IECCurve;
     Fseed: TCryptoLibByteArray;
     Fg: IECPoint;
-    Fn, Fh: TBigInteger;
+    Fn, Fh, FhInv: TBigInteger;
 
     function GetCurve: IECCurve; inline;
     function GetG: IECPoint; inline;
     function GetH: TBigInteger; inline;
     function GetN: TBigInteger; inline;
+    function GetHInv: TBigInteger; inline;
     function GetSeed: TCryptoLibByteArray; inline;
 
+    class constructor CreateECDomainParameters();
+    class destructor DestroyECDomainParameters();
+
   public
 
+    class function Validate(const c: IECCurve; const q: IECPoint)
+      : IECPoint; static;
+
     constructor Create(const curve: IECCurve; const g: IECPoint;
       const n: TBigInteger); overload;
     constructor Create(const curve: IECCurve; const g: IECPoint;
@@ -62,6 +79,7 @@ type
     property g: IECPoint read GetG;
     property n: TBigInteger read GetN;
     property h: TBigInteger read GetH;
+    property HInv: TBigInteger read GetHInv;
     property seed: TCryptoLibByteArray read GetSeed;
     function Equals(const other: IECDomainParameters): Boolean; reintroduce;
     function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
@@ -73,35 +91,65 @@ implementation
 
 { TECDomainParameters }
 
+class function TECDomainParameters.Validate(const c: IECCurve;
+  const q: IECPoint): IECPoint;
+begin
+  if (q = Nil) then
+    raise EArgumentNilCryptoLibException.CreateRes(@SQNil);
+
+  result := TECAlgorithms.ImportPoint(c, q).Normalize();
+
+  if (result.IsInfinity) then
+    raise EArgumentCryptoLibException.CreateRes(@SQInfinity);
+
+  if (not(result.IsValid())) then
+    raise EArgumentCryptoLibException.CreateRes(@SQPointNotOnCurve);
+
+end;
+
 function TECDomainParameters.GetCurve: IECCurve;
 begin
-  Result := Fcurve;
+  result := Fcurve;
 end;
 
 function TECDomainParameters.GetG: IECPoint;
 begin
-  Result := Fg;
+  result := Fg;
 end;
 
 function TECDomainParameters.GetH: TBigInteger;
 begin
-  Result := Fh;
+  result := Fh;
 end;
 
 function TECDomainParameters.GetN: TBigInteger;
 begin
-  Result := Fn;
+  result := Fn;
+end;
+
+function TECDomainParameters.GetHInv: TBigInteger;
+begin
+  FLock.Acquire;
+  try
+    if (not(FhInv.IsInitialized)) then
+    begin
+      FhInv := h.ModInverse(n);
+    end;
+    result := FhInv;
+  finally
+    FLock.Release;
+  end;
 end;
 
 function TECDomainParameters.GetSeed: TCryptoLibByteArray;
 begin
-  Result := Fseed;
+  result := System.Copy(Fseed);
 end;
 
 constructor TECDomainParameters.Create(const curve: IECCurve; const g: IECPoint;
   const n: TBigInteger);
 begin
-  Create(curve, g, n, TBigInteger.One)
+  Create(curve, g, n, TBigInteger.One, Nil);
 end;
 
 constructor TECDomainParameters.Create(const curve: IECCurve; const g: IECPoint;
@@ -122,35 +170,44 @@ begin
     raise EArgumentNilCryptoLibException.CreateResFmt
       (@SBigIntegerNotInitialized, ['n']);
 
-  if (not h.IsInitialized) then
-    raise EArgumentNilCryptoLibException.CreateResFmt
-      (@SBigIntegerNotInitialized, ['h']);
+  // we can't check for (not (h.IsInitialized)) here as h is optional in X9.62 as it is not required for ECDSA
 
   Fcurve := curve;
-  Fg := g.Normalize();
+  Fg := Validate(curve, g);
   Fn := n;
   Fh := h;
+  FhInv := Default (TBigInteger);
 
   Fseed := System.Copy(seed);
 
 end;
 
+class constructor TECDomainParameters.CreateECDomainParameters;
+begin
+  FLock := TCriticalSection.Create;
+end;
+
+class destructor TECDomainParameters.DestroyECDomainParameters;
+begin
+  FLock.Free;
+end;
+
 function TECDomainParameters.Equals(const other: IECDomainParameters): Boolean;
 begin
 
   if (other = Self as IECDomainParameters) then
   begin
-    Result := true;
+    result := true;
     Exit;
   end;
 
   if (other = Nil) then
   begin
-    Result := false;
+    result := false;
     Exit;
   end;
 
-  Result := curve.Equals(other.curve) and g.Equals(other.g) and
+  result := curve.Equals(other.curve) and g.Equals(other.g) and
     n.Equals(other.n) and h.Equals(other.h);
 
 end;
@@ -158,13 +215,13 @@ end;
 function TECDomainParameters.GetHashCode: {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
 {$ENDIF DELPHI}
 begin
-  Result := curve.GetHashCode();
-  Result := Result * 37;
-  Result := Result xor g.GetHashCode();
-  Result := Result * 37;
-  Result := Result xor n.GetHashCode();
-  Result := Result * 37;
-  Result := Result xor h.GetHashCode();
+  result := curve.GetHashCode();
+  result := result * 37;
+  result := result xor g.GetHashCode();
+  result := result * 37;
+  result := result xor n.GetHashCode();
+  result := result * 37;
+  result := result xor h.GetHashCode();
 end;
 
 end.

+ 1 - 2
CryptoLib/src/Crypto/Parameters/ClpECKeyParameters.pas

@@ -77,8 +77,7 @@ type
     function Equals(const other: IECKeyParameters): Boolean; reintroduce;
 
   public
-    class function VerifyAlgorithmName(const algorithm: String): String;
-      static;
+    class function VerifyAlgorithmName(const algorithm: String): String; static;
     class function LookupParameters(const publicKeyParamSet
       : IDerObjectIdentifier): IECDomainParameters; static;
     property AlgorithmName: String read GetAlgorithmName;

+ 9 - 20
CryptoLib/src/Crypto/Parameters/ClpECPublicKeyParameters.pas

@@ -23,6 +23,7 @@ interface
 
 uses
   ClpCryptoLibTypes,
+  ClpECDomainParameters,
   ClpBigInteger,
   ClpIECInterface,
   ClpIECPublicKeyParameters,
@@ -32,8 +33,6 @@ uses
 
 resourcestring
   SQNil = 'Q Cannot be Nil';
-  SQInfinity = 'Point at Infinity "Q"';
-  SQPointNotOnCurve = 'Point Not on Curve "Q"';
 
 type
   TECPublicKeyParameters = class sealed(TECKeyParameters,
@@ -44,7 +43,6 @@ type
     Fq: IECPoint;
 
     function GetQ: IECPoint; inline;
-    class function Validate(const q: IECPoint): IECPoint; static; inline;
 
   public
     constructor Create(const q: IECPoint;
@@ -73,29 +71,17 @@ begin
   result := Fq;
 end;
 
-class function TECPublicKeyParameters.Validate(const q: IECPoint): IECPoint;
-begin
-  if (q = Nil) then
-    raise EArgumentNilCryptoLibException.CreateRes(@SQNil);
-
-  if (q.IsInfinity) then
-    raise EArgumentCryptoLibException.CreateRes(@SQInfinity);
-
-  result := q.Normalize();
-
-  if (not(result.IsValid())) then
-    raise EArgumentCryptoLibException.CreateRes(@SQPointNotOnCurve);
-
-end;
-
 constructor TECPublicKeyParameters.Create(const algorithm: String;
   const q: IECPoint; const parameters: IECDomainParameters);
 begin
   Inherited Create(algorithm, false, parameters);
+
   if (q = Nil) then
+  begin
     raise EArgumentNilCryptoLibException.CreateRes(@SQNil);
+  end;
 
-  Fq := Validate(q);
+  Fq := TECDomainParameters.Validate(parameters.Curve, q);
 end;
 
 constructor TECPublicKeyParameters.Create(const q: IECPoint;
@@ -108,10 +94,13 @@ constructor TECPublicKeyParameters.Create(const algorithm: String;
   const q: IECPoint; const publicKeyParamSet: IDerObjectIdentifier);
 begin
   Inherited Create(algorithm, false, publicKeyParamSet);
+
   if (q = Nil) then
+  begin
     raise EArgumentNilCryptoLibException.CreateRes(@SQNil);
+  end;
 
-  Fq := Validate(q);
+  Fq := TECDomainParameters.Validate(parameters.Curve, q);
 end;
 
 function TECPublicKeyParameters.Equals(const other

+ 203 - 0
CryptoLib/src/Crypto/Parameters/ClpHkdfParameters.pas

@@ -0,0 +1,203 @@
+{ *********************************************************************************** }
+{ *                              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 ClpHkdfParameters;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIHkdfParameters,
+  ClpIDerivationParameters,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SIKMNil = '"ikm" is Nil';
+
+type
+
+  /// <summary>
+  /// Parameter class for the HkdfBytesGenerator class.
+  /// </summary>
+  THkdfParameters = class(TInterfacedObject, IDerivationParameters,
+    IHkdfParameters)
+
+  strict private
+  var
+    Fikm, Fsalt, Finfo: TCryptoLibByteArray;
+    FskipExpand: Boolean;
+
+    constructor Create(ikm: TCryptoLibByteArray; skip: Boolean;
+      salt, info: TCryptoLibByteArray); overload;
+
+  strict protected
+
+    /// <summary>
+    /// Returns if step 1: extract has to be skipped or not
+    /// </summary>
+    /// <returns>
+    /// true for skipping, false for no skipping of step 1
+    /// </returns>
+    function GetSkipExtract: Boolean; virtual;
+
+  public
+
+    /// <summary>
+    /// Generates parameters for HKDF, specifying both the optional salt and <br />
+    /// optional info. Step 1: Extract won't be skipped.
+    /// </summary>
+    /// <param name="ikm">
+    /// the input keying material or seed
+    /// </param>
+    /// <param name="salt">
+    /// the salt to use, may be null for a salt for hashLen zeros
+    /// </param>
+    /// <param name="info">
+    /// the info to use, may be null for an info field of zero bytes
+    /// </param>
+    constructor Create(ikm, salt, info: TCryptoLibByteArray); overload;
+
+    /// <summary>
+    /// Returns the input keying material or seed.
+    /// </summary>
+    /// <returns>
+    /// the keying material
+    /// </returns>
+    function GetIkm(): TCryptoLibByteArray; virtual;
+
+    /// <summary>
+    /// Returns the salt, or null if the salt should be generated as a byte
+    /// array <br />of HashLen zeros.
+    /// </summary>
+    /// <returns>
+    /// the salt, or null
+    /// </returns>
+    function GetSalt(): TCryptoLibByteArray; virtual;
+
+    /// <summary>
+    /// Returns the info field, which may be empty (null is converted to
+    /// empty).
+    /// </summary>
+    /// <returns>
+    /// the info field, never null
+    /// </returns>
+    function GetInfo(): TCryptoLibByteArray; virtual;
+
+    /// <summary>
+    /// Returns if step 1: extract has to be skipped or not
+    /// </summary>
+    /// <returns>
+    /// true for skipping, false for no skipping of step 1
+    /// </returns>
+    property SkipExtract: Boolean read GetSkipExtract;
+
+    /// <summary>
+    /// Factory method that makes the HKDF skip the extract part of the key <br />
+    /// derivation function.
+    /// </summary>
+    /// <param name="ikm">
+    /// the input keying material or seed, directly used for step 2: Expand
+    /// </param>
+    /// <param name="info">
+    /// the info to use, may be null for an info field of zero bytes
+    /// </param>
+    /// <returns>
+    /// that makes the implementation skip step 1
+    /// </returns>
+    class function SkipExtractParameters(ikm, info: TCryptoLibByteArray)
+      : IHkdfParameters; static; inline;
+
+    class function DefaultParameters(ikm: TCryptoLibByteArray): IHkdfParameters;
+      static; inline;
+
+  end;
+
+implementation
+
+{ THkdfParameters }
+
+constructor THkdfParameters.Create(ikm: TCryptoLibByteArray; skip: Boolean;
+  salt, info: TCryptoLibByteArray);
+begin
+  Inherited Create();
+
+  if (ikm = Nil) then
+  begin
+    raise EArgumentNilCryptoLibException.CreateRes(@SIKMNil);
+  end;
+
+  Fikm := System.Copy(ikm);
+  FskipExpand := skip;
+
+  if ((salt = Nil) or (System.Length(salt) = 0)) then
+  begin
+    Fsalt := Nil;
+  end
+  else
+  begin
+    Fsalt := System.Copy(salt);
+  end;
+
+  if (info = Nil) then
+  begin
+    System.SetLength(Finfo, 0);
+  end
+  else
+  begin
+    Finfo := System.Copy(info);
+  end;
+end;
+
+constructor THkdfParameters.Create(ikm, salt, info: TCryptoLibByteArray);
+begin
+  Create(ikm, false, salt, info);
+end;
+
+class function THkdfParameters.DefaultParameters(ikm: TCryptoLibByteArray)
+  : IHkdfParameters;
+begin
+  result := THkdfParameters.Create(ikm, false, Nil, Nil);
+end;
+
+function THkdfParameters.GetIkm: TCryptoLibByteArray;
+begin
+  result := System.Copy(Fikm);
+end;
+
+function THkdfParameters.GetInfo: TCryptoLibByteArray;
+begin
+  result := System.Copy(Finfo);
+end;
+
+function THkdfParameters.GetSalt: TCryptoLibByteArray;
+begin
+  result := System.Copy(Fsalt);
+end;
+
+function THkdfParameters.GetSkipExtract: Boolean;
+begin
+  result := FskipExpand;
+end;
+
+class function THkdfParameters.SkipExtractParameters(ikm,
+  info: TCryptoLibByteArray): IHkdfParameters;
+begin
+  result := THkdfParameters.Create(ikm, true, Nil, info);
+end;
+
+end.

+ 2 - 2
CryptoLib/src/Crypto/Parameters/ClpIESParameters.pas

@@ -71,12 +71,12 @@ end;
 
 function TIESParameters.GetDerivationV: TCryptoLibByteArray;
 begin
-  result := Fderivation;
+  result := System.Copy(Fderivation);
 end;
 
 function TIESParameters.GetEncodingV: TCryptoLibByteArray;
 begin
-  result := Fencoding;
+  result := System.Copy(Fencoding);
 end;
 
 function TIESParameters.GetMacKeySize: Int32;

+ 112 - 33
CryptoLib/src/Crypto/Parameters/ClpIESWithCipherParameters.pas

@@ -34,66 +34,145 @@ type
 
   strict private
   var
-    FCipherKeySize: Int32;
-    FPointCompression: Boolean;
-    FNonce: TCryptoLibByteArray;
-    function GetCipherKeySize(): Int32; inline;
-    function GetPointCompression(): Boolean; inline;
-    function GetNonce(): TCryptoLibByteArray; inline;
+    Fnonce: TCryptoLibByteArray;
+    FcipherKeySize: Int32;
+    FusePointCompression: Boolean;
+
+    function GetCipherKeySize: Int32; inline;
+    function GetNonce: TCryptoLibByteArray; inline;
+    function GetPointCompression: Boolean; inline;
   public
-    property CipherKeySize: Int32 read GetCipherKeySize;
-    property PointCompression: Boolean read GetPointCompression;
-    property Nonce: TCryptoLibByteArray read GetNonce;
 
-    /// <param name="derivation"> 
-    /// the derivation parameter for the KDF function.
+    /// <summary>
+    /// Set the IES engine parameters.
+    /// </summary>
+    /// <param name="derivation">
+    /// the optional derivation vector for the KDF.
+    /// </param>
+    /// <param name="encoding">
+    /// the optional encoding vector for the KDF.
+    /// </param>
+    /// <param name="macKeySize">
+    /// the key size (in bits) for the MAC.
+    /// </param>
+    /// <param name="CipherKeySize">
+    /// the key size (in bits) for the block cipher.
+    /// </param>
+    constructor Create(derivation, encoding: TCryptoLibByteArray;
+      macKeySize, CipherKeySize: Int32); overload;
+
+    /// <summary>
+    /// Set the IES engine parameters.
+    /// </summary>
+    /// <param name="derivation">
+    /// the optional derivation vector for the KDF.
     /// </param>
     /// <param name="encoding">
-    /// the encoding parameter for the KDF function.
+    /// the optional encoding vector for the KDF.
+    /// </param>
+    /// <param name="macKeySize">
+    /// the key size (in bits) for the MAC.
+    /// </param>
+    /// <param name="CipherKeySize">
+    /// the key size (in bits) for the block cipher.
     /// </param>
     /// <param name="nonce">
-    /// the iv used in the cipher engine.
+    /// an IV to use initialising the block cipher.
+    /// </param>
+    constructor Create(derivation, encoding: TCryptoLibByteArray;
+      macKeySize, CipherKeySize: Int32; nonce: TCryptoLibByteArray); overload;
+
+    /// <summary>
+    /// Set the IES engine parameters.
+    /// </summary>
+    /// <param name="derivation">
+    /// the optional derivation vector for the KDF.
     /// </param>
-    /// <param name="MacKeySize">
-    /// the size of the MAC key (in bits).
+    /// <param name="encoding">
+    /// the optional encoding vector for the KDF.
+    /// </param>
+    /// <param name="macKeySize">
+    /// the key size (in bits) for the MAC.
     /// </param>
     /// <param name="CipherKeySize">
-    /// the size of the associated Cipher key (in bits).
+    /// the key size (in bits) for the block cipher.
+    /// </param>
+    /// <param name="nonce">
+    /// an IV to use initialising the block cipher.
     /// </param>
-    /// <param name="PointCompression">
-    /// whether to use point compression or not in EphemeralKeyPairGenerator.
+    /// <param name="UsePointCompression">
+    /// whether to use EC point compression or not (false by default)
     /// </param>
-    constructor Create(derivation, encoding, Nonce: TCryptoLibByteArray;
-      MacKeySize, CipherKeySize: Int32; PointCompression: Boolean);
+    constructor Create(derivation, encoding: TCryptoLibByteArray;
+      macKeySize, CipherKeySize: Int32; nonce: TCryptoLibByteArray;
+      UsePointCompression: Boolean); overload;
+
+    /// <summary>
+    /// Return the key size in bits for the block cipher used with the message
+    /// </summary>
+    /// <value>
+    /// the key size in bits for the block cipher used with the message
+    /// </value>
+    property CipherKeySize: Int32 read GetCipherKeySize;
+
+    /// <summary>
+    /// Return the nonce (IV) value to be associated with message.
+    /// </summary>
+    /// <value>
+    /// block cipher IV for message.
+    /// </value>
+    property nonce: TCryptoLibByteArray read GetNonce;
+
+    /// <summary>
+    /// Return the 'point compression' flag.
+    /// </summary>
+    /// <value>
+    /// the point compression flag
+    /// </value>
+    property PointCompression: Boolean read GetPointCompression;
   end;
 
 implementation
 
 { TIESWithCipherParameters }
 
-constructor TIESWithCipherParameters.Create(derivation, encoding,
-  Nonce: TCryptoLibByteArray; MacKeySize, CipherKeySize: Int32;
-  PointCompression: Boolean);
-begin
-  Inherited Create(derivation, encoding, MacKeySize);
-  FNonce := Nonce;
-  FCipherKeySize := CipherKeySize;
-  FPointCompression := PointCompression;
-end;
-
 function TIESWithCipherParameters.GetCipherKeySize: Int32;
 begin
-  result := FCipherKeySize;
+  Result := FcipherKeySize;
 end;
 
 function TIESWithCipherParameters.GetNonce: TCryptoLibByteArray;
 begin
-  result := FNonce;
+  Result := System.Copy(Fnonce);
 end;
 
 function TIESWithCipherParameters.GetPointCompression: Boolean;
 begin
-  result := FPointCompression;
+  Result := FusePointCompression;
+end;
+
+constructor TIESWithCipherParameters.Create(derivation,
+  encoding: TCryptoLibByteArray; macKeySize, CipherKeySize: Int32);
+begin
+  Create(derivation, encoding, macKeySize, CipherKeySize, Nil);
+end;
+
+constructor TIESWithCipherParameters.Create(derivation,
+  encoding: TCryptoLibByteArray; macKeySize, CipherKeySize: Int32;
+  nonce: TCryptoLibByteArray);
+begin
+  Create(derivation, encoding, macKeySize, CipherKeySize, nonce, false);
+end;
+
+constructor TIESWithCipherParameters.Create(derivation,
+  encoding: TCryptoLibByteArray; macKeySize, CipherKeySize: Int32;
+  nonce: TCryptoLibByteArray; UsePointCompression: Boolean);
+begin
+  Inherited Create(derivation, encoding, macKeySize);
+
+  FcipherKeySize := CipherKeySize;
+  Fnonce := System.Copy(nonce);
+  FusePointCompression := UsePointCompression;
 end;
 
 end.

+ 2 - 1
CryptoLib/src/Crypto/Signers/ClpECSchnorrSigner.pas

@@ -290,7 +290,8 @@ end;
 
 function TECSchnorrSigner.GetAlgorithmName: String;
 begin
-  Result := FDigest.AlgorithmName + 'with' + 'ECSCHNORR' + FSigner.AlgorithmName;
+  Result := FDigest.AlgorithmName + 'with' + 'ECSCHNORR' +
+    FSigner.AlgorithmName;
 end;
 
 procedure TECSchnorrSigner.Init(forSigning: Boolean;

+ 224 - 0
CryptoLib/src/Crypto/Signers/ClpHMacDsaKCalculator.pas

@@ -0,0 +1,224 @@
+{ *********************************************************************************** }
+{ *                              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 ClpHMacDsaKCalculator;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Math,
+  ClpHMac,
+  ClpIHMac,
+  ClpIDigest,
+  ClpISecureRandom,
+  ClpBigInteger,
+  ClpBigIntegers,
+  ClpKeyParameter,
+  ClpIKeyParameter,
+  ClpIDsaKCalculator,
+  ClpIHMacDsaKCalculator,
+  ClpCryptoLibTypes;
+
+{$IFNDEF _FIXINSIGHT_}
+
+resourcestring
+  SUnSupportedOperation = 'Operation not Supported';
+{$ENDIF}
+
+type
+
+  /// <summary>
+  /// A deterministic K calculator based on the algorithm in section 3.2 of
+  /// RFC 6979.
+  /// </summary>
+  THMacDsaKCalculator = class(TInterfacedObject, IDsaKCalculator,
+    IHMacDsaKCalculator)
+
+  strict private
+  var
+    FhMac: IHMac;
+    FK, FV: TCryptoLibByteArray;
+    Fn: TBigInteger;
+
+    function BitsToInt(t: TCryptoLibByteArray): TBigInteger; inline;
+
+    function GetIsDeterministic: Boolean; virtual;
+
+  public
+
+    /// <summary>
+    /// Base constructor.
+    /// </summary>
+    /// <param name="digest">
+    /// digest to build the HMAC on.
+    /// </param>
+    constructor Create(const digest: IDigest);
+
+    procedure Init(const n: TBigInteger; const random: ISecureRandom);
+      overload; virtual;
+
+    procedure Init(const n, d: TBigInteger;
+      &message: TCryptoLibByteArray); overload;
+
+    function NextK(): TBigInteger; virtual;
+
+    property IsDeterministic: Boolean read GetIsDeterministic;
+
+  end;
+
+implementation
+
+{ THMacDsaKCalculator }
+
+function THMacDsaKCalculator.GetIsDeterministic: Boolean;
+begin
+  result := True;
+end;
+
+function THMacDsaKCalculator.BitsToInt(t: TCryptoLibByteArray): TBigInteger;
+begin
+  result := TBigInteger.Create(1, t);
+  if ((System.Length(t) * 8) > Fn.BitLength) then
+  begin
+    result := result.ShiftRight((System.Length(t) * 8) - Fn.BitLength);
+  end;
+end;
+
+constructor THMacDsaKCalculator.Create(const digest: IDigest);
+begin
+  Inherited Create();
+  FhMac := THMac.Create(digest);
+  System.SetLength(FV, FhMac.GetMacSize());
+  System.SetLength(FK, FhMac.GetMacSize());
+end;
+
+{$IFNDEF _FIXINSIGHT_}
+
+procedure THMacDsaKCalculator.Init(const n: TBigInteger;
+  const random: ISecureRandom);
+begin
+  raise EInvalidOperationCryptoLibException.CreateRes(@SUnSupportedOperation);
+end;
+{$ENDIF}
+
+procedure THMacDsaKCalculator.Init(const n, d: TBigInteger;
+  &message: TCryptoLibByteArray);
+var
+  x, dVal, m, mVal: TCryptoLibByteArray;
+  mInt: TBigInteger;
+begin
+  Fn := n;
+  System.FillChar(FV[0], System.Length(FV) * System.SizeOf(Byte), Byte($01));
+  System.FillChar(FK[0], System.Length(FK) * System.SizeOf(Byte), Byte(0));
+
+  System.SetLength(x, (n.BitLength + 7) div 8);
+
+  dVal := TBigIntegers.AsUnsignedByteArray(d);
+
+  System.Move(dVal[0], x[System.Length(x) - System.Length(dVal)],
+    System.Length(dVal));
+
+  System.SetLength(m, (n.BitLength + 7) div 8);
+
+  mInt := BitsToInt(&message);
+
+  if (mInt.CompareTo(n) >= 0) then
+  begin
+    mInt := mInt.Subtract(n);
+  end;
+
+  mVal := TBigIntegers.AsUnsignedByteArray(mInt);
+
+  System.Move(mVal[0], m[System.Length(m) - System.Length(mVal)],
+    System.Length(mVal));
+
+  FhMac.Init(TKeyParameter.Create(FK) as IKeyParameter);
+
+  FhMac.BlockUpdate(FV, 0, System.Length(FV));
+  FhMac.Update(Byte($00));
+  FhMac.BlockUpdate(x, 0, System.Length(x));
+  FhMac.BlockUpdate(m, 0, System.Length(m));
+
+  FhMac.DoFinal(FK, 0);
+
+  FhMac.Init(TKeyParameter.Create(FK) as IKeyParameter);
+
+  FhMac.BlockUpdate(FV, 0, System.Length(FV));
+
+  FhMac.DoFinal(FV, 0);
+
+  FhMac.BlockUpdate(FV, 0, System.Length(FV));
+  FhMac.Update(Byte($01));
+  FhMac.BlockUpdate(x, 0, System.Length(x));
+  FhMac.BlockUpdate(m, 0, System.Length(m));
+
+  FhMac.DoFinal(FK, 0);
+
+  FhMac.Init(TKeyParameter.Create(FK) as IKeyParameter);
+
+  FhMac.BlockUpdate(FV, 0, System.Length(FV));
+
+  FhMac.DoFinal(FV, 0);
+end;
+
+function THMacDsaKCalculator.NextK: TBigInteger;
+var
+  t: TCryptoLibByteArray;
+  tOff, len: Int32;
+begin
+  result := Default (TBigInteger);
+  System.SetLength(t, ((Fn.BitLength + 7) div 8));
+
+  while True do
+
+  begin
+    tOff := 0;
+
+    while (tOff < System.Length(t)) do
+    begin
+      FhMac.BlockUpdate(FV, 0, System.Length(FV));
+
+      FhMac.DoFinal(FV, 0);
+
+      len := Min(System.Length(t) - tOff, System.Length(FV));
+      System.Move(FV[0], t[tOff], len * System.SizeOf(Byte));
+      tOff := tOff + len;
+    end;
+
+    result := BitsToInt(t);
+
+    if ((result.SignValue > 0) and (result.CompareTo(Fn) < 0)) then
+    begin
+      Exit;
+    end;
+
+    FhMac.BlockUpdate(FV, 0, System.Length(FV));
+    FhMac.Update(Byte($00));
+
+    FhMac.DoFinal(FK, 0);
+
+    FhMac.Init(TKeyParameter.Create(FK) as IKeyParameter);
+
+    FhMac.BlockUpdate(FV, 0, System.Length(FV));
+
+    FhMac.DoFinal(FV, 0);
+  end;
+end;
+
+end.

+ 2 - 2
CryptoLib/src/Crypto/Signers/ClpRandomDsaKCalculator.pas

@@ -48,7 +48,7 @@ type
     property IsDeterministic: Boolean read GetIsDeterministic;
     procedure Init(const n: TBigInteger; const random: ISecureRandom);
       overload; virtual;
-    procedure Init(n, d: TBigInteger; &message: TCryptoLibByteArray);
+    procedure Init(const n, d: TBigInteger; &message: TCryptoLibByteArray);
       overload; virtual;
     function NextK(): TBigInteger; virtual;
   end;
@@ -71,7 +71,7 @@ end;
 
 {$IFNDEF _FIXINSIGHT_}
 
-procedure TRandomDsaKCalculator.Init(n, d: TBigInteger;
+procedure TRandomDsaKCalculator.Init(const n, d: TBigInteger;
   &message: TCryptoLibByteArray);
 begin
   raise EInvalidOperationCryptoLibException.CreateRes(@SUnSupportedOperation);

+ 100 - 0
CryptoLib/src/Interfaces/ClpIDSAParametersGenerator.pas

@@ -0,0 +1,100 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIDsaParametersGenerator;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpISecureRandom,
+  ClpIDsaParameters,
+  ClpIDsaParameterGenerationParameters;
+
+type
+  IDsaParametersGenerator = interface(IInterface)
+    ['{EB5A601B-2267-4485-A519-A80751FC39EA}']
+
+    /// <summary>
+    /// initialise the key generator.
+    /// </summary>
+    /// <param name="size">
+    /// size of the key (range 2^512 -&amp;gt; 2^1024 - 64 bit increments)
+    /// </param>
+    /// <param name="certainty">
+    /// measure of robustness of prime (for FIPS 186-2 compliance this should
+    /// be at least 80).
+    /// </param>
+    /// <param name="random">
+    /// random byte source.
+    /// </param>
+    procedure Init(size, certainty: Int32;
+      const random: ISecureRandom); overload;
+
+    /// <summary>
+    /// initialise the key generator.
+    /// </summary>
+    /// <param name="size">
+    /// size of the key (range 2^512 -&amp;gt; 2^1024 - 64 bit increments)
+    /// </param>
+    /// <param name="certainty">
+    /// measure of robustness of prime (for FIPS 186-2 compliance this should
+    /// be at least 80).
+    /// </param>
+    /// <param name="iterations">
+    /// iterations
+    /// </param>
+    /// <param name="random">
+    /// random byte source.
+    /// </param>
+    procedure Init(size, certainty, iterations: Int32;
+      const random: ISecureRandom); overload;
+
+    /// <summary>
+    /// <para>
+    /// Initialise the key generator for DSA 2.
+    /// </para>
+    /// <para>
+    /// Use this init method if you need to generate parameters for DSA 2
+    /// keys.
+    /// </para>
+    /// </summary>
+    /// <param name="params">
+    /// DSA 2 key generation parameters.
+    /// </param>
+    procedure Init(const params: IDsaParameterGenerationParameters); overload;
+
+    /// <summary>
+    /// <para>
+    /// which generates the p and g values from the given parameters,
+    /// returning the DSAParameters object.
+    /// </para>
+    /// <para>
+    /// Note: can take a while...
+    /// </para>
+    /// </summary>
+    /// <returns>
+    /// a generated DSA parameters object.
+    /// </returns>
+    function GenerateParameters(): IDsaParameters;
+
+  end;
+
+implementation
+
+end.

+ 2 - 1
CryptoLib/src/Interfaces/ClpIDsaKCalculator.pas

@@ -57,7 +57,8 @@ type
     // * @param d the DSA private value.
     // * @param message the message being signed.
     // */
-    procedure Init(n, d: TBigInteger; &message: TCryptoLibByteArray); overload;
+    procedure Init(const n, d: TBigInteger;
+      &message: TCryptoLibByteArray); overload;
 
     // /**
     // * Return the next valid value of K.

+ 45 - 0
CryptoLib/src/Interfaces/ClpIDsaParameter.pas

@@ -0,0 +1,45 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIDsaParameter;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIProxiedInterface,
+  ClpBigInteger;
+
+type
+  IDsaParameter = interface(IAsn1Convertible)
+    ['{037E0113-0BD6-4A61-8BDC-DBEBE6136A6C}']
+
+    function GetP: TBigInteger;
+    property p: TBigInteger read GetP;
+
+    function GetG: TBigInteger;
+    property g: TBigInteger read GetG;
+
+    function GetQ: TBigInteger;
+    property q: TBigInteger read GetQ;
+
+  end;
+
+implementation
+
+end.

+ 49 - 0
CryptoLib/src/Interfaces/ClpIDsaParameterGenerationParameters.pas

@@ -0,0 +1,49 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIDsaParameterGenerationParameters;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpISecureRandom;
+
+type
+  IDsaParameterGenerationParameters = interface(IInterface)
+    ['{52ACCC72-7FF6-4934-81E5-F616BEB0EE04}']
+
+    function GetL: Int32;
+    property L: Int32 read GetL;
+
+    function GetN: Int32;
+    property N: Int32 read GetN;
+
+    function GetUsageIndex: Int32;
+    property usageIndex: Int32 read GetUsageIndex;
+
+    function GetCertainty: Int32;
+    property certainty: Int32 read GetCertainty;
+
+    function GetRandom: ISecureRandom;
+    property random: ISecureRandom read GetRandom;
+  end;
+
+implementation
+
+end.

+ 3 - 0
CryptoLib/src/Interfaces/ClpIDsaPrivateKeyParameters.pas

@@ -1,3 +1,6 @@
+{ *********************************************************************************** }
+{ *                              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  * }

+ 4 - 1
CryptoLib/src/Interfaces/ClpIECDomainParameters.pas

@@ -33,14 +33,17 @@ type
 
     function GetCurve: IECCurve;
     function GetG: IECPoint;
-    function GetH: TBigInteger;
     function GetN: TBigInteger;
+    function GetH: TBigInteger;
+
+    function GetHInv: TBigInteger;
     function GetSeed: TCryptoLibByteArray;
 
     property Curve: IECCurve read GetCurve;
     property G: IECPoint read GetG;
     property N: TBigInteger read GetN;
     property H: TBigInteger read GetH;
+    property HInv: TBigInteger read GetHInv;
     property Seed: TCryptoLibByteArray read GetSeed;
     function Equals(const other: IECDomainParameters): Boolean;
     function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;

+ 17 - 2
CryptoLib/src/Interfaces/ClpIECFieldElement.pas

@@ -78,7 +78,13 @@ type
   end;
 
 type
-  IFpFieldElement = interface(IECFieldElement)
+  IAbstractFpFieldElement = interface(IECFieldElement)
+
+    ['{C3FFD257-58FB-4730-B26A-E225C48F374E}']
+  end;
+
+type
+  IFpFieldElement = interface(IAbstractFpFieldElement)
 
     ['{F5106EAC-DA8F-4815-8403-3D9C5438BF6F}']
 
@@ -102,7 +108,16 @@ type
   end;
 
 type
-  IF2mFieldElement = interface(IECFieldElement)
+  IAbstractF2mFieldElement = interface(IECFieldElement)
+
+    ['{EA6B19A3-77AF-4EDE-A96B-D736DBD71B81}']
+
+    function Trace(): Int32;
+    function HalfTrace(): IECFieldElement;
+  end;
+
+type
+  IF2mFieldElement = interface(IAbstractF2mFieldElement)
 
     ['{1B29CD22-21C3-424B-9496-BF5F1E4662E8}']
 

+ 13 - 33
CryptoLib/src/Interfaces/ClpIECInterface.pas

@@ -23,6 +23,7 @@ interface
 
 uses
   Generics.Collections,
+  ClpIPreCompCallback,
   ClpIECFieldElement,
   ClpCryptoLibTypes,
   ClpIFiniteField,
@@ -41,17 +42,13 @@ type
     procedure SetpreCompTable(const Value: TDictionary<String, IPreCompInfo>);
     function GetCurve: IECCurve;
     function GetCurveCoordinateSystem: Int32;
-    function GetX: IECFieldElement;
-      deprecated 'Use AffineXCoord, or Normalize() and XCoord, instead';
-    function GetY: IECFieldElement;
-      deprecated 'Use AffineYCoord, or Normalize() and YCoord, instead';
     function GetAffineXCoord: IECFieldElement;
     function GetAffineYCoord: IECFieldElement;
     function GetXCoord: IECFieldElement;
     function GetYCoord: IECFieldElement;
     function GetCompressionYTilde: Boolean;
 
-    function SatisfiesCofactor(): Boolean;
+    function SatisfiesOrder(): Boolean;
     function SatisfiesCurveEquation(): Boolean;
     function Detach(): IECPoint;
 
@@ -88,8 +85,12 @@ type
 
     function Normalize(const zInv: IECFieldElement): IECPoint; overload;
 
+    function ImplIsValid(decompressed, checkOrder: Boolean): Boolean;
+
     function IsValid(): Boolean;
 
+    function IsValidPartial(): Boolean;
+
     function ScaleX(const scale: IECFieldElement): IECPoint;
     function ScaleY(const scale: IECFieldElement): IECPoint;
 
@@ -115,27 +116,6 @@ type
     property preCompTable: TDictionary<String, IPreCompInfo>
       read GetpreCompTable write SetpreCompTable;
 
-    /// <summary>
-    /// <para>
-    /// Normalizes this point, and then returns the affine x-coordinate.
-    /// </para>
-    /// <para>
-    /// Note: normalization can be expensive, this method is deprecated
-    /// in favour of caller-controlled normalization.
-    /// </para>
-    /// </summary>
-    property x: IECFieldElement read GetX;
-    /// <summary>
-    /// <para>
-    /// Normalizes this point, and then returns the affine y-coordinate.
-    /// </para>
-    /// <para>
-    /// Note: normalization can be expensive, this method is deprecated
-    /// in favour of caller-controlled normalization.
-    /// </para>
-    /// </summary>
-    property y: IECFieldElement read GetY;
-
     /// <summary>
     /// Returns the affine x-coordinate after checking that this point is
     /// normalized.
@@ -340,8 +320,8 @@ type
       : IPreCompInfo;
 
     /// <summary>
-    /// Adds <c>PreCompInfo</c> for a point on this curve, under a given name.
-    /// Used by <c>ECMultiplier</c> to save the precomputation for this <c>
+    /// Compute a <c>PreCompInfo</c> for a point on this curve, under a given
+    /// name. Used by <c>ECMultiplier</c> to save the precomputation for this <c>
     /// ECPoint</c> for use by subsequent multiplication.
     /// </summary>
     /// <param name="point">
@@ -350,11 +330,11 @@ type
     /// <param name="name">
     /// A <c>String</c> used to index precomputations of different types.
     /// </param>
-    /// <param name="preCompInfo">
-    /// The values precomputed by the <c>ECMultiplier.</c>
+    /// <param name="callback">
+    /// Called to calculate the <c>PreCompInfo</c>
     /// </param>
-    procedure SetPreCompInfo(const point: IECPoint; const name: String;
-      const preCompInfo: IPreCompInfo);
+    function Precompute(const point: IECPoint; const name: String;
+      const callback: IPreCompCallback): IPreCompInfo;
 
     function ImportPoint(const p: IECPoint): IECPoint;
 
@@ -504,7 +484,7 @@ type
     // * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
     // *         <code>null</code> if no solution exists.
     // */
-    function SolveQuadradicEquation(const beta: IECFieldElement)
+    function SolveQuadraticEquation(const beta: IECFieldElement)
       : IECFieldElement;
 
     // /**

+ 1 - 1
CryptoLib/src/Interfaces/ClpIECSchnorrBSISigner.pas

@@ -27,7 +27,7 @@ uses
 type
   IECSchnorrBSISigner = interface(ISchnorr)
 
-   ['{799FABB1-D1BB-4B58-9E49-CF1CD8142554}']
+    ['{799FABB1-D1BB-4B58-9E49-CF1CD8142554}']
   end;
 
 implementation

+ 1 - 1
CryptoLib/src/Interfaces/ClpIFilterStream.pas

@@ -33,7 +33,7 @@ type
     procedure SetPosition(const Value: Int64);
 
     property Size: Int64 read GetSize;
-    property Position: Int64 read GetPosition write setPosition;
+    property Position: Int64 read GetPosition write SetPosition;
 
     function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
     function Read(var Buffer; Count: Int32): Int32;

+ 0 - 2
CryptoLib/src/Interfaces/ClpIFixedPointCombMultiplier.pas

@@ -28,8 +28,6 @@ type
   IFixedPointCombMultiplier = interface(IAbstractECMultiplier)
     ['{A3345E31-4D5C-4442-9C3D-ACC7F6DA4A14}']
 
-    function GetWidthForCombSize(combSize: Int32): Int32;
-      deprecated 'Is no longer used; remove any overrides in subclasses.';
   end;
 
 implementation

+ 1 - 6
CryptoLib/src/Interfaces/ClpIFixedPointPreCompInfo.pas

@@ -32,18 +32,13 @@ type
 
     function GetWidth: Int32;
     procedure SetWidth(const Value: Int32);
-    function GetPreComp: TCryptoLibGenericArray<IECPoint>;
-      deprecated 'Will be removed';
-    procedure SetPreComp(const Value: TCryptoLibGenericArray<IECPoint>);
-      deprecated 'Will be removed';
     function GetLookupTable: IECLookupTable;
     procedure SetLookupTable(const Value: IECLookupTable);
     function GetOffset: IECPoint;
     procedure SetOffset(const Value: IECPoint);
 
     property Offset: IECPoint read GetOffset write SetOffset;
-    property PreComp: TCryptoLibGenericArray<IECPoint> read GetPreComp
-      write SetPreComp; {$IFDEF FPC }deprecated 'Use "LookupTable" property instead.'; {$ENDIF FPC }
+
     property LookupTable: IECLookupTable read GetLookupTable
       write SetLookupTable;
     property Width: Int32 read GetWidth write SetWidth;

+ 0 - 1
CryptoLib/src/Interfaces/ClpIGF2Polynomial.pas

@@ -34,7 +34,6 @@ type
     function Equals(const other: IGF2Polynomial): Boolean;
     function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
 {$ENDIF DELPHI}
-
     property exponents: TCryptoLibInt32Array read GetExponents;
 
   end;

+ 0 - 1
CryptoLib/src/Interfaces/ClpIGenericPolynomialExtensionField.pas

@@ -34,7 +34,6 @@ type
       : Boolean; overload;
     function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
 {$ENDIF DELPHI}
-
   end;
 
 implementation

+ 1 - 1
CryptoLib/src/Interfaces/ClpIHMac.pas

@@ -27,7 +27,7 @@ uses
 type
 
   IHMac = interface(IMac)
- ['{B1182608-04D5-4985-91C8-571C51E07CB5}']
+    ['{B1182608-04D5-4985-91C8-571C51E07CB5}']
 
   end;
 

+ 39 - 0
CryptoLib/src/Interfaces/ClpIHMacDsaKCalculator.pas

@@ -0,0 +1,39 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIHMacDsaKCalculator;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIDsaKCalculator;
+
+type
+  /// <summary>
+  /// A deterministic K calculator based on the algorithm in section 3.2 of
+  /// RFC 6979.
+  /// </summary>
+  IHMacDsaKCalculator = interface(IDsaKCalculator)
+    ['{A075E2C3-2EE8-4CAC-BDF8-977408617B98}']
+
+  end;
+
+implementation
+
+end.

+ 35 - 0
CryptoLib/src/Interfaces/ClpIHkdfBytesGenerator.pas

@@ -0,0 +1,35 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIHkdfBytesGenerator;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIDerivationFunction;
+
+type
+  IHkdfBytesGenerator = interface(IDerivationFunction)
+    ['{79B29B35-33BB-4056-9101-828C88D1ADB0}']
+
+  end;
+
+implementation
+
+end.

+ 71 - 0
CryptoLib/src/Interfaces/ClpIHkdfParameters.pas

@@ -0,0 +1,71 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIHkdfParameters;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIDerivationParameters,
+  ClpCryptoLibTypes;
+
+type
+  IHkdfParameters = interface(IDerivationParameters)
+    ['{433636F6-C14E-41EB-84C6-B57746ABD13D}']
+
+    /// <summary>
+    /// Returns the input keying material or seed.
+    /// </summary>
+    /// <returns>
+    /// the keying material
+    /// </returns>
+    function GetIkm(): TCryptoLibByteArray;
+
+    /// <summary>
+    /// Returns the salt, or null if the salt should be generated as a byte
+    /// array <br />of HashLen zeros.
+    /// </summary>
+    /// <returns>
+    /// the salt, or null
+    /// </returns>
+    function GetSalt(): TCryptoLibByteArray;
+
+    /// <summary>
+    /// Returns the info field, which may be empty (null is converted to
+    /// empty).
+    /// </summary>
+    /// <returns>
+    /// the info field, never null
+    /// </returns>
+    function GetInfo(): TCryptoLibByteArray;
+
+    /// <summary>
+    /// Returns if step 1: extract has to be skipped or not
+    /// </summary>
+    /// <returns>
+    /// true for skipping, false for no skipping of step 1
+    /// </returns>
+    function GetSkipExtract: Boolean;
+
+    property SkipExtract: Boolean read GetSkipExtract;
+  end;
+
+implementation
+
+end.

Some files were not shown because too many files changed in this diff