Browse Source

some refactoring and cleanup.

Ugochukwu Mmaduekwe 7 years ago
parent
commit
274b66a3b6
28 changed files with 825 additions and 171 deletions
  1. 4 1
      CryptoLib.Samples/Delphi.Samples/UsageSamples.dpr
  2. 10 10
      CryptoLib.Samples/src/UsageExamples.pas
  3. 4 1
      CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.dpr
  4. 11 11
      CryptoLib.Tests/src/Crypto/DigestRandomNumberTests.pas
  5. 83 0
      CryptoLib.Tests/src/Others/ECTests.pas
  6. 46 1
      CryptoLib/src/Asn1/Nist/ClpNistObjectIdentifiers.pas
  7. 138 0
      CryptoLib/src/Crypto/Agreement/ClpECDHCBasicAgreement.pas
  8. 177 0
      CryptoLib/src/Crypto/Digests/ClpDigest.pas
  9. 7 7
      CryptoLib/src/Crypto/Generators/ClpBaseKdfBytesGenerator.pas
  10. 5 5
      CryptoLib/src/Crypto/Generators/ClpPascalCoinECIESKdfBytesGenerator.pas
  11. 2 2
      CryptoLib/src/Crypto/Generators/ClpPkcs5S2ParametersGenerator.pas
  12. 11 5
      CryptoLib/src/Crypto/Macs/ClpHMac.pas
  13. 29 0
      CryptoLib/src/Crypto/Parameters/ClpDsaParameters.pas
  14. 7 11
      CryptoLib/src/Crypto/Prng/ClpDigestRandomGenerator.pas
  15. 8 8
      CryptoLib/src/Crypto/Signers/ClpDsaDigestSigner.pas
  16. 11 8
      CryptoLib/src/Crypto/Signers/ClpECSchnorrBSISigner.pas
  17. 12 10
      CryptoLib/src/Crypto/Signers/ClpECSchnorrISOSigner.pas
  18. 8 6
      CryptoLib/src/Crypto/Signers/ClpECSchnorrISOXSigner.pas
  19. 9 6
      CryptoLib/src/Crypto/Signers/ClpECSchnorrLIBSECPSigner.pas
  20. 2 2
      CryptoLib/src/Crypto/Signers/ClpECSchnorrSigner.pas
  21. 64 3
      CryptoLib/src/Interfaces/ClpIDigest.pas
  22. 0 4
      CryptoLib/src/Interfaces/ClpIDsaKeyPairGenerator.pas
  23. 54 0
      CryptoLib/src/Interfaces/ClpIECDHCBasicAgreement.pas
  24. 14 2
      CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.lpk
  25. 2 1
      CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.pas
  26. 89 66
      CryptoLib/src/Security/ClpDigestUtilities.pas
  27. 1 1
      CryptoLib/src/Security/ClpSecureRandom.pas
  28. 17 0
      CryptoLib/src/Utils/ClpArrayUtils.pas

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

@@ -391,7 +391,10 @@ uses
   ClpIDsaKeyPairGenerator in '..\..\CryptoLib\src\Interfaces\ClpIDsaKeyPairGenerator.pas',
   ClpIDsaKeyPairGenerator in '..\..\CryptoLib\src\Interfaces\ClpIDsaKeyPairGenerator.pas',
   ClpDsaSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpDsaSigner.pas',
   ClpDsaSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpDsaSigner.pas',
   ClpBase58 in '..\..\CryptoLib\src\Utils\Encoders\ClpBase58.pas',
   ClpBase58 in '..\..\CryptoLib\src\Utils\Encoders\ClpBase58.pas',
-  ClpIDsaSigner in '..\..\CryptoLib\src\Interfaces\ClpIDsaSigner.pas';
+  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';
 
 
 begin
 begin
   try
   try

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

@@ -199,24 +199,24 @@ begin
   System.SetLength(IVBytes, LKey);
   System.SetLength(IVBytes, LKey);
   // Max size to start then reduce it at the end
   // Max size to start then reduce it at the end
   LDigest := TDigestUtilities.GetDigest('SHA-256'); // SHA2_256
   LDigest := TDigestUtilities.GetDigest('SHA-256'); // SHA2_256
-  System.Assert(LDigest.HashSize >= LKey);
-  System.Assert(LDigest.HashSize >= LIV);
+  System.Assert(LDigest.GetDigestSize >= LKey);
+  System.Assert(LDigest.GetDigestSize >= LIV);
   // Derive Key First
   // Derive Key First
-  LDigest.TransformBytes(PasswordBytes);
+  LDigest.BlockUpdate(PasswordBytes, 0, System.Length(PasswordBytes));
   if SaltBytes <> Nil then
   if SaltBytes <> Nil then
   begin
   begin
-    LDigest.TransformBytes(SaltBytes);
+    LDigest.BlockUpdate(SaltBytes, 0, System.Length(SaltBytes));
   end;
   end;
-  KeyBytes := System.Copy(LDigest.TransformFinal.GetBytes);
+  LDigest.DoFinal(KeyBytes, 0);
   // Derive IV Next
   // Derive IV Next
-  LDigest.Initialize();
-  LDigest.TransformBytes(KeyBytes);
-  LDigest.TransformBytes(PasswordBytes);
+  LDigest.Reset();
+  LDigest.BlockUpdate(KeyBytes, 0, System.Length(KeyBytes));
+  LDigest.BlockUpdate(PasswordBytes, 0, System.Length(PasswordBytes));
   if SaltBytes <> Nil then
   if SaltBytes <> Nil then
   begin
   begin
-    LDigest.TransformBytes(SaltBytes);
+    LDigest.BlockUpdate(SaltBytes, 0, System.Length(SaltBytes));
   end;
   end;
-  IVBytes := System.Copy(LDigest.TransformFinal.GetBytes);
+  LDigest.DoFinal(IVBytes, 0);
 
 
   System.SetLength(IVBytes, LIV);
   System.SetLength(IVBytes, LIV);
   Result := True;
   Result := True;

+ 4 - 1
CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.dpr

@@ -429,7 +429,10 @@ uses
   ClpIDsaKeyPairGenerator in '..\..\CryptoLib\src\Interfaces\ClpIDsaKeyPairGenerator.pas',
   ClpIDsaKeyPairGenerator in '..\..\CryptoLib\src\Interfaces\ClpIDsaKeyPairGenerator.pas',
   ClpDsaSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpDsaSigner.pas',
   ClpDsaSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpDsaSigner.pas',
   ClpBase58 in '..\..\CryptoLib\src\Utils\Encoders\ClpBase58.pas',
   ClpBase58 in '..\..\CryptoLib\src\Utils\Encoders\ClpBase58.pas',
-  ClpIDsaSigner in '..\..\CryptoLib\src\Interfaces\ClpIDsaSigner.pas';
+  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';
 
 
 begin
 begin
 
 

+ 11 - 11
CryptoLib.Tests/src/Crypto/DigestRandomNumberTests.pas

@@ -85,11 +85,11 @@ var
   i, j: Int32;
   i, j: Int32;
 begin
 begin
   rGen := TDigestRandomGenerator.Create(digest);
   rGen := TDigestRandomGenerator.Create(digest);
-  System.SetLength(output, digest.HashSize);
-  System.SetLength(averages, digest.HashSize);
-  System.SetLength(ands, digest.HashSize);
-  System.SetLength(xors, digest.HashSize);
-  System.SetLength(ors, digest.HashSize);
+  System.SetLength(output, digest.GetDigestSize);
+  System.SetLength(averages, digest.GetDigestSize);
+  System.SetLength(ands, digest.GetDigestSize);
+  System.SetLength(xors, digest.GetDigestSize);
+  System.SetLength(ors, digest.GetDigestSize);
 
 
   rGen.AddSeedMaterial(seed);
   rGen.AddSeedMaterial(seed);
 
 
@@ -115,19 +115,19 @@ begin
   begin
   begin
     if ((averages[i] div 1000000) <> 127) then
     if ((averages[i] div 1000000) <> 127) then
     begin
     begin
-      Fail(Format('average test failed for %s', [digest.Name]));
+      Fail(Format('average test failed for %s', [digest.AlgorithmName]));
     end;
     end;
     if (ands[i] <> 0) then
     if (ands[i] <> 0) then
     begin
     begin
-      Fail(Format('and test failed for %s', [digest.Name]));
+      Fail(Format('and test failed for %s', [digest.AlgorithmName]));
     end;
     end;
     if ((ors[i] and $FF) <> $FF) then
     if ((ors[i] and $FF) <> $FF) then
     begin
     begin
-      Fail(Format('or test failed for %s', [digest.Name]));
+      Fail(Format('or test failed for %s', [digest.AlgorithmName]));
     end;
     end;
     if (xors[i] <> expectedXors[i]) then
     if (xors[i] <> expectedXors[i]) then
     begin
     begin
-      Fail(Format('xor test failed for %s', [digest.Name]));
+      Fail(Format('xor test failed for %s', [digest.AlgorithmName]));
     end;
     end;
     System.Inc(i);
     System.Inc(i);
   end;
   end;
