Browse Source

add Scrypt support

Ugochukwu Mmaduekwe 6 years ago
parent
commit
8d6157dcfb

+ 2 - 0
CryptoLib.Samples/Delphi.Samples/UsageSamples.dpr

@@ -343,6 +343,8 @@ uses
   ClpIKdf1BytesGenerator in '..\..\CryptoLib\src\Interfaces\ClpIKdf1BytesGenerator.pas',
   ClpIArgon2ParametersGenerator in '..\..\CryptoLib\src\Interfaces\ClpIArgon2ParametersGenerator.pas',
   ClpArgon2ParametersGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpArgon2ParametersGenerator.pas',
+  ClpScryptParametersGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpScryptParametersGenerator.pas',
+  ClpIScryptParametersGenerator in '..\..\CryptoLib\src\Interfaces\ClpIScryptParametersGenerator.pas',
   UsageExamples in '..\src\UsageExamples.pas';
 
 begin

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

@@ -353,6 +353,8 @@ uses
   ClpIKdf1BytesGenerator in '..\..\CryptoLib\src\Interfaces\ClpIKdf1BytesGenerator.pas',
   ClpIArgon2ParametersGenerator in '..\..\CryptoLib\src\Interfaces\ClpIArgon2ParametersGenerator.pas',
   ClpArgon2ParametersGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpArgon2ParametersGenerator.pas',
+  ClpScryptParametersGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpScryptParametersGenerator.pas',
+  ClpIScryptParametersGenerator in '..\..\CryptoLib\src\Interfaces\ClpIScryptParametersGenerator.pas',
   ClpFixedSecureRandom in '..\src\Utils\ClpFixedSecureRandom.pas',
   ClpIFixedSecureRandom in '..\src\Utils\ClpIFixedSecureRandom.pas',
   ClpIShortenedDigest in '..\src\Utils\ClpIShortenedDigest.pas',
@@ -420,7 +422,8 @@ uses
   Kdf2GeneratorTests in '..\src\Crypto\Kdf2GeneratorTests.pas',
   Argon2Tests in '..\src\Crypto\Argon2Tests.pas',
   DigestUtilitiesTests in '..\src\Security\DigestUtilitiesTests.pas',
-  DigestTests in '..\src\Others\DigestTests.pas';
+  DigestTests in '..\src\Others\DigestTests.pas',
+  ScryptTests in '..\src\Crypto\ScryptTests.pas';
 
 begin
 

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

@@ -356,6 +356,8 @@ uses
   ClpIKdf1BytesGenerator in '..\..\CryptoLib\src\Interfaces\ClpIKdf1BytesGenerator.pas',
   ClpIArgon2ParametersGenerator in '..\..\CryptoLib\src\Interfaces\ClpIArgon2ParametersGenerator.pas',
   ClpArgon2ParametersGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpArgon2ParametersGenerator.pas',
+  ClpScryptParametersGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpScryptParametersGenerator.pas',
+  ClpIScryptParametersGenerator in '..\..\CryptoLib\src\Interfaces\ClpIScryptParametersGenerator.pas',
   ClpFixedSecureRandom in '..\src\Utils\ClpFixedSecureRandom.pas',
   ClpIFixedSecureRandom in '..\src\Utils\ClpIFixedSecureRandom.pas',
   ClpIShortenedDigest in '..\src\Utils\ClpIShortenedDigest.pas',
@@ -423,7 +425,8 @@ uses
   Kdf2GeneratorTests in '..\src\Crypto\Kdf2GeneratorTests.pas',
   Argon2Tests in '..\src\Crypto\Argon2Tests.pas',
   DigestUtilitiesTests in '..\src\Security\DigestUtilitiesTests.pas',
-  DigestTests in '..\src\Others\DigestTests.pas';
+  DigestTests in '..\src\Others\DigestTests.pas',
+  ScryptTests in '..\src\Crypto\ScryptTests.pas';
 
 begin
 

+ 9 - 1
CryptoLib.Tests/FreePascal.Tests/CryptoLib.Tests.lpi

@@ -77,7 +77,7 @@
         <PackageName Value="FCL"/>
       </Item4>
     </RequiredPackages>
-    <Units Count="69">
+    <Units Count="71">
       <Unit0>
         <Filename Value="CryptoLib.lpr"/>
         <IsPartOfProject Value="True"/>
@@ -355,6 +355,14 @@
         <Filename Value="..\src\Security\DigestUtilitiesTests.pas"/>
         <IsPartOfProject Value="True"/>
       </Unit68>
+      <Unit69>
+        <Filename Value="CryptoLib.Tests.lpi"/>
+        <IsPartOfProject Value="True"/>
+      </Unit69>
+      <Unit70>
+        <Filename Value="..\src\Crypto\ScryptTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit70>
     </Units>
   </ProjectOptions>
   <CompilerOptions>

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

@@ -68,6 +68,7 @@ uses
   Kdf1GeneratorTests,
   Kdf2GeneratorTests,
   Argon2Tests,
+  ScryptTests,
   DigestTests,
   DigestUtilitiesTests,
   ClpFixedSecureRandom,

+ 5 - 1
CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.Tests.lpi

@@ -37,7 +37,7 @@
         <PackageName Value="FCL"/>
       </Item2>
     </RequiredPackages>
-    <Units Count="69">
+    <Units Count="70">
       <Unit0>
         <Filename Value="CryptoLibConsole.lpr"/>
         <IsPartOfProject Value="True"/>
@@ -314,6 +314,10 @@
         <Filename Value="..\src\Security\DigestUtilitiesTests.pas"/>
         <IsPartOfProject Value="True"/>
       </Unit68>
+      <Unit69>
+        <Filename Value="..\src\Crypto\ScryptTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit69>
     </Units>
   </ProjectOptions>
   <CompilerOptions>

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

@@ -66,6 +66,7 @@ uses
   Kdf1GeneratorTests,
   Kdf2GeneratorTests,
   Argon2Tests,
+  ScryptTests,
   DigestTests,
   DigestUtilitiesTests,
   ClpFixedSecureRandom,

+ 3 - 4
CryptoLib.Tests/src/Crypto/Argon2Tests.pas

@@ -34,8 +34,7 @@ uses
   ClpIKeyParameter,
   ClpArgon2ParametersGenerator,
   ClpIArgon2ParametersGenerator,
-  ClpConverters,
-  ClpCryptoLibTypes;
+  ClpConverters;
 
 type
 