@@ -148,7 +148,7 @@ var
   i: Int32;
   i: Int32;
 begin
 begin
   rGen := TDigestRandomGenerator.Create(digest);
   rGen := TDigestRandomGenerator.Create(digest);
-  System.SetLength(output, digest.HashSize);
+  System.SetLength(output, digest.GetDigestSize);
 
 
   rGen.AddSeedMaterial(seed);
   rGen.AddSeedMaterial(seed);
 
 
@@ -182,7 +182,7 @@ var
   i: Int32;
   i: Int32;
 begin
 begin
   rGen := TDigestRandomGenerator.Create(digest);
   rGen := TDigestRandomGenerator.Create(digest);
-  System.SetLength(output, digest.HashSize);
+  System.SetLength(output, digest.GetDigestSize);
 
 
   rGen.AddSeedMaterial(seed);
   rGen.AddSeedMaterial(seed);
 
 

+ 83 - 0
CryptoLib.Tests/src/Others/ECTests.pas

@@ -37,6 +37,9 @@ uses
   ClpISecureRandom,
   ClpISecureRandom,
   ClpECDsaSigner,
   ClpECDsaSigner,
   ClpIECDsaSigner,
   ClpIECDsaSigner,
+  ClpIBasicAgreement,
+  ClpECDHBasicAgreement,
+  ClpECDHCBasicAgreement,
   ClpParametersWithRandom,
   ClpParametersWithRandom,
   ClpIParametersWithRandom,
   ClpIParametersWithRandom,
   ClpECPublicKeyParameters,
   ClpECPublicKeyParameters,
@@ -114,6 +117,11 @@ type
     /// </summary>
     /// </summary>
     procedure TestECDsaKeyGenTest();
     procedure TestECDsaKeyGenTest();
 
 
+    /// <summary>
+    /// Basic Key Agreement Test
+    /// </summary>
+    procedure TestECBasicAgreementTest();
+
   end;
   end;
 
 
 implementation
 implementation
@@ -644,6 +652,81 @@ begin
   end;
   end;
 end;
 end;
 
 
+procedure TTestEC.TestECBasicAgreementTest;
+var
+  random: ISecureRandom;
+  n, k1, k2: TBigInteger;
+  curve: IFpCurve;
+  parameters: IECDomainParameters;
+  pGen: IECKeyPairGenerator;
+  genParam: IECKeyGenerationParameters;
+  p1, p2: IAsymmetricCipherKeyPair;
+  e1, e2: IBasicAgreement;
+begin
+  random := TSecureRandom.Create();
+
+  n := TBigInteger.Create
+    ('883423532389192164791648750360308884807550341691627752275345424702807307');
+
+  curve := TFpCurve.Create
+    (TBigInteger.Create
+    ('883423532389192164791648750360308885314476597252960362792450860609699839'),
+    // q
+    TBigInteger.Create
+    ('7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc', 16), // a
+    TBigInteger.Create
+    ('6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a', 16), // b
+    n, TBigInteger.One);
+
+  parameters := TECDomainParameters.Create(curve,
+    curve.DecodePoint(THex.Decode
+    ('020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf')), // G
+    n);
+
+  pGen := TECKeyPairGenerator.Create();
+  genParam := TECKeyGenerationParameters.Create(parameters, random);
+
+  pGen.Init(genParam);
+
+  p1 := pGen.GenerateKeyPair();
+  p2 := pGen.GenerateKeyPair();
+
+  //
+  // two way
+  //
+  e1 := TECDHBasicAgreement.Create();
+  e2 := TECDHBasicAgreement.Create();
+
+  e1.Init(p1.Private);
+  e2.Init(p2.Private);
+
+  k1 := e1.CalculateAgreement(p2.Public);
+  k2 := e2.CalculateAgreement(p1.Public);
+
+  if (not(k1.Equals(k2))) then
+  begin
+    Fail('calculated agreement test failed');
+  end;
+
+  //
+  // two way
+  //
+  e1 := TECDHCBasicAgreement.Create();
+  e2 := TECDHCBasicAgreement.Create();
+
+  e1.Init(p1.Private);
+  e2.Init(p2.Private);
+
+  k1 := e1.CalculateAgreement(p2.Public);
+  k2 := e2.CalculateAgreement(p1.Public);
+
+  if (not(k1.Equals(k2))) then
+  begin
+    Fail('calculated agreement test failed');
+  end;
+
+end;
+
 initialization
 initialization
 
 
 // Register any test cases with the test runner
 // Register any test cases with the test runner

+ 46 - 1
CryptoLib/src/Asn1/Nist/ClpNistObjectIdentifiers.pas

@@ -39,7 +39,8 @@ type
       FIdAes128Cbc, FIdAes128Ofb, FIdAes128Cfb, FidAes192Ecb, FIdAes192Cbc,
       FIdAes128Cbc, FIdAes128Ofb, FIdAes128Cfb, FidAes192Ecb, FIdAes192Cbc,
       FIdAes192Ofb, FIdAes192Cfb, FIdAes256Ecb, FIdAes256Cbc, FIdAes256Ofb,
       FIdAes192Ofb, FIdAes192Cfb, FIdAes256Ecb, FIdAes256Cbc, FIdAes256Ofb,
       FIdAes256Cfb, FIdDsaWithSha2, FDsaWithSha224, FDsaWithSha256,
       FIdAes256Cfb, FIdDsaWithSha2, FDsaWithSha224, FDsaWithSha256,
-      FDsaWithSha384, FDsaWithSha512: IDerObjectIdentifier;
+      FDsaWithSha384, FDsaWithSha512, FIdDsaWithSha3_224, FIdDsaWithSha3_256,
+      FIdDsaWithSha3_384, FIdDsaWithSha3_512: IDerObjectIdentifier;
 
 
     class function GetNistAlgorithm: IDerObjectIdentifier; static; inline;
     class function GetNistAlgorithm: IDerObjectIdentifier; static; inline;
     class function GetHashAlgs: IDerObjectIdentifier; static; inline;
     class function GetHashAlgs: IDerObjectIdentifier; static; inline;
@@ -81,6 +82,11 @@ type
     class function GetDsaWithSha384: IDerObjectIdentifier; static; inline;
     class function GetDsaWithSha384: IDerObjectIdentifier; static; inline;
     class function GetDsaWithSha512: IDerObjectIdentifier; static; inline;
     class function GetDsaWithSha512: IDerObjectIdentifier; static; inline;
 
 
+    class function GetIdDsaWithSha3_224: IDerObjectIdentifier; static; inline;
+    class function GetIdDsaWithSha3_256: IDerObjectIdentifier; static; inline;
+    class function GetIdDsaWithSha3_384: IDerObjectIdentifier; static; inline;
+    class function GetIdDsaWithSha3_512: IDerObjectIdentifier; static; inline;
+
     class constructor NistObjectIdentifiers();
     class constructor NistObjectIdentifiers();
 
 
   public
   public
@@ -136,6 +142,15 @@ type
     class property DsaWithSha384: IDerObjectIdentifier read GetDsaWithSha384;
     class property DsaWithSha384: IDerObjectIdentifier read GetDsaWithSha384;
     class property DsaWithSha512: IDerObjectIdentifier read GetDsaWithSha512;
     class property DsaWithSha512: IDerObjectIdentifier read GetDsaWithSha512;
 
 
+    class property IdDsaWithSha3_224: IDerObjectIdentifier
+      read GetIdDsaWithSha3_224;
+    class property IdDsaWithSha3_256: IDerObjectIdentifier
+      read GetIdDsaWithSha3_256;
+    class property IdDsaWithSha3_384: IDerObjectIdentifier
+      read GetIdDsaWithSha3_384;
+    class property IdDsaWithSha3_512: IDerObjectIdentifier
+      read GetIdDsaWithSha3_512;
+
     class procedure Boot(); static;
     class procedure Boot(); static;
 
 
   end;
   end;
@@ -313,6 +328,30 @@ begin
   result := FIdSha512_256;
   result := FIdSha512_256;
 end;
 end;
 
 
+class function TNistObjectIdentifiers.GetIdDsaWithSha3_224
+  : IDerObjectIdentifier;
+begin
+  result := FIdDsaWithSha3_224;
+end;
+
+class function TNistObjectIdentifiers.GetIdDsaWithSha3_256
+  : IDerObjectIdentifier;
+begin
+  result := FIdDsaWithSha3_256;
+end;
+
+class function TNistObjectIdentifiers.GetIdDsaWithSha3_384
+  : IDerObjectIdentifier;
+begin
+  result := FIdDsaWithSha3_384;
+end;
+
+class function TNistObjectIdentifiers.GetIdDsaWithSha3_512
+  : IDerObjectIdentifier;
+begin
+  result := FIdDsaWithSha3_512;
+end;
+
 class function TNistObjectIdentifiers.GetNistAlgorithm: IDerObjectIdentifier;
 class function TNistObjectIdentifiers.GetNistAlgorithm: IDerObjectIdentifier;
 begin
 begin
   result := FNistAlgorithm;
   result := FNistAlgorithm;