@@ -87,7 +86,7 @@ procedure TTestArgon2.HashTestFromInternetDraft(AArgon2Type: TArgon2Type;
 var
   LArgon2Generator: IArgon2ParametersGenerator;
   LActual: String;
-  LAdditional, LSecret, LSalt, LPassword: TCryptoLibByteArray;
+  LAdditional, LSecret, LSalt, LPassword: TBytes;
 begin
 
   LAdditional := TConverters.ConvertHexStringToBytes(AAdditional);
@@ -121,7 +120,7 @@ procedure TTestArgon2.HashTestOthers(AArgon2Type: TArgon2Type;
   const APassword, ASalt, APasswordRef: String; AOutputLength: Int32);
 var
   LArgon2Generator: IArgon2ParametersGenerator;
-  LSalt, LPassword: TCryptoLibByteArray;
+  LSalt, LPassword: TBytes;
   LActual: String;
 begin
 

+ 250 - 0
CryptoLib.Tests/src/Crypto/ScryptTests.pas

@@ -0,0 +1,250 @@
+{ *********************************************************************************** }
+{ *                              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 ScryptTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+uses
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpIKeyParameter,
+  ClpScryptParametersGenerator,
+  ClpIScryptParametersGenerator,
+  ClpConverters,
+  HlpHashLibTypes,
+  ClpCryptoLibTypes;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  /// <summary>
+  /// A Test class for Scrypt.
+  /// </summary>
+  TTestScrypt = class(TCryptoLibTestCase)
+
+  private
+
+    const
+    // multiplied by 8 to get it in bits
+    DEFAULT_OUTPUTLEN_IN_BITS = Int32(64 * 8);
+    ONE_AS_OUTPUTLEN_IN_BITS = Int32(1 * 8);
+
+  var
+    FExpectedString, FActualString: String;
+
+    function DoTestVector(const APassword, ASalt: String;
+      ACost, ABlockSize, AParallelism, AOutputSize: Int32): String;
+
+    procedure DoCheckOk(const AMsg: String; const APassword, ASalt: TBytes;
+      ACost, ABlockSize, AParallelism, AOutputSize: Int32);
+
+    procedure DoCheckIllegal(const AMsg: String; const APassword, ASalt: TBytes;
+      ACost, ABlockSize, AParallelism, AOutputSize: Int32);
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+
+    procedure TestVectors;
+    procedure TestParameters;
+
+  end;
+
+implementation
+
+{ TTestScrypt }
+
+procedure TTestScrypt.SetUp;
+begin
+  inherited;
+
+end;
+
+procedure TTestScrypt.TearDown;
+begin
+  inherited;
+
+end;
+
+function TTestScrypt.DoTestVector(const APassword, ASalt: String;
+  ACost, ABlockSize, AParallelism, AOutputSize: Int32): String;
+var
+  LScryptGenerator: IScryptParametersGenerator;
+  APasswordBytes, ASaltBytes, OutputBytes: TBytes;
+begin
+  APasswordBytes := TConverters.ConvertStringToBytes(APassword,
+    TEncoding.ASCII);
+  ASaltBytes := TConverters.ConvertStringToBytes(ASalt, TEncoding.ASCII);
+
+  LScryptGenerator := TScryptParametersGenerator.Create();
+
+  //
+  // Set the parameters.
+  //
+
+  LScryptGenerator.Init(APasswordBytes, ASaltBytes, ACost, ABlockSize,
+    AParallelism);
+
+  OutputBytes := (LScryptGenerator.GenerateDerivedMacParameters(AOutputSize)
+    as IKeyParameter).GetKey();
+  LScryptGenerator.Clear();
+  Result := TConverters.ConvertBytesToHexString(OutputBytes, False);
+end;
+
+procedure TTestScrypt.DoCheckIllegal(const AMsg: String;
+  const APassword, ASalt: TBytes; ACost, ABlockSize, AParallelism,
+  AOutputSize: Int32);
+var
+  LScryptGenerator: IScryptParametersGenerator;
+  OutputBytes: TBytes;
+begin
+  try
+
+    LScryptGenerator := TScryptParametersGenerator.Create();
+    //
+    // Set the parameters.
+    //
+    //
+    LScryptGenerator.Init(APassword, ASalt, ACost, ABlockSize, AParallelism);
+
+    OutputBytes := (LScryptGenerator.GenerateDerivedMacParameters(AOutputSize)
+      as IKeyParameter).GetKey();
+
+    Fail(AMsg);
+  except
+    on e: EArgumentHashLibException do
+    begin
+      // pass so we do nothing
+    end;
+  end;
+end;
+
+procedure TTestScrypt.DoCheckOk(const AMsg: String;
+  const APassword, ASalt: TBytes; ACost, ABlockSize, AParallelism,
+  AOutputSize: Int32);
+var
+  LScryptGenerator: IScryptParametersGenerator;
+  OutputBytes: TBytes;
+begin
+  try
+    try
+
+      LScryptGenerator := TScryptParametersGenerator.Create();
+      //
+      // Set the parameters.
+      //
+      //
+      LScryptGenerator.Init(APassword, ASalt, ACost, ABlockSize, AParallelism);
+
+      OutputBytes := (LScryptGenerator.GenerateDerivedMacParameters(AOutputSize)
+        as IKeyParameter).GetKey();
+    except
+      on e: EArgumentHashLibException do
+      begin
+        Fail(AMsg);
+      end;
+    end;
+  finally
+    LScryptGenerator.Clear();
+  end;
+end;
+
+procedure TTestScrypt.TestParameters;
+begin
+  DoCheckOk('Minimal values', Nil, Nil, 2, 1, 1, ONE_AS_OUTPUTLEN_IN_BITS);
+  DoCheckIllegal('Cost parameter must be > 1', Nil, Nil, 1, 1, 1,
+    ONE_AS_OUTPUTLEN_IN_BITS);
+  DoCheckOk('Cost parameter 32768 OK for r = 1', Nil, Nil, 32768, 1, 1,
+    ONE_AS_OUTPUTLEN_IN_BITS);
+  DoCheckIllegal('Cost parameter must < 65536 for r = 1', Nil, Nil, 65536, 1, 1,
+    ONE_AS_OUTPUTLEN_IN_BITS);
+  DoCheckIllegal('Block size must be >= 1', Nil, Nil, 2, 0, 2,
+    ONE_AS_OUTPUTLEN_IN_BITS);
+  DoCheckIllegal('Parallelisation parameter must be >= 1', Nil, Nil, 2, 1, 0,
+    ONE_AS_OUTPUTLEN_IN_BITS);
+  // disabled test because it's very expensive
+  // DoCheckOk('Parallelisation parameter 65535 OK for r = 4', Nil, Nil, 2, 32,
+  // 65535, ONE_AS_OUTPUTLEN_IN_BITS);
+  DoCheckIllegal('Parallelisation parameter must be < 65535 for r = 4', Nil,
+    Nil, 2, 32, 65536, ONE_AS_OUTPUTLEN_IN_BITS);
+
+  DoCheckIllegal('Len parameter must be > 1', Nil, Nil, 2, 1, 1, 0);
+end;
+
+procedure TTestScrypt.TestVectors;
+begin
+
+  FActualString := DoTestVector('', '', 16, 1, 1, DEFAULT_OUTPUTLEN_IN_BITS);
+  FExpectedString :=
+    '77D6576238657B203B19CA42C18A0497F16B4844E3074AE8DFDFFA3FEDE21442FCD0069DED0948F8326A753A0FC81F17E8D3E0FB2E0D3628CF35E20C38D18906';
+
+  CheckEquals(FExpectedString, FActualString, Format('Expected %s but got %s.',
+    [FExpectedString, FActualString]));
+
+  FActualString := DoTestVector('password', 'NaCl', 1024, 8, 16,
+    DEFAULT_OUTPUTLEN_IN_BITS);
+  FExpectedString :=
+    'FDBABE1C9D3472007856E7190D01E9FE7C6AD7CBC8237830E77376634B3731622EAF30D92E22A3886FF109279D9830DAC727AFB94A83EE6D8360CBDFA2CC0640';
+
+  CheckEquals(FExpectedString, FActualString, Format('Expected %s but got %s.',
+    [FExpectedString, FActualString]));
+
+  FActualString := DoTestVector('pleaseletmein', 'SodiumChloride', 16384, 8, 1,
+    DEFAULT_OUTPUTLEN_IN_BITS);
+  FExpectedString :=
+    '7023BDCB3AFD7348461C06CD81FD38EBFDA8FBBA904F8E3EA9B543F6545DA1F2D5432955613F0FCF62D49705242A9AF9E61E85DC0D651E40DFCF017B45575887';
+
+  CheckEquals(FExpectedString, FActualString, Format('Expected %s but got %s.',
+    [FExpectedString, FActualString]));
+
+  FActualString := DoTestVector('pleaseletmein', 'SodiumChloride', 1048576, 8,
+    1, DEFAULT_OUTPUTLEN_IN_BITS);
+  FExpectedString :=
+    '2101CB9B6A511AAEADDBBE09CF70F881EC568D574A2FFD4DABE5EE9820ADAA478E56FD8F4BA5D09FFA1C6D927C40F4C337304049E8A952FBCBF45C6FA77A41A4';
+
+  CheckEquals(FExpectedString, FActualString, Format('Expected %s but got %s.',
+    [FExpectedString, FActualString]));
+
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestScrypt);
+{$ELSE}
+  RegisterTest(TTestScrypt.Suite);
+{$ENDIF FPC}
+
+end.

+ 12 - 1
CryptoLib/src/Asn1/Misc/ClpMiscObjectIdentifiers.pas

@@ -37,7 +37,7 @@ type
       Fcryptlib_algorithm_blowfish_CBC, Fcryptlib_algorithm_blowfish_CFB,
       Fcryptlib_algorithm_blowfish_OFB, Fblake2, Fid_blake2b160, Fid_blake2b256,
       Fid_blake2b384, Fid_blake2b512, Fid_blake2s128, Fid_blake2s160,
-      Fid_blake2s224, Fid_blake2s256: IDerObjectIdentifier;
+      Fid_blake2s224, Fid_blake2s256, Fid_scrypt: IDerObjectIdentifier;
 
     class function Getcryptlib: IDerObjectIdentifier; static; inline;
 
@@ -63,6 +63,8 @@ type
     class function Getid_blake2s224: IDerObjectIdentifier; static; inline;
     class function Getid_blake2s256: IDerObjectIdentifier; static; inline;
 
+    class function Getid_scrypt: IDerObjectIdentifier; static; inline;
+
     class constructor MiscObjectIdentifiers();
 
   public
@@ -92,6 +94,8 @@ type
     class property id_blake2s224: IDerObjectIdentifier read Getid_blake2s224;
     class property id_blake2s256: IDerObjectIdentifier read Getid_blake2s256;
 
+    class property id_scrypt: IDerObjectIdentifier read Getid_scrypt;
+
     class procedure Boot(); static;
 
   end;
@@ -180,6 +184,11 @@ begin
   result := Fid_blake2s256;
 end;
 
+class function TMiscObjectIdentifiers.Getid_scrypt: IDerObjectIdentifier;
+begin
+  result := Fid_scrypt;
+end;
+
 class procedure TMiscObjectIdentifiers.Boot;
 begin
 
@@ -213,6 +222,8 @@ begin
     Fid_blake2s224 := blake2.Branch('2.7');
     Fid_blake2s256 := blake2.Branch('2.8');
 
+    Fid_scrypt := TDerObjectIdentifier.Create('1.3.6.1.4.1.11591.4.11');
+
     FIsBooted := True;
   end;
 end;

+ 16 - 7
CryptoLib/src/Crypto/Generators/ClpArgon2ParametersGenerator.pas

@@ -26,6 +26,7 @@ uses
   HlpIHashInfo,
   HlpHashFactory,
   HlpPBKDF_Argon2NotBuildInAdapter,
+  ClpPbeParametersGenerator,
   ClpICipherParameters,
   ClpIArgon2ParametersGenerator,
   ClpKeyParameter,
@@ -46,7 +47,7 @@ type
   /// Argon2 Specification</see>, <see href="https://tools.ietf.org/html/draft-irtf-cfrg-argon2-04">
   /// ietf specs</see>
   /// </summary>
-  TArgon2ParametersGenerator = class sealed(TInterfacedObject,
+  TArgon2ParametersGenerator = class sealed(TPbeParametersGenerator,
     IArgon2ParametersGenerator)
 
   strict private
@@ -59,7 +60,7 @@ type
 
   public
 
-    procedure Clear();
+    procedure Clear(); override;
 
     /// <summary>
     /// construct an Argon2 Parameters generator.
@@ -90,7 +91,7 @@ type
     /// a parameters object representing a key.
     /// </returns>
     function GenerateDerivedParameters(const algorithm: String; keySize: Int32)
-      : ICipherParameters; overload;
+      : ICipherParameters; overload; override;
 
     /// <summary>
     /// Generate a key with initialisation vector parameter derived from <br />
@@ -110,7 +111,7 @@ type
     /// a parameters object representing a key and an iv.
     /// </returns>
     function GenerateDerivedParameters(const algorithm: String;
-      keySize, ivSize: Int32): ICipherParameters; overload;
+      keySize, ivSize: Int32): ICipherParameters; overload; override;
 
     /// <summary>
     /// Generate a key parameter for use with a MAC derived from the
@@ -124,7 +125,7 @@ type
     /// a parameters object representing a key.
     /// </returns>
     function GenerateDerivedMacParameters(keySize: Int32)
-      : ICipherParameters; overload;
+      : ICipherParameters; override;
 
   end;
 
@@ -135,8 +136,16 @@ implementation
 procedure TArgon2ParametersGenerator.Clear();
 begin
   TArrayUtils.ZeroFill(FPassword);
-  FArgon2Parameters.Clear();
-  FPBKDF_Argon2.Clear();
+
+  if FArgon2Parameters <> Nil then
+  begin
+    FArgon2Parameters.Clear();
+  end;
+
+  if FPBKDF_Argon2 <> Nil then
+  begin
+    FPBKDF_Argon2.Clear();
+  end;
 end;
 
 constructor TArgon2ParametersGenerator.Create();

+ 2 - 83
CryptoLib/src/Crypto/Generators/ClpPbeParametersGenerator.pas

@@ -23,13 +23,7 @@ interface
 
 uses
   ClpICipherParameters,
-  ClpIPbeParametersGenerator,
-  ClpCryptoLibTypes;
-
-resourcestring
-  SEmptyPassword = 'Password can''t be empty';
-  SEmptySalt = 'Salt can''t be empty';
-  SIterationtooSmall = 'Iteration must be greater than zero.';
+  ClpIPbeParametersGenerator;
 
 type
 
@@ -40,45 +34,9 @@ type
   TPbeParametersGenerator = class abstract(TInterfacedObject,
     IPbeParametersGenerator)
 
-  strict protected
-  var
-    FmPassword, FmSalt: TCryptoLibByteArray;
-    FmIterationCount: Int32;
-
-    /// <returns>
-    /// the password byte array.
-    /// </returns>
-    function GetPassword: TCryptoLibByteArray; virtual;
-
-    /// <returns>
-    /// the salt byte array.
-    /// </returns>
-    function GetSalt: TCryptoLibByteArray; virtual;
-
-    /// <returns>
-    /// the iteration count.
-    /// </returns>
-    function GetIterationCount: Int32; virtual;
-
   public
 
-    procedure Init(const password, salt: TCryptoLibByteArray;
-      iterationCount: Int32); virtual;
-
-    /// <value>
-    /// the password byte array.
-    /// </value>
-    property password: TCryptoLibByteArray read GetPassword;
-
-    /// <value>
-    /// the salt byte array.
-    /// </value>
-    property salt: TCryptoLibByteArray read GetSalt;
-
-    /// <value>
-    /// the iteration count.
-    /// </value>
-    property iterationCount: Int32 read GetIterationCount;
+    procedure Clear(); virtual; abstract;
 
     /// <summary>
     /// Generate derived parameters for a key of length keySize.
@@ -131,43 +89,4 @@ type
 
 implementation
 
-{ TPbeParametersGenerator }
-
-function TPbeParametersGenerator.GetIterationCount: Int32;
-begin
-  result := FmIterationCount;
-end;
-
-function TPbeParametersGenerator.GetPassword: TCryptoLibByteArray;
-begin
-  result := System.Copy(FmPassword);
-end;
-
-function TPbeParametersGenerator.GetSalt: TCryptoLibByteArray;
-begin
-  result := System.Copy(FmSalt);
-end;
-
-procedure TPbeParametersGenerator.Init(const password,
-  salt: TCryptoLibByteArray; iterationCount: Int32);
-begin
-
-  if (password = Nil) then
-  begin
-    raise EArgumentNilCryptoLibException.CreateRes(@SEmptyPassword);
-  end;
-
-  if (salt = Nil) then
-  begin
-    raise EArgumentNilCryptoLibException.CreateRes(@SEmptySalt);
-  end;
-
-  if (iterationCount < 1) then
-    raise EArgumentCryptoLibException.CreateRes(@SIterationtooSmall);
-
-  FmPassword := System.Copy(password);
-  FmSalt := System.Copy(salt);
-  FmIterationCount := iterationCount;
-end;
-
 end.

+ 16 - 7
CryptoLib/src/Crypto/Generators/ClpPkcs5S2ParametersGenerator.pas

@@ -33,6 +33,7 @@ uses
   ClpParametersWithIV,
   ClpParameterUtilities,
   ClpPbeParametersGenerator,
+  ClpArrayUtils,
   ClpCryptoLibTypes;
 
 type
@@ -46,6 +47,7 @@ type
 
   strict private
   var
+    FPassword, FSalt: TCryptoLibByteArray;
     Fdigest: IDigest;
     FPBKDF2_HMAC: HlpIHashInfo.IPBKDF2_HMAC;
 
@@ -58,7 +60,7 @@ type
 
   public
 
-    procedure Clear();
+    procedure Clear(); override;
     /// <summary>
     /// construct a Pkcs5 Scheme 2 Parameters generator.
     /// </summary>
@@ -70,7 +72,7 @@ type
     destructor Destroy; override;
 
     procedure Init(const password, salt: TCryptoLibByteArray;
-      iterationCount: Int32); override;
+      iterationCount: Int32);
 
     /// <summary>
     /// Generate a key parameter derived from the password, salt, and