@@ -368,6 +407,12 @@ begin
   FDsaWithSha256 := TDerObjectIdentifier.Create(IdDsaWithSha2.id + '.2');
   FDsaWithSha256 := TDerObjectIdentifier.Create(IdDsaWithSha2.id + '.2');
   FDsaWithSha384 := TDerObjectIdentifier.Create(IdDsaWithSha2.id + '.3');
   FDsaWithSha384 := TDerObjectIdentifier.Create(IdDsaWithSha2.id + '.3');
   FDsaWithSha512 := TDerObjectIdentifier.Create(IdDsaWithSha2.id + '.4');
   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');
+
 end;
 end;
 
 
 end.
 end.

+ 138 - 0
CryptoLib/src/Crypto/Agreement/ClpECDHCBasicAgreement.pas

@@ -0,0 +1,138 @@
+{ *********************************************************************************** }
+{ *                              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 ClpECDHCBasicAgreement;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpBigInteger,
+  ClpICipherParameters,
+  ClpIECInterface,
+  ClpIBasicAgreement,
+  ClpIECDomainParameters,
+  ClpIECDHCBasicAgreement,
+  ClpIECPrivateKeyParameters,
+  ClpIParametersWithRandom,
+  ClpIECPublicKeyParameters,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SWrongDomainParameter = 'ECDHC Public Key has Wrong Domain Parameters';
+  SInvalidAgreementValue = 'Infinity is not a Valid Agreement Value for ECDHC';
+
+type
+  /// <summary>
+  /// P1363 7.2.2 ECSVDP-DHC <br /><br />ECSVDP-DHC is Elliptic Curve Secret
+  /// Value Derivation Primitive, <br />Diffie-Hellman version with cofactor
+  /// multiplication. It is based on <br />the work of [DH76], [Mil86],
+  /// [Kob87], [LMQ98] and [Kal98a]. This <br />primitive derives a shared
+  /// secret value from one party's private key <br />and another party's
+  /// public key, where both have the same set of EC <br />domain parameters.
+  /// If two parties correctly execute this primitive, <br />they will
+  /// produce the same output. This primitive can be invoked by a <br />
+  /// scheme to derive a shared secret key; specifically, it may be used <br />
+  /// with the schemes ECKAS-DH1 and DL/ECKAS-DH2. It does not assume the <br />
+  /// validity of the input public key (see also Section 7.2.1). <br /><br />
+  /// Note: As stated P1363 compatibility mode with ECDH can be preset, and <br />
+  /// in this case the implementation doesn't have a ECDH compatibility mode <br />
+  /// (if you want that just use ECDHBasicAgreement and note they both
+  /// implement <br />BasicAgreement!). <br />
+  /// </summary>
+  TECDHCBasicAgreement = class(TInterfacedObject, IECDHCBasicAgreement,
+    IBasicAgreement)
+
+  strict protected
+  var
+    FprivKey: IECPrivateKeyParameters;
+
+  public
+    /// <summary>
+    /// initialise the agreement engine.
+    /// </summary>
+    procedure Init(const parameters: ICipherParameters); virtual;
+
+    /// <summary>
+    /// return the field size for the agreement algorithm in bytes.
+    /// </summary>
+    function GetFieldSize(): Int32; virtual;
+
+    /// <summary>
+    /// given a public key from a given party calculate the next message
+    /// in the agreement sequence.
+    /// </summary>
+    function CalculateAgreement(const pubKey: ICipherParameters)
+      : TBigInteger; virtual;
+
+  end;
+
+implementation
+
+{ TECDHCBasicAgreement }
+
+function TECDHCBasicAgreement.CalculateAgreement(const pubKey
+  : ICipherParameters): TBigInteger;
+var
+  pub: IECPublicKeyParameters;
+  parameters: IECDomainParameters;
+  hd: TBigInteger;
+  P: IECPoint;
+begin
+  pub := pubKey as IECPublicKeyParameters;
+  parameters := pub.parameters;
+  if (not(parameters.Equals(FprivKey.parameters))) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes(@SWrongDomainParameter);
+
+  end;
+
+  hd := parameters.H.Multiply(FprivKey.D).&Mod(parameters.N);
+
+  P := pub.Q.Multiply(hd).Normalize();
+
+  if (P.IsInfinity) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes
+      (@SInvalidAgreementValue);
+
+  end;
+
+  result := P.AffineXCoord.ToBigInteger();
+end;
+
+function TECDHCBasicAgreement.GetFieldSize: Int32;
+begin
+  result := (FprivKey.parameters.Curve.FieldSize + 7) div 8;
+end;
+
+procedure TECDHCBasicAgreement.Init(const parameters: ICipherParameters);
+var
+  Lparameters: ICipherParameters;
+begin
+  Lparameters := parameters;
+  if Supports(Lparameters, IParametersWithRandom) then
+  begin
+    Lparameters := (Lparameters as IParametersWithRandom).parameters;
+  end;
+
+  FprivKey := Lparameters as IECPrivateKeyParameters;
+end;
+
+end.

+ 177 - 0
CryptoLib/src/Crypto/Digests/ClpDigest.pas

@@ -0,0 +1,177 @@
+{ *                              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 ClpDigest;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  HlpIHash,
+  ClpIDigest,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SOutputBufferTooShort = 'Output Buffer Too Short';
+
+type
+
+  /// <summary>
+  /// Hash Wrapper For the Proper Implementation in HashLib4Pascal
+  /// </summary>
+  TDigest = class sealed(TInterfacedObject, IDigest)
+
+  strict private
+  var
+    FHash: IHash;
+
+    function GetAlgorithmName: string; inline;
+
+    function DoFinal: TCryptoLibByteArray; overload;
+
+  public
+    constructor Create(const hash: IHash);
+
+    /// <summary>
+    /// Gets the Underlying <b>IHash</b> Instance
+    /// </summary>
+    function GetUnderlyingIHash: IHash; inline;
+
+    /// <summary>
+    /// the size, in bytes, of the digest produced by this message digest.
+    /// </summary>
+    function GetDigestSize(): Int32; inline;
+
+    /// <summary>
+    /// the size, in bytes, of the internal buffer used by this digest.
+    /// </summary>
+    function GetByteLength(): Int32; inline;
+
+    /// <summary>
+    /// update the message digest with a single byte.
+    /// </summary>
+    procedure Update(input: Byte);
+
+    /// <summary>
+    /// update the message digest with a block of bytes.
+    /// </summary>
+    /// <param name="input">
+    /// the byte array containing the data.
+    /// </param>
+    /// <param name="inOff">
+    /// the offset into the byte array where the data starts.
+    /// </param>
+    /// <param name="len">
+    /// the length of the data.
+    /// </param>
+    procedure BlockUpdate(input: TCryptoLibByteArray; inOff, len: Int32);
+
+    /// <summary>
+    /// Close the digest, producing the final digest value. The doFinal call
+    /// leaves the digest reset.
+    /// </summary>
+    /// <param name="output">
+    /// the array the digest is to be copied into.
+    /// </param>
+    /// <param name="outOff">
+    /// the offset into the out array the digest is to start at.
+    /// </param>
+    function DoFinal(output: TCryptoLibByteArray; outOff: Int32)
+      : Int32; overload;
+
+    /// <summary>
+    /// Resets the digest back to it's initial state.
+    /// </summary>
+    procedure Reset();
+
+    /// <summary>
+    /// the algorithm name
+    /// </summary>
+    property AlgorithmName: String read GetAlgorithmName;
+
+  end;
+
+implementation
+
+{ TDigest }
+
+function TDigest.GetAlgorithmName: string;
+begin
+  result := FHash.Name;
+end;
+
+function TDigest.GetByteLength: Int32;
+begin
+  result := FHash.BlockSize;
+end;
+
+function TDigest.GetDigestSize: Int32;
+begin
+  result := FHash.HashSize;
+end;
+
+function TDigest.GetUnderlyingIHash: IHash;
+begin
+  result := FHash;
+end;
+
+procedure TDigest.Reset;
+begin
+  FHash.Initialize;
+end;
+
+procedure TDigest.BlockUpdate(input: TCryptoLibByteArray; inOff, len: Int32);
+begin
+  FHash.TransformBytes(input, inOff, len);
+end;
+
+constructor TDigest.Create(const hash: IHash);
+begin
+  Inherited Create();
+  FHash := hash;
+  FHash.Initialize;
+end;
+
+function TDigest.DoFinal(output: TCryptoLibByteArray; outOff: Int32): Int32;
+var
+  buf: TCryptoLibByteArray;
+begin
+
+  if (System.Length(output) - outOff) < GetDigestSize then
+  begin
+    raise EDataLengthCryptoLibException.CreateRes(@SOutputBufferTooShort);
+  end
+  else
+  begin
+    buf := DoFinal();
+    System.Move(buf[0], output[outOff], System.Length(buf) *
+      System.SizeOf(Byte));
+  end;
+  result := System.Length(buf);
+end;
+
+function TDigest.DoFinal: TCryptoLibByteArray;
+begin
+  result := FHash.TransformFinal.GetBytes();
+end;
+
+procedure TDigest.Update(input: Byte);
+begin
+  FHash.TransformUntyped(input, System.SizeOf(Byte));
+end;
+
+end.

+ 7 - 7
CryptoLib/src/Crypto/Generators/ClpBaseKdfBytesGenerator.pas

@@ -119,7 +119,7 @@ begin
   end;
   end;
 
 
   oBytes := length;
   oBytes := length;
-  outLen := Fdigest.HashSize;
+  outLen := Fdigest.GetDigestSize;
 
 
   //
   //
   // this is at odds with the standard implementation, the
   // this is at odds with the standard implementation, the
@@ -136,7 +136,7 @@ begin
 
 
   cThreshold := Int32((oBytes + outLen - 1) div outLen);
   cThreshold := Int32((oBytes + outLen - 1) div outLen);
 
 
-  System.SetLength(dig, Fdigest.HashSize);
+  System.SetLength(dig, Fdigest.GetDigestSize);
 
 
   System.SetLength(C, 4);
   System.SetLength(C, 4);
 
 
@@ -147,15 +147,15 @@ begin
   i := 0;
   i := 0;
   while i < cThreshold do
   while i < cThreshold do
   begin
   begin
-    Fdigest.TransformBytes(Fshared, 0, System.length(Fshared));
-    Fdigest.TransformBytes(C, 0, 4);
+    Fdigest.BlockUpdate(Fshared, 0, System.length(Fshared));
+    Fdigest.BlockUpdate(C, 0, 4);
 
 
     if (Fiv <> Nil) then
     if (Fiv <> Nil) then
     begin
     begin
-      Fdigest.TransformBytes(Fiv, 0, System.length(Fiv));
+      Fdigest.BlockUpdate(Fiv, 0, System.length(Fiv));
     end;
     end;
 
 
-    dig := Fdigest.TransformFinal.GetBytes;
+    Fdigest.DoFinal(dig, 0);
 
 
     if (length > outLen) then
     if (length > outLen) then
     begin
     begin
@@ -179,7 +179,7 @@ begin
     System.Inc(i);
     System.Inc(i);
   end;
   end;
 
 
-  Fdigest.Initialize();
+  Fdigest.Reset();
 
 
   result := Int32(oBytes);
   result := Int32(oBytes);
 end;
 end;

+ 5 - 5
CryptoLib/src/Crypto/Generators/ClpPascalCoinECIESKdfBytesGenerator.pas

@@ -103,7 +103,7 @@ begin
   end;
   end;
 
 
   oBytes := length;
   oBytes := length;
-  outLen := Fdigest.HashSize;
+  outLen := Fdigest.GetDigestSize;
 
 
   if (oBytes > outLen) then
   if (oBytes > outLen) then
   begin
   begin
@@ -111,13 +111,13 @@ begin
       (@SHashCannotNotProduceSufficientData);
       (@SHashCannotNotProduceSufficientData);
   end;
   end;
 
 
-  Fdigest.TransformBytes(Fshared, 0, System.length(Fshared));
-
-  temp := Fdigest.TransformFinal.GetBytes;
+  System.SetLength(temp, Fdigest.GetDigestSize);
+  Fdigest.BlockUpdate(Fshared, 0, System.length(Fshared));
+  Fdigest.DoFinal(temp, 0);
 
 
   System.Move(temp[0], output[outOff], length * System.SizeOf(Byte));
   System.Move(temp[0], output[outOff], length * System.SizeOf(Byte));
 
 
-  Fdigest.Initialize();
+  Fdigest.Reset();
 
 
   result := oBytes;
   result := oBytes;
 
 

+ 2 - 2
CryptoLib/src/Crypto/Generators/ClpPkcs5S2ParametersGenerator.pas

@@ -189,8 +189,8 @@ procedure TPkcs5S2ParametersGenerator.Init(password, salt: TCryptoLibByteArray;
   iterationCount: Int32);
   iterationCount: Int32);
 begin
 begin
   inherited Init(password, salt, iterationCount);
   inherited Init(password, salt, iterationCount);
-  FPBKDF2_HMAC := TKDF.TPBKDF2_HMAC.CreatePBKDF2_HMAC(Fdigest, password, salt,
-    iterationCount);
+  FPBKDF2_HMAC := TKDF.TPBKDF2_HMAC.CreatePBKDF2_HMAC
+    (Fdigest.GetUnderlyingIHash, password, salt, iterationCount);
 end;
 end;
 
 
 end.
 end.

+ 11 - 5
CryptoLib/src/Crypto/Macs/ClpHMac.pas

@@ -36,8 +36,14 @@ resourcestring
 type
 type
 
 
   /// <summary>
   /// <summary>
-  /// HMAC implementation based on RFC2104 <br />H(K XOR opad, H(K XOR ipad,
-  /// text))
+  /// <para>
+  /// HMAC implementation based on RFC2104 <br />H(K XOR opad, H(K XOR
+  /// ipad, text))
+  /// </para>
+  /// <para>
+  /// Note: This is Just a Wrapper for <b>HMAC</b> Implementation in
+  /// HashLib4Pascal
+  /// </para>
   /// </summary>
   /// </summary>
   THMac = class sealed(TInterfacedObject, IHMac, IMac)
   THMac = class sealed(TInterfacedObject, IHMac, IMac)
 
 
@@ -88,7 +94,7 @@ constructor THMac.Create(const digest: IDigest);
 begin
 begin
   Inherited Create();
   Inherited Create();
   FDigest := digest;
   FDigest := digest;
-  FHMAC := THashFactory.THMac.CreateHMAC(FDigest);
+  FHMAC := THashFactory.THMac.CreateHMAC(FDigest.GetUnderlyingIHash);
 end;
 end;
 
 
 function THMac.DoFinal(output: TCryptoLibByteArray; outOff: Int32): Int32;
 function THMac.DoFinal(output: TCryptoLibByteArray; outOff: Int32): Int32;
@@ -116,7 +122,7 @@ end;
 
 
 function THMac.GetAlgorithmName: string;
 function THMac.GetAlgorithmName: string;
 begin
 begin
-  result := FDigest.Name + '/HMAC';
+  result := FDigest.AlgorithmName + '/HMAC';
 end;
 end;
 
 
 function THMac.GetUnderlyingDigest: IDigest;
 function THMac.GetUnderlyingDigest: IDigest;
@@ -137,7 +143,7 @@ end;
 
 
 procedure THMac.Update(input: Byte);
 procedure THMac.Update(input: Byte);
 begin
 begin
-  FHMAC.TransformBytes(TCryptoLibByteArray.Create(input));
+  FHMAC.TransformUntyped(input, System.SizeOf(Byte));
 end;
 end;
 
 
 end.
 end.

+ 29 - 0
CryptoLib/src/Crypto/Parameters/ClpDsaParameters.pas

@@ -47,7 +47,36 @@ type
     function GetValidationParameters: IDsaValidationParameters; inline;
     function GetValidationParameters: IDsaValidationParameters; inline;
 
 
   public
   public
+
+    /// <summary>
+    /// Creates a new DSAParameter with the specified parameter values.
+    /// </summary>
+    /// <param name="p">
+    /// the prime.
+    /// </param>
+    /// <param name="q">
+    /// the sub-prime.
+    /// </param>
+    /// <param name="g">
+    /// the base.
+    /// </param>
     constructor Create(const p, q, g: TBigInteger); overload;
     constructor Create(const p, q, g: TBigInteger); overload;
+    /// <summary>
+    /// Creates a new DSAParameter with the specified parameter values.
+    /// </summary>
+    /// <param name="p">
+    /// the prime.
+    /// </param>
+    /// <param name="q">
+    /// the sub-prime.
+    /// </param>
+    /// <param name="g">
+    /// the base.
+    /// </param>
+    /// <param name="parameters">
+    /// dsa validation parameters (this includes the seed, counter and usage
+    /// index)
+    /// </param>
     constructor Create(const p, q, g: TBigInteger;
     constructor Create(const p, q, g: TBigInteger;
       const parameters: IDsaValidationParameters); overload;
       const parameters: IDsaValidationParameters); overload;
 
 

+ 7 - 11
CryptoLib/src/Crypto/Prng/ClpDigestRandomGenerator.pas

@@ -53,7 +53,7 @@ type
     procedure GenerateState(); inline;
     procedure GenerateState(); inline;
     procedure DigestAddCounter(seedVal: Int64); inline;
     procedure DigestAddCounter(seedVal: Int64); inline;
     procedure DigestUpdate(inSeed: TCryptoLibByteArray); inline;
     procedure DigestUpdate(inSeed: TCryptoLibByteArray); inline;
-    procedure DigestDoFinal(value: TCryptoLibByteArray); inline;
+    procedure DigestDoFinal(result: TCryptoLibByteArray); inline;
 
 
     class var
     class var
 
 
@@ -83,21 +83,17 @@ var
 begin
 begin
   System.SetLength(bytes, 8);
   System.SetLength(bytes, 8);
   bytes := TConverters.ReadUInt64AsBytesLE(UInt64(seedVal));
   bytes := TConverters.ReadUInt64AsBytesLE(UInt64(seedVal));
-  Fdigest.TransformBytes(bytes, 0, System.Length(bytes));
+  Fdigest.BlockUpdate(bytes, 0, System.Length(bytes));
 end;
 end;
 
 
 procedure TDigestRandomGenerator.DigestUpdate(inSeed: TCryptoLibByteArray);
 procedure TDigestRandomGenerator.DigestUpdate(inSeed: TCryptoLibByteArray);
 begin
 begin
-  Fdigest.TransformBytes(inSeed, 0, System.Length(inSeed));
+  Fdigest.BlockUpdate(inSeed, 0, System.Length(inSeed));
 end;
 end;
 
 
-procedure TDigestRandomGenerator.DigestDoFinal(value: TCryptoLibByteArray);
-var
-  digest: TCryptoLibByteArray;
+procedure TDigestRandomGenerator.DigestDoFinal(result: TCryptoLibByteArray);
 begin
 begin
-  digest := Fdigest.TransformFinal().GetBytes;
-  System.Move(digest[0], value[0], System.Length(digest) * System.SizeOf(Byte));
-  // value := Fdigest.TransformFinal().GetBytes; // Review
+  Fdigest.DoFinal(result, 0);
 end;
 end;
 
 
 procedure TDigestRandomGenerator.AddSeedMaterial(rSeed: Int64);
 procedure TDigestRandomGenerator.AddSeedMaterial(rSeed: Int64);
@@ -128,9 +124,9 @@ constructor TDigestRandomGenerator.Create(const digest: IDigest);
 begin
 begin
   Inherited Create();
   Inherited Create();
   Fdigest := digest;
   Fdigest := digest;
-  System.SetLength(Fseed, digest.HashSize);
+  System.SetLength(Fseed, digest.GetDigestSize);
   FseedCounter := 1;
   FseedCounter := 1;
-  System.SetLength(Fstate, digest.HashSize);
+  System.SetLength(Fstate, digest.GetDigestSize);
   FstateCounter := 1;
   FstateCounter := 1;
 end;
 end;
 
 

+ 8 - 8
CryptoLib/src/Crypto/Signers/ClpDsaDigestSigner.pas

@@ -107,7 +107,7 @@ implementation
 procedure TDsaDigestSigner.BlockUpdate(input: TCryptoLibByteArray;
 procedure TDsaDigestSigner.BlockUpdate(input: TCryptoLibByteArray;
   inOff, length: Int32);
   inOff, length: Int32);
 begin
 begin
-  Fdigest.TransformBytes(input, inOff, length);
+  Fdigest.BlockUpdate(input, inOff, length);
 end;
 end;
 
 
 constructor TDsaDigestSigner.Create(const signer: IDsa; const digest: IDigest);
 constructor TDsaDigestSigner.Create(const signer: IDsa; const digest: IDigest);
@@ -145,9 +145,9 @@ begin
       (@SDSaDigestSignerNotInitializedForSignatureGeneration);
       (@SDSaDigestSignerNotInitializedForSignatureGeneration);
   end;
   end;
 
 
-  System.SetLength(hash, Fdigest.HashSize);
+  System.SetLength(hash, Fdigest.GetDigestSize);
 
 
-  hash := Fdigest.TransformFinal().GetBytes;
+  Fdigest.DoFinal(hash, 0);
 
 
   sig := FdsaSigner.GenerateSignature(hash);
   sig := FdsaSigner.GenerateSignature(hash);
 
 
@@ -156,7 +156,7 @@ end;
 
 
 function TDsaDigestSigner.GetAlgorithmName: String;
 function TDsaDigestSigner.GetAlgorithmName: String;
 begin
 begin
-  Result := Fdigest.Name + 'with' + FdsaSigner.AlgorithmName;
+  Result := Fdigest.AlgorithmName + 'with' + FdsaSigner.AlgorithmName;
 end;
 end;
 
 
 procedure TDsaDigestSigner.Init(forSigning: Boolean;
 procedure TDsaDigestSigner.Init(forSigning: Boolean;
@@ -193,12 +193,12 @@ end;
 
 
 procedure TDsaDigestSigner.Reset;
 procedure TDsaDigestSigner.Reset;
 begin
 begin
-  Fdigest.Initialize;
+  Fdigest.Reset;
 end;
 end;
 
 
 procedure TDsaDigestSigner.Update(input: Byte);
 procedure TDsaDigestSigner.Update(input: Byte);
 begin
 begin
-  Fdigest.TransformUntyped(input, System.SizeOf(Byte));
+  Fdigest.Update(input);
 end;
 end;
 
 
 function TDsaDigestSigner.VerifySignature
 function TDsaDigestSigner.VerifySignature
@@ -213,9 +213,9 @@ begin
       (@SDSaDigestSignerNotInitializedForVerification);
       (@SDSaDigestSignerNotInitializedForVerification);
   end;
   end;
 
 
-  System.SetLength(hash, Fdigest.HashSize);
+  System.SetLength(hash, Fdigest.GetDigestSize);
 
 
-  hash := Fdigest.TransformFinal().GetBytes;
+  Fdigest.DoFinal(hash, 0);
 
 
   try
   try
 
 

+ 11 - 8
CryptoLib/src/Crypto/Signers/ClpECSchnorrBSISigner.pas

@@ -44,8 +44,9 @@ type
       const pv_key: IECPrivateKeyParameters; const k: TBigInteger)
       const pv_key: IECPrivateKeyParameters; const k: TBigInteger)
       : TCryptoLibByteArray;
       : TCryptoLibByteArray;
 
 
-    function Do_Verify(const &message: TCryptoLibByteArray; const digest: IDigest;
-      const pu_key: IECPublicKeyParameters; const sig: TCryptoLibByteArray): Boolean;
+    function Do_Verify(const &message: TCryptoLibByteArray;
+      const digest: IDigest; const pu_key: IECPublicKeyParameters;
+      const sig: TCryptoLibByteArray): Boolean;
 
 
   end;
   end;
 
 
@@ -75,9 +76,10 @@ begin
 
 
   xQ := q.Normalize.XCoord.ToBigInteger.ToByteArray;
   xQ := q.Normalize.XCoord.ToBigInteger.ToByteArray;
 
 
-  digest.TransformBytes(&message);
-  digest.TransformBytes(xQ);
-  tempR := digest.TransformFinal.GetBytes();
+  System.SetLength(tempR, digest.GetDigestSize);
+  digest.BlockUpdate(&message, 0, System.Length(&message));
+  digest.BlockUpdate(xQ, 0, System.Length(xQ));
+  digest.DoFinal(tempR, 0);
 
 
   r := TBigInteger.Create(1, tempR);
   r := TBigInteger.Create(1, tempR);
   s := (k.Subtract(r.Multiply(pv_key.D))).&Mod(n);
   s := (k.Subtract(r.Multiply(pv_key.D))).&Mod(n);
@@ -130,9 +132,10 @@ begin
   q := sG.Add(rW);
   q := sG.Add(rW);
   xQ := q.Normalize.XCoord.ToBigInteger.ToByteArray;
   xQ := q.Normalize.XCoord.ToBigInteger.ToByteArray;
 
 
-  digest.TransformBytes(&message);
-  digest.TransformBytes(xQ);
-  tempV := digest.TransformFinal.GetBytes();
+  System.SetLength(tempV, digest.GetDigestSize);
+  digest.BlockUpdate(&message, 0, System.Length(&message));
+  digest.BlockUpdate(xQ, 0, System.Length(xQ));
+  digest.DoFinal(tempV, 0);
 
 
   v := TBigInteger.Create(1, tempV);
   v := TBigInteger.Create(1, tempV);
   Result := v.Equals(r);
   Result := v.Equals(r);

+ 12 - 10
CryptoLib/src/Crypto/Signers/ClpECSchnorrISOSigner.pas

@@ -44,8 +44,8 @@ type
       const pv_key: IECPrivateKeyParameters; const k: TBigInteger)
       const pv_key: IECPrivateKeyParameters; const k: TBigInteger)
       : TCryptoLibByteArray;
       : TCryptoLibByteArray;
 
 
-    function Do_Verify(const &message: TCryptoLibByteArray; const digest: IDigest;
-      const pu_key: IECPublicKeyParameters;
+    function Do_Verify(const &message: TCryptoLibByteArray;
+      const digest: IDigest; const pu_key: IECPublicKeyParameters;
       const sig: TCryptoLibByteArray): Boolean;
       const sig: TCryptoLibByteArray): Boolean;
 
 
   end;
   end;
@@ -77,10 +77,11 @@ begin
   xQ := q.Normalize.XCoord.ToBigInteger.ToByteArray;
   xQ := q.Normalize.XCoord.ToBigInteger.ToByteArray;
   yQ := q.Normalize.YCoord.ToBigInteger.ToByteArray;
   yQ := q.Normalize.YCoord.ToBigInteger.ToByteArray;
 
 
-  digest.TransformBytes(xQ);
-  digest.TransformBytes(yQ);
-  digest.TransformBytes(&message);
-  tempR := digest.TransformFinal.GetBytes();
+  System.SetLength(tempR, digest.GetDigestSize);
+  digest.BlockUpdate(xQ, 0, System.Length(xQ));
+  digest.BlockUpdate(yQ, 0, System.Length(yQ));
+  digest.BlockUpdate(&message, 0, System.Length(&message));
+  digest.DoFinal(tempR, 0);
 
 
   r := TBigInteger.Create(1, tempR);
   r := TBigInteger.Create(1, tempR);
   s := (k.Add(r.Multiply(pv_key.D))).&Mod(n);
   s := (k.Add(r.Multiply(pv_key.D))).&Mod(n);