@@ -119,8 +121,8 @@ type
     /// <returns>
     /// a parameters object representing a key.
     /// </returns>
-    function GenerateDerivedMacParameters(keySize: Int32): ICipherParameters;
-      overload; override;
+    function GenerateDerivedMacParameters(keySize: Int32)
+      : ICipherParameters; override;
 
     /// <value>
     /// the underlying digest.
@@ -134,7 +136,13 @@ implementation
 
 procedure TPkcs5S2ParametersGenerator.Clear();
 begin
-  FPBKDF2_HMAC.Clear();
+  TArrayUtils.ZeroFill(FPassword);
+  TArrayUtils.ZeroFill(FSalt);
+
+  if FPBKDF2_HMAC <> Nil then
+  begin
+    FPBKDF2_HMAC.Clear();
+  end;
 end;
 
 constructor TPkcs5S2ParametersGenerator.Create(const digest: IDigest);
@@ -202,9 +210,10 @@ end;
 procedure TPkcs5S2ParametersGenerator.Init(const password,
   salt: TCryptoLibByteArray; iterationCount: Int32);
 begin
-  inherited Init(password, salt, iterationCount);
+  FPassword := System.Copy(password);
+  FSalt := System.Copy(salt);
   FPBKDF2_HMAC := TKDF.TPBKDF2_HMAC.CreatePBKDF2_HMAC