@@ -134,10 +135,11 @@ begin
   xQ := q.Normalize.XCoord.ToBigInteger.ToByteArray;
   xQ := q.Normalize.XCoord.ToBigInteger.ToByteArray;
   yQ := q.Normalize.YCoord.ToBigInteger.ToByteArray;
   yQ := q.Normalize.YCoord.ToBigInteger.ToByteArray;
 
 
-  digest.TransformBytes(xQ);
-  digest.TransformBytes(yQ);
-  digest.TransformBytes(&message);
-  tempV := digest.TransformFinal.GetBytes();
+  System.SetLength(tempV, digest.GetDigestSize);
+  digest.BlockUpdate(xQ, 0, System.Length(xQ));
+  digest.BlockUpdate(yQ, 0, System.Length(yQ));
+  digest.BlockUpdate(&message, 0, System.Length(&message));
+  digest.DoFinal(tempV, 0);
 
 
   v := TBigInteger.Create(1, tempV);
   v := TBigInteger.Create(1, tempV);
   Result := v.Equals(r);
   Result := v.Equals(r);

+ 8 - 6
CryptoLib/src/Crypto/Signers/ClpECSchnorrISOXSigner.pas

@@ -76,9 +76,10 @@ begin
 
 
   xQ := q.Normalize.XCoord.ToBigInteger.ToByteArray;
   xQ := q.Normalize.XCoord.ToBigInteger.ToByteArray;
 
 
-  digest.TransformBytes(xQ);
-  digest.TransformBytes(&message);
-  tempR := digest.TransformFinal.GetBytes();
+  System.SetLength(tempR, digest.GetDigestSize);
+  digest.BlockUpdate(xQ, 0, System.Length(xQ));
+  digest.BlockUpdate(&message, 0, System.Length(&message));
+  digest.DoFinal(tempR, 0);
 
 
   r := TBigInteger.Create(1, tempR);
   r := TBigInteger.Create(1, tempR);
   s := (k.Add(r.Multiply(pv_key.D))).&Mod(n);
   s := (k.Add(r.Multiply(pv_key.D))).&Mod(n);
@@ -131,9 +132,10 @@ begin
   q := sG.Subtract(rW);
   q := sG.Subtract(rW);
   xQ := q.Normalize.XCoord.ToBigInteger.ToByteArray;
   xQ := q.Normalize.XCoord.ToBigInteger.ToByteArray;
 
 
-  digest.TransformBytes(xQ);
-  digest.TransformBytes(&message);
-  tempV := digest.TransformFinal.GetBytes();
+  System.SetLength(tempV, digest.GetDigestSize);
+  digest.BlockUpdate(xQ, 0, System.Length(xQ));
+  digest.BlockUpdate(&message, 0, System.Length(&message));
+  digest.DoFinal(tempV, 0);
 
 
   v := TBigInteger.Create(1, tempV);
   v := TBigInteger.Create(1, tempV);
   Result := v.Equals(r);
   Result := v.Equals(r);

+ 9 - 6
CryptoLib/src/Crypto/Signers/ClpECSchnorrLIBSECPSigner.pas

@@ -83,9 +83,11 @@ begin
   end;
   end;
 
 
   rQ := q.Normalize.XCoord.ToBigInteger.&Mod(n).ToByteArray;
   rQ := q.Normalize.XCoord.ToBigInteger.&Mod(n).ToByteArray;
-  digest.TransformBytes(rQ);
-  digest.TransformBytes(&message);
-  tempH := digest.TransformFinal.GetBytes();
+
+  System.SetLength(tempH, digest.GetDigestSize);
+  digest.BlockUpdate(rQ, 0, System.Length(rQ));
+  digest.BlockUpdate(&message, 0, System.Length(&message));
+  digest.DoFinal(tempH, 0);
 
 
   h := TBigInteger.Create(1, tempH);
   h := TBigInteger.Create(1, tempH);
   r := q.Normalize.XCoord.ToBigInteger.&Mod(n);
   r := q.Normalize.XCoord.ToBigInteger.&Mod(n);
@@ -130,9 +132,10 @@ begin
 
 
   rb := r.ToByteArray;
   rb := r.ToByteArray;
 
 
-  digest.TransformBytes(rb);
-  digest.TransformBytes(&message);
-  tempH := digest.TransformFinal.GetBytes();
+  System.SetLength(tempH, digest.GetDigestSize);
+  digest.BlockUpdate(rb, 0, System.Length(rb));
+  digest.BlockUpdate(&message, 0, System.Length(&message));
+  digest.DoFinal(tempH, 0);
 
 
   h := TBigInteger.Create(1, tempH);
   h := TBigInteger.Create(1, tempH);
   if (h.CompareTo(TBigInteger.Zero) = 0) or (h.CompareTo(n) = 1) then
   if (h.CompareTo(TBigInteger.Zero) = 0) or (h.CompareTo(n) = 1) then

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

@@ -290,7 +290,7 @@ end;
 
 
 function TECSchnorrSigner.GetAlgorithmName: String;
 function TECSchnorrSigner.GetAlgorithmName: String;
 begin
 begin