-    (Fdigest.GetUnderlyingIHash, password, salt, iterationCount);
+    (Fdigest.GetUnderlyingIHash, FPassword, FSalt, iterationCount);
 end;
 
 end.

+ 199 - 0
CryptoLib/src/Crypto/Generators/ClpScryptParametersGenerator.pas

@@ -0,0 +1,199 @@
+{ *********************************************************************************** }
+{ *                              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 ClpScryptParametersGenerator;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+
+  HlpIHashInfo,
+  HlpHashFactory,
+  ClpICipherParameters,
+  ClpPbeParametersGenerator,
+  ClpIScryptParametersGenerator,
+  ClpKeyParameter,
+  ClpIKeyParameter,
+  ClpParametersWithIV,
+  ClpParameterUtilities,
+  ClpArrayUtils,
+  ClpCryptoLibTypes;
+
+type
+
+  /// <summary>
+  /// <a href="http://tools.ietf.org/html/draft-josefsson-scrypt-kdf-01">draft-josefsson-scrypt-kd</a>
+  /// Scrypt Specification</see>
+  /// </summary>
+  TScryptParametersGenerator = class sealed(TPbeParametersGenerator,
+    IScryptParametersGenerator)
+
+  strict private
+  var
+    FPassword, FSalt: TCryptoLibByteArray;
+    FPBKDF_Scrypt: HlpIHashInfo.IPBKDF_Scrypt;
+
+    function GenerateDerivedKey(dkLen: Int32): TCryptoLibByteArray; inline;
+
+  public
+
+    procedure Clear(); override;
+    /// <summary>
+    /// construct an Scrypt Parameters generator.
+    /// </summary>
+    constructor Create();
+
+    destructor Destroy; override;
+
+    procedure Init(const password, salt: TCryptoLibByteArray;
+      cost, blockSize, parallelism: Int32);
+
+    /// <summary>
+    /// Generate a key parameter derived from the password, salt,
+    /// cost, blockSize, parallelism we are currently initialised with.
+    /// </summary>
+    /// <param name="algorithm">
+    /// a parameters object representing a key.
+    /// </param>
+    /// <param name="keySize">
+    /// the length, in bits, of the key required.
+    /// </param>
+    /// <returns>
+    /// a parameters object representing a key.
+    /// </returns>
+    function GenerateDerivedParameters(const algorithm: String; keySize: Int32)
+      : ICipherParameters; overload; override;
+
+    /// <summary>
+    /// Generate a key with initialisation vector parameter derived from <br />
+    /// the password, salt, cost, blockSize, parallelism we are currently initialised with.
+    /// </summary>
+    /// </summary>
+    /// <param name="algorithm">
+    /// a parameters object representing a key.
+    /// </param>
+    /// <param name="keySize">
+    /// the length, in bits, of the key required.
+    /// </param>
+    /// <param name="ivSize">
+    /// the length, in bits, of the iv required.
+    /// </param>
+    /// <returns>
+    /// a parameters object representing a key and an iv.
+    /// </returns>
+    function GenerateDerivedParameters(const algorithm: String;
+      keySize, ivSize: Int32): ICipherParameters; overload; override;
+
+    /// <summary>
+    /// Generate a key parameter for use with a MAC derived from the
+    /// the password, salt, cost, blockSize, parallelism we are currently initialised with.
+    /// with.
+    /// </summary>
+    /// <param name="keySize">
+    /// the length, in bits, of the key required.
+    /// </param>
+    /// <returns>
+    /// a parameters object representing a key.
+    /// </returns>
+    function GenerateDerivedMacParameters(keySize: Int32)
+      : ICipherParameters; override;
+
+  end;
+
+implementation
+
+{ TPkcs5S2ParametersGenerator }
+
+procedure TScryptParametersGenerator.Clear();
+begin
+  TArrayUtils.ZeroFill(FPassword);
+  TArrayUtils.ZeroFill(FSalt);
+
+  if FPBKDF_Scrypt <> Nil then
+  begin
+    FPBKDF_Scrypt.Clear();
+  end;
+end;
+
+constructor TScryptParametersGenerator.Create();
+begin
+  Inherited Create();
+end;
+
+destructor TScryptParametersGenerator.Destroy;
+begin
+  Clear();
+  inherited Destroy;
+end;
+
+function TScryptParametersGenerator.GenerateDerivedKey(dkLen: Int32)
+  : TCryptoLibByteArray;
+begin
+  result := FPBKDF_Scrypt.GetBytes(dkLen);
+end;
+
+function TScryptParametersGenerator.GenerateDerivedMacParameters(keySize: Int32)
+  : ICipherParameters;
+var
+  dKey: TCryptoLibByteArray;
+begin
+  keySize := keySize div 8;
+
+  dKey := GenerateDerivedKey(keySize);
+
+  result := TKeyParameter.Create(dKey, 0, keySize);
+end;
+
+function TScryptParametersGenerator.GenerateDerivedParameters(const algorithm
+  : String; keySize: Int32): ICipherParameters;
+var
+  dKey: TCryptoLibByteArray;
+begin
+  keySize := keySize div 8;
+
+  dKey := GenerateDerivedKey(keySize);
+
+  result := TParameterUtilities.CreateKeyParameter(algorithm, dKey, 0, keySize);
+end;
+
+function TScryptParametersGenerator.GenerateDerivedParameters(const algorithm
+  : String; keySize, ivSize: Int32): ICipherParameters;
+var
+  dKey: TCryptoLibByteArray;
+  key: IKeyParameter;
+begin
+  keySize := keySize div 8;
+  ivSize := ivSize div 8;
+
+  dKey := GenerateDerivedKey(keySize + ivSize);
+  key := TParameterUtilities.CreateKeyParameter(algorithm, dKey, 0, keySize);
+
+  result := TParametersWithIV.Create(key, dKey, keySize, ivSize);
+end;
+
+procedure TScryptParametersGenerator.Init(const password,
+  salt: TCryptoLibByteArray; cost, blockSize, parallelism: Int32);
+begin
+  FPassword := System.Copy(password);
+  FSalt := System.Copy(salt);
+  FPBKDF_Scrypt := TKDF.TPBKDF_Scrypt.CreatePBKDF_Scrypt(FPassword, FSalt, cost,
+    blockSize, parallelism);
+end;
+
+end.

+ 2 - 51
CryptoLib/src/Interfaces/ClpIArgon2ParametersGenerator.pas

@@ -22,9 +22,8 @@ unit ClpIArgon2ParametersGenerator;
 interface
 
 uses
-  HlpIHashInfo,
   HlpArgon2TypeAndVersion,
-  ClpICipherParameters,
+  ClpIPbeParametersGenerator,
   ClpCryptoLibTypes;
 
 type
@@ -35,63 +34,15 @@ type
 {$SCOPEDENUMS OFF}
 
 type
-  IArgon2ParametersGenerator = interface(IInterface)
+  IArgon2ParametersGenerator = interface(IPbeParametersGenerator)
 
     ['{0AC3D3A8-9422-405F-B0EE-6B7AE0F64F74}']
 
-    procedure Clear();
-
     procedure Init(argon2Type: TArgon2Type; argon2Version: TArgon2Version;
       const password, salt, secret, additional: TCryptoLibByteArray;
       iterations, memory, parallelism: Int32;
       memoryCostType: TArgon2MemoryCostType);
 
-    /// <summary>
-    /// Generate derived parameters for a key of length keySize.
-    /// </summary>
-    /// <param name="algorithm">
-    /// a parameters object representing a key.
-    /// </param>
-    /// <param name="keySize">
-    /// the length, in bits, of the key required.
-    /// </param>
-    /// <returns>
-    /// a parameters object representing a key.
-    /// </returns>
-    function GenerateDerivedParameters(const algorithm: String; keySize: Int32)
-      : ICipherParameters; overload;
-
-    /// <summary>
-    /// Generate derived parameters for a key of length keySize and iv
-    /// of length ivSize.
-    /// </summary>
-    /// <param name="algorithm">
-    /// a parameters object representing a key.
-    /// </param>
-    /// <param name="keySize">
-    /// the length, in bits, of the key required.
-    /// </param>
-    /// <param name="ivSize">
-    /// the length, in bits, of the iv required.
-    /// </param>
-    /// <returns>
-    /// a parameters object representing a key and an iv.
-    /// </returns>
-    function GenerateDerivedParameters(const algorithm: String;
-      keySize, ivSize: Int32): ICipherParameters; overload;
-
-    /// <summary>
-    /// Generate derived parameters for a key of length keySize,
-    /// specifically <br />for use with a MAC.
-    /// </summary>
-    /// <param name="keySize">
-    /// the length, in bits, of the key required.
-    /// </param>
-    /// <returns>
-    /// a parameters object representing a key.
-    /// </returns>
-    function GenerateDerivedMacParameters(keySize: Int32): ICipherParameters;
-
   end;
 
 implementation

+ 1 - 32
CryptoLib/src/Interfaces/ClpIPbeParametersGenerator.pas

@@ -30,38 +30,7 @@ type
 
     ['{8C530FB2-6B8F-4E22-8EA0-D538665471EF}']
 
-    procedure Init(const password, salt: TCryptoLibByteArray;
-      iterationCount: Int32);
-
-    /// <returns>
-    /// the password byte array.
-    /// </returns>
-    function GetPassword: TCryptoLibByteArray;
-
-    /// <value>
-    /// the password byte array.
-    /// </value>
-    property password: TCryptoLibByteArray read GetPassword;
-
-    /// <returns>
-    /// the salt byte array.
-    /// </returns>
-    function GetSalt: TCryptoLibByteArray;
-
-    /// <value>
-    /// the salt byte array.
-    /// </value>
-    property salt: TCryptoLibByteArray read GetSalt;
-
-    /// <returns>
-    /// the iteration count.
-    /// </returns>
-    function GetIterationCount: Int32;
-
-    /// <value>
-    /// the iteration count.
-    /// </value>
-    property iterationCount: Int32 read GetIterationCount;
+    procedure Clear();
 
     /// <summary>
     /// Generate derived parameters for a key of length keySize.

+ 4 - 2
CryptoLib/src/Interfaces/ClpIPkcs5S2ParametersGenerator.pas

@@ -23,14 +23,16 @@ interface
 
 uses
   ClpIPbeParametersGenerator,
-  ClpIDigest;
+  ClpIDigest,
+  ClpCryptoLibTypes;
 
 type
   IPkcs5S2ParametersGenerator = interface(IPbeParametersGenerator)
 
     ['{AD345DB8-2341-4C56-B401-23444C2A81BA}']
 
-    procedure Clear();
+    procedure Init(const password, salt: TCryptoLibByteArray;
+      iterationCount: Int32);
 
     function GetDigest: IDigest;
 

+ 40 - 0
CryptoLib/src/Interfaces/ClpIScryptParametersGenerator.pas

@@ -0,0 +1,40 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIScryptParametersGenerator;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIPbeParametersGenerator,
+  ClpCryptoLibTypes;
+
+type
+  IScryptParametersGenerator = interface(IPbeParametersGenerator)
+
+    ['{1EB9E081-1F90-409F-A5B9-3A999EB6CC70}']
+
+    procedure Init(const password, salt: TCryptoLibByteArray;
+      cost, blockSize, parallelism: Int32);
+
+  end;
+
+implementation
+
+end.

+ 3 - 1
CryptoLib/src/Packages/Delphi/CryptoLib4PascalPackage.dpk

@@ -371,6 +371,8 @@ contains
   ClpIKdf1BytesGenerator in '..\..\Interfaces\ClpIKdf1BytesGenerator.pas',
   ClpKdf1BytesGenerator in '..\..\Crypto\Generators\ClpKdf1BytesGenerator.pas',
   ClpIArgon2ParametersGenerator in '..\..\Interfaces\ClpIArgon2ParametersGenerator.pas',
-  ClpArgon2ParametersGenerator in '..\..\Crypto\Generators\ClpArgon2ParametersGenerator.pas';
+  ClpArgon2ParametersGenerator in '..\..\Crypto\Generators\ClpArgon2ParametersGenerator.pas',
+  ClpIScryptParametersGenerator in '..\..\Interfaces\ClpIScryptParametersGenerator.pas',
+  ClpScryptParametersGenerator in '..\..\Crypto\Generators\ClpScryptParametersGenerator.pas';
 
 end.

+ 9 - 1
CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.lpk

@@ -25,7 +25,7 @@
  Acknowledgements: 
 Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring the development of this library "/>
     <Version Major="3" Minor="1"/>
-    <Files Count="339">
+    <Files Count="341">
       <Item1>
         <Filename Value="..\..\Asn1\ClpOidTokenizer.pas"/>
         <UnitName Value="ClpOidTokenizer"/>
@@ -1384,6 +1384,14 @@ Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring the devel
         <Filename Value="..\..\Crypto\Generators\ClpArgon2ParametersGenerator.pas"/>
         <UnitName Value="ClpArgon2ParametersGenerator"/>
       </Item339>
+      <Item340>
+        <Filename Value="..\..\Interfaces\ClpIScryptParametersGenerator.pas"/>
+        <UnitName Value="ClpIScryptParametersGenerator"/>
+      </Item340>
+      <Item341>
+        <Filename Value="..\..\Crypto\Generators\ClpScryptParametersGenerator.pas"/>
+        <UnitName Value="ClpScryptParametersGenerator"/>
+      </Item341>
     </Files>
     <RequiredPkgs Count="3">
       <Item1>

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

@@ -121,7 +121,8 @@ uses
   ClpEd25519Signer, ClpEd25519CtxBlake2BSigner, ClpEd25519CtxSigner, 
   ClpEd25519Blake2BSigner, ClpTeleTrusTNamedCurves, ClpAgreementUtilities, 
   ClpIKdf1BytesGenerator, ClpKdf1BytesGenerator, 
-  ClpIArgon2ParametersGenerator, ClpArgon2ParametersGenerator;
+  ClpIArgon2ParametersGenerator, ClpArgon2ParametersGenerator, 
+  ClpIScryptParametersGenerator, ClpScryptParametersGenerator;
 
 implementation