-  Result := FDigest.Name + 'with' + 'ECSCHNORR' + FSigner.AlgorithmName;
+  Result := FDigest.AlgorithmName + 'with' + 'ECSCHNORR' + FSigner.AlgorithmName;
 end;
 end;
 
 
 procedure TECSchnorrSigner.Init(forSigning: Boolean;
 procedure TECSchnorrSigner.Init(forSigning: Boolean;
@@ -337,7 +337,7 @@ end;
 
 
 procedure TECSchnorrSigner.Reset;
 procedure TECSchnorrSigner.Reset;
 begin
 begin
-  FDigest.Initialize;
+  FDigest.Reset;
   FBuffer.Clear;
   FBuffer.Clear;
   FBuffer.SetSize(0);
   FBuffer.SetSize(0);
 end;
 end;

+ 64 - 3
CryptoLib/src/Interfaces/ClpIDigest.pas

@@ -22,13 +22,74 @@ unit ClpIDigest;
 interface
 interface
 
 
 uses
 uses
-  HlpIHash;
+  HlpIHash,
+  ClpCryptoLibTypes;
 
 
 type
 type
-
-  IDigest = interface(IHash)
+  // interface that a message digest conforms to.
+  IDigest = interface(IInterface)
     ['{4AF1A541-DABE-4F89-8E9E-26DB61097330}']
     ['{4AF1A541-DABE-4F89-8E9E-26DB61097330}']
 
 
+    function GetAlgorithmName: string;
+
+    /// <summary>
+    /// the algorithm name
+    /// </summary>
+    property AlgorithmName: String read GetAlgorithmName;
+
+    /// <summary>
+    /// Gets the Underlying <b>IHash</b> Instance
+    /// </summary>
+    function GetUnderlyingIHash: IHash;
+
+    /// <summary>
+    /// the size, in bytes, of the digest produced by this message digest.
+    /// </summary>
+    function GetDigestSize(): Int32;
+
+    /// <summary>
+    /// the size, in bytes, of the internal buffer used by this digest.
+    /// </summary>
+    function GetByteLength(): Int32;
+
+    /// <summary>
+    /// update the message digest with a single byte.
+    /// </summary>
+    procedure Update(input: Byte);
+
+    /// <summary>
+    /// update the message digest with a block of bytes.
+    /// </summary>
+    /// <param name="input">
+    /// the byte array containing the data.
+    /// </param>
+    /// <param name="inOff">
+    /// the offset into the byte array where the data starts.
+    /// </param>
+    /// <param name="len">
+    /// the length of the data.
+    /// </param>
+    procedure BlockUpdate(input: TCryptoLibByteArray; inOff, len: Int32);
+
+    /// <summary>
+    /// Close the digest, producing the final digest value. The doFinal call
+    /// leaves the digest reset.
+    /// </summary>
+    /// <param name="output">
+    /// the array the digest is to be copied into.
+    /// </param>
+    /// <param name="outOff">
+    /// the offset into the out array the digest is to start at.
+    /// </param>
+    function DoFinal(output: TCryptoLibByteArray; outOff: Int32)
+      : Int32; overload;
+    function DoFinal: TCryptoLibByteArray; overload;
+
+    /// <summary>
+    /// Resets the digest back to it's initial state.
+    /// </summary>
+    procedure Reset();
+
   end;
   end;
 
 
 implementation
 implementation

+ 0 - 4
CryptoLib/src/Interfaces/ClpIDsaKeyPairGenerator.pas

@@ -22,15 +22,11 @@ unit ClpIDsaKeyPairGenerator;
 interface
 interface
 
 
 uses
 uses
-  ClpIAsymmetricCipherKeyPair,
-  ClpIKeyGenerationParameters,
   ClpIAsymmetricCipherKeyPairGenerator;
   ClpIAsymmetricCipherKeyPairGenerator;
 
 
 type
 type
   IDsaKeyPairGenerator = interface(IAsymmetricCipherKeyPairGenerator)
   IDsaKeyPairGenerator = interface(IAsymmetricCipherKeyPairGenerator)
     ['{37A4647D-2D9A-4EB1-A2AF-B3FBE72B66F3}']
     ['{37A4647D-2D9A-4EB1-A2AF-B3FBE72B66F3}']
-    procedure Init(const parameters: IKeyGenerationParameters);
-    function GenerateKeyPair(): IAsymmetricCipherKeyPair;
   end;
   end;
 
 
 implementation
 implementation

+ 54 - 0
CryptoLib/src/Interfaces/ClpIECDHCBasicAgreement.pas

@@ -0,0 +1,54 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIECDHCBasicAgreement;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIBasicAgreement;
+
+type
+
+  /// <summary>
+  /// P1363 7.2.2 ECSVDP-DHC <br /><br />ECSVDP-DHC is Elliptic Curve Secret
+  /// Value Derivation Primitive, <br />Diffie-Hellman version with cofactor
+  /// multiplication. It is based on <br />the work of [DH76], [Mil86],
+  /// [Kob87], [LMQ98] and [Kal98a]. This <br />primitive derives a shared
+  /// secret value from one party's private key <br />and another party's
+  /// public key, where both have the same set of EC <br />domain parameters.
+  /// If two parties correctly execute this primitive, <br />they will
+  /// produce the same output. This primitive can be invoked by a <br />
+  /// scheme to derive a shared secret key; specifically, it may be used <br />
+  /// with the schemes ECKAS-DH1 and DL/ECKAS-DH2. It does not assume the <br />
+  /// validity of the input public key (see also Section 7.2.1). <br /><br />
+  /// Note: As stated P1363 compatibility mode with ECDH can be preset, and <br />
+  /// in this case the implementation doesn't have a ECDH compatibility mode <br />
+  /// (if you want that just use ECDHBasicAgreement and note they both
+  /// implement <br />BasicAgreement!). <br />
+  /// </summary>
+  IECDHCBasicAgreement = interface(IBasicAgreement)
+
+    ['{5938300B-2722-49D4-9486-98EDD5C34239}']
+
+  end;
+
+implementation
+
+end.

+ 14 - 2
CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.lpk

@@ -10,7 +10,7 @@
       <PathDelim Value="\"/>
       <PathDelim Value="\"/>
       <SearchPaths>
       <SearchPaths>
         <IncludeFiles Value="..\..\Include"/>
         <IncludeFiles Value="..\..\Include"/>
-        <OtherUnitFiles Value="..\..\Asn1;..\..\Asn1\CryptoPro;..\..\Asn1\Nist;..\..\Asn1\Oiw;..\..\Asn1\Pkcs;..\..\Asn1\RossStandart;..\..\Asn1\Sec;..\..\Asn1\TeleTrust;..\..\Asn1\X9;..\..\Crypto;..\..\Crypto\Generators;..\..\Crypto\Parameters;..\..\Crypto\Prng;..\..\Crypto\Signers;..\..\Interfaces;..\..\Math;..\..\Math\EC;..\..\Math\EC\Abc;..\..\Math\EC\Endo;..\..\Math\EC\Multiplier;..\..\Math\Field;..\..\Math\Raw;..\..\Security;..\..\Utils;..\..\Utils\Collections;..\..\Utils\Encoders;..\..\Utils\Helpers;..\..\Utils\IO;..\..\Utils\Randoms;..\..\Utils\Rng;..\..\Crypto\Modes;..\..\Crypto\Paddings;..\..\Crypto\Engines;..\..\Crypto\Parsers;..\..\Crypto\Agreement;..\..\Crypto\Macs;..\..\Asn1\Misc;..\..\Asn1\Iana"/>
+        <OtherUnitFiles Value="..\..\Asn1;..\..\Asn1\CryptoPro;..\..\Asn1\Nist;..\..\Asn1\Oiw;..\..\Asn1\Pkcs;..\..\Asn1\RossStandart;..\..\Asn1\Sec;..\..\Asn1\TeleTrust;..\..\Asn1\X9;..\..\Crypto;..\..\Crypto\Generators;..\..\Crypto\Parameters;..\..\Crypto\Prng;..\..\Crypto\Signers;..\..\Interfaces;..\..\Math;..\..\Math\EC;..\..\Math\EC\Abc;..\..\Math\EC\Endo;..\..\Math\EC\Multiplier;..\..\Math\Field;..\..\Math\Raw;..\..\Security;..\..\Utils;..\..\Utils\Collections;..\..\Utils\Encoders;..\..\Utils\Helpers;..\..\Utils\IO;..\..\Utils\Randoms;..\..\Utils\Rng;..\..\Crypto\Modes;..\..\Crypto\Paddings;..\..\Crypto\Engines;..\..\Crypto\Parsers;..\..\Crypto\Agreement;..\..\Crypto\Macs;..\..\Asn1\Misc;..\..\Asn1\Iana;..\..\Crypto\Digests"/>
         <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
         <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
       </SearchPaths>
       </SearchPaths>
       <CodeGeneration>
       <CodeGeneration>
@@ -25,7 +25,7 @@
  Acknowledgements: 
  Acknowledgements: 
 Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring the development of this library "/>
 Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring the development of this library "/>
     <Version Major="2" Minor="2"/>
     <Version Major="2" Minor="2"/>
-    <Files Count="388">
+    <Files Count="391">
       <Item1>
       <Item1>
         <Filename Value="..\..\Asn1\ClpAsn1Encodable.pas"/>
         <Filename Value="..\..\Asn1\ClpAsn1Encodable.pas"/>
         <UnitName Value="ClpAsn1Encodable"/>
         <UnitName Value="ClpAsn1Encodable"/>
@@ -1579,6 +1579,18 @@ Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring the devel
         <Filename Value="..\..\Utils\Encoders\ClpBase58.pas"/>
         <Filename Value="..\..\Utils\Encoders\ClpBase58.pas"/>
         <UnitName Value="ClpBase58"/>
         <UnitName Value="ClpBase58"/>
       </Item388>
       </Item388>
+      <Item389>
+        <Filename Value="..\..\Crypto\Digests\ClpDigest.pas"/>
+        <UnitName Value="ClpDigest"/>
+      </Item389>
+      <Item390>
+        <Filename Value="..\..\Crypto\Agreement\ClpECDHCBasicAgreement.pas"/>
+        <UnitName Value="ClpECDHCBasicAgreement"/>
+      </Item390>
+      <Item391>
+        <Filename Value="..\..\Interfaces\ClpIECDHCBasicAgreement.pas"/>
+        <UnitName Value="ClpIECDHCBasicAgreement"/>
+      </Item391>
     </Files>
     </Files>
     <RequiredPkgs Count="3">
     <RequiredPkgs Count="3">
       <Item1>
       <Item1>

+ 2 - 1
CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.pas

@@ -128,7 +128,8 @@ uses
   ClpDsaKeyParameters, ClpIECNRSigner, ClpIDsaSigner, ClpIDsaKeyPairGenerator, 
   ClpDsaKeyParameters, ClpIECNRSigner, ClpIDsaSigner, ClpIDsaKeyPairGenerator, 
   ClpIDsaPrivateKeyParameters, ClpIDsaKeyGenerationParameters, 
   ClpIDsaPrivateKeyParameters, ClpIDsaKeyGenerationParameters, 
   ClpIDsaKeyParameters, ClpIDsaPublicKeyParameters, ClpIDsaParameters, 
   ClpIDsaKeyParameters, ClpIDsaPublicKeyParameters, ClpIDsaParameters, 
-  ClpIDsaValidationParameters, ClpBase58;
+  ClpIDsaValidationParameters, ClpBase58, ClpDigest, ClpECDHCBasicAgreement, 
+  ClpIECDHCBasicAgreement;
 
 
 implementation
 implementation
 
 

+ 89 - 66
CryptoLib/src/Security/ClpDigestUtilities.pas

@@ -27,6 +27,7 @@ uses
   Generics.Collections,
   Generics.Collections,
   HlpHashFactory,
   HlpHashFactory,
   ClpIDigest,
   ClpIDigest,
+  ClpDigest,
   ClpPkcsObjectIdentifiers,
   ClpPkcsObjectIdentifiers,
   ClpRosstandartObjectIdentifiers,
   ClpRosstandartObjectIdentifiers,
   ClpOiwObjectIdentifiers,
   ClpOiwObjectIdentifiers,
@@ -78,6 +79,11 @@ type
     class function GetAlgorithmName(const oid: IDerObjectIdentifier): String;
     class function GetAlgorithmName(const oid: IDerObjectIdentifier): String;
       static; inline;
       static; inline;
 
 
+    class function DoFinal(const digest: IDigest): TCryptoLibByteArray;
+      overload; static; inline;
+    class function DoFinal(const digest: IDigest; input: TCryptoLibByteArray)
+      : TCryptoLibByteArray; overload; static; inline;
+
     class function CalculateDigest(const algorithm: String;
     class function CalculateDigest(const algorithm: String;
       input: TCryptoLibByteArray): TCryptoLibByteArray; static; inline;
       input: TCryptoLibByteArray): TCryptoLibByteArray; static; inline;
 
 
@@ -123,226 +129,229 @@ begin
 
 
     TDigestAlgorithm.BLAKE2B_160:
     TDigestAlgorithm.BLAKE2B_160:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateBlake2B_160);
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateBlake2B_160);
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.BLAKE2B_256:
     TDigestAlgorithm.BLAKE2B_256:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateBlake2B_256);
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateBlake2B_256);
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.BLAKE2B_384:
     TDigestAlgorithm.BLAKE2B_384:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateBlake2B_384);
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateBlake2B_384);
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.BLAKE2B_512:
     TDigestAlgorithm.BLAKE2B_512:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateBlake2B_512);
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateBlake2B_512);
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.BLAKE2S_128:
     TDigestAlgorithm.BLAKE2S_128:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateBlake2S_128);
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateBlake2S_128);
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.BLAKE2S_160:
     TDigestAlgorithm.BLAKE2S_160:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateBlake2S_160);
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateBlake2S_160);
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.BLAKE2S_224:
     TDigestAlgorithm.BLAKE2S_224:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateBlake2S_224);
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateBlake2S_224);
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.BLAKE2S_256:
     TDigestAlgorithm.BLAKE2S_256:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateBlake2S_256);
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateBlake2S_256);
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.GOST3411:
     TDigestAlgorithm.GOST3411:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateGost());
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateGost());
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.GOST3411_2012_256:
     TDigestAlgorithm.GOST3411_2012_256:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateGOST3411_2012_256());
-        result.Initialize;
+        result := TDigest.Create
+          (THashFactory.TCrypto.CreateGOST3411_2012_256());
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.GOST3411_2012_512:
     TDigestAlgorithm.GOST3411_2012_512:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateGOST3411_2012_512());
-        result.Initialize;
+        result := TDigest.Create
+          (THashFactory.TCrypto.CreateGOST3411_2012_512());
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.MD2:
     TDigestAlgorithm.MD2:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateMD2());
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateMD2());
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.MD4:
     TDigestAlgorithm.MD4:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateMD4());
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateMD4());
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.MD5:
     TDigestAlgorithm.MD5:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateMD5());
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateMD5());
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.NULL:
     TDigestAlgorithm.NULL:
       begin
       begin
-        result := IDigest(THashFactory.TNullDigestFactory.CreateNullDigest());
-        result.Initialize;
+        result := TDigest.Create
+          (THashFactory.TNullDigestFactory.CreateNullDigest());
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.RIPEMD128:
     TDigestAlgorithm.RIPEMD128:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateRIPEMD128());
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateRIPEMD128());
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.RIPEMD160:
     TDigestAlgorithm.RIPEMD160:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateRIPEMD160());
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateRIPEMD160());
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.RIPEMD256:
     TDigestAlgorithm.RIPEMD256:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateRIPEMD256());
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateRIPEMD256());
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.RIPEMD320:
     TDigestAlgorithm.RIPEMD320:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateRIPEMD320());
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateRIPEMD320());
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.SHA_1:
     TDigestAlgorithm.SHA_1:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateSHA1());
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateSHA1());
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.SHA_224:
     TDigestAlgorithm.SHA_224:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateSHA2_224());
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateSHA2_224());
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.SHA_256:
     TDigestAlgorithm.SHA_256:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateSHA2_256());
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateSHA2_256());
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.SHA_384:
     TDigestAlgorithm.SHA_384:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateSHA2_384());
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateSHA2_384());
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.SHA_512:
     TDigestAlgorithm.SHA_512:
       begin
       begin
 
 
-        result := IDigest(THashFactory.TCrypto.CreateSHA2_512());
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateSHA2_512());
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.SHA_512_224:
     TDigestAlgorithm.SHA_512_224:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateSHA2_512_224());
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateSHA2_512_224());
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.SHA_512_256:
     TDigestAlgorithm.SHA_512_256:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateSHA2_512_256());
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateSHA2_512_256());
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.SHA3_224:
     TDigestAlgorithm.SHA3_224:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateSHA3_224());
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateSHA3_224());
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.SHA3_256:
     TDigestAlgorithm.SHA3_256:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateSHA3_256());
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateSHA3_256());
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.SHA3_384:
     TDigestAlgorithm.SHA3_384:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateSHA3_384());
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateSHA3_384());
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.SHA3_512:
     TDigestAlgorithm.SHA3_512:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateSHA3_512());
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateSHA3_512());
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.TIGER:
     TDigestAlgorithm.TIGER:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateTiger_3_192);
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateTiger_3_192);
+
         Exit;
         Exit;
       end;
       end;
 
 
     TDigestAlgorithm.WHIRLPOOL:
     TDigestAlgorithm.WHIRLPOOL:
       begin
       begin
-        result := IDigest(THashFactory.TCrypto.CreateWhirlPool);
-        result.Initialize;
+        result := TDigest.Create(THashFactory.TCrypto.CreateWhirlPool);
+
         Exit;
         Exit;
       end
       end
   else
   else
@@ -458,14 +467,28 @@ begin
     TRosstandartObjectIdentifiers.id_tc26_gost_3411_12_512);
     TRosstandartObjectIdentifiers.id_tc26_gost_3411_12_512);
 end;
 end;
 
 
+class function TDigestUtilities.DoFinal(const digest: IDigest)
+  : TCryptoLibByteArray;
+begin
+  System.SetLength(result, digest.GetDigestSize());
+  digest.DoFinal(result, 0);
+end;
+
+class function TDigestUtilities.DoFinal(const digest: IDigest;
+  input: TCryptoLibByteArray): TCryptoLibByteArray;
+begin
+  digest.BlockUpdate(input, 0, System.Length(input));
+  result := DoFinal(digest);
+end;
+
 class function TDigestUtilities.CalculateDigest(const algorithm: String;
 class function TDigestUtilities.CalculateDigest(const algorithm: String;
   input: TCryptoLibByteArray): TCryptoLibByteArray;
   input: TCryptoLibByteArray): TCryptoLibByteArray;
 var
 var
   digest: IDigest;
   digest: IDigest;
 begin
 begin
   digest := GetDigest(algorithm);
   digest := GetDigest(algorithm);
-  digest.TransformBytes(input, 0, System.Length(input));
-  result := digest.TransformFinal().GetBytes();
+  digest.BlockUpdate(input, 0, System.Length(input));
+  result := DoFinal(digest);
 end;
 end;
 
 
 class constructor TDigestUtilities.CreateDigestUtilities;
 class constructor TDigestUtilities.CreateDigestUtilities;

+ 1 - 1
CryptoLib/src/Security/ClpSecureRandom.pas

@@ -302,7 +302,7 @@ begin
   if (autoSeed) then
   if (autoSeed) then
   begin
   begin
     prng.AddSeedMaterial(NextCounterValue());
     prng.AddSeedMaterial(NextCounterValue());
-    prng.AddSeedMaterial(GetNextBytes(Master, digest.HashSize));
+    prng.AddSeedMaterial(GetNextBytes(Master, digest.GetDigestSize));
   end;
   end;
   Result := prng;
   Result := prng;
 end;
 end;

+ 17 - 0
CryptoLib/src/Utils/ClpArrayUtils.pas

@@ -58,6 +58,9 @@ type
     class function Prepend(const A: TCryptoLibByteArray; B: Byte)
     class function Prepend(const A: TCryptoLibByteArray; B: Byte)
       : TCryptoLibByteArray; static;
       : TCryptoLibByteArray; static;
 
 
+    class function CopyOf(const data: TCryptoLibByteArray; newLength: Int32)
+      : TCryptoLibByteArray; static;
+
     class function CopyOfRange(const data: TCryptoLibByteArray;
     class function CopyOfRange(const data: TCryptoLibByteArray;
       from, &to: Int32): TCryptoLibByteArray; static;
       from, &to: Int32): TCryptoLibByteArray; static;
 
 
@@ -158,6 +161,20 @@ end;
 
 
 {$B-}
 {$B-}
 
 
+class function TArrayUtils.CopyOf(const data: TCryptoLibByteArray;
+  newLength: Int32): TCryptoLibByteArray;
+begin
+  System.SetLength(Result, newLength);
+  if (newLength < System.Length(data)) then
+  begin
+    System.Move(data[0], Result[0], newLength * System.SizeOf(Byte));
+  end
+  else
+  begin
+    System.Move(data[0], Result[0], System.Length(data) * System.SizeOf(Byte));
+  end;
+end;
+
 class function TArrayUtils.CopyOfRange(const data: TCryptoLibByteArray;
 class function TArrayUtils.CopyOfRange(const data: TCryptoLibByteArray;
   from, &to: Int32): TCryptoLibByteArray;
   from, &to: Int32): TCryptoLibByteArray;
 var
 var