Browse Source

partial Rsa implementation

Ugochukwu Mmaduekwe 1 tháng trước cách đây
mục cha
commit
a6cea3a43a
54 tập tin đã thay đổi với 7342 bổ sung157 xóa
  1. 48 0
      CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.dpr
  2. 230 0
      CryptoLib.Tests/src/Crypto/ISO9796Tests.pas
  3. 457 0
      CryptoLib.Tests/src/Crypto/RSABlindedTests.pas
  4. 325 0
      CryptoLib.Tests/src/Crypto/RSADigestSignerTests.pas
  5. 336 0
      CryptoLib.Tests/src/Crypto/RSATests.pas
  6. 37 2
      CryptoLib.Tests/src/Others/SignerUtilitiesTests.pas
  7. 238 39
      CryptoLib/src/Asn1/Pkcs/ClpPkcsObjectIdentifiers.pas
  8. 184 81
      CryptoLib/src/Asn1/TeleTrust/ClpTeleTrusTObjectIdentifiers.pas
  9. 161 0
      CryptoLib/src/Asn1/X509/ClpAlgorithmIdentifier.pas
  10. 184 0
      CryptoLib/src/Asn1/X509/ClpDigestInfo.pas
  11. 326 0
      CryptoLib/src/Asn1/X509/ClpX509ObjectIdentifiers.pas
  12. 314 0
      CryptoLib/src/Crypto/ClpBufferedAsymmetricBlockCipher.pas
  13. 111 19
      CryptoLib/src/Crypto/Digests/ClpDigest.pas
  14. 302 0
      CryptoLib/src/Crypto/Encodings/ClpISO9796d1Encoding.pas
  15. 360 0
      CryptoLib/src/Crypto/Encodings/ClpOaepEncoding.pas
  16. 447 0
      CryptoLib/src/Crypto/Encodings/ClpPkcs1Encoding.pas
  17. 186 0
      CryptoLib/src/Crypto/Engines/ClpRsaBlindedEngine.pas
  18. 158 0
      CryptoLib/src/Crypto/Engines/ClpRsaBlindingEngine.pas
  19. 219 0
      CryptoLib/src/Crypto/Engines/ClpRsaCoreEngine.pas
  20. 113 0
      CryptoLib/src/Crypto/Engines/ClpRsaEngine.pas
  21. 112 0
      CryptoLib/src/Crypto/Generators/ClpRsaBlindingFactorGenerator.pas
  22. 264 0
      CryptoLib/src/Crypto/Generators/ClpRsaKeyPairGenerator.pas
  23. 86 0
      CryptoLib/src/Crypto/Parameters/ClpRsaBlindingParameters.pas
  24. 139 0
      CryptoLib/src/Crypto/Parameters/ClpRsaKeyGenerationParameters.pas
  25. 207 0
      CryptoLib/src/Crypto/Parameters/ClpRsaKeyParameters.pas
  26. 183 0
      CryptoLib/src/Crypto/Parameters/ClpRsaPrivateCrtKeyParameters.pas
  27. 390 0
      CryptoLib/src/Crypto/Signers/ClpRsaDigestSigner.pas
  28. 50 0
      CryptoLib/src/Interfaces/ClpIAlgorithmIdentifier.pas
  29. 79 0
      CryptoLib/src/Interfaces/ClpIAsymmetricBlockCipher.pas
  30. 37 0
      CryptoLib/src/Interfaces/ClpIBufferedAsymmetricBlockCipher.pas
  31. 3 1
      CryptoLib/src/Interfaces/ClpIDigest.pas
  32. 52 0
      CryptoLib/src/Interfaces/ClpIDigestInfo.pas
  33. 45 0
      CryptoLib/src/Interfaces/ClpIISO9796d1Encoding.pas
  34. 41 0
      CryptoLib/src/Interfaces/ClpIOaepEncoding.pas
  35. 41 0
      CryptoLib/src/Interfaces/ClpIPkcs1Encoding.pas
  36. 50 0
      CryptoLib/src/Interfaces/ClpIRsa.pas
  37. 38 0
      CryptoLib/src/Interfaces/ClpIRsaBlindedEngine.pas
  38. 37 0
      CryptoLib/src/Interfaces/ClpIRsaBlindingEngine.pas
  39. 42 0
      CryptoLib/src/Interfaces/ClpIRsaBlindingFactorGenerator.pas
  40. 46 0
      CryptoLib/src/Interfaces/ClpIRsaBlindingParameters.pas
  41. 37 0
      CryptoLib/src/Interfaces/ClpIRsaCoreEngine.pas
  42. 37 0
      CryptoLib/src/Interfaces/ClpIRsaDigestSigner.pas
  43. 38 0
      CryptoLib/src/Interfaces/ClpIRsaEngine.pas
  44. 44 0
      CryptoLib/src/Interfaces/ClpIRsaKeyGenerationParameters.pas
  45. 34 0
      CryptoLib/src/Interfaces/ClpIRsaKeyPairGenerator.pas
  46. 44 0
      CryptoLib/src/Interfaces/ClpIRsaKeyParameters.pas
  47. 50 0
      CryptoLib/src/Interfaces/ClpIRsaPrivateCrtKeyParameters.pas
  48. 39 1
      CryptoLib/src/Packages/Delphi/CryptoLib4PascalPackage.dpk
  49. 70 5
      CryptoLib/src/Security/ClpCipherUtilities.pas
  50. 31 9
      CryptoLib/src/Security/ClpDigestUtilities.pas
  51. 10 0
      CryptoLib/src/Security/ClpGeneratorUtilities.pas
  52. 34 0
      CryptoLib/src/Security/ClpParameterUtilities.pas
  53. 119 0
      CryptoLib/src/Security/ClpSignerUtilities.pas
  54. 77 0
      CryptoLib/src/Utils/ClpBigIntegers.pas

+ 48 - 0
CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.dpr

@@ -16,6 +16,11 @@ program CryptoLib.Tests;
 {$ENDIF}
 {$ENDIF}
 
 
 uses
 uses
+  madExcept,
+  madLinkDisAsm,
+  madListHardware,
+  madListProcesses,
+  madListModules,
   Forms,
   Forms,
   TestFramework,
   TestFramework,
   GUITestRunner,
   GUITestRunner,
@@ -450,6 +455,49 @@ uses
   DHTests in '..\src\Crypto\DHTests.pas',
   DHTests in '..\src\Crypto\DHTests.pas',
   Asn1IntegerTests in '..\src\Asn1\Asn1IntegerTests.pas',
   Asn1IntegerTests in '..\src\Asn1\Asn1IntegerTests.pas',
   KMacTests in '..\src\Crypto\KMacTests.pas',
   KMacTests in '..\src\Crypto\KMacTests.pas',
+  { RSA Implementation }
+  ClpIRsa in '..\..\CryptoLib\src\Interfaces\ClpIRsa.pas',
+  ClpIRsaKeyParameters in '..\..\CryptoLib\src\Interfaces\ClpIRsaKeyParameters.pas',
+  ClpRsaKeyParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpRsaKeyParameters.pas',
+  ClpIRsaPrivateCrtKeyParameters in '..\..\CryptoLib\src\Interfaces\ClpIRsaPrivateCrtKeyParameters.pas',
+  ClpRsaPrivateCrtKeyParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpRsaPrivateCrtKeyParameters.pas',
+  ClpIRsaKeyGenerationParameters in '..\..\CryptoLib\src\Interfaces\ClpIRsaKeyGenerationParameters.pas',
+  ClpRsaKeyGenerationParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpRsaKeyGenerationParameters.pas',
+  ClpIAsymmetricBlockCipher in '..\..\CryptoLib\src\Interfaces\ClpIAsymmetricBlockCipher.pas',
+  ClpIRsaCoreEngine in '..\..\CryptoLib\src\Interfaces\ClpIRsaCoreEngine.pas',
+  ClpRsaCoreEngine in '..\..\CryptoLib\src\Crypto\Engines\ClpRsaCoreEngine.pas',
+  ClpIRsaBlindedEngine in '..\..\CryptoLib\src\Interfaces\ClpIRsaBlindedEngine.pas',
+  ClpRsaBlindedEngine in '..\..\CryptoLib\src\Crypto\Engines\ClpRsaBlindedEngine.pas',
+  ClpIRsaEngine in '..\..\CryptoLib\src\Interfaces\ClpIRsaEngine.pas',
+  ClpRsaEngine in '..\..\CryptoLib\src\Crypto\Engines\ClpRsaEngine.pas',
+  ClpIRsaKeyPairGenerator in '..\..\CryptoLib\src\Interfaces\ClpIRsaKeyPairGenerator.pas',
+  ClpRsaKeyPairGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpRsaKeyPairGenerator.pas',
+  ClpIPkcs1Encoding in '..\..\CryptoLib\src\Interfaces\ClpIPkcs1Encoding.pas',
+  ClpPkcs1Encoding in '..\..\CryptoLib\src\Crypto\Encodings\ClpPkcs1Encoding.pas',
+  ClpIOaepEncoding in '..\..\CryptoLib\src\Interfaces\ClpIOaepEncoding.pas',
+  ClpOaepEncoding in '..\..\CryptoLib\src\Crypto\Encodings\ClpOaepEncoding.pas',
+  ClpIISO9796d1Encoding in '..\..\CryptoLib\src\Interfaces\ClpIISO9796d1Encoding.pas',
+  ClpISO9796d1Encoding in '..\..\CryptoLib\src\Crypto\Encodings\ClpISO9796d1Encoding.pas',
+  ClpIRsaDigestSigner in '..\..\CryptoLib\src\Interfaces\ClpIRsaDigestSigner.pas',
+  ClpRsaDigestSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpRsaDigestSigner.pas',
+  ClpIRsaBlindingParameters in '..\..\CryptoLib\src\Interfaces\ClpIRsaBlindingParameters.pas',
+  ClpRsaBlindingParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpRsaBlindingParameters.pas',
+  ClpIRsaBlindingFactorGenerator in '..\..\CryptoLib\src\Interfaces\ClpIRsaBlindingFactorGenerator.pas',
+  ClpRsaBlindingFactorGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpRsaBlindingFactorGenerator.pas',
+  ClpIAlgorithmIdentifier in '..\..\CryptoLib\src\Interfaces\ClpIAlgorithmIdentifier.pas',
+  ClpAlgorithmIdentifier in '..\..\CryptoLib\src\Asn1\X509\ClpAlgorithmIdentifier.pas',
+  ClpIDigestInfo in '..\..\CryptoLib\src\Interfaces\ClpIDigestInfo.pas',
+  ClpDigestInfo in '..\..\CryptoLib\src\Asn1\X509\ClpDigestInfo.pas',
+  ClpX509ObjectIdentifiers in '..\..\CryptoLib\src\Asn1\X509\ClpX509ObjectIdentifiers.pas',
+  ClpIRsaBlindingEngine in '..\..\CryptoLib\src\Interfaces\ClpIRsaBlindingEngine.pas',
+  ClpRsaBlindingEngine in '..\..\CryptoLib\src\Crypto\Engines\ClpRsaBlindingEngine.pas',
+  ClpIBufferedAsymmetricBlockCipher in '..\..\CryptoLib\src\Interfaces\ClpIBufferedAsymmetricBlockCipher.pas',
+  ClpBufferedAsymmetricBlockCipher in '..\..\CryptoLib\src\Crypto\ClpBufferedAsymmetricBlockCipher.pas',
+  { RSA Tests }
+  RSATests in '..\src\Crypto\RSATests.pas',
+  RSABlindedTests in '..\src\Crypto\RSABlindedTests.pas',
+  RSADigestSignerTests in '..\src\Crypto\RSADigestSignerTests.pas',
+  ISO9796Tests in '..\src\Crypto\ISO9796Tests.pas',
   CryptoLibTestBase in '..\src\CryptoLibTestBase.pas';
   CryptoLibTestBase in '..\src\CryptoLibTestBase.pas';
 
 
 begin
 begin

+ 230 - 0
CryptoLib.Tests/src/Crypto/ISO9796Tests.pas

@@ -0,0 +1,230 @@
+{ *********************************************************************************** }
+{ *                              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 ISO9796Tests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+uses
+  Classes,
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpBigInteger,
+  ClpEncoders,
+  ClpRsaEngine,
+  ClpIRsaEngine,
+  ClpISO9796d1Encoding,
+  ClpIISO9796d1Encoding,
+  ClpRsaKeyParameters,
+  ClpIRsaKeyParameters,
+  ClpIAsymmetricBlockCipher,
+  ClpCryptoLibTypes,
+  CryptoLibTestBase;
+
+type
+
+  TTestISO9796 = class(TCryptoLibAlgorithmTestCase)
+  private
+  class var
+    // Test 1 and 2 parameters
+    FMod1, FPub1, FPri1: TBigInteger;
+    FMsg1, FSig1, FMsg2, FSig2: TCryptoLibByteArray;
+    
+    // Test 3 parameters
+    FMod2, FPub2, FPri2: TBigInteger;
+    FMsg3, FSig3: TCryptoLibByteArray;
+
+    class constructor Create;
+
+  private
+    function IsSameAs(const a: TCryptoLibByteArray; off: Int32;
+      const b: TCryptoLibByteArray): Boolean;
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+
+  published
+    procedure TestISO9796d1_Test1;
+    procedure TestISO9796d1_Test2;
+    procedure TestISO9796d1_Test3;
+
+  end;
+
+implementation
+
+{ TTestISO9796 }
+
+class constructor TTestISO9796.Create;
+begin
+  // ISO 9796-1 Test 1 and 2 parameters
+  FMod1 := TBigInteger.Create('0100000000000000000000000000000000bba2d15dbb303c8a21c5ebbcbae52b7125087920dd7cdf358ea119fd66fb064012ec8ce692f0a0b8e8321b041acd40b7', 16);
+  FPub1 := TBigInteger.Create('03', 16);
+  FPri1 := TBigInteger.Create('2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac9f0783a49dd5f6c5af651f4c9d0dc9281c96a3f16a85f9572d7cc3f2d0f25a9dbf1149e4cdc32273faadd3fda5dcda7', 16);
+
+  FMsg1 := THex.Decode('0cbbaa99887766554433221100');
+  // sig1 = mod1.Subtract(BigInteger("309f873d8ded8379490f6097eaafdabc137d3ebfd8f25ab5f138d56a719cdc526bdd022ea65dabab920a81013a85d092e04d3e421caab717c90d89ea45a8d23a", 16)).ToByteArray()
+  FSig1 := FMod1.Subtract(TBigInteger.Create('309f873d8ded8379490f6097eaafdabc137d3ebfd8f25ab5f138d56a719cdc526bdd022ea65dabab920a81013a85d092e04d3e421caab717c90d89ea45a8d23a', 16)).ToByteArray();
+
+  FMsg2 := THex.Decode('fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210');
+  FSig2 := TBigInteger.Create('319bb9becb49f3ed1bca26d0fcf09b0b0a508e4d0bd43b350f959b72cd25b3af47d608fdcd248eada74fbe19990dbeb9bf0da4b4e1200243a14e5cab3f7e610c', 16).ToByteArray();
+
+  // ISO 9796-1 Test 3 parameters
+  FMod2 := TBigInteger.Create('ffffff7fa27087c35ebead78412d2bdffe0301edd494df13458974ea89b364708f7d0f5a00a50779ddf9f7d4cb80b8891324da251a860c4ec9ef288104b3858d', 16);
+  FPub2 := TBigInteger.Create('03', 16);
+  FPri2 := TBigInteger.Create('2aaaaa9545bd6bf5e51fc7940adcdca5550080524e18cfd88b96e8d1c19de6121b13fac0eb0495d47928e047724d91d1740f6968457ce53ec8e24c9362ce84b5', 16);
+
+  FMsg3 := THex.Decode('0112233445566778899aabbccd');
+  FSig3 := FMod2.Subtract(TBigInteger.Create('58e59ffb4b1fb1bcdbf8d1fe9afa3730c78a318a1134f5791b7313d480ff07ac319b068edf8f212945cb09cf33df30ace54f4a063fcca0b732f4b662dc4e2454', 16)).ToByteArray();
+end;
+
+procedure TTestISO9796.SetUp;
+begin
+  inherited;
+end;
+
+procedure TTestISO9796.TearDown;
+begin
+  inherited;
+end;
+
+function TTestISO9796.IsSameAs(const a: TCryptoLibByteArray; off: Int32;
+  const b: TCryptoLibByteArray): Boolean;
+var
+  i: Int32;
+begin
+  if (System.Length(a) - off) <> System.Length(b) then
+  begin
+    Result := False;
+    Exit;
+  end;
+
+  for i := 0 to System.Length(b) - 1 do
+  begin
+    if a[i + off] <> b[i] then
+    begin
+      Result := False;
+      Exit;
+    end;
+  end;
+
+  Result := True;
+end;
+
+procedure TTestISO9796.TestISO9796d1_Test1;
+var
+  pubParameters, privParameters: IRsaKeyParameters;
+  rsa: IRsaEngine;
+  eng: IISO9796d1Encoding;
+  data: TCryptoLibByteArray;
+begin
+  pubParameters := TRsaKeyParameters.Create(False, FMod1, FPub1);
+  privParameters := TRsaKeyParameters.Create(True, FMod1, FPri1);
+  rsa := TRsaEngine.Create();
+
+  // ISO 9796-1 - private sign, public verify
+  eng := TISO9796d1Encoding.Create(rsa as IAsymmetricBlockCipher);
+
+  eng.Init(True, privParameters);
+  eng.SetPadBits(4);
+
+  data := eng.ProcessBlock(FMsg1, 0, System.Length(FMsg1));
+
+  eng.Init(False, pubParameters);
+
+  CheckTrue(AreEqual(FSig1, data), 'failed ISO9796-1 generation Test 1');
+
+  data := eng.ProcessBlock(data, 0, System.Length(data));
+
+  CheckTrue(AreEqual(FMsg1, data), 'failed ISO9796-1 retrieve Test 1');
+end;
+
+procedure TTestISO9796.TestISO9796d1_Test2;
+var
+  pubParameters, privParameters: IRsaKeyParameters;
+  rsa: IRsaEngine;
+  eng: IISO9796d1Encoding;
+  data: TCryptoLibByteArray;
+begin
+  pubParameters := TRsaKeyParameters.Create(False, FMod1, FPub1);
+  privParameters := TRsaKeyParameters.Create(True, FMod1, FPri1);
+  rsa := TRsaEngine.Create();
+
+  // ISO 9796-1 - private sign, public verify
+  eng := TISO9796d1Encoding.Create(rsa as IAsymmetricBlockCipher);
+
+  eng.Init(True, privParameters);
+
+  data := eng.ProcessBlock(FMsg2, 0, System.Length(FMsg2));
+
+  eng.Init(False, pubParameters);
+
+  CheckTrue(IsSameAs(data, 1, FSig2), 'failed ISO9796-1 generation Test 2');
+
+  data := eng.ProcessBlock(data, 0, System.Length(data));
+
+  CheckTrue(AreEqual(FMsg2, data), 'failed ISO9796-1 retrieve Test 2');
+end;
+
+procedure TTestISO9796.TestISO9796d1_Test3;
+var
+  pubParameters, privParameters: IRsaKeyParameters;
+  rsa: IRsaEngine;
+  eng: IISO9796d1Encoding;
+  data: TCryptoLibByteArray;
+begin
+  pubParameters := TRsaKeyParameters.Create(False, FMod2, FPub2);
+  privParameters := TRsaKeyParameters.Create(True, FMod2, FPri2);
+  rsa := TRsaEngine.Create();
+
+  // ISO 9796-1 - private sign, public verify
+  eng := TISO9796d1Encoding.Create(rsa as IAsymmetricBlockCipher);
+
+  eng.Init(True, privParameters);
+  eng.SetPadBits(4);
+
+  data := eng.ProcessBlock(FMsg3, 0, System.Length(FMsg3));
+
+  eng.Init(False, pubParameters);
+
+  CheckTrue(IsSameAs(FSig3, 1, data), 'failed ISO9796-1 generation Test 3');
+
+  data := eng.ProcessBlock(data, 0, System.Length(data));
+
+  CheckTrue(IsSameAs(FMsg3, 0, data), 'failed ISO9796-1 retrieve Test 3');
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestISO9796);
+{$ELSE}
+  RegisterTest(TTestISO9796.Suite);
+{$ENDIF FPC}
+
+end.

+ 457 - 0
CryptoLib.Tests/src/Crypto/RSABlindedTests.pas

@@ -0,0 +1,457 @@
+unit RSABlindedTests;
+
+{$IFDEF FPC}
+  {$MODE DELPHI}
+{$ENDIF}
+
+interface
+
+uses
+  SysUtils,
+  Classes,
+  {$IFDEF FPC}
+  fpcunit,
+  testregistry,
+  {$ELSE}
+  TestFramework,
+  {$ENDIF}
+  ClpBigInteger,
+  ClpSecureRandom,
+  ClpISecureRandom,
+  ClpEncoders,
+  ClpConverters,
+  ClpICipherParameters,
+  ClpIAsymmetricBlockCipher,
+  ClpIAsymmetricCipherKeyPair,
+  ClpRsaKeyParameters,
+  ClpIRsaKeyParameters,
+  ClpRsaPrivateCrtKeyParameters,
+  ClpIRsaPrivateCrtKeyParameters,
+  ClpRsaKeyGenerationParameters,
+  ClpIRsaKeyGenerationParameters,
+  ClpRsaKeyPairGenerator,
+  ClpIRsaKeyPairGenerator,
+  ClpRsaBlindedEngine,
+  ClpIRsaBlindedEngine,
+  ClpPkcs1Encoding,
+  ClpIPkcs1Encoding,
+  ClpOaepEncoding,
+  ClpIOaepEncoding,
+  ClpCryptoLibTypes;
+
+type
+  TTestRSABlinded = class(TTestCase)
+  private
+    class var
+      FMod: TBigInteger;
+      FPubExp: TBigInteger;
+      FPrivExp: TBigInteger;
+      FP: TBigInteger;
+      FQ: TBigInteger;
+      FPExp: TBigInteger;
+      FQExp: TBigInteger;
+      FCrtCoef: TBigInteger;
+
+      FOversizedSig: TCryptoLibByteArray;
+      FDudBlock: TCryptoLibByteArray;
+      FTruncatedDataBlock: TCryptoLibByteArray;
+      FIncorrectPadding: TCryptoLibByteArray;
+      FMissingDataBlock: TCryptoLibByteArray;
+
+    class constructor Create;
+
+    function GetPubParameters: IRsaKeyParameters;
+    function GetPrivParameters: IRsaPrivateCrtKeyParameters;
+
+    procedure DoTestOaep(const pubParameters: IRsaKeyParameters;
+      const privParameters: IRsaPrivateCrtKeyParameters);
+
+    procedure CheckForPkcs1Exception(const pubParameters: IRsaKeyParameters;
+      const privParameters: IRsaPrivateCrtKeyParameters;
+      const inputData: TCryptoLibByteArray; const expectedMessage: String);
+
+  published
+    procedure TestRawRSA;
+    procedure TestRawRSAEdge;
+    procedure TestPkcs1PublicPrivate;
+    procedure TestPkcs1PrivatePublic;
+    procedure TestPkcs1OutputBlockSize;
+    procedure TestOaep;
+    procedure TestKeyGeneration768;
+    procedure TestKeyGeneration1024;
+    procedure TestStrictPkcs1Length;
+    procedure TestDudPkcs1Block;
+    procedure TestMissingDataPkcs1Block;
+    procedure TestTruncatedPkcs1Block;
+    procedure TestWrongPaddingPkcs1Block;
+    procedure TestUninitializedEngine;
+  end;
+
+implementation
+
+const
+  Input = '4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e';
+  EdgeInput = 'ff6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e';
+
+{ TTestRSABlinded }
+
+class constructor TTestRSABlinded.Create;
+begin
+  FMod := TBigInteger.Create('b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e' + '92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5', 16);
+  FPubExp := TBigInteger.Create('11', 16);
+  FPrivExp := TBigInteger.Create('92e08f83cc9920746989ca5034dcb384a094fb9c5a6288fcc4304424ab8f56388f72652d8fafc65a4b9020896f2c' + 'de297080f2a540e7b7ce5af0b3446e1258d1dd7f245cf54124b4c6e17da21b90a0ebd22605e6f45c9f136d7a13eaac1c0f7487de8bd6d924972408ebb58af71e76fd7b012a8d0e165f3ae2e5077a8648e619', 16);
+  FP := TBigInteger.Create('f75e80839b9b9379f1cf1128f321639757dba514642c206bbbd99f9a4846208b3e93fbbe5e0527cc59b1d4b929d9555853004c7c8b30ee6a213c3d1bb7415d03', 16);
+  FQ := TBigInteger.Create('b892d9ebdbfc37e397256dd8a5d3123534d1f03726284743ddc6be3a709edb696fc40c7d902ed804c6eee730eee3d5b20bf6bd8d87a296813c87d3b3cc9d7947', 16);
+  FPExp := TBigInteger.Create('1d1a2d3ca8e52068b3094d501c9a842fec37f54db16e9a67070a8b3f53cc03d4257ad252a1a640eadd603724d7bf3737914b544ae332eedf4f34436cac25ceb5', 16);
+  FQExp := TBigInteger.Create('6c929e4e81672fef49d9c825163fec97c4b7ba7acb26c0824638ac22605d7201c94625770984f78a56e6e25904fe7db407099cad9b14588841b94f5ab498dded', 16);
+  FCrtCoef := TBigInteger.Create('dae7651ee69ad1d081ec5e7188ae126f6004ff39556bde90e0b870962fa7b926d070686d8244fe5a9aa709a95686a104614834b0ada4b10f53197a5cb4c97339', 16);
+
+  // Test block data for PKCS1 padding validation
+  FOversizedSig := THex.Decode('01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' + 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e');
+  FDudBlock := THex.Decode('000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' + 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e');
+  FTruncatedDataBlock := THex.Decode('0001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' + 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e');
+  FIncorrectPadding := THex.Decode('0001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' + 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e');
+  FMissingDataBlock := THex.Decode('0001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' + 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
+end;
+
+function TTestRSABlinded.GetPubParameters: IRsaKeyParameters;
+begin
+  Result := TRsaKeyParameters.Create(False, FMod, FPubExp);
+end;
+
+function TTestRSABlinded.GetPrivParameters: IRsaPrivateCrtKeyParameters;
+begin
+  Result := TRsaPrivateCrtKeyParameters.Create(FMod, FPubExp, FPrivExp, FP, FQ, FPExp, FQExp, FCrtCoef);
+end;
+
+procedure TTestRSABlinded.CheckForPkcs1Exception(
+  const pubParameters: IRsaKeyParameters;
+  const privParameters: IRsaPrivateCrtKeyParameters;
+  const inputData: TCryptoLibByteArray; const expectedMessage: String);
+var
+  eng: IAsymmetricBlockCipher;
+  data: TCryptoLibByteArray;
+  exceptionCaught: Boolean;
+begin
+  eng := TRsaBlindedEngine.Create();
+  eng.Init(True, privParameters as ICipherParameters);
+  data := eng.ProcessBlock(inputData, 0, System.Length(inputData));
+
+  eng := TPkcs1Encoding.Create(eng);
+  eng.Init(False, pubParameters as ICipherParameters);
+
+  exceptionCaught := False;
+  try
+    data := eng.ProcessBlock(data, 0, System.Length(data));
+  except
+    on E: EInvalidCipherTextCryptoLibException do
+    begin
+      exceptionCaught := True;
+      Check(Pos(expectedMessage, E.Message) > 0,
+        'Expected message containing "' + expectedMessage + '" but got: ' + E.Message);
+    end;
+  end;
+
+  Check(exceptionCaught, 'Expected PKCS1 exception not thrown');
+end;
+
+procedure TTestRSABlinded.TestRawRSA;
+var
+  pubParams: IRsaKeyParameters;
+  privParams: IRsaPrivateCrtKeyParameters;
+  eng: IAsymmetricBlockCipher;
+  data: TCryptoLibByteArray;
+begin
+  pubParams := GetPubParameters;
+  privParams := GetPrivParameters;
+
+  data := THex.Decode(Input);
+
+  eng := TRsaBlindedEngine.Create();
+  eng.Init(True, pubParams as ICipherParameters);
+
+  data := eng.ProcessBlock(data, 0, System.Length(data));
+
+  eng.Init(False, privParams as ICipherParameters);
+  data := eng.ProcessBlock(data, 0, System.Length(data));
+
+  CheckEquals(Input, THex.Encode(data, False), 'Raw RSA test failed');
+end;
+
+procedure TTestRSABlinded.TestRawRSAEdge;
+var
+  pubParams: IRsaKeyParameters;
+  privParams: IRsaPrivateCrtKeyParameters;
+  eng: IAsymmetricBlockCipher;
+  data: TCryptoLibByteArray;
+begin
+  pubParams := GetPubParameters;
+  privParams := GetPrivParameters;
+
+  data := THex.Decode(EdgeInput);
+
+  eng := TRsaBlindedEngine.Create();
+  eng.Init(True, pubParams as ICipherParameters);
+
+  data := eng.ProcessBlock(data, 0, System.Length(data));
+
+  eng.Init(False, privParams as ICipherParameters);
+  data := eng.ProcessBlock(data, 0, System.Length(data));
+
+  CheckEquals(EdgeInput, THex.Encode(data, False), 'Raw RSA edge test failed');
+end;
+
+procedure TTestRSABlinded.TestPkcs1PublicPrivate;
+var
+  pubParams: IRsaKeyParameters;
+  privParams: IRsaPrivateCrtKeyParameters;
+  eng: IAsymmetricBlockCipher;
+  data: TCryptoLibByteArray;
+begin
+  pubParams := GetPubParameters;
+  privParams := GetPrivParameters;
+
+  data := THex.Decode(Input);
+
+  eng := TPkcs1Encoding.Create(TRsaBlindedEngine.Create());
+  eng.Init(True, pubParams as ICipherParameters);
+
+  data := eng.ProcessBlock(data, 0, System.Length(data));
+
+  eng.Init(False, privParams as ICipherParameters);
+  data := eng.ProcessBlock(data, 0, System.Length(data));
+
+  CheckEquals(Input, THex.Encode(data, False), 'PKCS1 public/private test failed');
+end;
+
+procedure TTestRSABlinded.TestPkcs1PrivatePublic;
+var
+  pubParams: IRsaKeyParameters;
+  privParams: IRsaPrivateCrtKeyParameters;
+  eng: IAsymmetricBlockCipher;
+  data: TCryptoLibByteArray;
+begin
+  pubParams := GetPubParameters;
+  privParams := GetPrivParameters;
+
+  data := THex.Decode(Input);
+
+  eng := TPkcs1Encoding.Create(TRsaBlindedEngine.Create());
+  eng.Init(True, privParams as ICipherParameters);
+
+  data := eng.ProcessBlock(data, 0, System.Length(data));
+
+  eng.Init(False, pubParams as ICipherParameters);
+  data := eng.ProcessBlock(data, 0, System.Length(data));
+
+  CheckEquals(Input, THex.Encode(data, False), 'PKCS1 private/public test failed');
+end;
+
+procedure TTestRSABlinded.TestPkcs1OutputBlockSize;
+var
+  pubParams: IRsaKeyParameters;
+  eng: IPkcs1Encoding;
+begin
+  pubParams := GetPubParameters;
+
+  eng := TPkcs1Encoding.Create(TRsaBlindedEngine.Create());
+  eng.Init(True, pubParams as ICipherParameters);
+
+  // PKCS1 output block size should equal underlying cipher's output block size
+  CheckEquals(eng.OutputBlockSize, eng.UnderlyingCipher.OutputBlockSize,
+    'PKCS1 output block size incorrect');
+end;
+
+procedure TTestRSABlinded.DoTestOaep(const pubParameters: IRsaKeyParameters;
+  const privParameters: IRsaPrivateCrtKeyParameters);
+var
+  eng: IAsymmetricBlockCipher;
+  data: TCryptoLibByteArray;
+begin
+  data := THex.Decode(Input);
+
+  eng := TOaepEncoding.Create(TRsaBlindedEngine.Create());
+  eng.Init(True, pubParameters as ICipherParameters);
+
+  data := eng.ProcessBlock(data, 0, System.Length(data));
+
+  eng.Init(False, privParameters as ICipherParameters);
+  data := eng.ProcessBlock(data, 0, System.Length(data));
+
+  CheckEquals(Input, THex.Encode(data, False), 'OAEP test failed');
+end;
+
+procedure TTestRSABlinded.TestOaep;
+begin
+  DoTestOaep(GetPubParameters, GetPrivParameters);
+end;
+
+procedure TTestRSABlinded.TestKeyGeneration768;
+var
+  pGen: IRsaKeyPairGenerator;
+  genParam: IRsaKeyGenerationParameters;
+  pair: IAsymmetricCipherKeyPair;
+  eng: IAsymmetricBlockCipher;
+  data: TCryptoLibByteArray;
+  pubKey: IRsaKeyParameters;
+begin
+  pGen := TRsaKeyPairGenerator.Create();
+  genParam := TRsaKeyGenerationParameters.Create(TBigInteger.ValueOf($11),
+    TSecureRandom.Create(), 768, 25);
+
+  pGen.Init(genParam);
+  pair := pGen.GenerateKeyPair();
+
+  pubKey := pair.Public as IRsaKeyParameters;
+  Check(pubKey.Modulus.BitLength >= 768, 'Key generation (768) length test failed');
+
+  data := THex.Decode(Input);
+
+  eng := TRsaBlindedEngine.Create();
+  eng.Init(True, pair.Public);
+
+  data := eng.ProcessBlock(data, 0, System.Length(data));
+
+  eng.Init(False, pair.Private);
+  data := eng.ProcessBlock(data, 0, System.Length(data));
+
+  CheckEquals(Input, THex.Encode(data, False), 'Key generation (768) test failed');
+end;
+
+procedure TTestRSABlinded.TestKeyGeneration1024;
+var
+  pGen: IRsaKeyPairGenerator;
+  genParam: IRsaKeyGenerationParameters;
+  pair: IAsymmetricCipherKeyPair;
+  eng: IAsymmetricBlockCipher;
+  data: TCryptoLibByteArray;
+  pubKey: IRsaKeyParameters;
+begin
+  pGen := TRsaKeyPairGenerator.Create();
+  genParam := TRsaKeyGenerationParameters.Create(TBigInteger.ValueOf($11),
+    TSecureRandom.Create(), 1024, 25);
+
+  pGen.Init(genParam);
+  pair := pGen.GenerateKeyPair();
+
+  pubKey := pair.Public as IRsaKeyParameters;
+  Check(pubKey.Modulus.BitLength >= 1024, 'Key generation (1024) length test failed');
+
+  data := THex.Decode(Input);
+
+  eng := TRsaBlindedEngine.Create();
+  eng.Init(True, pair.Public);
+
+  data := eng.ProcessBlock(data, 0, System.Length(data));
+
+  eng.Init(False, pair.Private);
+  data := eng.ProcessBlock(data, 0, System.Length(data));
+
+  CheckEquals(Input, THex.Encode(data, False), 'Key generation (1024) test failed');
+end;
+
+procedure TTestRSABlinded.TestStrictPkcs1Length;
+var
+  pubParams: IRsaKeyParameters;
+  privParams: IRsaPrivateCrtKeyParameters;
+  eng: IAsymmetricBlockCipher;
+  data: TCryptoLibByteArray;
+  exceptionCaught: Boolean;
+  savedStrictLength: Boolean;
+begin
+  pubParams := GetPubParameters;
+  privParams := GetPrivParameters;
+
+  eng := TRsaBlindedEngine.Create();
+  eng.Init(True, privParams as ICipherParameters);
+  data := eng.ProcessBlock(FOversizedSig, 0, System.Length(FOversizedSig));
+
+  eng := TPkcs1Encoding.Create(eng);
+  eng.Init(False, pubParams as ICipherParameters);
+
+  // Test with strict length enabled (should throw)
+  exceptionCaught := False;
+  try
+    data := eng.ProcessBlock(data, 0, System.Length(data));
+  except
+    on E: EInvalidCipherTextCryptoLibException do
+    begin
+      exceptionCaught := True;
+      Check(Pos('Block incorrect size', E.Message) > 0,
+        'Expected "Block incorrect size" but got: ' + E.Message);
+    end;
+  end;
+
+  Check(exceptionCaught, 'Oversized signature block not recognised');
+
+  // Test with strict length disabled (should pass)
+  savedStrictLength := TPkcs1Encoding.StrictLengthEnabled;
+  try
+    TPkcs1Encoding.StrictLengthEnabled := False;
+
+    eng := TPkcs1Encoding.Create(TRsaBlindedEngine.Create());
+    eng.Init(False, pubParams as ICipherParameters);
+
+    // Re-encrypt the data first
+    eng := TRsaBlindedEngine.Create();
+    eng.Init(True, privParams as ICipherParameters);
+    data := eng.ProcessBlock(FOversizedSig, 0, System.Length(FOversizedSig));
+
+    eng := TPkcs1Encoding.Create(eng);
+    eng.Init(False, pubParams as ICipherParameters);
+    data := eng.ProcessBlock(data, 0, System.Length(data));
+    // Should not throw
+  finally
+    TPkcs1Encoding.StrictLengthEnabled := savedStrictLength;
+  end;
+end;
+
+procedure TTestRSABlinded.TestDudPkcs1Block;
+begin
+  CheckForPkcs1Exception(GetPubParameters, GetPrivParameters, FDudBlock, 'Block incorrect');
+end;
+
+procedure TTestRSABlinded.TestMissingDataPkcs1Block;
+begin
+  CheckForPkcs1Exception(GetPubParameters, GetPrivParameters, FMissingDataBlock, 'Block incorrect');
+end;
+
+procedure TTestRSABlinded.TestTruncatedPkcs1Block;
+begin
+  CheckForPkcs1Exception(GetPubParameters, GetPrivParameters, FTruncatedDataBlock, 'Block incorrect');
+end;
+
+procedure TTestRSABlinded.TestWrongPaddingPkcs1Block;
+begin
+  CheckForPkcs1Exception(GetPubParameters, GetPrivParameters, FIncorrectPadding, 'Block incorrect');
+end;
+
+procedure TTestRSABlinded.TestUninitializedEngine;
+var
+  eng: IAsymmetricBlockCipher;
+  data: TCryptoLibByteArray;
+  ExceptionCaught: Boolean;
+begin
+  ExceptionCaught := False;
+  SetLength(data, 1);
+  data[0] := 1;
+
+  eng := TRsaBlindedEngine.Create();
+  try
+    eng.ProcessBlock(data, 0, 1);
+  except
+    on E: EInvalidOperationCryptoLibException do
+      ExceptionCaught := True;
+  end;
+
+  Check(ExceptionCaught, 'Uninitialized engine should raise exception');
+end;
+
+initialization
+  {$IFDEF FPC}
+  RegisterTest(TTestRSABlinded);
+  {$ELSE}
+  RegisterTest(TTestRSABlinded.Suite);
+  {$ENDIF}
+
+end.

+ 325 - 0
CryptoLib.Tests/src/Crypto/RSADigestSignerTests.pas

@@ -0,0 +1,325 @@
+{ *********************************************************************************** }
+{ *                              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 RSADigestSignerTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+uses
+  SysUtils,
+  Classes,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpBigInteger,
+  ClpIDigest,
+  ClpISigner,
+  ClpRsaDigestSigner,
+  ClpIRsaDigestSigner,
+  ClpRsaKeyParameters,
+  ClpIRsaKeyParameters,
+  ClpRsaPrivateCrtKeyParameters,
+  ClpIRsaPrivateCrtKeyParameters,
+  ClpIAsn1Objects,
+  ClpIAlgorithmIdentifier,
+  ClpAlgorithmIdentifier,
+  ClpIDigestInfo,
+  ClpDigestInfo,
+  ClpAsn1Objects,
+  ClpDigestUtilities,
+  ClpX509ObjectIdentifiers,
+  ClpNistObjectIdentifiers,
+  ClpPkcsObjectIdentifiers,
+  ClpTeleTrusTObjectIdentifiers,
+  ClpEncoders,
+  ClpCryptoLibTypes;
+
+type
+
+  TTestRSADigestSigner = class(TTestCase)
+  strict private
+    class var
+      FRsaPublic: IRsaKeyParameters;
+      FRsaPrivate: IRsaPrivateCrtKeyParameters;
+
+    class procedure SetUpKeys;
+    procedure CheckDigest(const digest: IDigest;
+      const digOid: IDerObjectIdentifier);
+    procedure CheckNullDigest(const digest: IDigest;
+      const digOid: IDerObjectIdentifier);
+    class function CreatePrehashSigner: IRsaDigestSigner;
+
+  protected
+    procedure SetUp; override;
+  published
+    procedure TestRipeMD128;
+    procedure TestRipeMD160;
+    procedure TestRipeMD256;
+    procedure TestSha1;
+    procedure TestSha224;
+    procedure TestSha256;
+    procedure TestSha384;
+    procedure TestSha512;
+    procedure TestSha512_224;
+    procedure TestSha512_256;
+    procedure TestSha3_224;
+    procedure TestSha3_256;
+    procedure TestSha3_384;
+    procedure TestSha3_512;
+    procedure TestMD2;
+    procedure TestMD4;
+    procedure TestMD5;
+    procedure TestNullDigestSha1;
+    procedure TestNullDigestSha256;
+    procedure TestNullFormatError;
+  end;
+
+implementation
+
+{ TTestRSADigestSigner }
+
+class procedure TTestRSADigestSigner.SetUpKeys;
+var
+  rsaPubMod, rsaPubExp, rsaPrivMod, rsaPrivExp: TBigInteger;
+  rsaPrivP, rsaPrivQ, rsaPrivDP, rsaPrivDQ, rsaPrivQinv: TBigInteger;
+begin
+  rsaPubMod := TBigInteger.Create(1, TBase64.Decode(
+    'AIASoe2PQb1IP7bTyC9usjHP7FvnUMVpKW49iuFtrw/dMpYlsMMoIU2jupfifDpdFxIktSB4P+6Ymg5WjvHKTIrvQ7SR4zV4jaPTu56Ys0pZ9EDA6gb3HLjtU+8Bb1mfWM+yjKxcPDuFjwEtjGlPHg1Vq+CA9HNcMSKNn2+tW6qt'));
+  rsaPubExp := TBigInteger.Create(1, TBase64.Decode('EQ=='));
+
+  rsaPrivMod := TBigInteger.Create(1, TBase64.Decode(
+    'AIASoe2PQb1IP7bTyC9usjHP7FvnUMVpKW49iuFtrw/dMpYlsMMoIU2jupfifDpdFxIktSB4P+6Ymg5WjvHKTIrvQ7SR4zV4jaPTu56Ys0pZ9EDA6gb3HLjtU+8Bb1mfWM+yjKxcPDuFjwEtjGlPHg1Vq+CA9HNcMSKNn2+tW6qt'));
+  rsaPrivExp := TBigInteger.Create(1, TBase64.Decode(
+    'DxFAOhDajr00rBjqX+7nyZ/9sHWRCCp9WEN5wCsFiWVRPtdB+NeLcou7mWXwf1Y+8xNgmmh//fPV45G2dsyBeZbXeJwB7bzx9NMEAfedchyOwjR8PYdjK3NpTLKtZlEJ6Jkh4QihrXpZMO4fKZWUm9bid3+lmiq43FwW+Hof8/E='));
+
+  rsaPrivP := TBigInteger.Create(1, TBase64.Decode(
+    'AJ9StyTVW+AL/1s7RBtFwZGFBgd3zctBqzzwKPda6LbtIFDznmwDCqAlIQH9X14X7UPLokCDhuAa76OnDXb1OiE='));
+  rsaPrivQ := TBigInteger.Create(1, TBase64.Decode(
+    'AM3JfD79dNJ5A3beScSzPtWxx/tSLi0QHFtkuhtSizeXdkv5FSba7lVzwEOGKHmW829bRoNxThDy4ds1IihW1w0='));
+  rsaPrivDP := TBigInteger.Create(1, TBase64.Decode(
+    'JXzfzG5v+HtLJIZqYMUefJfFLu8DPuJGaLD6lI3cZ0babWZ/oPGoJa5iHpX4Ul/7l3s1PFsuy1GhzCdOdlfRcQ=='));
+  rsaPrivDQ := TBigInteger.Create(1, TBase64.Decode(
+    'YNdJhw3cn0gBoVmMIFRZzflPDNthBiWy/dUMSRfJCxoZjSnr1gysZHK01HteV1YYNGcwPdr3j4FbOfri5c6DUQ=='));
+  rsaPrivQinv := TBigInteger.Create(1, TBase64.Decode(
+    'Lt0g7wrsNsQxuDdB8q/rH8fSFeBXMGLtCIqfOec1j7FEIuYA/ACiRDgXkHa0WgN7nLXSjHoy630wC5Toq8vvUg=='));
+
+  FRsaPublic := TRsaKeyParameters.Create(False, rsaPubMod, rsaPubExp);
+  FRsaPrivate := TRsaPrivateCrtKeyParameters.Create(rsaPrivMod, rsaPubExp,
+    rsaPrivExp, rsaPrivP, rsaPrivQ, rsaPrivDP, rsaPrivDQ, rsaPrivQinv);
+end;
+
+procedure TTestRSADigestSigner.SetUp;
+begin
+  inherited;
+  if FRsaPublic = nil then
+    SetUpKeys;
+end;
+
+procedure TTestRSADigestSigner.CheckDigest(const digest: IDigest;
+  const digOid: IDerObjectIdentifier);
+var
+  msg, sig: TCryptoLibByteArray;
+  signer: ISigner;
+begin
+  msg := TCryptoLibByteArray.Create(1, 6, 3, 32, 7, 43, 2, 5, 7, 78, 4, 23);
+
+  signer := TRsaDigestSigner.Create(digest);
+  signer.Init(True, FRsaPrivate);
+  signer.BlockUpdate(msg, 0, Length(msg));
+  sig := signer.GenerateSignature();
+
+  signer := TRsaDigestSigner.Create(digest, digOid);
+  signer.Init(False, FRsaPublic);
+  signer.BlockUpdate(msg, 0, Length(msg));
+  CheckTrue(signer.VerifySignature(sig), 'RSA Digest Signer failed for ' + digest.AlgorithmName);
+end;
+
+procedure TTestRSADigestSigner.CheckNullDigest(const digest: IDigest;
+  const digOid: IDerObjectIdentifier);
+var
+  msg, hash, infoEnc, sig: TCryptoLibByteArray;
+  digInfo: IDigestInfo;
+  signer: ISigner;
+begin
+  msg := TCryptoLibByteArray.Create(1, 6, 3, 32, 7, 43, 2, 5, 7, 78, 4, 23);
+  hash := TDigestUtilities.DoFinal(digest, msg);
+
+  digInfo := TDigestInfo.Create(TAlgorithmIdentifier.Create(digOid, TDerNull.Instance), hash);
+  infoEnc := digInfo.GetDerEncoded();
+
+  // Sign with prehash signer
+  signer := CreatePrehashSigner();
+  signer.Init(True, FRsaPrivate);
+  signer.BlockUpdate(infoEnc, 0, Length(infoEnc));
+  sig := signer.GenerateSignature();
+
+  // Verify with regular signer
+  signer := TRsaDigestSigner.Create(digest, digOid);
+  signer.Init(False, FRsaPublic);
+  signer.BlockUpdate(msg, 0, Length(msg));
+  CheckTrue(signer.VerifySignature(sig), 'NONE - RSA Digest Signer failed (1)');
+
+  // Verify with prehash signer
+  signer := CreatePrehashSigner();
+  signer.Init(False, FRsaPublic);
+  signer.BlockUpdate(infoEnc, 0, Length(infoEnc));
+  CheckTrue(signer.VerifySignature(sig), 'NONE - RSA Digest Signer failed (2)');
+end;
+
+class function TTestRSADigestSigner.CreatePrehashSigner: IRsaDigestSigner;
+var
+  nullOid: IDerObjectIdentifier;
+begin
+  nullOid := nil;
+  Result := TRsaDigestSigner.Create(TDigestUtilities.GetDigest('None'), nullOid);
+end;
+
+procedure TTestRSADigestSigner.TestRipeMD128;
+begin
+  CheckDigest(TDigestUtilities.GetDigest('RIPEMD128'), TTeleTrusTObjectIdentifiers.RipeMD128);
+end;
+
+procedure TTestRSADigestSigner.TestRipeMD160;
+begin
+  CheckDigest(TDigestUtilities.GetDigest('RIPEMD160'), TTeleTrusTObjectIdentifiers.RipeMD160);
+end;
+
+procedure TTestRSADigestSigner.TestRipeMD256;
+begin
+  CheckDigest(TDigestUtilities.GetDigest('RIPEMD256'), TTeleTrusTObjectIdentifiers.RipeMD256);
+end;
+
+procedure TTestRSADigestSigner.TestSha1;
+begin
+  CheckDigest(TDigestUtilities.GetDigest('SHA-1'), TX509ObjectIdentifiers.IdSha1);
+end;
+
+procedure TTestRSADigestSigner.TestSha224;
+begin
+  CheckDigest(TDigestUtilities.GetDigest('SHA-224'), TNistObjectIdentifiers.IdSha224);
+end;
+
+procedure TTestRSADigestSigner.TestSha256;
+begin
+  CheckDigest(TDigestUtilities.GetDigest('SHA-256'), TNistObjectIdentifiers.IdSha256);
+end;
+
+procedure TTestRSADigestSigner.TestSha384;
+begin
+  CheckDigest(TDigestUtilities.GetDigest('SHA-384'), TNistObjectIdentifiers.IdSha384);
+end;
+
+procedure TTestRSADigestSigner.TestSha512;
+begin
+  CheckDigest(TDigestUtilities.GetDigest('SHA-512'), TNistObjectIdentifiers.IdSha512);
+end;
+
+procedure TTestRSADigestSigner.TestSha512_224;
+begin
+  CheckDigest(TDigestUtilities.GetDigest('SHA-512/224'), TNistObjectIdentifiers.IdSha512_224);
+end;
+
+procedure TTestRSADigestSigner.TestSha512_256;
+begin
+  CheckDigest(TDigestUtilities.GetDigest('SHA-512/256'), TNistObjectIdentifiers.IdSha512_256);
+end;
+
+procedure TTestRSADigestSigner.TestSha3_224;
+begin
+  CheckDigest(TDigestUtilities.GetDigest('SHA3-224'), TNistObjectIdentifiers.IdSha3_224);
+end;
+
+procedure TTestRSADigestSigner.TestSha3_256;
+begin
+  CheckDigest(TDigestUtilities.GetDigest('SHA3-256'), TNistObjectIdentifiers.IdSha3_256);
+end;
+
+procedure TTestRSADigestSigner.TestSha3_384;
+begin
+  CheckDigest(TDigestUtilities.GetDigest('SHA3-384'), TNistObjectIdentifiers.IdSha3_384);
+end;
+
+procedure TTestRSADigestSigner.TestSha3_512;
+begin
+  CheckDigest(TDigestUtilities.GetDigest('SHA3-512'), TNistObjectIdentifiers.IdSha3_512);
+end;
+
+procedure TTestRSADigestSigner.TestMD2;
+begin
+  CheckDigest(TDigestUtilities.GetDigest('MD2'), TPkcsObjectIdentifiers.MD2);
+end;
+
+procedure TTestRSADigestSigner.TestMD4;
+begin
+  CheckDigest(TDigestUtilities.GetDigest('MD4'), TPkcsObjectIdentifiers.MD4);
+end;
+
+procedure TTestRSADigestSigner.TestMD5;
+begin
+  CheckDigest(TDigestUtilities.GetDigest('MD5'), TPkcsObjectIdentifiers.MD5);
+end;
+
+procedure TTestRSADigestSigner.TestNullDigestSha1;
+begin
+  CheckNullDigest(TDigestUtilities.GetDigest('SHA-1'), TX509ObjectIdentifiers.IdSha1);
+end;
+
+procedure TTestRSADigestSigner.TestNullDigestSha256;
+begin
+  CheckNullDigest(TDigestUtilities.GetDigest('SHA-256'), TNistObjectIdentifiers.IdSha256);
+end;
+
+procedure TTestRSADigestSigner.TestNullFormatError;
+var
+  signer: ISigner;
+  exceptionRaised: Boolean;
+begin
+  signer := CreatePrehashSigner();
+  signer.Init(True, FRsaPrivate);
+  signer.BlockUpdate(TCryptoLibByteArray.Create(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), 0, 20);
+
+  exceptionRaised := False;
+  try
+    signer.GenerateSignature();
+  except
+    on E: Exception do
+    begin
+      exceptionRaised := True;
+      CheckTrue(Pos('unable to encode signature', E.Message) > 0,
+        'Wrong exception message: ' + E.Message);
+    end;
+  end;
+
+  CheckTrue(exceptionRaised, 'Expected exception not raised');
+end;
+
+initialization
+
+{$IFDEF FPC}
+  RegisterTest(TTestRSADigestSigner);
+{$ELSE}
+  RegisterTest(TTestRSADigestSigner.Suite);
+{$ENDIF FPC}
+
+end.

+ 336 - 0
CryptoLib.Tests/src/Crypto/RSATests.pas

@@ -0,0 +1,336 @@
+{ *********************************************************************************** }
+{ *                              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 RSATests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+uses
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpBigInteger,
+  ClpIRsaKeyParameters,
+  ClpRsaKeyParameters,
+  ClpIRsaPrivateCrtKeyParameters,
+  ClpRsaPrivateCrtKeyParameters,
+  ClpIRsaKeyGenerationParameters,
+  ClpRsaKeyGenerationParameters,
+  ClpIRsaKeyPairGenerator,
+  ClpRsaKeyPairGenerator,
+  ClpIRsaCoreEngine,
+  ClpRsaCoreEngine,
+  ClpIRsaBlindedEngine,
+  ClpRsaBlindedEngine,
+  ClpIPkcs1Encoding,
+  ClpPkcs1Encoding,
+  ClpIOaepEncoding,
+  ClpOaepEncoding,
+  ClpIAsymmetricBlockCipher,
+  ClpIAsymmetricCipherKeyPair,
+  ClpIAsymmetricKeyParameter,
+  ClpISigner,
+  ClpSignerUtilities,
+  ClpDigestUtilities,
+  ClpGeneratorUtilities,
+  ClpISecureRandom,
+  ClpSecureRandom,
+  ClpConverters,
+  ClpArrayUtils,
+  ClpCryptoLibTypes,
+  CryptoLibTestBase;
+
+type
+
+  TTestRSA = class(TCryptoLibAlgorithmTestCase)
+  private
+    class var
+      FModulus: TBigInteger;
+      FPubExp: TBigInteger;
+      FPrivExp: TBigInteger;
+      FP: TBigInteger;
+      FQ: TBigInteger;
+      FPExp: TBigInteger;
+      FQExp: TBigInteger;
+      FCrtCoef: TBigInteger;
+
+    class constructor CreateTestRSA();
+
+    procedure DoTestRawRsa;
+    procedure DoTestPkcs1Encoding;
+    procedure DoTestOaepEncoding;
+    procedure DoTestKeyGeneration;
+    procedure DoTestRsaSignature;
+
+  published
+    procedure TestRawRsa;
+    procedure TestPkcs1Encoding;
+    procedure TestOaepEncoding;
+    procedure TestKeyGeneration;
+    procedure TestRsaSignature;
+
+  end;
+
+implementation
+
+{ TTestRSA }
+
+class constructor TTestRSA.CreateTestRSA;
+begin
+  FModulus := TBigInteger.Create(
+    'b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6' +
+    'f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdb' +
+    'f3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26' +
+    'c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5', 16);
+
+  FPubExp := TBigInteger.Create('11', 16);
+
+  FPrivExp := TBigInteger.Create(
+    '92e08f83cc9920746989ca5034dcb384a094fb9c5a6288fcc4304424ab8f5638' +
+    '8f72652d8fafc65a4b9020896f2cde297080f2a540e7b7ce5af0b3446e1258d1' +
+    'dd7f245cf54124b4c6e17da21b90a0ebd22605e6f45c9f136d7a13eaac1c0f74' +
+    '87de8bd6d924972408ebb58af71e76fd7b012a8d0e165f3ae2e5077a8648e619', 16);
+
+  FP := TBigInteger.Create(
+    'f75e80839b9b9379f1cf1128f321639757dba514642c206bbbd99f9a4846208b' +
+    '3e93fbbe5e0527cc59b1d4b929d9555853004c7c8b30ee6a213c3d1bb7415d03', 16);
+
+  FQ := TBigInteger.Create(
+    'b892d9ebdbfc37e397256dd8a5d3123534d1f03726284743ddc6be3a709edb69' +
+    '6fc40c7d902ed804c6eee730eee3d5b20bf6bd8d87a296813c87d3b3cc9d7947', 16);
+
+  FPExp := TBigInteger.Create(
+    '1d1a2d3ca8e52068b3094d501c9a842fec37f54db16e9a67070a8b3f53cc03d4' +
+    '257ad252a1a640eadd603724d7bf3737914b544ae332eedf4f34436cac25ceb5', 16);
+
+  FQExp := TBigInteger.Create(
+    '6c929e4e81672fef49d9c825163fec97c4b7ba7acb26c0824638ac22605d7201' +
+    'c94625770984f78a56e6e25904fe7db407099cad9b14588841b94f5ab498dded', 16);
+
+  FCrtCoef := TBigInteger.Create(
+    'dae7651ee69ad1d081ec5e7188ae126f6004ff39556bde90e0b870962fa7b926' +
+    'd070686d8244fe5a9aa709a95686a104614834b0ada4b10f53197a5cb4c97339', 16);
+end;
+
+procedure TTestRSA.DoTestRawRsa;
+var
+  pubParams: IRsaKeyParameters;
+  privParams: IRsaPrivateCrtKeyParameters;
+  engine: IAsymmetricBlockCipher;
+  input, encrypted, decrypted: TCryptoLibByteArray;
+begin
+  // Create key parameters
+  pubParams := TRsaKeyParameters.Create(False, FModulus, FPubExp);
+  privParams := TRsaPrivateCrtKeyParameters.Create(
+    FModulus, FPubExp, FPrivExp, FP, FQ, FPExp, FQExp, FCrtCoef);
+
+  // Test input
+  input := TConverters.ConvertHexStringToBytes(
+    '4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e');
+
+  // Encrypt with public key
+  engine := TRsaBlindedEngine.Create();
+  engine.Init(True, pubParams);
+  encrypted := engine.ProcessBlock(input, 0, System.Length(input));
+
+  CheckTrue(System.Length(encrypted) > 0, 'Encryption produced empty output');
+
+  // Decrypt with private key
+  engine.Init(False, privParams);
+  decrypted := engine.ProcessBlock(encrypted, 0, System.Length(encrypted));
+
+  CheckTrue(TArrayUtils.AreEqual(input, decrypted), 'RSA round-trip failed');
+end;
+
+procedure TTestRSA.DoTestPkcs1Encoding;
+var
+  pubParams: IRsaKeyParameters;
+  privParams: IRsaPrivateCrtKeyParameters;
+  engine: IAsymmetricBlockCipher;
+  input, encrypted, decrypted: TCryptoLibByteArray;
+begin
+  pubParams := TRsaKeyParameters.Create(False, FModulus, FPubExp);
+  privParams := TRsaPrivateCrtKeyParameters.Create(
+    FModulus, FPubExp, FPrivExp, FP, FQ, FPExp, FQExp, FCrtCoef);
+
+  input := TConverters.ConvertHexStringToBytes(
+    '4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e');
+
+  // Encrypt with PKCS1 padding
+  engine := TPkcs1Encoding.Create(TRsaBlindedEngine.Create());
+  engine.Init(True, pubParams);
+  encrypted := engine.ProcessBlock(input, 0, System.Length(input));
+
+  // Decrypt
+  engine.Init(False, privParams);
+  decrypted := engine.ProcessBlock(encrypted, 0, System.Length(encrypted));
+
+  CheckTrue(TArrayUtils.AreEqual(input, decrypted), 'PKCS1 round-trip failed');
+end;
+
+procedure TTestRSA.DoTestOaepEncoding;
+var
+  pubParams: IRsaKeyParameters;
+  privParams: IRsaPrivateCrtKeyParameters;
+  engine: IAsymmetricBlockCipher;
+  input, encrypted, decrypted: TCryptoLibByteArray;
+begin
+  pubParams := TRsaKeyParameters.Create(False, FModulus, FPubExp);
+  privParams := TRsaPrivateCrtKeyParameters.Create(
+    FModulus, FPubExp, FPrivExp, FP, FQ, FPExp, FQExp, FCrtCoef);
+
+  // Shorter input for OAEP (needs room for padding)
+  input := TConverters.ConvertHexStringToBytes('48656c6c6f20576f726c6421'); // "Hello World!"
+
+  // Encrypt with OAEP padding
+  engine := TOaepEncoding.Create(TRsaBlindedEngine.Create());
+  engine.Init(True, pubParams);
+  encrypted := engine.ProcessBlock(input, 0, System.Length(input));
+
+  // Decrypt
+  engine.Init(False, privParams);
+  decrypted := engine.ProcessBlock(encrypted, 0, System.Length(encrypted));
+
+  CheckTrue(TArrayUtils.AreEqual(input, decrypted), 'OAEP round-trip failed');
+end;
+
+procedure TTestRSA.DoTestKeyGeneration;
+var
+  kpGen: IRsaKeyPairGenerator;
+  kpParams: IRsaKeyGenerationParameters;
+  keyPair: IAsymmetricCipherKeyPair;
+  pubKey: IRsaKeyParameters;
+  privKey: IRsaPrivateCrtKeyParameters;
+  engine: IAsymmetricBlockCipher;
+  input, encrypted, decrypted: TCryptoLibByteArray;
+begin
+  // Generate 1024-bit RSA key pair
+  kpGen := TRsaKeyPairGenerator.Create();
+  kpParams := TRsaKeyGenerationParameters.Create(
+    TBigInteger.ValueOf($10001),  // 65537 public exponent
+    TSecureRandom.Create(),
+    1024,  // Key size
+    80);   // Certainty
+
+  kpGen.Init(kpParams);
+  keyPair := kpGen.GenerateKeyPair();
+
+  pubKey := keyPair.Public as IRsaKeyParameters;
+  privKey := keyPair.Private as IRsaPrivateCrtKeyParameters;
+
+  CheckEquals(1024, pubKey.Modulus.BitLength, 'Key size mismatch');
+  CheckTrue(not pubKey.IsPrivate, 'Public key marked as private');
+  CheckTrue(privKey.IsPrivate, 'Private key not marked as private');
+
+  // Test encryption/decryption with generated keys
+  input := TConverters.ConvertHexStringToBytes('48656c6c6f'); // "Hello"
+
+  engine := TPkcs1Encoding.Create(TRsaBlindedEngine.Create());
+  engine.Init(True, pubKey);
+  encrypted := engine.ProcessBlock(input, 0, System.Length(input));
+
+  engine.Init(False, privKey);
+  decrypted := engine.ProcessBlock(encrypted, 0, System.Length(encrypted));
+
+  CheckTrue(TArrayUtils.AreEqual(input, decrypted), 'Generated key round-trip failed');
+end;
+
+procedure TTestRSA.DoTestRsaSignature;
+var
+  kpGen: IRsaKeyPairGenerator;
+  kpParams: IRsaKeyGenerationParameters;
+  keyPair: IAsymmetricCipherKeyPair;
+  signer: ISigner;
+  message, signature: TCryptoLibByteArray;
+  verified: Boolean;
+begin
+  // Generate key pair
+  kpGen := TRsaKeyPairGenerator.Create();
+  kpParams := TRsaKeyGenerationParameters.Create(
+    TBigInteger.ValueOf($10001),
+    TSecureRandom.Create(),
+    1024,
+    80);
+
+  kpGen.Init(kpParams);
+  keyPair := kpGen.GenerateKeyPair();
+
+  message := TConverters.ConvertStringToBytes('Test message for RSA signature',
+    TEncoding.UTF8);
+
+  // Sign with SHA-256
+  signer := TSignerUtilities.GetSigner('SHA-256withRSA');
+  signer.Init(True, keyPair.Private);
+  signer.BlockUpdate(message, 0, System.Length(message));
+  signature := signer.GenerateSignature();
+
+  CheckTrue(System.Length(signature) > 0, 'Signature is empty');
+
+  // Verify
+  signer.Init(False, keyPair.Public);
+  signer.BlockUpdate(message, 0, System.Length(message));
+  verified := signer.VerifySignature(signature);
+
+  CheckTrue(verified, 'Signature verification failed');
+
+  // Test with modified message (should fail)
+  message[0] := message[0] xor $FF;
+  signer.Init(False, keyPair.Public);
+  signer.BlockUpdate(message, 0, System.Length(message));
+  verified := signer.VerifySignature(signature);
+
+  CheckFalse(verified, 'Modified message should fail verification');
+end;
+
+procedure TTestRSA.TestRawRsa;
+begin
+  DoTestRawRsa;
+end;
+
+procedure TTestRSA.TestPkcs1Encoding;
+begin
+  DoTestPkcs1Encoding;
+end;
+
+procedure TTestRSA.TestOaepEncoding;
+begin
+  DoTestOaepEncoding;
+end;
+
+procedure TTestRSA.TestKeyGeneration;
+begin
+  DoTestKeyGeneration;
+end;
+
+procedure TTestRSA.TestRsaSignature;
+begin
+  DoTestRsaSignature;
+end;
+
+initialization
+
+RegisterTest(TTestRSA.Suite);
+
+end.

+ 37 - 2
CryptoLib.Tests/src/Others/SignerUtilitiesTests.pas

@@ -53,6 +53,10 @@ uses
   ClpDsaParameters,
   ClpDsaParameters,
   ClpDsaPrivateKeyParameters,
   ClpDsaPrivateKeyParameters,
   ClpDsaPublicKeyParameters,
   ClpDsaPublicKeyParameters,
+  ClpRsaKeyParameters,
+  ClpIRsaKeyParameters,
+  ClpRsaPrivateCrtKeyParameters,
+  ClpIRsaPrivateCrtKeyParameters,
   ClpIAsymmetricCipherKeyPairGenerator,
   ClpIAsymmetricCipherKeyPairGenerator,
   ClpEd25519KeyGenerationParameters,
   ClpEd25519KeyGenerationParameters,
   ClpIEd25519KeyGenerationParameters,
   ClpIEd25519KeyGenerationParameters,
@@ -66,8 +70,13 @@ type
   private
   private
 
 
   var
   var
+    // ECDSA parameters
     FECParraGX, FECParraGY, FECParraH, FECParraN, FECPubQX, FECPubQY, FECPrivD,
     FECParraGX, FECParraGY, FECParraH, FECParraN, FECPubQX, FECPubQY, FECPrivD,
-      FDSAParaG, FDSAParaP, FDSAParaQ, FDSAPublicY, FDsaPrivateX: TBigInteger;
+    // DSA parameters
+    FDSAParaG, FDSAParaP, FDSAParaQ, FDSAPublicY, FDsaPrivateX,
+    // RSA parameters
+    FRsaMod, FRsaPubExp, FRsaPrivExp, FRsaPrivP, FRsaPrivQ,
+    FRsaPrivDP, FRsaPrivDQ, FRsaPrivQinv: TBigInteger;
     Fcurve: IECCurve;
     Fcurve: IECCurve;
     FecDomain: IECDomainParameters;
     FecDomain: IECDomainParameters;
     FecPub: IECPublicKeyParameters;
     FecPub: IECPublicKeyParameters;
@@ -75,6 +84,8 @@ type
     Fpara: IDsaParameters;
     Fpara: IDsaParameters;
     FdsaPriv: IDsaPrivateKeyParameters;
     FdsaPriv: IDsaPrivateKeyParameters;
     FdsaPub: IDsaPublicKeyParameters;
     FdsaPub: IDsaPublicKeyParameters;
+    FRsaPublic: IRsaKeyParameters;
+    FRsaPrivate: IRsaPrivateCrtKeyParameters;
     Fed25519Kpg: IAsymmetricCipherKeyPairGenerator;
     Fed25519Kpg: IAsymmetricCipherKeyPairGenerator;
     Fed25519Pair: IAsymmetricCipherKeyPair;
     Fed25519Pair: IAsymmetricCipherKeyPair;
 
 
@@ -94,6 +105,22 @@ procedure TTestSignerUtilities.SetUp;
 begin
 begin
   inherited;
   inherited;
 
 
+  //
+  // RSA parameters
+  //
+  FRsaMod := TBigInteger.Create('a7295693155b1813bb84877fb45343556e0568043de5910872a3a518cc11e23e2db74eaf4545068c4e3d258a2718fbacdcc3eafa457695b957e88fbf110aed049a992d9c430232d02f3529c67a3419' + '935ea9b569f85b1bcd37de6b899cd62697e843130ff0529d09c97d813cb15f293751ff56f943fbdabb63971cc7f4f6d5bff1594416b1f5907bde5a84a44f9802ef29b43bda1960f948f8afb8766c1ab80d32eec88ed66d0b65aebe44a6d0b3c5e0ab051aaa1b912' + 'fbcc17b8e751ddecc5365b6db6dab0020c3057db4013a51213a5798a3aab67985b0f4d88627a54a0f3f0285fbcb4afdfeb65cb153af66825656d43238b75503231500753f4e421e3c57', 16);
+  FRsaPubExp := TBigInteger.Create('10001', 16);
+  FRsaPrivExp := TBigInteger.Create('65dad56ac7df7abb434e4cb5eeadb16093aa6da7f0033aad3815289b04757d32bfee6ade7749c8e4a323b5050a2fb9e2a99e23469e1ed4ba5bab54336af20a5bfccb8b3424cc6923db2ffca5787' + 'ed87aa87aa614cd04cedaebc8f623a2d2063017910f436dff18bb06f01758610787f8b258f0a8efd8bd7de30007c47b2a1031696c7d6523bc191d4d918927a7e0b09584ed205bd2ff4fc4382678df82353f7532b3bbb81d69e3f39070aed3fb64fce032a089e8e6' + '4955afa5213a6eb241231bd98d702fba725a9b205952fda186412d9e0d9344d2998c455ad8c2bae85ee672751466d5288304032b5b7e02f7e558c7af82c7fbf58eea0bb4ef0f001e6cd0a9', 16);
+  FRsaPrivP := TBigInteger.Create('d4fd9ac3474fb83aaf832470643609659e511b322632b239b688f3cd2aad87527d6cf652fb9c9ca67940e84789444f2e99b0cb0cfabbd4de95396106c865f38e2fb7b82b231260a94df0e01756bf73' + 'ce0386868d9c41645560a81af2f53c18e4f7cdf3d51d80267372e6e0216afbf67f655c9450769cca494e4f6631b239ce1b', 16);
+  FRsaPrivQ := TBigInteger.Create('c8eaa0e2a1b3a4412a702bccda93f4d150da60d736c99c7c566fdea4dd1b401cbc0d8c063daaf0b579953d36343aa18b33dbf8b9eae94452490cc905245f8f7b9e29b1a288bc66731a29e1dd1a45c9f' + 'd7f8238ff727adc49fff73991d0dc096206b9d3a08f61e7462e2b804d78cb8c5eccdb9b7fbd2ad6a8fea46c1053e1be75', 16);
+  FRsaPrivDP := TBigInteger.Create('10edcb544421c0f9e123624d1099feeb35c72a8b34e008ac6fa6b90210a7543f293af4e5299c8c12eb464e70092805c7256e18e5823455ba0f504d36f5ccacac1b7cd5c58ff710f9c3f92646949d88f' + 'dd1e7ea5fed1081820bb9b0d2a8cd4b093fecfdb96dabd6e28c3a6f8c186dc86cddc89afd3e403e0fcf8a9e0bcb27af0b', 16);
+  FRsaPrivDQ := TBigInteger.Create('97fc25484b5a415eaa63c03e6efa8dafe9a1c8b004d9ee6e80548fefd6f2ce44ee5cb117e77e70285798f57d137566ce8ea4503b13e0f1b5ed5ca6942537c4aa96b2a395782a4cb5b58d0936e0b0fa6' + '3b1192954d39ced176d71ef32c6f42c84e2e19f9d4dd999c2151b032b97bd22aa73fd8c5bcd15a2dca4046d5acc997021', 16);
+  FRsaPrivQinv := TBigInteger.Create('4bb8064e1eff7e9efc3c4578fcedb59ca4aef0993a8312dfdcb1b3decf458aa6650d3d0866f143cbf0d3825e9381181170a0a1651eefcd7def786b8eb356555d9fa07c85b5f5cbdd74382f1129b5e' + '36b4166b6cc9157923699708648212c484958351fdc9cf14f218dbe7fbf7cbd93a209a4681fe23ceb44bab67d66f45d1c9d', 16);
+
+  FRsaPublic := TRsaKeyParameters.Create(false, FRsaMod, FRsaPubExp);
+  FRsaPrivate := TRsaPrivateCrtKeyParameters.Create(FRsaMod, FRsaPubExp, FRsaPrivExp,
+    FRsaPrivP, FRsaPrivQ, FRsaPrivDP, FRsaPrivDQ, FRsaPrivQinv);
+
   //
   //
   // ECDSA parameters
   // ECDSA parameters
   //
   //
@@ -209,7 +236,15 @@ begin
         System.length(upper) - withPos + System.length('WITH'));
         System.length(upper) - withPos + System.length('WITH'));
     end;
     end;
 
 
-    if ((cipherName = 'ECDSA') or (cipherName = 'CVC-ECDSA') or
+    signParams := nil;
+    verifyParams := nil;
+
+    if (cipherName = 'RSA') or (cipherName = 'RSAANDMGF1') then
+    begin
+      signParams := FRsaPrivate;
+      verifyParams := FRsaPublic;
+    end
+    else if ((cipherName = 'ECDSA') or (cipherName = 'CVC-ECDSA') or
       (cipherName = 'PLAIN-ECDSA')) then
       (cipherName = 'PLAIN-ECDSA')) then
     begin
     begin
       signParams := FecPriv;
       signParams := FecPriv;

+ 238 - 39
CryptoLib/src/Asn1/Pkcs/ClpPkcsObjectIdentifiers.pas

@@ -32,9 +32,11 @@ type
 
 
   const
   const
     //
     //
-    // object identifiers for digests
+    // pkcs-1 OBJECT IDENTIFIER ::= {
+    //       iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
     //
     //
-    DigestAlgorithm: String = '1.2.840.113549.2';
+    Pkcs1: String = '1.2.840.113549.1.1';
+
     //
     //
     // pkcs-3 OBJECT IDENTIFIER ::= {
     // pkcs-3 OBJECT IDENTIFIER ::= {
     // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 3 }
     // iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 3 }
@@ -47,57 +49,130 @@ type
     //
     //
     Pkcs5: String = '1.2.840.113549.1.5';
     Pkcs5: String = '1.2.840.113549.1.5';
 
 
+    //
+    // object identifiers for digests
+    //
+    DigestAlgorithm: String = '1.2.840.113549.2';
+
   class var
   class var
 
 
     FIsBooted: Boolean;
     FIsBooted: Boolean;
-    FDhKeyAgreement, FIdPbkdf2, FMD2, FMD4, FMD5, FIdHmacWithSha1,
-      FIdHmacWithSha224, FIdHmacWithSha256, FIdHmacWithSha384, FIdHmacWithSha512
+
+    // PKCS#1 RSA OIDs
+    FRsaEncryption,
+    FMD2WithRsaEncryption,
+    FMD4WithRsaEncryption,
+    FMD5WithRsaEncryption,
+    FSha1WithRsaEncryption,
+    FSrsaOaepEncryptionSet,
+    FIdRsaesOaep,
+    FIdMgf1,
+    FIdPSpecified,
+    FIdRsassaPss,
+    FSha256WithRsaEncryption,
+    FSha384WithRsaEncryption,
+    FSha512WithRsaEncryption,
+    FSha224WithRsaEncryption,
+    FSha512_224WithRsaEncryption,
+    FSha512_256WithRsaEncryption,
+
+    // PKCS#3
+    FDhKeyAgreement,
+
+    // PKCS#5
+    FIdPbkdf2,
+
+    // Digest algorithms
+    FMD2, FMD4, FMD5,
+    FIdHmacWithSha1, FIdHmacWithSha224, FIdHmacWithSha256,
+    FIdHmacWithSha384, FIdHmacWithSha512,
+    FIdHmacWithSha512_224, FIdHmacWithSha512_256
       : IDerObjectIdentifier;
       : IDerObjectIdentifier;
 
 
+    // PKCS#1 RSA getters
+    class function GetRsaEncryption: IDerObjectIdentifier; static; inline;
+    class function GetMD2WithRsaEncryption: IDerObjectIdentifier; static; inline;
+    class function GetMD4WithRsaEncryption: IDerObjectIdentifier; static; inline;
+    class function GetMD5WithRsaEncryption: IDerObjectIdentifier; static; inline;
+    class function GetSha1WithRsaEncryption: IDerObjectIdentifier; static; inline;
+    class function GetSrsaOaepEncryptionSet: IDerObjectIdentifier; static; inline;
+    class function GetIdRsaesOaep: IDerObjectIdentifier; static; inline;
+    class function GetIdMgf1: IDerObjectIdentifier; static; inline;
+    class function GetIdPSpecified: IDerObjectIdentifier; static; inline;
+    class function GetIdRsassaPss: IDerObjectIdentifier; static; inline;
+    class function GetSha256WithRsaEncryption: IDerObjectIdentifier; static; inline;
+    class function GetSha384WithRsaEncryption: IDerObjectIdentifier; static; inline;
+    class function GetSha512WithRsaEncryption: IDerObjectIdentifier; static; inline;
+    class function GetSha224WithRsaEncryption: IDerObjectIdentifier; static; inline;
+    class function GetSha512_224WithRsaEncryption: IDerObjectIdentifier; static; inline;
+    class function GetSha512_256WithRsaEncryption: IDerObjectIdentifier; static; inline;
+
+    // PKCS#3
     class function GetDhKeyAgreement: IDerObjectIdentifier; static; inline;
     class function GetDhKeyAgreement: IDerObjectIdentifier; static; inline;
+
+    // PKCS#5
     class function GetIdPbkdf2: IDerObjectIdentifier; static; inline;
     class function GetIdPbkdf2: IDerObjectIdentifier; static; inline;
+
+    // Digest algorithm getters
     class function GetMD2: IDerObjectIdentifier; static; inline;
     class function GetMD2: IDerObjectIdentifier; static; inline;
     class function GetMD4: IDerObjectIdentifier; static; inline;
     class function GetMD4: IDerObjectIdentifier; static; inline;
     class function GetMD5: IDerObjectIdentifier; static; inline;
     class function GetMD5: IDerObjectIdentifier; static; inline;
-
     class function GetIdHmacWithSha1: IDerObjectIdentifier; static; inline;
     class function GetIdHmacWithSha1: IDerObjectIdentifier; static; inline;
     class function GetIdHmacWithSha224: IDerObjectIdentifier; static; inline;
     class function GetIdHmacWithSha224: IDerObjectIdentifier; static; inline;
     class function GetIdHmacWithSha256: IDerObjectIdentifier; static; inline;
     class function GetIdHmacWithSha256: IDerObjectIdentifier; static; inline;
     class function GetIdHmacWithSha384: IDerObjectIdentifier; static; inline;
     class function GetIdHmacWithSha384: IDerObjectIdentifier; static; inline;
     class function GetIdHmacWithSha512: IDerObjectIdentifier; static; inline;
     class function GetIdHmacWithSha512: IDerObjectIdentifier; static; inline;
+    class function GetIdHmacWithSha512_224: IDerObjectIdentifier; static; inline;
+    class function GetIdHmacWithSha512_256: IDerObjectIdentifier; static; inline;
 
 
     class constructor PkcsObjectIdentifiers();
     class constructor PkcsObjectIdentifiers();
 
 
   public
   public
 
 
-    class property DhKeyAgreement: IDerObjectIdentifier read GetDhKeyAgreement;
+    //
+    // PKCS#1 RSA OIDs
+    //
+    class property RsaEncryption: IDerObjectIdentifier read GetRsaEncryption;
+    class property MD2WithRsaEncryption: IDerObjectIdentifier read GetMD2WithRsaEncryption;
+    class property MD4WithRsaEncryption: IDerObjectIdentifier read GetMD4WithRsaEncryption;
+    class property MD5WithRsaEncryption: IDerObjectIdentifier read GetMD5WithRsaEncryption;
+    class property Sha1WithRsaEncryption: IDerObjectIdentifier read GetSha1WithRsaEncryption;
+    class property SrsaOaepEncryptionSet: IDerObjectIdentifier read GetSrsaOaepEncryptionSet;
+    class property IdRsaesOaep: IDerObjectIdentifier read GetIdRsaesOaep;
+    class property IdMgf1: IDerObjectIdentifier read GetIdMgf1;
+    class property IdPSpecified: IDerObjectIdentifier read GetIdPSpecified;
+    class property IdRsassaPss: IDerObjectIdentifier read GetIdRsassaPss;
+    class property Sha256WithRsaEncryption: IDerObjectIdentifier read GetSha256WithRsaEncryption;
+    class property Sha384WithRsaEncryption: IDerObjectIdentifier read GetSha384WithRsaEncryption;
+    class property Sha512WithRsaEncryption: IDerObjectIdentifier read GetSha512WithRsaEncryption;
+    class property Sha224WithRsaEncryption: IDerObjectIdentifier read GetSha224WithRsaEncryption;
+    class property Sha512_224WithRsaEncryption: IDerObjectIdentifier read GetSha512_224WithRsaEncryption;
+    class property Sha512_256WithRsaEncryption: IDerObjectIdentifier read GetSha512_256WithRsaEncryption;
 
 
-    class property IdPbkdf2: IDerObjectIdentifier read GetIdPbkdf2;
     //
     //
-    // md2 OBJECT IDENTIFIER ::=
-    // {iso(1) member-body(2) US(840) rsadsi(113549) DigestAlgorithm(2) 2}
+    // PKCS#3
     //
     //
-    class property MD2: IDerObjectIdentifier read GetMD2;
+    class property DhKeyAgreement: IDerObjectIdentifier read GetDhKeyAgreement;
+
     //
     //
-    // md4 OBJECT IDENTIFIER ::=
-    // {iso(1) member-body(2) US(840) rsadsi(113549) DigestAlgorithm(2) 4}
+    // PKCS#5
     //
     //
-    class property MD4: IDerObjectIdentifier read GetMD4;
+    class property IdPbkdf2: IDerObjectIdentifier read GetIdPbkdf2;
+
     //
     //
-    // md5 OBJECT IDENTIFIER ::=
-    // {iso(1) member-body(2) US(840) rsadsi(113549) DigestAlgorithm(2) 5}
+    // Digest algorithms
     //
     //
+    class property MD2: IDerObjectIdentifier read GetMD2;
+    class property MD4: IDerObjectIdentifier read GetMD4;
     class property MD5: IDerObjectIdentifier read GetMD5;
     class property MD5: IDerObjectIdentifier read GetMD5;
 
 
     class property IdHmacWithSha1: IDerObjectIdentifier read GetIdHmacWithSha1;
     class property IdHmacWithSha1: IDerObjectIdentifier read GetIdHmacWithSha1;
-    class property IdHmacWithSha224: IDerObjectIdentifier
-      read GetIdHmacWithSha224;
-    class property IdHmacWithSha256: IDerObjectIdentifier
-      read GetIdHmacWithSha256;
-    class property IdHmacWithSha384: IDerObjectIdentifier
-      read GetIdHmacWithSha384;
-    class property IdHmacWithSha512: IDerObjectIdentifier
-      read GetIdHmacWithSha512;
+    class property IdHmacWithSha224: IDerObjectIdentifier read GetIdHmacWithSha224;
+    class property IdHmacWithSha256: IDerObjectIdentifier read GetIdHmacWithSha256;
+    class property IdHmacWithSha384: IDerObjectIdentifier read GetIdHmacWithSha384;
+    class property IdHmacWithSha512: IDerObjectIdentifier read GetIdHmacWithSha512;
+    class property IdHmacWithSha512_224: IDerObjectIdentifier read GetIdHmacWithSha512_224;
+    class property IdHmacWithSha512_256: IDerObjectIdentifier read GetIdHmacWithSha512_256;
 
 
     class procedure Boot(); static;
     class procedure Boot(); static;
 
 
@@ -111,8 +186,31 @@ class procedure TPkcsObjectIdentifiers.Boot;
 begin
 begin
   if not FIsBooted then
   if not FIsBooted then
   begin
   begin
+    // PKCS#1 RSA
+    FRsaEncryption := TDerObjectIdentifier.Create(Pkcs1 + '.1');
+    FMD2WithRsaEncryption := TDerObjectIdentifier.Create(Pkcs1 + '.2');
+    FMD4WithRsaEncryption := TDerObjectIdentifier.Create(Pkcs1 + '.3');
+    FMD5WithRsaEncryption := TDerObjectIdentifier.Create(Pkcs1 + '.4');
+    FSha1WithRsaEncryption := TDerObjectIdentifier.Create(Pkcs1 + '.5');
+    FSrsaOaepEncryptionSet := TDerObjectIdentifier.Create(Pkcs1 + '.6');
+    FIdRsaesOaep := TDerObjectIdentifier.Create(Pkcs1 + '.7');
+    FIdMgf1 := TDerObjectIdentifier.Create(Pkcs1 + '.8');
+    FIdPSpecified := TDerObjectIdentifier.Create(Pkcs1 + '.9');
+    FIdRsassaPss := TDerObjectIdentifier.Create(Pkcs1 + '.10');
+    FSha256WithRsaEncryption := TDerObjectIdentifier.Create(Pkcs1 + '.11');
+    FSha384WithRsaEncryption := TDerObjectIdentifier.Create(Pkcs1 + '.12');
+    FSha512WithRsaEncryption := TDerObjectIdentifier.Create(Pkcs1 + '.13');
+    FSha224WithRsaEncryption := TDerObjectIdentifier.Create(Pkcs1 + '.14');
+    FSha512_224WithRsaEncryption := TDerObjectIdentifier.Create(Pkcs1 + '.15');
+    FSha512_256WithRsaEncryption := TDerObjectIdentifier.Create(Pkcs1 + '.16');
+
+    // PKCS#3
     FDhKeyAgreement := TDerObjectIdentifier.Create(Pkcs3 + '.1');
     FDhKeyAgreement := TDerObjectIdentifier.Create(Pkcs3 + '.1');
+
+    // PKCS#5
     FIdPbkdf2 := TDerObjectIdentifier.Create(Pkcs5 + '.12');
     FIdPbkdf2 := TDerObjectIdentifier.Create(Pkcs5 + '.12');
+
+    // Digest algorithms
     FMD2 := TDerObjectIdentifier.Create(DigestAlgorithm + '.2');
     FMD2 := TDerObjectIdentifier.Create(DigestAlgorithm + '.2');
     FMD4 := TDerObjectIdentifier.Create(DigestAlgorithm + '.4');
     FMD4 := TDerObjectIdentifier.Create(DigestAlgorithm + '.4');
     FMD5 := TDerObjectIdentifier.Create(DigestAlgorithm + '.5');
     FMD5 := TDerObjectIdentifier.Create(DigestAlgorithm + '.5');
@@ -121,59 +219,159 @@ begin
     FIdHmacWithSha256 := TDerObjectIdentifier.Create(DigestAlgorithm + '.9');
     FIdHmacWithSha256 := TDerObjectIdentifier.Create(DigestAlgorithm + '.9');
     FIdHmacWithSha384 := TDerObjectIdentifier.Create(DigestAlgorithm + '.10');
     FIdHmacWithSha384 := TDerObjectIdentifier.Create(DigestAlgorithm + '.10');
     FIdHmacWithSha512 := TDerObjectIdentifier.Create(DigestAlgorithm + '.11');
     FIdHmacWithSha512 := TDerObjectIdentifier.Create(DigestAlgorithm + '.11');
+    FIdHmacWithSha512_224 := TDerObjectIdentifier.Create(DigestAlgorithm + '.12');
+    FIdHmacWithSha512_256 := TDerObjectIdentifier.Create(DigestAlgorithm + '.13');
 
 
     FIsBooted := True;
     FIsBooted := True;
   end;
   end;
 end;
 end;
 
 
-class function TPkcsObjectIdentifiers.GetDhKeyAgreement: IDerObjectIdentifier;
+// PKCS#1 RSA getters
+
+class function TPkcsObjectIdentifiers.GetRsaEncryption: IDerObjectIdentifier;
 begin
 begin
-  result := FDhKeyAgreement;
+  Result := FRsaEncryption;
 end;
 end;
 
 
-class function TPkcsObjectIdentifiers.GetIdHmacWithSha1: IDerObjectIdentifier;
+class function TPkcsObjectIdentifiers.GetMD2WithRsaEncryption: IDerObjectIdentifier;
 begin
 begin
-  result := FIdHmacWithSha1;
+  Result := FMD2WithRsaEncryption;
 end;
 end;
 
 
-class function TPkcsObjectIdentifiers.GetIdHmacWithSha224: IDerObjectIdentifier;
+class function TPkcsObjectIdentifiers.GetMD4WithRsaEncryption: IDerObjectIdentifier;
 begin
 begin
-  result := FIdHmacWithSha224;
+  Result := FMD4WithRsaEncryption;
 end;
 end;
 
 
-class function TPkcsObjectIdentifiers.GetIdHmacWithSha256: IDerObjectIdentifier;
+class function TPkcsObjectIdentifiers.GetMD5WithRsaEncryption: IDerObjectIdentifier;
 begin
 begin
-  result := FIdHmacWithSha256;
+  Result := FMD5WithRsaEncryption;
 end;
 end;
 
 
-class function TPkcsObjectIdentifiers.GetIdHmacWithSha384: IDerObjectIdentifier;
+class function TPkcsObjectIdentifiers.GetSha1WithRsaEncryption: IDerObjectIdentifier;
 begin
 begin
-  result := FIdHmacWithSha384;
+  Result := FSha1WithRsaEncryption;
 end;
 end;
 
 
-class function TPkcsObjectIdentifiers.GetIdHmacWithSha512: IDerObjectIdentifier;
+class function TPkcsObjectIdentifiers.GetSrsaOaepEncryptionSet: IDerObjectIdentifier;
+begin
+  Result := FSrsaOaepEncryptionSet;
+end;
+
+class function TPkcsObjectIdentifiers.GetIdRsaesOaep: IDerObjectIdentifier;
+begin
+  Result := FIdRsaesOaep;
+end;
+
+class function TPkcsObjectIdentifiers.GetIdMgf1: IDerObjectIdentifier;
+begin
+  Result := FIdMgf1;
+end;
+
+class function TPkcsObjectIdentifiers.GetIdPSpecified: IDerObjectIdentifier;
+begin
+  Result := FIdPSpecified;
+end;
+
+class function TPkcsObjectIdentifiers.GetIdRsassaPss: IDerObjectIdentifier;
+begin
+  Result := FIdRsassaPss;
+end;
+
+class function TPkcsObjectIdentifiers.GetSha256WithRsaEncryption: IDerObjectIdentifier;
 begin
 begin
-  result := FIdHmacWithSha512;
+  Result := FSha256WithRsaEncryption;
 end;
 end;
 
 
+class function TPkcsObjectIdentifiers.GetSha384WithRsaEncryption: IDerObjectIdentifier;
+begin
+  Result := FSha384WithRsaEncryption;
+end;
+
+class function TPkcsObjectIdentifiers.GetSha512WithRsaEncryption: IDerObjectIdentifier;
+begin
+  Result := FSha512WithRsaEncryption;
+end;
+
+class function TPkcsObjectIdentifiers.GetSha224WithRsaEncryption: IDerObjectIdentifier;
+begin
+  Result := FSha224WithRsaEncryption;
+end;
+
+class function TPkcsObjectIdentifiers.GetSha512_224WithRsaEncryption: IDerObjectIdentifier;
+begin
+  Result := FSha512_224WithRsaEncryption;
+end;
+
+class function TPkcsObjectIdentifiers.GetSha512_256WithRsaEncryption: IDerObjectIdentifier;
+begin
+  Result := FSha512_256WithRsaEncryption;
+end;
+
+// PKCS#3
+
+class function TPkcsObjectIdentifiers.GetDhKeyAgreement: IDerObjectIdentifier;
+begin
+  Result := FDhKeyAgreement;
+end;
+
+// PKCS#5
+
 class function TPkcsObjectIdentifiers.GetIdPbkdf2: IDerObjectIdentifier;
 class function TPkcsObjectIdentifiers.GetIdPbkdf2: IDerObjectIdentifier;
 begin
 begin
-  result := FIdPbkdf2;
+  Result := FIdPbkdf2;
 end;
 end;
 
 
+// Digest algorithms
+
 class function TPkcsObjectIdentifiers.GetMD2: IDerObjectIdentifier;
 class function TPkcsObjectIdentifiers.GetMD2: IDerObjectIdentifier;
 begin
 begin
-  result := FMD2;
+  Result := FMD2;
 end;
 end;
 
 
 class function TPkcsObjectIdentifiers.GetMD4: IDerObjectIdentifier;
 class function TPkcsObjectIdentifiers.GetMD4: IDerObjectIdentifier;
 begin
 begin
-  result := FMD4;
+  Result := FMD4;
 end;
 end;
 
 
 class function TPkcsObjectIdentifiers.GetMD5: IDerObjectIdentifier;
 class function TPkcsObjectIdentifiers.GetMD5: IDerObjectIdentifier;
 begin
 begin
-  result := FMD5;
+  Result := FMD5;
+end;
+
+class function TPkcsObjectIdentifiers.GetIdHmacWithSha1: IDerObjectIdentifier;
+begin
+  Result := FIdHmacWithSha1;
+end;
+
+class function TPkcsObjectIdentifiers.GetIdHmacWithSha224: IDerObjectIdentifier;
+begin
+  Result := FIdHmacWithSha224;
+end;
+
+class function TPkcsObjectIdentifiers.GetIdHmacWithSha256: IDerObjectIdentifier;
+begin
+  Result := FIdHmacWithSha256;
+end;
+
+class function TPkcsObjectIdentifiers.GetIdHmacWithSha384: IDerObjectIdentifier;
+begin
+  Result := FIdHmacWithSha384;
+end;
+
+class function TPkcsObjectIdentifiers.GetIdHmacWithSha512: IDerObjectIdentifier;
+begin
+  Result := FIdHmacWithSha512;
+end;
+
+class function TPkcsObjectIdentifiers.GetIdHmacWithSha512_224: IDerObjectIdentifier;
+begin
+  Result := FIdHmacWithSha512_224;
+end;
+
+class function TPkcsObjectIdentifiers.GetIdHmacWithSha512_256: IDerObjectIdentifier;
+begin
+  Result := FIdHmacWithSha512_256;
 end;
 end;
 
 
 class constructor TPkcsObjectIdentifiers.PkcsObjectIdentifiers;
 class constructor TPkcsObjectIdentifiers.PkcsObjectIdentifiers;
@@ -183,3 +381,4 @@ end;
 
 
 end.
 end.
 
 
+

+ 184 - 81
CryptoLib/src/Asn1/TeleTrust/ClpTeleTrusTObjectIdentifiers.pas

@@ -33,21 +33,41 @@ type
   class var
   class var
 
 
     FIsBooted: Boolean;
     FIsBooted: Boolean;
-    FTeleTrusTAlgorithm, FRipeMD160, FRipeMD128, FRipeMD256, FECSign,
-      FECSignWithSha1, FECSignWithRipeMD160, FEccBrainpool, FEllipticCurve,
+    FTeleTrusT, FAlgorithm, FEncryptionAlgorithm, FHashAlgorithm,
+      FSignatureAlgorithm, FSignatureScheme,
+      FRipeMD160, FRipeMD128, FRipeMD256,
+      FRsaSignature, FRsaSignatureWithRipeMD160, FRsaSignatureWithRipeMD128,
+      FRsaSignatureWithRipeMD256,
+      FECSign, FECSignWithSha1, FECSignWithRipeMD160, FECSignWithMD2,
+      FECSignWithMD5, FTttEcg, FEcStdCurvesAndGeneration,
+      FEccBrainpool, FEllipticCurve,
       FVersionOne, FBrainpoolP160R1, FBrainpoolP160T1, FBrainpoolP192R1,
       FVersionOne, FBrainpoolP160R1, FBrainpoolP160T1, FBrainpoolP192R1,
       FBrainpoolP192T1, FBrainpoolP224R1, FBrainpoolP224T1, FBrainpoolP256R1,
       FBrainpoolP192T1, FBrainpoolP224R1, FBrainpoolP224T1, FBrainpoolP256R1,
       FBrainpoolP256T1, FBrainpoolP320R1, FBrainpoolP320T1, FBrainpoolP384R1,
       FBrainpoolP256T1, FBrainpoolP320R1, FBrainpoolP320T1, FBrainpoolP384R1,
       FBrainpoolP384T1, FBrainpoolP512R1, FBrainpoolP512T1
       FBrainpoolP384T1, FBrainpoolP512R1, FBrainpoolP512T1
       : IDerObjectIdentifier;
       : IDerObjectIdentifier;
 
 
+    class function GetTeleTrusT: IDerObjectIdentifier; static; inline;
+    class function GetAlgorithm: IDerObjectIdentifier; static; inline;
+    class function GetTeleTrusTAlgorithm: IDerObjectIdentifier; static; inline;
+    class function GetEncryptionAlgorithm: IDerObjectIdentifier; static; inline;
+    class function GetHashAlgorithm: IDerObjectIdentifier; static; inline;
+    class function GetSignatureAlgorithm: IDerObjectIdentifier; static; inline;
+    class function GetSignatureScheme: IDerObjectIdentifier; static; inline;
     class function GetRipeMD128: IDerObjectIdentifier; static; inline;
     class function GetRipeMD128: IDerObjectIdentifier; static; inline;
     class function GetRipeMD160: IDerObjectIdentifier; static; inline;
     class function GetRipeMD160: IDerObjectIdentifier; static; inline;
     class function GetRipeMD256: IDerObjectIdentifier; static; inline;
     class function GetRipeMD256: IDerObjectIdentifier; static; inline;
-    class function GetTeleTrusTAlgorithm: IDerObjectIdentifier; static; inline;
+    class function GetRsaSignature: IDerObjectIdentifier; static; inline;
+    class function GetRsaSignatureWithRipeMD160: IDerObjectIdentifier; static; inline;
+    class function GetRsaSignatureWithRipeMD128: IDerObjectIdentifier; static; inline;
+    class function GetRsaSignatureWithRipeMD256: IDerObjectIdentifier; static; inline;
     class function GetECSign: IDerObjectIdentifier; static; inline;
     class function GetECSign: IDerObjectIdentifier; static; inline;
-    class function GetECSignWithRipeMD160: IDerObjectIdentifier; static; inline;
     class function GetECSignWithSha1: IDerObjectIdentifier; static; inline;
     class function GetECSignWithSha1: IDerObjectIdentifier; static; inline;
+    class function GetECSignWithRipeMD160: IDerObjectIdentifier; static; inline;
+    class function GetECSignWithMD2: IDerObjectIdentifier; static; inline;
+    class function GetECSignWithMD5: IDerObjectIdentifier; static; inline;
+    class function GetTttEcg: IDerObjectIdentifier; static; inline;
+    class function GetEcStdCurvesAndGeneration: IDerObjectIdentifier; static; inline;
 
 
     class function GetBrainpoolP160R1: IDerObjectIdentifier; static; inline;
     class function GetBrainpoolP160R1: IDerObjectIdentifier; static; inline;
     class function GetBrainpoolP160T1: IDerObjectIdentifier; static; inline;
     class function GetBrainpoolP160T1: IDerObjectIdentifier; static; inline;
@@ -71,15 +91,27 @@ type
 
 
   public
   public
 
 
+    class property TeleTrusT: IDerObjectIdentifier read GetTeleTrusT;
+    class property Algorithm: IDerObjectIdentifier read GetAlgorithm;
+    class property TeleTrusTAlgorithm: IDerObjectIdentifier read GetTeleTrusTAlgorithm;
+    class property EncryptionAlgorithm: IDerObjectIdentifier read GetEncryptionAlgorithm;
+    class property HashAlgorithm: IDerObjectIdentifier read GetHashAlgorithm;
+    class property SignatureAlgorithm: IDerObjectIdentifier read GetSignatureAlgorithm;
+    class property SignatureScheme: IDerObjectIdentifier read GetSignatureScheme;
     class property RipeMD160: IDerObjectIdentifier read GetRipeMD160;
     class property RipeMD160: IDerObjectIdentifier read GetRipeMD160;
     class property RipeMD128: IDerObjectIdentifier read GetRipeMD128;
     class property RipeMD128: IDerObjectIdentifier read GetRipeMD128;
     class property RipeMD256: IDerObjectIdentifier read GetRipeMD256;
     class property RipeMD256: IDerObjectIdentifier read GetRipeMD256;
-    class property TeleTrusTAlgorithm: IDerObjectIdentifier
-      read GetTeleTrusTAlgorithm;
+    class property RsaSignature: IDerObjectIdentifier read GetRsaSignature;
+    class property RsaSignatureWithRipeMD160: IDerObjectIdentifier read GetRsaSignatureWithRipeMD160;
+    class property RsaSignatureWithRipeMD128: IDerObjectIdentifier read GetRsaSignatureWithRipeMD128;
+    class property RsaSignatureWithRipeMD256: IDerObjectIdentifier read GetRsaSignatureWithRipeMD256;
     class property ECSign: IDerObjectIdentifier read GetECSign;
     class property ECSign: IDerObjectIdentifier read GetECSign;
     class property ECSignWithSha1: IDerObjectIdentifier read GetECSignWithSha1;
     class property ECSignWithSha1: IDerObjectIdentifier read GetECSignWithSha1;
-    class property ECSignWithRipeMD160: IDerObjectIdentifier
-      read GetECSignWithRipeMD160;
+    class property ECSignWithRipeMD160: IDerObjectIdentifier read GetECSignWithRipeMD160;
+    class property ECSignWithMD2: IDerObjectIdentifier read GetECSignWithMD2;
+    class property ECSignWithMD5: IDerObjectIdentifier read GetECSignWithMD5;
+    class property TttEcg: IDerObjectIdentifier read GetTttEcg;
+    class property EcStdCurvesAndGeneration: IDerObjectIdentifier read GetEcStdCurvesAndGeneration;
 
 
     class property EccBrainpool: IDerObjectIdentifier read GetEccBrainpool;
     class property EccBrainpool: IDerObjectIdentifier read GetEccBrainpool;
     class property EllipticCurve: IDerObjectIdentifier read GetEllipticCurve;
     class property EllipticCurve: IDerObjectIdentifier read GetEllipticCurve;
@@ -121,27 +153,39 @@ implementation
 
 
 { TTeleTrusTObjectIdentifiers }
 { TTeleTrusTObjectIdentifiers }
 
 
-class function TTeleTrusTObjectIdentifiers.GetTeleTrusTAlgorithm
-  : IDerObjectIdentifier;
+class function TTeleTrusTObjectIdentifiers.GetTeleTrusT: IDerObjectIdentifier;
 begin
 begin
-  result := FTeleTrusTAlgorithm;
+  result := FTeleTrusT;
 end;
 end;
 
 
-class function TTeleTrusTObjectIdentifiers.GetECSign: IDerObjectIdentifier;
+class function TTeleTrusTObjectIdentifiers.GetAlgorithm: IDerObjectIdentifier;
 begin
 begin
-  result := FECSign;
+  result := FAlgorithm;
 end;
 end;
 
 
-class function TTeleTrusTObjectIdentifiers.GetECSignWithRipeMD160
-  : IDerObjectIdentifier;
+class function TTeleTrusTObjectIdentifiers.GetTeleTrusTAlgorithm: IDerObjectIdentifier;
 begin
 begin
-  result := FECSignWithRipeMD160;
+  result := FAlgorithm;
 end;
 end;
 
 
-class function TTeleTrusTObjectIdentifiers.GetECSignWithSha1
-  : IDerObjectIdentifier;
+class function TTeleTrusTObjectIdentifiers.GetEncryptionAlgorithm: IDerObjectIdentifier;
 begin
 begin
-  result := FECSignWithSha1;
+  result := FEncryptionAlgorithm;
+end;
+
+class function TTeleTrusTObjectIdentifiers.GetHashAlgorithm: IDerObjectIdentifier;
+begin
+  result := FHashAlgorithm;
+end;
+
+class function TTeleTrusTObjectIdentifiers.GetSignatureAlgorithm: IDerObjectIdentifier;
+begin
+  result := FSignatureAlgorithm;
+end;
+
+class function TTeleTrusTObjectIdentifiers.GetSignatureScheme: IDerObjectIdentifier;
+begin
+  result := FSignatureScheme;
 end;
 end;
 
 
 class function TTeleTrusTObjectIdentifiers.GetRipeMD128: IDerObjectIdentifier;
 class function TTeleTrusTObjectIdentifiers.GetRipeMD128: IDerObjectIdentifier;
@@ -159,8 +203,62 @@ begin
   result := FRipeMD256;
   result := FRipeMD256;
 end;
 end;
 
 
-class function TTeleTrusTObjectIdentifiers.GetEccBrainpool
-  : IDerObjectIdentifier;
+class function TTeleTrusTObjectIdentifiers.GetRsaSignature: IDerObjectIdentifier;
+begin
+  result := FRsaSignature;
+end;
+
+class function TTeleTrusTObjectIdentifiers.GetRsaSignatureWithRipeMD160: IDerObjectIdentifier;
+begin
+  result := FRsaSignatureWithRipeMD160;
+end;
+
+class function TTeleTrusTObjectIdentifiers.GetRsaSignatureWithRipeMD128: IDerObjectIdentifier;
+begin
+  result := FRsaSignatureWithRipeMD128;
+end;
+
+class function TTeleTrusTObjectIdentifiers.GetRsaSignatureWithRipeMD256: IDerObjectIdentifier;
+begin
+  result := FRsaSignatureWithRipeMD256;
+end;
+
+class function TTeleTrusTObjectIdentifiers.GetECSign: IDerObjectIdentifier;
+begin
+  result := FECSign;
+end;
+
+class function TTeleTrusTObjectIdentifiers.GetECSignWithSha1: IDerObjectIdentifier;
+begin
+  result := FECSignWithSha1;
+end;
+
+class function TTeleTrusTObjectIdentifiers.GetECSignWithRipeMD160: IDerObjectIdentifier;
+begin
+  result := FECSignWithRipeMD160;
+end;
+
+class function TTeleTrusTObjectIdentifiers.GetECSignWithMD2: IDerObjectIdentifier;
+begin
+  result := FECSignWithMD2;
+end;
+
+class function TTeleTrusTObjectIdentifiers.GetECSignWithMD5: IDerObjectIdentifier;
+begin
+  result := FECSignWithMD5;
+end;
+
+class function TTeleTrusTObjectIdentifiers.GetTttEcg: IDerObjectIdentifier;
+begin
+  result := FTttEcg;
+end;
+
+class function TTeleTrusTObjectIdentifiers.GetEcStdCurvesAndGeneration: IDerObjectIdentifier;
+begin
+  result := FEcStdCurvesAndGeneration;
+end;
+
+class function TTeleTrusTObjectIdentifiers.GetEccBrainpool: IDerObjectIdentifier;
 begin
 begin
   result := FEccBrainpool;
   result := FEccBrainpool;
 end;
 end;
@@ -170,92 +268,77 @@ begin
   result := FVersionOne;
   result := FVersionOne;
 end;
 end;
 
 
-class function TTeleTrusTObjectIdentifiers.GetEllipticCurve
-  : IDerObjectIdentifier;
+class function TTeleTrusTObjectIdentifiers.GetEllipticCurve: IDerObjectIdentifier;
 begin
 begin
   result := FEllipticCurve;
   result := FEllipticCurve;
 end;
 end;
 
 
-class function TTeleTrusTObjectIdentifiers.GetBrainpoolP160R1
-  : IDerObjectIdentifier;
+class function TTeleTrusTObjectIdentifiers.GetBrainpoolP160R1: IDerObjectIdentifier;
 begin
 begin
   result := FBrainpoolP160R1;
   result := FBrainpoolP160R1;
 end;
 end;
 
 
-class function TTeleTrusTObjectIdentifiers.GetBrainpoolP160T1
-  : IDerObjectIdentifier;
+class function TTeleTrusTObjectIdentifiers.GetBrainpoolP160T1: IDerObjectIdentifier;
 begin
 begin
   result := FBrainpoolP160T1;
   result := FBrainpoolP160T1;
 end;
 end;
 
 
-class function TTeleTrusTObjectIdentifiers.GetBrainpoolP192R1
-  : IDerObjectIdentifier;
+class function TTeleTrusTObjectIdentifiers.GetBrainpoolP192R1: IDerObjectIdentifier;
 begin
 begin
   result := FBrainpoolP192R1;
   result := FBrainpoolP192R1;
 end;
 end;
 
 
-class function TTeleTrusTObjectIdentifiers.GetBrainpoolP192T1
-  : IDerObjectIdentifier;
+class function TTeleTrusTObjectIdentifiers.GetBrainpoolP192T1: IDerObjectIdentifier;
 begin
 begin
   result := FBrainpoolP192T1;
   result := FBrainpoolP192T1;
 end;
 end;
 
 
-class function TTeleTrusTObjectIdentifiers.GetBrainpoolP224R1
-  : IDerObjectIdentifier;
+class function TTeleTrusTObjectIdentifiers.GetBrainpoolP224R1: IDerObjectIdentifier;
 begin
 begin
   result := FBrainpoolP224R1;
   result := FBrainpoolP224R1;
 end;
 end;
 
 
-class function TTeleTrusTObjectIdentifiers.GetBrainpoolP224T1
-  : IDerObjectIdentifier;
+class function TTeleTrusTObjectIdentifiers.GetBrainpoolP224T1: IDerObjectIdentifier;
 begin
 begin
   result := FBrainpoolP224T1;
   result := FBrainpoolP224T1;
 end;
 end;
 
 
-class function TTeleTrusTObjectIdentifiers.GetBrainpoolP256R1
-  : IDerObjectIdentifier;
+class function TTeleTrusTObjectIdentifiers.GetBrainpoolP256R1: IDerObjectIdentifier;
 begin
 begin
   result := FBrainpoolP256R1;
   result := FBrainpoolP256R1;
 end;
 end;
 
 
-class function TTeleTrusTObjectIdentifiers.GetBrainpoolP256T1
-  : IDerObjectIdentifier;
+class function TTeleTrusTObjectIdentifiers.GetBrainpoolP256T1: IDerObjectIdentifier;
 begin
 begin
   result := FBrainpoolP256T1;
   result := FBrainpoolP256T1;
 end;
 end;
 
 
-class function TTeleTrusTObjectIdentifiers.GetBrainpoolP320R1
-  : IDerObjectIdentifier;
+class function TTeleTrusTObjectIdentifiers.GetBrainpoolP320R1: IDerObjectIdentifier;
 begin
 begin
   result := FBrainpoolP320R1;
   result := FBrainpoolP320R1;
 end;
 end;
 
 
-class function TTeleTrusTObjectIdentifiers.GetBrainpoolP320T1
-  : IDerObjectIdentifier;
+class function TTeleTrusTObjectIdentifiers.GetBrainpoolP320T1: IDerObjectIdentifier;
 begin
 begin
   result := FBrainpoolP320T1;
   result := FBrainpoolP320T1;
 end;
 end;
 
 
-class function TTeleTrusTObjectIdentifiers.GetBrainpoolP384R1
-  : IDerObjectIdentifier;
+class function TTeleTrusTObjectIdentifiers.GetBrainpoolP384R1: IDerObjectIdentifier;
 begin
 begin
   result := FBrainpoolP384R1;
   result := FBrainpoolP384R1;
 end;
 end;
 
 
-class function TTeleTrusTObjectIdentifiers.GetBrainpoolP384T1
-  : IDerObjectIdentifier;
+class function TTeleTrusTObjectIdentifiers.GetBrainpoolP384T1: IDerObjectIdentifier;
 begin
 begin
   result := FBrainpoolP384T1;
   result := FBrainpoolP384T1;
 end;
 end;
 
 
-class function TTeleTrusTObjectIdentifiers.GetBrainpoolP512R1
-  : IDerObjectIdentifier;
+class function TTeleTrusTObjectIdentifiers.GetBrainpoolP512R1: IDerObjectIdentifier;
 begin
 begin
   result := FBrainpoolP512R1;
   result := FBrainpoolP512R1;
 end;
 end;
 
 
-class function TTeleTrusTObjectIdentifiers.GetBrainpoolP512T1
-  : IDerObjectIdentifier;
+class function TTeleTrusTObjectIdentifiers.GetBrainpoolP512T1: IDerObjectIdentifier;
 begin
 begin
   result := FBrainpoolP512T1;
   result := FBrainpoolP512T1;
 end;
 end;
@@ -264,39 +347,58 @@ class procedure TTeleTrusTObjectIdentifiers.Boot;
 begin
 begin
   if not FIsBooted then
   if not FIsBooted then
   begin
   begin
-    FTeleTrusTAlgorithm := TDerObjectIdentifier.Create('1.3.36.3');
-    FRipeMD160 := TDerObjectIdentifier.Create(TeleTrusTAlgorithm.ID + '.2.1');
-    FRipeMD128 := TDerObjectIdentifier.Create(TeleTrusTAlgorithm.ID + '.2.2');
-    FRipeMD256 := TDerObjectIdentifier.Create(TeleTrusTAlgorithm.ID + '.2.3');
-
-    FECSign := TDerObjectIdentifier.Create(TeleTrusTAlgorithm.ID + '.3.2');
-
-    FECSignWithSha1 := TDerObjectIdentifier.Create(ECSign.ID + '.1');
-    FECSignWithRipeMD160 := TDerObjectIdentifier.Create(ECSign.ID + '.2');
-
-    FEccBrainpool := TDerObjectIdentifier.Create(TeleTrusTAlgorithm.ID +
-      '.3.2.8');
-    FEllipticCurve := TDerObjectIdentifier.Create(EccBrainpool.ID + '.1');
-    FVersionOne := TDerObjectIdentifier.Create(EllipticCurve.ID + '.1');
-
-    FBrainpoolP160R1 := TDerObjectIdentifier.Create(VersionOne.ID + '.1');
-    FBrainpoolP160T1 := TDerObjectIdentifier.Create(VersionOne.ID + '.2');
-    FBrainpoolP192R1 := TDerObjectIdentifier.Create(VersionOne.ID + '.3');
-    FBrainpoolP192T1 := TDerObjectIdentifier.Create(VersionOne.ID + '.4');
-    FBrainpoolP224R1 := TDerObjectIdentifier.Create(VersionOne.ID + '.5');
-    FBrainpoolP224T1 := TDerObjectIdentifier.Create(VersionOne.ID + '.6');
-    FBrainpoolP256R1 := TDerObjectIdentifier.Create(VersionOne.ID + '.7');
-    FBrainpoolP256T1 := TDerObjectIdentifier.Create(VersionOne.ID + '.8');
-    FBrainpoolP320R1 := TDerObjectIdentifier.Create(VersionOne.ID + '.9');
-    FBrainpoolP320T1 := TDerObjectIdentifier.Create(VersionOne.ID + '.10');
-    FBrainpoolP384R1 := TDerObjectIdentifier.Create(VersionOne.ID + '.11');
-    FBrainpoolP384T1 := TDerObjectIdentifier.Create(VersionOne.ID + '.12');
-    FBrainpoolP512R1 := TDerObjectIdentifier.Create(VersionOne.ID + '.13');
-    FBrainpoolP512T1 := TDerObjectIdentifier.Create(VersionOne.ID + '.14');
+    // Base OID: 1.3.36
+    FTeleTrusT := TDerObjectIdentifier.Create('1.3.36');
+    FAlgorithm := FTeleTrusT.Branch('3');
+
+    // Algorithm sub-branches
+    FEncryptionAlgorithm := FAlgorithm.Branch('1');
+    FHashAlgorithm := FAlgorithm.Branch('2');
+    FSignatureAlgorithm := FAlgorithm.Branch('3');
+    FSignatureScheme := FAlgorithm.Branch('4');
+
+    // Hash algorithms
+    FRipeMD160 := FHashAlgorithm.Branch('1');
+    FRipeMD128 := FHashAlgorithm.Branch('2');
+    FRipeMD256 := FHashAlgorithm.Branch('3');
+
+    // RSA Signatures
+    FRsaSignature := FSignatureAlgorithm.Branch('1');
+    FRsaSignatureWithRipeMD160 := FRsaSignature.Branch('2');
+    FRsaSignatureWithRipeMD128 := FRsaSignature.Branch('3');
+    FRsaSignatureWithRipeMD256 := FRsaSignature.Branch('4');
+
+    // EC Signatures
+    FECSign := FSignatureAlgorithm.Branch('2');
+    FECSignWithSha1 := FECSign.Branch('1');
+    FECSignWithRipeMD160 := FECSign.Branch('2');
+    FECSignWithMD2 := FECSign.Branch('3');
+    FECSignWithMD5 := FECSign.Branch('4');
+    FTttEcg := FECSign.Branch('5');
+    FEcStdCurvesAndGeneration := FECSign.Branch('8');
+
+    // Brainpool curves
+    FEccBrainpool := FEcStdCurvesAndGeneration;
+    FEllipticCurve := FEccBrainpool.Branch('1');
+    FVersionOne := FEllipticCurve.Branch('1');
+
+    FBrainpoolP160R1 := FVersionOne.Branch('1');
+    FBrainpoolP160T1 := FVersionOne.Branch('2');
+    FBrainpoolP192R1 := FVersionOne.Branch('3');
+    FBrainpoolP192T1 := FVersionOne.Branch('4');
+    FBrainpoolP224R1 := FVersionOne.Branch('5');
+    FBrainpoolP224T1 := FVersionOne.Branch('6');
+    FBrainpoolP256R1 := FVersionOne.Branch('7');
+    FBrainpoolP256T1 := FVersionOne.Branch('8');
+    FBrainpoolP320R1 := FVersionOne.Branch('9');
+    FBrainpoolP320T1 := FVersionOne.Branch('10');
+    FBrainpoolP384R1 := FVersionOne.Branch('11');
+    FBrainpoolP384T1 := FVersionOne.Branch('12');
+    FBrainpoolP512R1 := FVersionOne.Branch('13');
+    FBrainpoolP512T1 := FVersionOne.Branch('14');
 
 
     FIsBooted := True;
     FIsBooted := True;
   end;
   end;
-
 end;
 end;
 
 
 class constructor TTeleTrusTObjectIdentifiers.TeleTrusTObjectIdentifiers;
 class constructor TTeleTrusTObjectIdentifiers.TeleTrusTObjectIdentifiers;
@@ -305,3 +407,4 @@ begin
 end;
 end;
 
 
 end.
 end.
+

+ 161 - 0
CryptoLib/src/Asn1/X509/ClpAlgorithmIdentifier.pas

@@ -0,0 +1,161 @@
+{ *********************************************************************************** }
+{ *                              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 ClpAlgorithmIdentifier;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpAsn1Objects,
+  ClpIAsn1Objects,
+  ClpIAlgorithmIdentifier,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SBadSequenceSize = 'Bad sequence size: %d';
+  SAlgorithmNil = 'algorithm';
+
+type
+  /// <summary>
+  /// The AlgorithmIdentifier object.
+  /// <code>
+  /// AlgorithmIdentifier ::= SEQUENCE {
+  ///   algorithm OBJECT IDENTIFIER,
+  ///   parameters ANY DEFINED BY algorithm OPTIONAL
+  /// }
+  /// </code>
+  /// </summary>
+  TAlgorithmIdentifier = class(TAsn1Encodable, IAlgorithmIdentifier)
+
+  strict private
+  var
+    FAlgorithm: IDerObjectIdentifier;
+    FParameters: IAsn1Encodable;
+
+  strict protected
+    function GetAlgorithm: IDerObjectIdentifier;
+    function GetParameters: IAsn1Encodable;
+
+  public
+    /// <summary>
+    /// Parse an AlgorithmIdentifier from an object.
+    /// </summary>
+    class function GetInstance(obj: TObject): IAlgorithmIdentifier; overload; static;
+
+    /// <summary>
+    /// Parse an AlgorithmIdentifier from a tagged object.
+    /// </summary>
+    class function GetInstance(const obj: IAsn1TaggedObject;
+      explicitly: Boolean): IAlgorithmIdentifier; overload; static;
+
+    constructor Create(const seq: IAsn1Sequence); overload;
+    constructor Create(const algorithm: IDerObjectIdentifier); overload;
+    constructor Create(const algorithm: IDerObjectIdentifier;
+      const parameters: IAsn1Encodable); overload;
+
+    function ToAsn1Object: IAsn1Object; override;
+
+    property Algorithm: IDerObjectIdentifier read GetAlgorithm;
+    property Parameters: IAsn1Encodable read GetParameters;
+
+  end;
+
+implementation
+
+{ TAlgorithmIdentifier }
+
+class function TAlgorithmIdentifier.GetInstance(obj: TObject): IAlgorithmIdentifier;
+begin
+  if obj = nil then
+  begin
+    Result := nil;
+    Exit;
+  end;
+
+  if Supports(obj, IAlgorithmIdentifier, Result) then
+    Exit;
+
+  Result := TAlgorithmIdentifier.Create(TAsn1Sequence.GetInstance(obj));
+end;
+
+class function TAlgorithmIdentifier.GetInstance(const obj: IAsn1TaggedObject;
+  explicitly: Boolean): IAlgorithmIdentifier;
+begin
+  Result := TAlgorithmIdentifier.Create(TAsn1Sequence.GetInstance(obj, explicitly));
+end;
+
+constructor TAlgorithmIdentifier.Create(const seq: IAsn1Sequence);
+var
+  count: Int32;
+begin
+  inherited Create();
+
+  count := seq.Count;
+  if (count < 1) or (count > 2) then
+  begin
+    raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [count]);
+  end;
+
+  //FAlgorithm := TDerObjectIdentifier.GetInstance(seq[0].ToAsn1Object as TObject);
+  FAlgorithm := TDerObjectIdentifier.GetInstance(seq[0] as TAsn1Encodable);
+  if count < 2 then
+    FParameters := nil
+  else
+    FParameters := seq[1] as IAsn1Encodable;
+end;
+
+constructor TAlgorithmIdentifier.Create(const algorithm: IDerObjectIdentifier);
+begin
+  Create(algorithm, nil);
+end;
+
+constructor TAlgorithmIdentifier.Create(const algorithm: IDerObjectIdentifier;
+  const parameters: IAsn1Encodable);
+begin
+  inherited Create();
+
+  if algorithm = nil then
+  begin
+    raise EArgumentNilCryptoLibException.Create(SAlgorithmNil);
+  end;
+
+  FAlgorithm := algorithm;
+  FParameters := parameters;
+end;
+
+function TAlgorithmIdentifier.GetAlgorithm: IDerObjectIdentifier;
+begin
+  Result := FAlgorithm;
+end;
+
+function TAlgorithmIdentifier.GetParameters: IAsn1Encodable;
+begin
+  Result := FParameters;
+end;
+
+function TAlgorithmIdentifier.ToAsn1Object: IAsn1Object;
+begin
+  if FParameters = nil then
+    Result := TDerSequence.Create([FAlgorithm as IAsn1Encodable])
+  else
+    Result := TDerSequence.Create([FAlgorithm as IAsn1Encodable, FParameters]);
+end;
+
+end.

+ 184 - 0
CryptoLib/src/Asn1/X509/ClpDigestInfo.pas

@@ -0,0 +1,184 @@
+{ *********************************************************************************** }
+{ *                              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 ClpDigestInfo;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpAsn1Objects,
+  ClpIAsn1Objects,
+  ClpIAlgorithmIdentifier,
+  ClpAlgorithmIdentifier,
+  ClpIDigestInfo,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SBadSequenceSize = 'Bad sequence size: %d';
+
+type
+  /// <summary>
+  /// The DigestInfo object.
+  /// DigestInfo ::= SEQUENCE {
+  ///   digestAlgorithm AlgorithmIdentifier,
+  ///   digest OCTET STRING
+  /// }
+  /// </summary>
+  TDigestInfo = class(TAsn1Encodable, IDigestInfo)
+
+  strict private
+  var
+    FDigestAlgorithm: IAlgorithmIdentifier;
+    FDigest: IAsn1OctetString;
+
+  strict protected
+    function GetDigestAlgorithm: IAlgorithmIdentifier;
+    function GetDigest: IAsn1OctetString;
+    function GetDigestBytes: TCryptoLibByteArray;
+
+  public
+    /// <summary>
+    /// Parse a DigestInfo from an object.
+    /// </summary>
+    class function GetInstance(obj: TObject): IDigestInfo; overload; static;
+
+    /// <summary>
+    /// Parse a DigestInfo from DER-encoded bytes.
+    /// </summary>
+    class function GetInstance(const encoded: TCryptoLibByteArray): IDigestInfo; overload; static;
+
+    constructor Create(const seq: IAsn1Sequence); overload;
+    constructor Create(const algId: IAlgorithmIdentifier;
+      const digest: TCryptoLibByteArray); overload;
+    constructor Create(const digestAlgorithm: IAlgorithmIdentifier;
+      const digest: IAsn1OctetString); overload;
+
+    function GetDerEncoded: TCryptoLibByteArray;
+    function ToAsn1Object: IAsn1Object; override;
+
+    property DigestAlgorithm: IAlgorithmIdentifier read GetDigestAlgorithm;
+    property Digest: IAsn1OctetString read GetDigest;
+
+  end;
+
+implementation
+
+{ TDigestInfo }
+
+class function TDigestInfo.GetInstance(obj: TObject): IDigestInfo;
+begin
+  if obj = nil then
+  begin
+    Result := nil;
+    Exit;
+  end;
+
+  if Supports(obj, IDigestInfo, Result) then
+    Exit;
+
+  if obj is TAsn1Sequence then
+    Result := TDigestInfo.Create(obj as TAsn1Sequence)
+  else
+    Result := TDigestInfo.Create(TAsn1Sequence.GetInstance(obj as TAsn1Encodable));
+end;
+
+class function TDigestInfo.GetInstance(const encoded: TCryptoLibByteArray): IDigestInfo;
+var
+  asn1Obj: IAsn1Object;
+begin
+  asn1Obj := TAsn1Object.FromByteArray(encoded);
+  Result := TDigestInfo.Create(asn1Obj as IAsn1Sequence);
+end;
+
+constructor TDigestInfo.Create(const seq: IAsn1Sequence);
+var
+  count: Int32;
+begin
+  inherited Create();
+
+  count := seq.Count;
+  if count <> 2 then
+  begin
+    raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [count]);
+  end;
+
+  FDigestAlgorithm := TAlgorithmIdentifier.GetInstance(seq[0].ToAsn1Object() as TObject);
+  FDigest := TAsn1OctetString.GetInstance(seq[1].ToAsn1Object() as TObject);
+end;
+
+constructor TDigestInfo.Create(const algId: IAlgorithmIdentifier;
+  const digest: TCryptoLibByteArray);
+begin
+  inherited Create();
+
+  if algId = nil then
+  begin
+    raise EArgumentNilCryptoLibException.Create('algId');
+  end;
+
+  FDigestAlgorithm := algId;
+  FDigest := TDerOctetString.Create(digest);
+end;
+
+constructor TDigestInfo.Create(const digestAlgorithm: IAlgorithmIdentifier;
+  const digest: IAsn1OctetString);
+begin
+  inherited Create();
+
+  if digestAlgorithm = nil then
+  begin
+    raise EArgumentNilCryptoLibException.Create('digestAlgorithm');
+  end;
+
+  if digest = nil then
+  begin
+    raise EArgumentNilCryptoLibException.Create('digest');
+  end;
+
+  FDigestAlgorithm := digestAlgorithm;
+  FDigest := digest;
+end;
+
+function TDigestInfo.GetDigestAlgorithm: IAlgorithmIdentifier;
+begin
+  Result := FDigestAlgorithm;
+end;
+
+function TDigestInfo.GetDigest: IAsn1OctetString;
+begin
+  Result := FDigest;
+end;
+
+function TDigestInfo.GetDigestBytes: TCryptoLibByteArray;
+begin
+  Result := FDigest.GetOctets();
+end;
+
+function TDigestInfo.GetDerEncoded: TCryptoLibByteArray;
+begin
+  Result := ToAsn1Object.GetDerEncoded();
+end;
+
+function TDigestInfo.ToAsn1Object: IAsn1Object;
+begin
+  Result := TDerSequence.Create([FDigestAlgorithm, FDigest]);
+end;
+
+end.

+ 326 - 0
CryptoLib/src/Asn1/X509/ClpX509ObjectIdentifiers.pas

@@ -0,0 +1,326 @@
+{ *********************************************************************************** }
+{ *                              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 ClpX509ObjectIdentifiers;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpAsn1Objects,
+  ClpIAsn1Objects;
+
+type
+  /// <summary>
+  /// X.509 Object Identifiers
+  /// </summary>
+  TX509ObjectIdentifiers = class abstract(TObject)
+
+  strict private
+  const
+    // base id
+    AttributeType: String = '2.5.4';
+
+  class var
+    FAttributeType: IDerObjectIdentifier;
+    FCommonName: IDerObjectIdentifier;
+    FCountryName: IDerObjectIdentifier;
+    FLocalityName: IDerObjectIdentifier;
+    FStateOrProvinceName: IDerObjectIdentifier;
+    FOrganization: IDerObjectIdentifier;
+    FOrganizationalUnitName: IDerObjectIdentifier;
+    FIdAtTelephoneNumber: IDerObjectIdentifier;
+    FIdAtName: IDerObjectIdentifier;
+    FIdAtOrganizationIdentifier: IDerObjectIdentifier;
+    FIdSha1: IDerObjectIdentifier;
+    FRipeMD160: IDerObjectIdentifier;
+    FRipeMD160WithRsaEncryption: IDerObjectIdentifier;
+    FIdEARsa: IDerObjectIdentifier;
+    FIdPkix: IDerObjectIdentifier;
+    FIdPE: IDerObjectIdentifier;
+    FPkixAlgorithms: IDerObjectIdentifier;
+    FIdRsassaPssShake128: IDerObjectIdentifier;
+    FIdRsassaPssShake256: IDerObjectIdentifier;
+    FIdEcdsaWithShake128: IDerObjectIdentifier;
+    FIdEcdsaWithShake256: IDerObjectIdentifier;
+    FIdPda: IDerObjectIdentifier;
+    FIdAD: IDerObjectIdentifier;
+    FIdADOcsp: IDerObjectIdentifier;
+    FIdADCAIssuers: IDerObjectIdentifier;
+    FIdCe: IDerObjectIdentifier;
+
+    class function GetAttributeType: IDerObjectIdentifier; static; inline;
+    class function GetCommonName: IDerObjectIdentifier; static; inline;
+    class function GetCountryName: IDerObjectIdentifier; static; inline;
+    class function GetLocalityName: IDerObjectIdentifier; static; inline;
+    class function GetStateOrProvinceName: IDerObjectIdentifier; static; inline;
+    class function GetOrganization: IDerObjectIdentifier; static; inline;
+    class function GetOrganizationalUnitName: IDerObjectIdentifier; static; inline;
+    class function GetIdAtTelephoneNumber: IDerObjectIdentifier; static; inline;
+    class function GetIdAtName: IDerObjectIdentifier; static; inline;
+    class function GetIdAtOrganizationIdentifier: IDerObjectIdentifier; static; inline;
+    class function GetIdSha1: IDerObjectIdentifier; static; inline;
+    class function GetRipeMD160: IDerObjectIdentifier; static; inline;
+    class function GetRipeMD160WithRsaEncryption: IDerObjectIdentifier; static; inline;
+    class function GetIdEARsa: IDerObjectIdentifier; static; inline;
+    class function GetIdPkix: IDerObjectIdentifier; static; inline;
+    class function GetIdPE: IDerObjectIdentifier; static; inline;
+    class function GetPkixAlgorithms: IDerObjectIdentifier; static; inline;
+    class function GetIdRsassaPssShake128: IDerObjectIdentifier; static; inline;
+    class function GetIdRsassaPssShake256: IDerObjectIdentifier; static; inline;
+    class function GetIdEcdsaWithShake128: IDerObjectIdentifier; static; inline;
+    class function GetIdEcdsaWithShake256: IDerObjectIdentifier; static; inline;
+    class function GetIdPda: IDerObjectIdentifier; static; inline;
+    class function GetIdAD: IDerObjectIdentifier; static; inline;
+    class function GetIdADOcsp: IDerObjectIdentifier; static; inline;
+    class function GetIdADCAIssuers: IDerObjectIdentifier; static; inline;
+    class function GetIdCe: IDerObjectIdentifier; static; inline;
+
+    class procedure Boot(); static;
+    class constructor X509ObjectIdentifiers();
+
+  public
+    // Attribute types
+    class property AttributeTypeOid: IDerObjectIdentifier read GetAttributeType;
+    class property CommonName: IDerObjectIdentifier read GetCommonName;
+    class property CountryName: IDerObjectIdentifier read GetCountryName;
+    class property LocalityName: IDerObjectIdentifier read GetLocalityName;
+    class property StateOrProvinceName: IDerObjectIdentifier read GetStateOrProvinceName;
+    class property Organization: IDerObjectIdentifier read GetOrganization;
+    class property OrganizationalUnitName: IDerObjectIdentifier read GetOrganizationalUnitName;
+    class property IdAtTelephoneNumber: IDerObjectIdentifier read GetIdAtTelephoneNumber;
+    class property IdAtName: IDerObjectIdentifier read GetIdAtName;
+    class property IdAtOrganizationIdentifier: IDerObjectIdentifier read GetIdAtOrganizationIdentifier;
+
+    // Hash algorithms
+    class property IdSha1: IDerObjectIdentifier read GetIdSha1;
+    class property RipeMD160: IDerObjectIdentifier read GetRipeMD160;
+    class property RipeMD160WithRsaEncryption: IDerObjectIdentifier read GetRipeMD160WithRsaEncryption;
+
+    // Encryption
+    class property IdEARsa: IDerObjectIdentifier read GetIdEARsa;
+
+    // PKIX
+    class property IdPkix: IDerObjectIdentifier read GetIdPkix;
+    class property IdPE: IDerObjectIdentifier read GetIdPE;
+    class property PkixAlgorithms: IDerObjectIdentifier read GetPkixAlgorithms;
+    class property IdRsassaPssShake128: IDerObjectIdentifier read GetIdRsassaPssShake128;
+    class property IdRsassaPssShake256: IDerObjectIdentifier read GetIdRsassaPssShake256;
+    class property IdEcdsaWithShake128: IDerObjectIdentifier read GetIdEcdsaWithShake128;
+    class property IdEcdsaWithShake256: IDerObjectIdentifier read GetIdEcdsaWithShake256;
+    class property IdPda: IDerObjectIdentifier read GetIdPda;
+
+    // Authority Information Access
+    class property IdAD: IDerObjectIdentifier read GetIdAD;
+    class property IdADOcsp: IDerObjectIdentifier read GetIdADOcsp;
+    class property IdADCAIssuers: IDerObjectIdentifier read GetIdADCAIssuers;
+    class property OcspAccessMethod: IDerObjectIdentifier read GetIdADOcsp;
+    class property CrlAccessMethod: IDerObjectIdentifier read GetIdADCAIssuers;
+
+    // Certificate Extensions
+    class property IdCe: IDerObjectIdentifier read GetIdCe;
+
+  end;
+
+implementation
+
+{ TX509ObjectIdentifiers }
+
+class procedure TX509ObjectIdentifiers.Boot;
+begin
+  // Base attribute type
+  FAttributeType := TDerObjectIdentifier.Create(AttributeType);
+
+  // Attribute types
+  FCommonName := FAttributeType.Branch('3');
+  FCountryName := FAttributeType.Branch('6');
+  FLocalityName := FAttributeType.Branch('7');
+  FStateOrProvinceName := FAttributeType.Branch('8');
+  FOrganization := FAttributeType.Branch('10');
+  FOrganizationalUnitName := FAttributeType.Branch('11');
+  FIdAtTelephoneNumber := FAttributeType.Branch('20');
+  FIdAtName := FAttributeType.Branch('41');
+  FIdAtOrganizationIdentifier := FAttributeType.Branch('97');
+
+  // SHA-1: 1.3.14.3.2.26
+  FIdSha1 := TDerObjectIdentifier.Create('1.3.14.3.2.26');
+
+  // RIPEMD-160: 1.3.36.3.2.1
+  FRipeMD160 := TDerObjectIdentifier.Create('1.3.36.3.2.1');
+
+  // RIPEMD-160 with RSA: 1.3.36.3.3.1.2
+  FRipeMD160WithRsaEncryption := TDerObjectIdentifier.Create('1.3.36.3.3.1.2');
+
+  // EA RSA: 2.5.8.1.1
+  FIdEARsa := TDerObjectIdentifier.Create('2.5.8.1.1');
+
+  // PKIX: 1.3.6.1.5.5.7
+  FIdPkix := TDerObjectIdentifier.Create('1.3.6.1.5.5.7');
+  FIdPE := FIdPkix.Branch('1');
+  FPkixAlgorithms := FIdPkix.Branch('6');
+  FIdRsassaPssShake128 := FPkixAlgorithms.Branch('30');
+  FIdRsassaPssShake256 := FPkixAlgorithms.Branch('31');
+  FIdEcdsaWithShake128 := FPkixAlgorithms.Branch('32');
+  FIdEcdsaWithShake256 := FPkixAlgorithms.Branch('33');
+  FIdPda := FIdPkix.Branch('9');
+
+  // Authority Information Access
+  FIdAD := FIdPkix.Branch('48');
+  FIdADOcsp := FIdAD.Branch('1');
+  FIdADCAIssuers := FIdAD.Branch('2');
+
+  // Certificate Extensions: 2.5.29
+  FIdCe := TDerObjectIdentifier.Create('2.5.29');
+end;
+
+class constructor TX509ObjectIdentifiers.X509ObjectIdentifiers;
+begin
+  TX509ObjectIdentifiers.Boot();
+end;
+
+class function TX509ObjectIdentifiers.GetAttributeType: IDerObjectIdentifier;
+begin
+  Result := FAttributeType;
+end;
+
+class function TX509ObjectIdentifiers.GetCommonName: IDerObjectIdentifier;
+begin
+  Result := FCommonName;
+end;
+
+class function TX509ObjectIdentifiers.GetCountryName: IDerObjectIdentifier;
+begin
+  Result := FCountryName;
+end;
+
+class function TX509ObjectIdentifiers.GetLocalityName: IDerObjectIdentifier;
+begin
+  Result := FLocalityName;
+end;
+
+class function TX509ObjectIdentifiers.GetStateOrProvinceName: IDerObjectIdentifier;
+begin
+  Result := FStateOrProvinceName;
+end;
+
+class function TX509ObjectIdentifiers.GetOrganization: IDerObjectIdentifier;
+begin
+  Result := FOrganization;
+end;
+
+class function TX509ObjectIdentifiers.GetOrganizationalUnitName: IDerObjectIdentifier;
+begin
+  Result := FOrganizationalUnitName;
+end;
+
+class function TX509ObjectIdentifiers.GetIdAtTelephoneNumber: IDerObjectIdentifier;
+begin
+  Result := FIdAtTelephoneNumber;
+end;
+
+class function TX509ObjectIdentifiers.GetIdAtName: IDerObjectIdentifier;
+begin
+  Result := FIdAtName;
+end;
+
+class function TX509ObjectIdentifiers.GetIdAtOrganizationIdentifier: IDerObjectIdentifier;
+begin
+  Result := FIdAtOrganizationIdentifier;
+end;
+
+class function TX509ObjectIdentifiers.GetIdSha1: IDerObjectIdentifier;
+begin
+  Result := FIdSha1;
+end;
+
+class function TX509ObjectIdentifiers.GetRipeMD160: IDerObjectIdentifier;
+begin
+  Result := FRipeMD160;
+end;
+
+class function TX509ObjectIdentifiers.GetRipeMD160WithRsaEncryption: IDerObjectIdentifier;
+begin
+  Result := FRipeMD160WithRsaEncryption;
+end;
+
+class function TX509ObjectIdentifiers.GetIdEARsa: IDerObjectIdentifier;
+begin
+  Result := FIdEARsa;
+end;
+
+class function TX509ObjectIdentifiers.GetIdPkix: IDerObjectIdentifier;
+begin
+  Result := FIdPkix;
+end;
+
+class function TX509ObjectIdentifiers.GetIdPE: IDerObjectIdentifier;
+begin
+  Result := FIdPE;
+end;
+
+class function TX509ObjectIdentifiers.GetPkixAlgorithms: IDerObjectIdentifier;
+begin
+  Result := FPkixAlgorithms;
+end;
+
+class function TX509ObjectIdentifiers.GetIdRsassaPssShake128: IDerObjectIdentifier;
+begin
+  Result := FIdRsassaPssShake128;
+end;
+
+class function TX509ObjectIdentifiers.GetIdRsassaPssShake256: IDerObjectIdentifier;
+begin
+  Result := FIdRsassaPssShake256;
+end;
+
+class function TX509ObjectIdentifiers.GetIdEcdsaWithShake128: IDerObjectIdentifier;
+begin
+  Result := FIdEcdsaWithShake128;
+end;
+
+class function TX509ObjectIdentifiers.GetIdEcdsaWithShake256: IDerObjectIdentifier;
+begin
+  Result := FIdEcdsaWithShake256;
+end;
+
+class function TX509ObjectIdentifiers.GetIdPda: IDerObjectIdentifier;
+begin
+  Result := FIdPda;
+end;
+
+class function TX509ObjectIdentifiers.GetIdAD: IDerObjectIdentifier;
+begin
+  Result := FIdAD;
+end;
+
+class function TX509ObjectIdentifiers.GetIdADOcsp: IDerObjectIdentifier;
+begin
+  Result := FIdADOcsp;
+end;
+
+class function TX509ObjectIdentifiers.GetIdADCAIssuers: IDerObjectIdentifier;
+begin
+  Result := FIdADCAIssuers;
+end;
+
+class function TX509ObjectIdentifiers.GetIdCe: IDerObjectIdentifier;
+begin
+  Result := FIdCe;
+end;
+
+end.

+ 314 - 0
CryptoLib/src/Crypto/ClpBufferedAsymmetricBlockCipher.pas

@@ -0,0 +1,314 @@
+{ *********************************************************************************** }
+{ *                              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 ClpBufferedAsymmetricBlockCipher;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  SysUtils,
+  ClpICipherParameters,
+  ClpIAsymmetricBlockCipher,
+  ClpIBufferedCipher,
+  ClpIBufferedAsymmetricBlockCipher,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SOutputBufferTooShort = 'Output buffer too short';
+  SDataTooLongForCipher = 'Attempt to process message too long for cipher';
+
+type
+  /// <summary>
+  /// A buffer wrapper for an asymmetric block cipher, allowing input
+  /// to be accumulated in a piecemeal fashion until final processing.
+  /// </summary>
+  TBufferedAsymmetricBlockCipher = class(TInterfacedObject, IBufferedCipher, IBufferedAsymmetricBlockCipher)
+
+  strict private
+    FCipher: IAsymmetricBlockCipher;
+    FBuffer: TCryptoLibByteArray;
+    FBufOff: Int32;
+    FBufferSize: Int32;
+    FOnProgress: TBufferedCipherProgressEvent;
+
+  strict protected
+    function GetAlgorithmName: String;
+    function GetBlockSize: Int32;
+    function GetBufferSize: Int32;
+    procedure SetBufferSize(value: Int32);
+    function GetOnProgress: TBufferedCipherProgressEvent;
+    procedure SetOnProgress(const value: TBufferedCipherProgressEvent);
+
+  public
+    constructor Create(const cipher: IAsymmetricBlockCipher);
+
+    procedure Init(forEncryption: Boolean; const parameters: ICipherParameters);
+    function GetOutputSize(inputLen: Int32): Int32;
+    function GetUpdateOutputSize(inputLen: Int32): Int32;
+
+    procedure ProcessStream(const inputStream, outputStream: TStream;
+      Length: Int64); overload;
+    procedure ProcessStream(const inputStream: TStream; inOff: Int64;
+      const outputStream: TStream; outOff: Int64; Length: Int64); overload;
+
+    function ProcessByte(input: Byte): TCryptoLibByteArray; overload;
+    function ProcessByte(input: Byte; const output: TCryptoLibByteArray;
+      outOff: Int32): Int32; overload;
+    function ProcessBytes(const input: TCryptoLibByteArray; inOff,
+      length: Int32): TCryptoLibByteArray; overload;
+    function ProcessBytes(const input: TCryptoLibByteArray)
+      : TCryptoLibByteArray; overload;
+    function ProcessBytes(const input, output: TCryptoLibByteArray;
+      outOff: Int32): Int32; overload;
+    function ProcessBytes(const input: TCryptoLibByteArray; inOff, length: Int32;
+      const output: TCryptoLibByteArray; outOff: Int32): Int32; overload;
+    function DoFinal(): TCryptoLibByteArray; overload;
+    function DoFinal(const input: TCryptoLibByteArray): TCryptoLibByteArray; overload;
+    function DoFinal(const input: TCryptoLibByteArray; inOff, inLen: Int32)
+      : TCryptoLibByteArray; overload;
+    function DoFinal(const output: TCryptoLibByteArray; outOff: Int32)
+      : Int32; overload;
+    function DoFinal(const input: TCryptoLibByteArray;
+      const output: TCryptoLibByteArray; outOff: Int32): Int32; overload;
+    function DoFinal(const input: TCryptoLibByteArray; inOff, length: Int32;
+      const output: TCryptoLibByteArray; outOff: Int32): Int32; overload;
+    procedure Reset();
+
+    property AlgorithmName: String read GetAlgorithmName;
+    property BlockSize: Int32 read GetBlockSize;
+    property BufferSize: Int32 read GetBufferSize write SetBufferSize;
+    property OnProgress: TBufferedCipherProgressEvent read GetOnProgress write SetOnProgress;
+
+  end;
+
+implementation
+
+{ TBufferedAsymmetricBlockCipher }
+
+constructor TBufferedAsymmetricBlockCipher.Create(const cipher: IAsymmetricBlockCipher);
+begin
+  inherited Create();
+  FCipher := cipher;
+  FBufferSize := 4096;
+end;
+
+function TBufferedAsymmetricBlockCipher.GetAlgorithmName: String;
+begin
+  Result := FCipher.AlgorithmName;
+end;
+
+function TBufferedAsymmetricBlockCipher.GetBlockSize: Int32;
+begin
+  Result := FCipher.InputBlockSize;
+end;
+
+function TBufferedAsymmetricBlockCipher.GetBufferSize: Int32;
+begin
+  Result := FBufferSize;
+end;
+
+procedure TBufferedAsymmetricBlockCipher.SetBufferSize(value: Int32);
+begin
+  FBufferSize := value;
+end;
+
+function TBufferedAsymmetricBlockCipher.GetOnProgress: TBufferedCipherProgressEvent;
+begin
+  Result := FOnProgress;
+end;
+
+procedure TBufferedAsymmetricBlockCipher.SetOnProgress(const value: TBufferedCipherProgressEvent);
+begin
+  FOnProgress := value;
+end;
+
+procedure TBufferedAsymmetricBlockCipher.Init(forEncryption: Boolean;
+  const parameters: ICipherParameters);
+begin
+  Reset();
+  FCipher.Init(forEncryption, parameters);
+  // Allow for an extra byte where people are using their own padding
+  // mechanisms on a raw cipher.
+  if forEncryption then
+    SetLength(FBuffer, FCipher.InputBlockSize + 1)
+  else
+    SetLength(FBuffer, FCipher.InputBlockSize);
+  FBufOff := 0;
+end;
+
+function TBufferedAsymmetricBlockCipher.GetOutputSize(inputLen: Int32): Int32;
+begin
+  Result := FCipher.OutputBlockSize;
+end;
+
+function TBufferedAsymmetricBlockCipher.GetUpdateOutputSize(inputLen: Int32): Int32;
+begin
+  Result := 0;
+end;
+
+procedure TBufferedAsymmetricBlockCipher.ProcessStream(const inputStream,
+  outputStream: TStream; Length: Int64);
+begin
+  ProcessStream(inputStream, inputStream.Position, outputStream, outputStream.Position, Length);
+end;
+
+procedure TBufferedAsymmetricBlockCipher.ProcessStream(const inputStream: TStream;
+  inOff: Int64; const outputStream: TStream; outOff: Int64; Length: Int64);
+var
+  inputData, outputData: TCryptoLibByteArray;
+begin
+  // For asymmetric ciphers, we read the whole input, process, and write
+  inputStream.Position := inOff;
+  SetLength(inputData, Length);
+  inputStream.ReadBuffer(inputData[0], Length);
+
+  outputData := DoFinal(inputData, 0, Length);
+
+  outputStream.Position := outOff;
+  if outputData <> nil then
+    outputStream.WriteBuffer(outputData[0], System.Length(outputData));
+end;
+
+function TBufferedAsymmetricBlockCipher.ProcessByte(input: Byte): TCryptoLibByteArray;
+begin
+  if FBufOff >= System.Length(FBuffer) then
+    raise EDataLengthCryptoLibException.CreateRes(@SDataTooLongForCipher);
+
+  FBuffer[FBufOff] := input;
+  Inc(FBufOff);
+  Result := nil;
+end;
+
+function TBufferedAsymmetricBlockCipher.ProcessByte(input: Byte;
+  const output: TCryptoLibByteArray; outOff: Int32): Int32;
+begin
+  if FBufOff >= System.Length(FBuffer) then
+    raise EDataLengthCryptoLibException.CreateRes(@SDataTooLongForCipher);
+
+  FBuffer[FBufOff] := input;
+  Inc(FBufOff);
+  Result := 0;
+end;
+
+function TBufferedAsymmetricBlockCipher.ProcessBytes(const input: TCryptoLibByteArray;
+  inOff, length: Int32): TCryptoLibByteArray;
+begin
+  if length < 1 then
+  begin
+    Result := nil;
+    Exit;
+  end;
+
+  if input = nil then
+    raise EArgumentNilCryptoLibException.Create('input');
+
+  if length > System.Length(FBuffer) - FBufOff then
+    raise EDataLengthCryptoLibException.CreateRes(@SDataTooLongForCipher);
+
+  System.Move(input[inOff], FBuffer[FBufOff], length);
+  Inc(FBufOff, length);
+  Result := nil;
+end;
+
+function TBufferedAsymmetricBlockCipher.ProcessBytes(const input: TCryptoLibByteArray)
+  : TCryptoLibByteArray;
+begin
+  Result := ProcessBytes(input, 0, System.Length(input));
+end;
+
+function TBufferedAsymmetricBlockCipher.ProcessBytes(const input, output: TCryptoLibByteArray;
+  outOff: Int32): Int32;
+begin
+  ProcessBytes(input, 0, System.Length(input));
+  Result := 0;
+end;
+
+function TBufferedAsymmetricBlockCipher.ProcessBytes(const input: TCryptoLibByteArray;
+  inOff, length: Int32; const output: TCryptoLibByteArray; outOff: Int32): Int32;
+begin
+  ProcessBytes(input, inOff, length);
+  Result := 0;
+end;
+
+function TBufferedAsymmetricBlockCipher.DoFinal: TCryptoLibByteArray;
+begin
+  if FBufOff > 0 then
+    Result := FCipher.ProcessBlock(FBuffer, 0, FBufOff)
+  else
+    Result := nil;
+  Reset();
+end;
+
+function TBufferedAsymmetricBlockCipher.DoFinal(const input: TCryptoLibByteArray)
+  : TCryptoLibByteArray;
+begin
+  ProcessBytes(input, 0, System.Length(input));
+  Result := DoFinal();
+end;
+
+function TBufferedAsymmetricBlockCipher.DoFinal(const input: TCryptoLibByteArray;
+  inOff, inLen: Int32): TCryptoLibByteArray;
+begin
+  ProcessBytes(input, inOff, inLen);
+  Result := DoFinal();
+end;
+
+function TBufferedAsymmetricBlockCipher.DoFinal(const output: TCryptoLibByteArray;
+  outOff: Int32): Int32;
+var
+  outBytes: TCryptoLibByteArray;
+begin
+  outBytes := DoFinal();
+  if outBytes <> nil then
+  begin
+    if (System.Length(output) - outOff) < System.Length(outBytes) then
+      raise EDataLengthCryptoLibException.CreateRes(@SOutputBufferTooShort);
+    System.Move(outBytes[0], output[outOff], System.Length(outBytes));
+    Result := System.Length(outBytes);
+  end
+  else
+    Result := 0;
+end;
+
+function TBufferedAsymmetricBlockCipher.DoFinal(const input: TCryptoLibByteArray;
+  const output: TCryptoLibByteArray; outOff: Int32): Int32;
+begin
+  ProcessBytes(input, 0, System.Length(input));
+  Result := DoFinal(output, outOff);
+end;
+
+function TBufferedAsymmetricBlockCipher.DoFinal(const input: TCryptoLibByteArray;
+  inOff, length: Int32; const output: TCryptoLibByteArray; outOff: Int32): Int32;
+begin
+  ProcessBytes(input, inOff, length);
+  Result := DoFinal(output, outOff);
+end;
+
+procedure TBufferedAsymmetricBlockCipher.Reset;
+begin
+  if FBuffer <> nil then
+  begin
+    FillChar(FBuffer[0], System.Length(FBuffer), 0);
+    FBufOff := 0;
+  end;
+end;
+
+end.
+

+ 111 - 19
CryptoLib/src/Crypto/Digests/ClpDigest.pas

@@ -22,6 +22,7 @@ interface
 
 
 uses
 uses
   SysUtils,
   SysUtils,
+  Generics.Collections,
   HlpIHash,
   HlpIHash,
   HlpIHashInfo,
   HlpIHashInfo,
   ClpIDigest,
   ClpIDigest,
@@ -41,11 +42,16 @@ type
   var
   var
     FHash: IHash;
     FHash: IHash;
 
 
-    function GetAlgorithmName: string; inline;
+    class var FNameMap: TDictionary<string, string>;
 
 
-    function DoFinal: TCryptoLibByteArray; overload;
+    class function NormalizeHashLibName(const AName: string): string; static;
+
+    function GetAlgorithmName: string; inline;
 
 
   public
   public
+    class constructor Create;
+    class destructor Destroy;
+
     constructor Create(const hash: IHash; doInitialize: Boolean = True);
     constructor Create(const hash: IHash; doInitialize: Boolean = True);
 
 
     /// <summary>
     /// <summary>
@@ -82,6 +88,8 @@ type
     /// </param>
     /// </param>
     procedure BlockUpdate(const input: TCryptoLibByteArray; inOff, len: Int32);
     procedure BlockUpdate(const input: TCryptoLibByteArray; inOff, len: Int32);
 
 
+    function DoFinal: TCryptoLibByteArray; overload;
+
     /// <summary>
     /// <summary>
     /// Close the digest, producing the final digest value. The doFinal call
     /// Close the digest, producing the final digest value. The doFinal call
     /// leaves the digest reset.
     /// leaves the digest reset.
@@ -116,32 +124,117 @@ implementation
 
 
 { TDigest }
 { TDigest }
 
 
+class constructor TDigest.Create;
+begin
+  FNameMap := TDictionary<string, string>.Create;
+
+  FNameMap.Add('NullDigest', 'NULL');
+
+  FNameMap.Add('Tiger_3_128', 'Tiger');
+  FNameMap.Add('Tiger_3_160', 'Tiger');
+  FNameMap.Add('Tiger_3_192', 'Tiger');
+  FNameMap.Add('Tiger_4_128', 'Tiger');
+  FNameMap.Add('Tiger_4_160', 'Tiger');
+  FNameMap.Add('Tiger_4_192', 'Tiger');
+  FNameMap.Add('Tiger_5_128', 'Tiger');
+  FNameMap.Add('Tiger_5_160', 'Tiger');
+  FNameMap.Add('Tiger_5_192', 'Tiger');
+
+  FNameMap.Add('MD2', 'MD2');
+  FNameMap.Add('MD4', 'MD4');
+  FNameMap.Add('MD5', 'MD5');
+
+  FNameMap.Add('SHA0', 'SHA-0');
+  FNameMap.Add('SHA1', 'SHA-1');
+  FNameMap.Add('SHA2_224', 'SHA-224');
+  FNameMap.Add('SHA2_256', 'SHA-256');
+  FNameMap.Add('SHA2_384', 'SHA-384');
+  FNameMap.Add('SHA2_512', 'SHA-512');
+  FNameMap.Add('SHA2_512_224', 'SHA-512/224');
+  FNameMap.Add('SHA2_512_256', 'SHA-512/256');
+
+  FNameMap.Add('WhirlPool', 'Whirlpool');
+
+  FNameMap.Add('Gost', 'Gost3411');
+
+  FNameMap.Add('GOST3411_2012_256', 'GOST3411-2012-256');
+  FNameMap.Add('GOST3411_2012_512', 'GOST3411-2012-512');
+
+  FNameMap.Add('RIPEMD', 'RIPEMD');
+  FNameMap.Add('RIPEMD128', 'RIPEMD128');
+  FNameMap.Add('RIPEMD160', 'RIPEMD160');
+  FNameMap.Add('RIPEMD256', 'RIPEMD256');
+  FNameMap.Add('RIPEMD320', 'RIPEMD320');
+
+  FNameMap.Add('Keccak_224', 'Keccak-224');
+  FNameMap.Add('Keccak_256', 'Keccak-256');
+  FNameMap.Add('Keccak_288', 'Keccak-288');
+  FNameMap.Add('Keccak_384', 'Keccak-384');
+  FNameMap.Add('Keccak_512', 'Keccak-512');
+
+  FNameMap.Add('SHA3_224', 'SHA3-224');
+  FNameMap.Add('SHA3_256', 'SHA3-256');
+  FNameMap.Add('SHA3_384', 'SHA3-384');
+  FNameMap.Add('SHA3_512', 'SHA3-512');
+
+  FNameMap.Add('Shake_128', 'SHAKE128');
+  FNameMap.Add('Shake_256', 'SHAKE256');
+
+  FNameMap.Add('Blake2B_160', 'BLAKE2b');
+  FNameMap.Add('Blake2B_256', 'BLAKE2b');
+  FNameMap.Add('Blake2B_384', 'BLAKE2b');
+  FNameMap.Add('Blake2B_512', 'BLAKE2b');
+
+  FNameMap.Add('Blake2S_128', 'BLAKE2s');
+  FNameMap.Add('Blake2S_160', 'BLAKE2s');
+  FNameMap.Add('Blake2S_224', 'BLAKE2s');
+  FNameMap.Add('Blake2S_256', 'BLAKE2s');
+
+  FNameMap.Add('Blake3_256', 'BLAKE3');
+end;
+
+class destructor TDigest.Destroy;
+begin
+  FNameMap.Free;
+end;
+
+class function TDigest.NormalizeHashLibName(const AName: string): string;
+begin
+  // HashLib4Pascal names are typically class-like (e.g., "TSHA2_256", "TKeccak_256", ...)
+  if (AName <> '') and (AName[1] = 'T') then
+    Result := Copy(AName, 2, System.Length(AName) - 1)
+  else
+    Result := AName;
+end;
+
 function TDigest.GetAlgorithmName: string;
 function TDigest.GetAlgorithmName: string;
 var
 var
-  LName: String;
-  LowPoint, HighPoint: Int32;
+  LRawName, LNormalized, LMapped: String;
 begin
 begin
-  LName := FHash.Name;
+  LRawName := FHash.Name;
+  LNormalized := NormalizeHashLibName(LRawName);
 
 
-  LowPoint := 1;
-  HighPoint := System.Length(LName);
+  // Default/fallback is the normalized HashLib name (without the leading 'T')
+  Result := LNormalized;
 
 
-  result := Copy(LName, LowPoint + 1, HighPoint - 1);
+  // If we have a canonical CryptoLib name, return it
+  if FNameMap.TryGetValue(Result, LMapped) then
+    Result := LMapped;
 end;
 end;
 
 
 function TDigest.GetByteLength: Int32;
 function TDigest.GetByteLength: Int32;
 begin
 begin
-  result := FHash.BlockSize;
+  Result := FHash.BlockSize;
 end;
 end;
 
 
 function TDigest.GetDigestSize: Int32;
 function TDigest.GetDigestSize: Int32;
 begin
 begin
-  result := FHash.HashSize;
+  Result := FHash.HashSize;
 end;
 end;
 
 
 function TDigest.GetUnderlyingIHash: IHash;
 function TDigest.GetUnderlyingIHash: IHash;
 begin
 begin
-  result := FHash;
+  Result := FHash;
 end;
 end;
 
 
 procedure TDigest.Reset;
 procedure TDigest.Reset;
@@ -149,24 +242,23 @@ begin
   FHash.Initialize;
   FHash.Initialize;
 end;
 end;
 
 
-procedure TDigest.BlockUpdate(const input: TCryptoLibByteArray;
-  inOff, len: Int32);
+procedure TDigest.BlockUpdate(const input: TCryptoLibByteArray; inOff, len: Int32);
 begin
 begin
   FHash.TransformBytes(input, inOff, len);
   FHash.TransformBytes(input, inOff, len);
 end;
 end;
 
 
 constructor TDigest.Create(const hash: IHash; doInitialize: Boolean);
 constructor TDigest.Create(const hash: IHash; doInitialize: Boolean);
 begin
 begin
-  Inherited Create();
+  inherited Create();
   FHash := hash;
   FHash := hash;
+
   if doInitialize then
   if doInitialize then
   begin
   begin
     FHash.Initialize;
     FHash.Initialize;
   end;
   end;
 end;
 end;
 
 
-function TDigest.DoFinal(const output: TCryptoLibByteArray;
-  outOff: Int32): Int32;
+function TDigest.DoFinal(const output: TCryptoLibByteArray; outOff: Int32): Int32;
 var
 var
   buf: TCryptoLibByteArray;
   buf: TCryptoLibByteArray;
   Limit, LXOFSizeInBits: Int32;
   Limit, LXOFSizeInBits: Int32;
@@ -194,12 +286,12 @@ begin
       System.SizeOf(Byte));
       System.SizeOf(Byte));
   end;
   end;
 
 
-  result := System.Length(buf);
+  Result := System.Length(buf);
 end;
 end;
 
 
 function TDigest.DoFinal: TCryptoLibByteArray;
 function TDigest.DoFinal: TCryptoLibByteArray;
 begin
 begin
-  result := FHash.TransformFinal.GetBytes();
+  Result := FHash.TransformFinal.GetBytes();
 end;
 end;
 
 
 procedure TDigest.Update(input: Byte);
 procedure TDigest.Update(input: Byte);
@@ -209,7 +301,7 @@ end;
 
 
 function TDigest.Clone(): IDigest;
 function TDigest.Clone(): IDigest;
 begin
 begin
-  result := TDigest.Create(FHash.Clone(), False);
+  Result := TDigest.Create(FHash.Clone(), False);
 end;
 end;
 
 
 end.
 end.

+ 302 - 0
CryptoLib/src/Crypto/Encodings/ClpISO9796d1Encoding.pas

@@ -0,0 +1,302 @@
+{ *********************************************************************************** }
+{ *                              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 ClpISO9796d1Encoding;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpBigInteger,
+  ClpICipherParameters,
+  ClpParameterUtilities,
+  ClpIRsaKeyParameters,
+  ClpIAsymmetricBlockCipher,
+  ClpIISO9796d1Encoding,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SPadBitsOutOfRange = 'padBits out of range (0-7)';
+  SInvalidForcingByte = 'Invalid forcing byte in block';
+  SInvalidCongruence = 'Resulting integer is not congruent to 6 mod 16';
+  SInvalidTsums = 'Invalid tsums in block';
+
+type
+  /// <summary>
+  /// ISO 9796-1 padding.
+  /// you should only use this with RSA and never use it with anything other than a hash.
+  /// </summary>
+  TISO9796d1Encoding = class(TInterfacedObject, IAsymmetricBlockCipher, IISO9796d1Encoding)
+
+  strict private
+  const
+    Shadows: array[0..15] of Byte = (14, 3, 5, 8, 9, 4, 2, 15, 0, 13, 11, 6, 7, 10, 12, 1);
+    Inverse: array[0..15] of Byte = (8, 15, 6, 1, 5, 2, 11, 12, 3, 4, 13, 10, 14, 9, 0, 7);
+
+  var
+    FCipher: IAsymmetricBlockCipher;
+    FForEncryption: Boolean;
+    FBitSize: Int32;
+    FPadBits: Int32;
+    FModulus: TBigInteger;
+
+    function EncodeBlock(const input: TCryptoLibByteArray;
+      inOff, inLen: Int32): TCryptoLibByteArray;
+    function DecodeBlock(const input: TCryptoLibByteArray;
+      inOff, inLen: Int32): TCryptoLibByteArray;
+
+  strict protected
+    function GetAlgorithmName: String;
+    function GetInputBlockSize: Int32;
+    function GetOutputBlockSize: Int32;
+    function GetUnderlyingCipher: IAsymmetricBlockCipher;
+    function GetPadBits: Int32;
+    procedure SetPadBits(padBits: Int32);
+
+  public
+    constructor Create(const cipher: IAsymmetricBlockCipher);
+
+    procedure Init(forEncryption: Boolean; const parameters: ICipherParameters);
+    function ProcessBlock(const inBuf: TCryptoLibByteArray;
+      inOff, inLen: Int32): TCryptoLibByteArray;
+
+    property AlgorithmName: String read GetAlgorithmName;
+    property InputBlockSize: Int32 read GetInputBlockSize;
+    property OutputBlockSize: Int32 read GetOutputBlockSize;
+    property UnderlyingCipher: IAsymmetricBlockCipher read GetUnderlyingCipher;
+    property PadBits: Int32 read GetPadBits write SetPadBits;
+
+  end;
+
+implementation
+
+{ TISO9796d1Encoding }
+
+constructor TISO9796d1Encoding.Create(const cipher: IAsymmetricBlockCipher);
+begin
+  inherited Create();
+  FCipher := cipher;
+  FPadBits := 0;
+end;
+
+function TISO9796d1Encoding.GetAlgorithmName: String;
+begin
+  Result := FCipher.AlgorithmName + '/ISO9796-1Padding';
+end;
+
+function TISO9796d1Encoding.GetUnderlyingCipher: IAsymmetricBlockCipher;
+begin
+  Result := FCipher;
+end;
+
+function TISO9796d1Encoding.GetPadBits: Int32;
+begin
+  Result := FPadBits;
+end;
+
+procedure TISO9796d1Encoding.SetPadBits(padBits: Int32);
+begin
+  if (padBits < 0) or (padBits > 7) then
+  begin
+    raise EArgumentOutOfRangeCryptoLibException.CreateRes(@SPadBitsOutOfRange);
+  end;
+  FPadBits := padBits;
+end;
+
+procedure TISO9796d1Encoding.Init(forEncryption: Boolean;
+  const parameters: ICipherParameters);
+var
+  kParam: IRsaKeyParameters;
+  LParameters: ICipherParameters;
+begin
+  LParameters := parameters;
+
+  FCipher.Init(forEncryption, LParameters);
+
+  LParameters := TParameterUtilities.IgnoreRandom(LParameters);
+
+  kParam := LParameters as IRsaKeyParameters;
+  FModulus := kParam.Modulus;
+  FBitSize := FModulus.BitLength;
+  FForEncryption := forEncryption;
+end;
+
+function TISO9796d1Encoding.GetInputBlockSize: Int32;
+begin
+  if FForEncryption then
+    Result := (FCipher.InputBlockSize + 1) div 2
+  else
+    Result := FCipher.InputBlockSize;
+end;
+
+function TISO9796d1Encoding.GetOutputBlockSize: Int32;
+begin
+  if FForEncryption then
+    Result := FCipher.OutputBlockSize
+  else
+    Result := (FCipher.OutputBlockSize + 1) div 2;
+end;
+
+function TISO9796d1Encoding.ProcessBlock(const inBuf: TCryptoLibByteArray;
+  inOff, inLen: Int32): TCryptoLibByteArray;
+begin
+  if FForEncryption then
+    Result := EncodeBlock(inBuf, inOff, inLen)
+  else
+    Result := DecodeBlock(inBuf, inOff, inLen);
+end;
+
+function TISO9796d1Encoding.EncodeBlock(const input: TCryptoLibByteArray;
+  inOff, inLen: Int32): TCryptoLibByteArray;
+var
+  block: TCryptoLibByteArray;
+  r, z, t, i, maxBit, offset: Int32;
+  val: Byte;
+begin
+  SetLength(block, (FBitSize + 7) div 8);
+  r := FPadBits + 1;
+  z := inLen;
+  t := (FBitSize + 13) div 16;
+
+  i := 0;
+  while i < t do
+  begin
+    if i > t - z then
+    begin
+      Move(input[inOff + z - (t - i)],
+        block[Length(block) - t], t - i);
+    end
+    else
+    begin
+      Move(input[inOff],
+        block[Length(block) - (i + z)], z);
+    end;
+    Inc(i, z);
+  end;
+
+  i := Length(block) - 2 * t;
+  while i < Length(block) do
+  begin
+    val := block[Length(block) - t + i div 2];
+    block[i] := Byte((Shadows[val shr 4] shl 4) or Shadows[val and $0F]);
+    block[i + 1] := val;
+    Inc(i, 2);
+  end;
+
+  block[Length(block) - 2 * z] :=
+    block[Length(block) - 2 * z] xor Byte(r);
+  block[Length(block) - 1] :=
+    Byte((block[Length(block) - 1] shl 4) or $06);
+
+  maxBit := 8 - ((FBitSize - 1) mod 8);
+  offset := 0;
+
+  if maxBit <> 8 then
+  begin
+    block[0] := block[0] and Byte($FF shr maxBit);
+    block[0] := block[0] or Byte($80 shr maxBit);
+  end
+  else
+  begin
+    block[0] := $00;
+    block[1] := block[1] or $80;
+    offset := 1;
+  end;
+
+  Result := FCipher.ProcessBlock(block, offset, Length(block) - offset);
+end;
+
+function TISO9796d1Encoding.DecodeBlock(const input: TCryptoLibByteArray;
+  inOff, inLen: Int32): TCryptoLibByteArray;
+var
+  block, nblock: TCryptoLibByteArray;
+  r, t, i, val, x, boundary: Int32;
+  &iS, iR: TBigInteger;
+  boundaryFound: Boolean;
+begin
+  block := FCipher.ProcessBlock(input, inOff, inLen);
+  r := 1;
+  t := (FBitSize + 13) div 16;
+
+  &iS := TBigInteger.Create(1, block);
+
+  if (&iS.Int32Value and 15) = 6 then
+  begin
+    iR := &iS;
+  end
+  else
+  begin
+    iR := FModulus.Subtract(&iS);
+    if (iR.Int32Value and 15) <> 6 then
+    begin
+      raise EInvalidCipherTextCryptoLibException.CreateRes(@SInvalidCongruence);
+    end;
+  end;
+
+  block := iR.ToByteArrayUnsigned();
+
+  if (block[Length(block) - 1] and $F) <> $6 then
+  begin
+    raise EInvalidCipherTextCryptoLibException.CreateRes(@SInvalidForcingByte);
+  end;
+
+  block[Length(block) - 1] := Byte(
+    (block[Length(block) - 1] shr 4) or
+    (Inverse[block[Length(block) - 2] shr 4] shl 4));
+
+  block[0] := Byte(
+    (Shadows[block[1] shr 4] shl 4) or
+    Shadows[block[1] and $0F]);
+
+  boundaryFound := False;
+  boundary := 0;
+
+  i := Length(block) - 1;
+  while i >= Length(block) - 2 * t do
+  begin
+    val := (Shadows[block[i] shr 4] shl 4) or Shadows[block[i] and $0F];
+    x := val xor block[i - 1];
+
+    if x <> 0 then
+    begin
+      if boundaryFound then
+      begin
+        raise EInvalidCipherTextCryptoLibException.CreateRes(@SInvalidTsums);
+      end;
+      boundaryFound := True;
+      r := x;
+      boundary := i - 1;
+    end;
+
+    Dec(i, 2);
+  end;
+
+  block[boundary] := 0;
+
+  SetLength(nblock, (Length(block) - boundary) div 2);
+  for i := 0 to Length(nblock) - 1 do
+  begin
+    nblock[i] := block[2 * i + boundary + 1];
+  end;
+
+  FPadBits := r - 1;
+  Result := nblock;
+end;
+
+end.

+ 360 - 0
CryptoLib/src/Crypto/Encodings/ClpOaepEncoding.pas

@@ -0,0 +1,360 @@
+{ *********************************************************************************** }
+{ *                              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 ClpOaepEncoding;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpBits,
+  ClpICipherParameters,
+  ClpIParametersWithRandom,
+  ClpIDigest,
+  ClpDigestUtilities,
+  ClpIAsymmetricBlockCipher,
+  ClpIOaepEncoding,
+  ClpISecureRandom,
+  ClpSecureRandom,
+  ClpCryptoLibTypes,
+  ClpConverters;
+
+resourcestring
+  SInputDataTooLong = 'Input data too long';
+  SDataWrong = 'Data wrong';
+
+type
+  /// <summary>
+  /// Optimal Asymmetric Encryption Padding (OAEP) - see PKCS #1 V 2.
+  /// </summary>
+  TOaepEncoding = class(TInterfacedObject, IAsymmetricBlockCipher, IOaepEncoding)
+
+  strict private
+  var
+    FEngine: IAsymmetricBlockCipher;
+    FMgf1Hash: IDigest;
+    FDefHash: TCryptoLibByteArray;
+    FRandom: ISecureRandom;
+    FForEncryption: Boolean;
+
+    function EncodeBlock(const inBytes: TCryptoLibByteArray;
+      inOff, inLen: Int32): TCryptoLibByteArray;
+    function DecodeBlock(const inBytes: TCryptoLibByteArray;
+      inOff, inLen: Int32): TCryptoLibByteArray;
+
+    procedure MaskGeneratorFunction(
+      const z: TCryptoLibByteArray; zOff, zLen: Int32;
+      const mask: TCryptoLibByteArray; maskOff, maskLen: Int32);
+
+    function GetReducedBlockSize(blockSize: Int32): Int32; inline;
+
+  strict protected
+    function GetAlgorithmName: String;
+    function GetInputBlockSize: Int32;
+    function GetOutputBlockSize: Int32;
+    function GetUnderlyingCipher: IAsymmetricBlockCipher;
+
+  public
+    constructor Create(const cipher: IAsymmetricBlockCipher); overload;
+    constructor Create(const cipher: IAsymmetricBlockCipher;
+      const hash: IDigest); overload;
+    constructor Create(const cipher: IAsymmetricBlockCipher;
+      const hash: IDigest;
+      const encodingParams: TCryptoLibByteArray); overload;
+    constructor Create(const cipher: IAsymmetricBlockCipher;
+      const hash, mgf1Hash: IDigest;
+      const encodingParams: TCryptoLibByteArray); overload;
+
+    procedure Init(forEncryption: Boolean; const parameters: ICipherParameters);
+    function ProcessBlock(const inBuf: TCryptoLibByteArray;
+      inOff, inLen: Int32): TCryptoLibByteArray;
+
+    property AlgorithmName: String read GetAlgorithmName;
+    property InputBlockSize: Int32 read GetInputBlockSize;
+    property OutputBlockSize: Int32 read GetOutputBlockSize;
+    property UnderlyingCipher: IAsymmetricBlockCipher read GetUnderlyingCipher;
+
+  end;
+
+implementation
+
+{ TOaepEncoding }
+
+constructor TOaepEncoding.Create(const cipher: IAsymmetricBlockCipher);
+begin
+  Create(cipher, TDigestUtilities.GetDigest('SHA-1'), nil);
+end;
+
+constructor TOaepEncoding.Create(const cipher: IAsymmetricBlockCipher;
+  const hash: IDigest);
+begin
+  Create(cipher, hash, nil);
+end;
+
+constructor TOaepEncoding.Create(const cipher: IAsymmetricBlockCipher;
+  const hash: IDigest; const encodingParams: TCryptoLibByteArray);
+begin
+  Create(cipher, hash, hash, encodingParams);
+end;
+
+constructor TOaepEncoding.Create(const cipher: IAsymmetricBlockCipher;
+  const hash, mgf1Hash: IDigest; const encodingParams: TCryptoLibByteArray);
+begin
+  inherited Create();
+  FEngine := cipher;
+  FMgf1Hash := mgf1Hash;
+  SetLength(FDefHash, hash.GetDigestSize);
+
+  hash.Reset();
+  if encodingParams <> nil then
+  begin
+    hash.BlockUpdate(encodingParams, 0, System.Length(encodingParams));
+  end;
+  hash.DoFinal(FDefHash, 0);
+end;
+
+function TOaepEncoding.GetAlgorithmName: String;
+begin
+  Result := FEngine.AlgorithmName + '/OAEPPadding';
+end;
+
+function TOaepEncoding.GetUnderlyingCipher: IAsymmetricBlockCipher;
+begin
+  Result := FEngine;
+end;
+
+procedure TOaepEncoding.Init(forEncryption: Boolean;
+  const parameters: ICipherParameters);
+var
+  rndParam: IParametersWithRandom;
+begin
+  if Supports(parameters, IParametersWithRandom, rndParam) then
+    FRandom := rndParam.Random
+  else
+    FRandom := TSecureRandom.Create();
+
+  FForEncryption := forEncryption;
+  FEngine.Init(forEncryption, parameters);
+end;
+
+function TOaepEncoding.GetReducedBlockSize(blockSize: Int32): Int32;
+begin
+  Result := blockSize - 1 - 2 * System.Length(FDefHash);
+end;
+
+function TOaepEncoding.GetInputBlockSize: Int32;
+begin
+  if FForEncryption then
+    Result := GetReducedBlockSize(FEngine.InputBlockSize)
+  else
+    Result := FEngine.InputBlockSize;
+end;
+
+function TOaepEncoding.GetOutputBlockSize: Int32;
+begin
+  if FForEncryption then
+    Result := FEngine.OutputBlockSize
+  else
+    Result := GetReducedBlockSize(FEngine.OutputBlockSize);
+end;
+
+function TOaepEncoding.ProcessBlock(const inBuf: TCryptoLibByteArray;
+  inOff, inLen: Int32): TCryptoLibByteArray;
+begin
+  if FForEncryption then
+    Result := EncodeBlock(inBuf, inOff, inLen)
+  else
+    Result := DecodeBlock(inBuf, inOff, inLen);
+end;
+
+function TOaepEncoding.EncodeBlock(const inBytes: TCryptoLibByteArray;
+  inOff, inLen: Int32): TCryptoLibByteArray;
+var
+  inBlockSize, defHashLen: Int32;
+  block: TCryptoLibByteArray;
+begin
+  inBlockSize := FEngine.InputBlockSize;
+  defHashLen := System.Length(FDefHash);
+
+  if inLen > GetReducedBlockSize(inBlockSize) then
+  begin
+    raise EDataLengthCryptoLibException.CreateRes(@SInputDataTooLong);
+  end;
+
+  SetLength(block, inBlockSize);
+
+  // Copy in the message
+  System.Move(inBytes[inOff], block[System.Length(block) - inLen], inLen);
+
+  // Add sentinel
+  block[System.Length(block) - inLen - 1] := $01;
+
+  // Add the hash of the encoding params
+  System.Move(FDefHash[0], block[defHashLen], defHashLen);
+
+  // Generate the seed (random bytes in first defHashLen bytes)
+  FRandom.NextBytes(block, 0, defHashLen);
+
+  FMgf1Hash.Reset();
+
+  // Mask the message block (DB)
+  MaskGeneratorFunction(block, 0, defHashLen,
+    block, defHashLen, System.Length(block) - defHashLen);
+
+  // Mask the seed
+  MaskGeneratorFunction(block, defHashLen, System.Length(block) - defHashLen,
+    block, 0, defHashLen);
+
+  Result := FEngine.ProcessBlock(block, 0, System.Length(block));
+end;
+
+function TOaepEncoding.DecodeBlock(const inBytes: TCryptoLibByteArray;
+  inOff, inLen: Int32): TCryptoLibByteArray;
+var
+  outBlockSize, defHashLen, wrongMask, copyLen: Int32;
+  block, data: TCryptoLibByteArray;
+  start, index, octet, shouldSetMask: Int32;
+  i: Int32;
+begin
+  outBlockSize := FEngine.OutputBlockSize;
+  defHashLen := System.Length(FDefHash);
+
+  // Check reduced block size is valid
+  wrongMask := TBits.Asr32(GetReducedBlockSize(outBlockSize), 31);
+
+  SetLength(block, outBlockSize);
+  data := FEngine.ProcessBlock(inBytes, inOff, inLen);
+
+  wrongMask := wrongMask or TBits.Asr32((System.Length(block) - System.Length(data)), 31);
+
+  copyLen := System.Length(data);
+  if copyLen > System.Length(block) then
+    copyLen := System.Length(block);
+
+  System.Move(data[0], block[System.Length(block) - copyLen], copyLen);
+  FillChar(data[0], System.Length(data), 0);
+
+  FMgf1Hash.Reset();
+
+  // Unmask the seed
+  MaskGeneratorFunction(block, defHashLen, System.Length(block) - defHashLen,
+    block, 0, defHashLen);
+
+  // Unmask the message block
+  MaskGeneratorFunction(block, 0, defHashLen,
+    block, defHashLen, System.Length(block) - defHashLen);
+
+  // Check the hash of the encoding params (constant time)
+  for i := 0 to defHashLen - 1 do
+  begin
+    wrongMask := wrongMask or (FDefHash[i] xor block[defHashLen + i]);
+  end;
+
+  // Find the data block
+  start := -1;
+  for index := 2 * defHashLen to System.Length(block) - 1 do
+  begin
+    octet := block[index];
+    // Mask will be 0xFFFFFFFF if octet is non-zero and start is (still) negative
+    shouldSetMask := TBits.Asr32((-octet) and start, 31);
+    start := start + (index and shouldSetMask);
+  end;
+
+  wrongMask := wrongMask or TBits.Asr32(start, 31);
+  Inc(start);
+  wrongMask := wrongMask or (block[start] xor 1);
+
+  if wrongMask <> 0 then
+  begin
+    FillChar(block[0], System.Length(block), 0);
+    raise EInvalidCipherTextCryptoLibException.CreateRes(@SDataWrong);
+  end;
+
+  Inc(start);
+
+  // Extract the data block
+  SetLength(Result, System.Length(block) - start);
+  System.Move(block[start], Result[0], System.Length(Result));
+  FillChar(block[0], System.Length(block), 0);
+end;
+
+procedure TOaepEncoding.MaskGeneratorFunction(
+  const z: TCryptoLibByteArray; zOff, zLen: Int32;
+  const mask: TCryptoLibByteArray; maskOff, maskLen: Int32);
+var
+  digestSize, counter, maskPos, maskEnd, maskLimit, xorLen: Int32;
+  hash, C: TCryptoLibByteArray;
+  i: Int32;
+begin
+  digestSize := FMgf1Hash.GetDigestSize;
+  SetLength(hash, digestSize);
+  SetLength(C, 4);
+  counter := 0;
+
+  maskEnd := maskOff + maskLen;
+  maskLimit := maskEnd - digestSize;
+  maskPos := maskOff;
+
+  // Note: we are re-hashing z on each iteration. Our approach recomputes Hash(z || counter) each time.
+
+  while maskPos < maskLimit do
+  begin
+    // C = I2OSP(counter, 4)
+    C[0] := Byte(counter shr 24);
+    C[1] := Byte(counter shr 16);
+    C[2] := Byte(counter shr 8);
+    C[3] := Byte(counter);
+
+    FMgf1Hash.Reset();
+    FMgf1Hash.BlockUpdate(z, zOff, zLen);
+    FMgf1Hash.BlockUpdate(C, 0, 4);
+    FMgf1Hash.DoFinal(hash, 0);
+
+    // XOR hash with mask
+    for i := 0 to digestSize - 1 do
+    begin
+      mask[maskPos + i] := mask[maskPos + i] xor hash[i];
+    end;
+
+    Inc(maskPos, digestSize);
+    Inc(counter);
+  end;
+
+  // Handle remaining bytes
+  if maskPos < maskEnd then
+  begin
+    C[0] := Byte(counter shr 24);
+    C[1] := Byte(counter shr 16);
+    C[2] := Byte(counter shr 8);
+    C[3] := Byte(counter);
+
+    FMgf1Hash.Reset();
+    FMgf1Hash.BlockUpdate(z, zOff, zLen);
+    FMgf1Hash.BlockUpdate(C, 0, 4);
+    FMgf1Hash.DoFinal(hash, 0);
+
+    xorLen := maskEnd - maskPos;
+    for i := 0 to xorLen - 1 do
+    begin
+      mask[maskPos + i] := mask[maskPos + i] xor hash[i];
+    end;
+  end;
+end;
+
+end.

+ 447 - 0
CryptoLib/src/Crypto/Encodings/ClpPkcs1Encoding.pas

@@ -0,0 +1,447 @@
+{ *********************************************************************************** }
+{ *                              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 ClpPkcs1Encoding;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  Math,
+  ClpBits,
+  ClpICipherParameters,
+  ClpIParametersWithRandom,
+  ClpIAsymmetricKeyParameter,
+  ClpIAsymmetricBlockCipher,
+  ClpIPkcs1Encoding,
+  ClpISecureRandom,
+  ClpSecureRandom,
+  ClpParameterUtilities,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SInputDataTooLarge = 'Input data too large';
+  SBlockIncorrect = 'Block incorrect';
+  SBlockIncorrectSize = 'Block incorrect size';
+  SDecryptionOnly = 'This method is only for decryption, not for signing';
+
+type
+  /// <summary>
+  /// PKCS#1 v1.5 padding.
+  /// Type 1 (0x01) for private key operations (signing).
+  /// Type 2 (0x02) for public key operations (encryption).
+  /// </summary>
+  TPkcs1Encoding = class(TInterfacedObject, IAsymmetricBlockCipher, IPkcs1Encoding)
+
+  strict private
+  const
+    HeaderLength = 10;
+
+  class var
+    FStrictLengthEnabled: Boolean;
+
+  var
+    FEngine: IAsymmetricBlockCipher;
+    FRandom: ISecureRandom;
+    FForEncryption: Boolean;
+    FForPrivateKey: Boolean;
+    FUseStrictLength: Boolean;
+    FPLen: Int32;
+    FFallback: TCryptoLibByteArray;
+    FBlockBuffer: TCryptoLibByteArray;
+
+    function EncodeBlock(const input: TCryptoLibByteArray;
+      inOff, inLen: Int32): TCryptoLibByteArray;
+    function DecodeBlock(const input: TCryptoLibByteArray;
+      inOff, inLen: Int32): TCryptoLibByteArray;
+    function DecodeBlockOrRandom(const input: TCryptoLibByteArray;
+      inOff, inLen: Int32): TCryptoLibByteArray;
+
+    class function CheckPkcs1Encoding1(const buf: TCryptoLibByteArray): Int32; static;
+    class function CheckPkcs1Encoding2(const buf: TCryptoLibByteArray): Int32; overload; static;
+    class function CheckPkcs1Encoding2(const buf: TCryptoLibByteArray;
+      plaintextLength: Int32): Int32; overload; static;
+
+  strict protected
+    function GetAlgorithmName: String;
+    function GetInputBlockSize: Int32;
+    function GetOutputBlockSize: Int32;
+    function GetUnderlyingCipher: IAsymmetricBlockCipher;
+
+  public
+    class constructor CreatePkcs1Encoding;
+
+    constructor Create(const cipher: IAsymmetricBlockCipher); overload;
+    constructor Create(const cipher: IAsymmetricBlockCipher; pLen: Int32); overload;
+    constructor Create(const cipher: IAsymmetricBlockCipher;
+      const fallback: TCryptoLibByteArray); overload;
+
+    procedure Init(forEncryption: Boolean; const parameters: ICipherParameters);
+    function ProcessBlock(const inBuf: TCryptoLibByteArray;
+      inOff, inLen: Int32): TCryptoLibByteArray;
+
+    class property StrictLengthEnabled: Boolean read FStrictLengthEnabled
+      write FStrictLengthEnabled;
+
+    property AlgorithmName: String read GetAlgorithmName;
+    property InputBlockSize: Int32 read GetInputBlockSize;
+    property OutputBlockSize: Int32 read GetOutputBlockSize;
+    property UnderlyingCipher: IAsymmetricBlockCipher read GetUnderlyingCipher;
+
+  end;
+
+implementation
+
+{ TPkcs1Encoding }
+
+class constructor TPkcs1Encoding.CreatePkcs1Encoding;
+begin
+  FStrictLengthEnabled := True;
+end;
+
+constructor TPkcs1Encoding.Create(const cipher: IAsymmetricBlockCipher);
+begin
+  inherited Create();
+  FEngine := cipher;
+  FUseStrictLength := FStrictLengthEnabled;
+  FPLen := -1;
+  FFallback := nil;
+end;
+
+constructor TPkcs1Encoding.Create(const cipher: IAsymmetricBlockCipher; pLen: Int32);
+begin
+  inherited Create();
+  FEngine := cipher;
+  FUseStrictLength := FStrictLengthEnabled;
+  FPLen := pLen;
+  FFallback := nil;
+end;
+
+constructor TPkcs1Encoding.Create(const cipher: IAsymmetricBlockCipher;
+  const fallback: TCryptoLibByteArray);
+begin
+  inherited Create();
+  FEngine := cipher;
+  FUseStrictLength := FStrictLengthEnabled;
+  FFallback := fallback;
+  FPLen := System.Length(fallback);
+end;
+
+function TPkcs1Encoding.GetAlgorithmName: String;
+begin
+  Result := FEngine.AlgorithmName + '/PKCS1Padding';
+end;
+
+function TPkcs1Encoding.GetUnderlyingCipher: IAsymmetricBlockCipher;
+begin
+  Result := FEngine;
+end;
+
+procedure TPkcs1Encoding.Init(forEncryption: Boolean;
+  const parameters: ICipherParameters);
+var
+  kParam: IAsymmetricKeyParameter;
+  LParameters: ICipherParameters;
+  providedRandom: ISecureRandom;
+  NeedsRandom: Boolean;
+begin
+  FEngine.Init(forEncryption, parameters);
+
+  LParameters := TParameterUtilities.GetRandom(parameters, providedRandom);
+
+  kParam := LParameters as IAsymmetricKeyParameter;
+  FForPrivateKey := kParam.IsPrivate;
+  FForEncryption := forEncryption;
+  SetLength(FBlockBuffer, FEngine.OutputBlockSize);
+
+  if FForPrivateKey then
+    NeedsRandom := (FPLen <> -1) and (FFallback = nil)
+  else
+    NeedsRandom := FForEncryption;
+
+  if NeedsRandom then
+  begin
+    if providedRandom <> nil then
+      FRandom := providedRandom
+    else
+      FRandom := TSecureRandom.Create();
+  end
+  else
+    FRandom := nil;
+end;
+
+function TPkcs1Encoding.GetInputBlockSize: Int32;
+begin
+  if FForEncryption then
+    Result := FEngine.InputBlockSize - HeaderLength
+  else
+    Result := FEngine.InputBlockSize;
+end;
+
+function TPkcs1Encoding.GetOutputBlockSize: Int32;
+begin
+  if FForEncryption then
+    Result := FEngine.OutputBlockSize
+  else
+    Result := FEngine.OutputBlockSize - HeaderLength;
+end;
+
+function TPkcs1Encoding.ProcessBlock(const inBuf: TCryptoLibByteArray;
+  inOff, inLen: Int32): TCryptoLibByteArray;
+begin
+  if FForEncryption then
+    Result := EncodeBlock(inBuf, inOff, inLen)
+  else
+    Result := DecodeBlock(inBuf, inOff, inLen);
+end;
+
+function TPkcs1Encoding.EncodeBlock(const input: TCryptoLibByteArray;
+  inOff, inLen: Int32): TCryptoLibByteArray;
+var
+  blockSize, lastPadPos, i: Int32;
+  block: TCryptoLibByteArray;
+begin
+  blockSize := FEngine.InputBlockSize;
+
+  if inLen > (blockSize - HeaderLength) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SInputDataTooLarge);
+  end;
+
+  SetLength(block, blockSize);
+  lastPadPos := blockSize - 1 - inLen;
+
+  if FForPrivateKey then
+  begin
+    // Type 1
+    block[0] := $01;
+    for i := 1 to lastPadPos - 1 do
+    begin
+      block[i] := $FF;
+    end;
+  end
+  else
+  begin
+    // Type 2 - random fill
+    FRandom.NextBytes(block, 0, blockSize);
+    block[0] := $02;
+
+    // A zero byte marks the end of the padding, so all pad bytes must be non-zero
+    for i := 1 to lastPadPos - 1 do
+    begin
+      while block[i] = 0 do
+      begin
+        block[i] := Byte(FRandom.NextInt32);
+      end;
+    end;
+  end;
+
+  // Mark the end of the padding
+  block[lastPadPos] := $00;
+
+  // Copy the data
+  System.Move(input[inOff], block[blockSize - inLen], inLen);
+
+  Result := FEngine.ProcessBlock(block, 0, blockSize);
+end;
+
+class function TPkcs1Encoding.CheckPkcs1Encoding1(
+  const buf: TCryptoLibByteArray): Int32;
+var
+  i, foundZeroMask, lastPadPos, badPadSign: Int32;
+  padByte, is0x00Mask, is0xFFMask: Int32;
+  plaintextLength: Int32;
+begin
+  foundZeroMask := 0;
+  lastPadPos := 0;
+
+  // The first byte should be 0x01
+  badPadSign := -(buf[0] xor $01);
+
+  // There must be a zero terminator for the padding somewhere
+  for i := 1 to System.Length(buf) - 1 do
+  begin
+    padByte := buf[i];
+    is0x00Mask := TBits.Asr32((padByte xor $00) - 1, 31);
+    is0xFFMask := TBits.Asr32((padByte xor $FF) - 1, 31);
+    lastPadPos := lastPadPos xor (i and (not foundZeroMask) and is0x00Mask);
+    foundZeroMask := foundZeroMask or is0x00Mask;
+    badPadSign := badPadSign or (not (foundZeroMask or is0xFFMask));
+  end;
+
+  // The header should be at least 10 bytes
+  badPadSign := badPadSign or (lastPadPos - 9);
+
+  plaintextLength := System.Length(buf) - 1 - lastPadPos;
+  Result := plaintextLength or TBits.Asr32(badPadSign, 31);
+end;
+
+class function TPkcs1Encoding.CheckPkcs1Encoding2(
+  const buf: TCryptoLibByteArray): Int32;
+var
+  i, foundZeroMask, lastPadPos, badPadSign: Int32;
+  padByte, is0x00Mask: Int32;
+  plaintextLength: Int32;
+begin
+  foundZeroMask := 0;
+  lastPadPos := 0;
+
+  // The first byte should be 0x02
+  badPadSign := -(buf[0] xor $02);
+
+  // There must be a zero terminator for the padding somewhere
+  for i := 1 to System.Length(buf) - 1 do
+  begin
+    padByte := buf[i];
+    is0x00Mask := TBits.Asr32((padByte xor $00) - 1, 31);
+    lastPadPos := lastPadPos xor (i and (not foundZeroMask) and is0x00Mask);
+    foundZeroMask := foundZeroMask or is0x00Mask;
+  end;
+
+  // The header should be at least 10 bytes
+  badPadSign := badPadSign or (lastPadPos - 9);
+
+  plaintextLength := System.Length(buf) - 1 - lastPadPos;
+  Result := plaintextLength or TBits.Asr32(badPadSign, 31);
+end;
+
+class function TPkcs1Encoding.CheckPkcs1Encoding2(
+  const buf: TCryptoLibByteArray; plaintextLength: Int32): Int32;
+var
+  i, badPadSign, lastPadPos: Int32;
+begin
+  // The first byte should be 0x02
+  badPadSign := -(buf[0] xor $02);
+  lastPadPos := System.Length(buf) - 1 - plaintextLength;
+
+  // The header should be at least 10 bytes
+  badPadSign := badPadSign or (lastPadPos - 9);
+
+  // All pad bytes before the last one should be non-zero
+  for i := 1 to lastPadPos - 1 do
+  begin
+    badPadSign := badPadSign or (buf[i] - 1);
+  end;
+
+  // Last pad byte should be zero
+  badPadSign := badPadSign or (-buf[lastPadPos]);
+
+  Result := TBits.Asr32(badPadSign, 31);
+end;
+
+function TPkcs1Encoding.DecodeBlockOrRandom(const input: TCryptoLibByteArray;
+  inOff, inLen: Int32): TCryptoLibByteArray;
+var
+  plaintextLength, strictBlockSize, badPadMask, dataOff, i: Int32;
+  randomBytes, block, data: TCryptoLibByteArray;
+begin
+  if not FForPrivateKey then
+  begin
+    raise EInvalidCipherTextCryptoLibException.CreateRes(@SDecryptionOnly);
+  end;
+
+  plaintextLength := FPLen;
+
+  if FFallback <> nil then
+    randomBytes := FFallback
+  else
+  begin
+    SetLength(randomBytes, plaintextLength);
+    FRandom.NextBytes(randomBytes);
+  end;
+
+  badPadMask := 0;
+  strictBlockSize := FEngine.OutputBlockSize;
+  block := FEngine.ProcessBlock(input, inOff, inLen);
+
+  data := block;
+  if System.Length(block) <> strictBlockSize then
+  begin
+    if FUseStrictLength or (System.Length(block) < strictBlockSize) then
+    begin
+      data := FBlockBuffer;
+    end;
+  end;
+
+  badPadMask := badPadMask or CheckPkcs1Encoding2(data, plaintextLength);
+
+  // Constant time copy
+  dataOff := System.Length(data) - plaintextLength;
+  SetLength(Result, plaintextLength);
+  for i := 0 to plaintextLength - 1 do
+  begin
+    Result[i] := Byte((data[dataOff + i] and (not badPadMask)) or
+      (randomBytes[i] and badPadMask));
+  end;
+
+  // Clear sensitive data
+  FillChar(block[0], System.Length(block), 0);
+end;
+
+function TPkcs1Encoding.DecodeBlock(const input: TCryptoLibByteArray;
+  inOff, inLen: Int32): TCryptoLibByteArray;
+var
+  strictBlockSize, plaintextLength: Int32;
+  incorrectLength: Boolean;
+  block, data: TCryptoLibByteArray;
+begin
+  // If expected plaintext length is known, use constant-time decryption
+  if FForPrivateKey and (FPLen <> -1) then
+  begin
+    Result := DecodeBlockOrRandom(input, inOff, inLen);
+    Exit;
+  end;
+
+  strictBlockSize := FEngine.OutputBlockSize;
+  block := FEngine.ProcessBlock(input, inOff, inLen);
+
+  incorrectLength := FUseStrictLength and (System.Length(block) <> strictBlockSize);
+
+  data := block;
+  if System.Length(block) < strictBlockSize then
+  begin
+    data := FBlockBuffer;
+  end;
+
+  if FForPrivateKey then
+    plaintextLength := CheckPkcs1Encoding2(data)
+  else
+    plaintextLength := CheckPkcs1Encoding1(data);
+
+  try
+    if plaintextLength < 0 then
+    begin
+      raise EInvalidCipherTextCryptoLibException.CreateRes(@SBlockIncorrect);
+    end;
+
+    if incorrectLength then
+    begin
+      raise EInvalidCipherTextCryptoLibException.CreateRes(@SBlockIncorrectSize);
+    end;
+
+    SetLength(Result, plaintextLength);
+    System.Move(data[System.Length(data) - plaintextLength], Result[0], plaintextLength);
+  finally
+    // Clear sensitive data
+    FillChar(block[0], System.Length(block), 0);
+    FillChar(FBlockBuffer[0], Math.Max(0, System.Length(FBlockBuffer) - System.Length(block)), 0);
+  end;
+end;
+
+end.

+ 186 - 0
CryptoLib/src/Crypto/Engines/ClpRsaBlindedEngine.pas

@@ -0,0 +1,186 @@
+{ *********************************************************************************** }
+{ *                              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 ClpRsaBlindedEngine;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpBigInteger,
+  ClpBigIntegers,
+  ClpICipherParameters,
+  ClpIParametersWithRandom,
+  ClpIRsaKeyParameters,
+  ClpIRsaPrivateCrtKeyParameters,
+  ClpIRsa,
+  ClpIAsymmetricBlockCipher,
+  ClpIRsaBlindedEngine,
+  ClpIRsaCoreEngine,
+  ClpRsaCoreEngine,
+  ClpISecureRandom,
+  ClpSecureRandom,
+  ClpParameterUtilities,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SRsaEngineNotInitialised = 'RSA engine not initialised';
+
+type
+  /// <summary>
+  /// RSA engine with blinding to protect against side-channel attacks.
+  /// Implements IAsymmetricBlockCipher, wrapping an IRsa implementation.
+  /// </summary>
+  TRsaBlindedEngine = class(TInterfacedObject, IAsymmetricBlockCipher, IRsaBlindedEngine)
+
+  strict private
+  var
+    FCore: IRsa;
+    FKey: IRsaKeyParameters;
+    FRandom: ISecureRandom;
+
+  strict protected
+    function GetAlgorithmName: String;
+    function GetInputBlockSize: Int32;
+    function GetOutputBlockSize: Int32;
+    function InitSecureRandom(needed: Boolean; const provided: ISecureRandom): ISecureRandom; virtual;
+
+  public
+    constructor Create(); overload;
+    constructor Create(const rsa: IRsa); overload;
+
+    procedure Init(forEncryption: Boolean;
+      const parameters: ICipherParameters);
+
+    function ProcessBlock(const inBuf: TCryptoLibByteArray;
+      inOff, inLen: Int32): TCryptoLibByteArray;
+
+    property AlgorithmName: String read GetAlgorithmName;
+    property InputBlockSize: Int32 read GetInputBlockSize;
+    property OutputBlockSize: Int32 read GetOutputBlockSize;
+
+  end;
+
+implementation
+
+{ TRsaBlindedEngine }
+
+constructor TRsaBlindedEngine.Create;
+begin
+  Create(TRsaCoreEngine.Create() as IRsa);
+end;
+
+constructor TRsaBlindedEngine.Create(const rsa: IRsa);
+begin
+  inherited Create();
+  FCore := rsa;
+end;
+
+function TRsaBlindedEngine.GetAlgorithmName: String;
+begin
+  Result := 'RSA';
+end;
+
+function TRsaBlindedEngine.InitSecureRandom(needed: Boolean;
+  const provided: ISecureRandom): ISecureRandom;
+begin
+  if needed then
+  begin
+    if provided <> nil then
+      Result := provided
+    else
+      Result := TSecureRandom.Create();
+  end
+  else
+    Result := nil;
+end;
+
+procedure TRsaBlindedEngine.Init(forEncryption: Boolean;
+  const parameters: ICipherParameters);
+var
+  LParameters: ICipherParameters;
+  providedRandom: ISecureRandom;
+begin
+  LParameters := TParameterUtilities.GetRandom(parameters, providedRandom);
+
+  FCore.Init(forEncryption, LParameters);
+
+  FKey := LParameters as IRsaKeyParameters;
+  FRandom := InitSecureRandom(Supports(FKey, IRsaPrivateCrtKeyParameters), providedRandom);
+end;
+
+function TRsaBlindedEngine.GetInputBlockSize: Int32;
+begin
+  Result := FCore.InputBlockSize;
+end;
+
+function TRsaBlindedEngine.GetOutputBlockSize: Int32;
+begin
+  Result := FCore.OutputBlockSize;
+end;
+
+function TRsaBlindedEngine.ProcessBlock(const inBuf: TCryptoLibByteArray;
+  inOff, inLen: Int32): TCryptoLibByteArray;
+var
+  input, output: TBigInteger;
+  crtKey: IRsaPrivateCrtKeyParameters;
+  e, m, n: TBigInteger;
+  r, blind, unblind: TBigInteger;
+  blindedInput, blindedResult: TBigInteger;
+begin
+  if FKey = nil then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes(@SRsaEngineNotInitialised);
+  end;
+
+  input := FCore.ConvertInput(inBuf, inOff, inLen);
+
+  // Only apply blinding for private CRT key operations
+  if Supports(FKey, IRsaPrivateCrtKeyParameters, crtKey) then
+  begin
+    e := crtKey.PublicExponent;
+    m := crtKey.Modulus;
+
+    // Generate random r in range [1, m-1]
+    r := TBigIntegers.CreateRandomInRange(TBigInteger.One, m.Subtract(TBigInteger.One), FRandom);
+
+    // blind = r^e mod m
+    blind := r.ModPow(e, m);
+    // unblind = r^(-1) mod m
+    unblind := TBigIntegers.ModOddInverse(m, r);
+
+    // Blind the input: blindedInput = blind * input mod m
+    blindedInput := blind.Multiply(input).&Mod(m);
+
+    // Process the blinded input through the core engine
+    blindedResult := FCore.ProcessBlock(blindedInput);
+
+    // Unblind: output = unblind * blindedResult mod m
+    output := unblind.Multiply(blindedResult).&Mod(m);
+  end
+  else
+  begin
+    // Public key operation or non-CRT private key - no blinding
+    output := FCore.ProcessBlock(input);
+  end;
+
+  Result := FCore.ConvertOutput(output);
+end;
+
+end.

+ 158 - 0
CryptoLib/src/Crypto/Engines/ClpRsaBlindingEngine.pas

@@ -0,0 +1,158 @@
+{ *********************************************************************************** }
+{ *                              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 ClpRsaBlindingEngine;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpBigInteger,
+  ClpBigIntegers,
+  ClpICipherParameters,
+  ClpIParametersWithRandom,
+  ClpIRsaBlindingParameters,
+  ClpIRsaKeyParameters,
+  ClpIRsa,
+  ClpRsaCoreEngine,
+  ClpIAsymmetricBlockCipher,
+  ClpIRsaBlindingEngine,
+  ClpCryptoLibTypes;
+
+type
+  /// <summary>
+  /// This does your basic RSA Chaum's blinding and unblinding as outlined in
+  /// "Handbook of Applied Cryptography", page 475. You need to use this if you are
+  /// trying to get another party to generate signatures without them being aware
+  /// of the message they are signing.
+  /// </summary>
+  TRsaBlindingEngine = class(TInterfacedObject, IAsymmetricBlockCipher, IRsaBlindingEngine)
+
+  strict private
+    FCore: IRsa;
+    FKey: IRsaKeyParameters;
+    FBlindingFactor: TBigInteger;
+    FForEncryption: Boolean;
+
+    function BlindMessage(const msg: TBigInteger): TBigInteger;
+    function UnblindMessage(const blindedMsg: TBigInteger): TBigInteger;
+
+  strict protected
+    function GetAlgorithmName: String;
+    function GetInputBlockSize: Int32;
+    function GetOutputBlockSize: Int32;
+
+  public
+    constructor Create(); overload;
+    constructor Create(const rsa: IRsa); overload;
+
+    procedure Init(forEncryption: Boolean; const parameters: ICipherParameters);
+    function ProcessBlock(const inBuf: TCryptoLibByteArray;
+      inOff, inLen: Int32): TCryptoLibByteArray;
+
+    property AlgorithmName: String read GetAlgorithmName;
+    property InputBlockSize: Int32 read GetInputBlockSize;
+    property OutputBlockSize: Int32 read GetOutputBlockSize;
+
+  end;
+
+implementation
+
+{ TRsaBlindingEngine }
+
+constructor TRsaBlindingEngine.Create;
+begin
+  Create(TRsaCoreEngine.Create() as IRsa);
+end;
+
+constructor TRsaBlindingEngine.Create(const rsa: IRsa);
+begin
+  inherited Create();
+  FCore := rsa;
+end;
+
+function TRsaBlindingEngine.GetAlgorithmName: String;
+begin
+  Result := 'RSA';
+end;
+
+procedure TRsaBlindingEngine.Init(forEncryption: Boolean;
+  const parameters: ICipherParameters);
+var
+  p: IRsaBlindingParameters;
+  rParam: IParametersWithRandom;
+begin
+  if Supports(parameters, IParametersWithRandom, rParam) then
+    p := rParam.Parameters as IRsaBlindingParameters
+  else
+    p := parameters as IRsaBlindingParameters;
+
+  FCore.Init(forEncryption, p.PublicKey);
+
+  FForEncryption := forEncryption;
+  FKey := p.PublicKey;
+  FBlindingFactor := p.BlindingFactor;
+end;
+
+function TRsaBlindingEngine.GetInputBlockSize: Int32;
+begin
+  Result := FCore.InputBlockSize;
+end;
+
+function TRsaBlindingEngine.GetOutputBlockSize: Int32;
+begin
+  Result := FCore.OutputBlockSize;
+end;
+
+function TRsaBlindingEngine.ProcessBlock(const inBuf: TCryptoLibByteArray;
+  inOff, inLen: Int32): TCryptoLibByteArray;
+var
+  msg: TBigInteger;
+begin
+  msg := FCore.ConvertInput(inBuf, inOff, inLen);
+
+  if FForEncryption then
+    msg := BlindMessage(msg)
+  else
+    msg := UnblindMessage(msg);
+
+  Result := FCore.ConvertOutput(msg);
+end;
+
+function TRsaBlindingEngine.BlindMessage(const msg: TBigInteger): TBigInteger;
+var
+  blindMsg: TBigInteger;
+begin
+  // msg * (blindingFactor ^ e) mod n
+  blindMsg := FBlindingFactor.ModPow(FKey.Exponent, FKey.Modulus);
+  blindMsg := msg.Multiply(blindMsg);
+  Result := blindMsg.&Mod(FKey.Modulus);
+end;
+
+function TRsaBlindingEngine.UnblindMessage(const blindedMsg: TBigInteger): TBigInteger;
+var
+  m, blindFactorInverse, res: TBigInteger;
+begin
+  m := FKey.Modulus;
+  blindFactorInverse := TBigIntegers.ModOddInverse(m, FBlindingFactor);
+  res := blindedMsg.Multiply(blindFactorInverse);
+  Result := res.&Mod(m);
+end;
+
+end.

+ 219 - 0
CryptoLib/src/Crypto/Engines/ClpRsaCoreEngine.pas

@@ -0,0 +1,219 @@
+{ *********************************************************************************** }
+{ *                              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 ClpRsaCoreEngine;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpBigInteger,
+  ClpBigIntegers,
+  ClpICipherParameters,
+  ClpParameterUtilities,
+  ClpIRsaKeyParameters,
+  ClpIRsaPrivateCrtKeyParameters,
+  ClpIRsa,
+  ClpIRsaCoreEngine,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SRsaEngineNotInitialised = 'RSA engine not initialised';
+  SInputTooLargeForRsa = 'input too large for RSA cipher.';
+  SInputTooSmallForRsa = 'input too small for RSA cipher.';
+  SFaultyDecryption = 'RSA engine faulty decryption/signing detected';
+
+type
+  /// <summary>
+  /// The basic RSA algorithm.
+  /// </summary>
+  TRsaCoreEngine = class(TInterfacedObject, IRsa, IRsaCoreEngine)
+
+  strict private
+  var
+    FKey: IRsaKeyParameters;
+    FForEncryption: Boolean;
+    FBitSize: Int32;
+
+    procedure CheckInitialised;
+
+  strict protected
+    function GetInputBlockSize: Int32; virtual;
+    function GetOutputBlockSize: Int32; virtual;
+
+  public
+    constructor Create();
+
+    procedure Init(forEncryption: Boolean;
+      const parameters: ICipherParameters); virtual;
+
+    function ConvertInput(const buf: TCryptoLibByteArray; off, len: Int32): TBigInteger;
+    function ConvertOutput(const res: TBigInteger): TCryptoLibByteArray;
+    function ProcessBlock(const input: TBigInteger): TBigInteger;
+
+    property InputBlockSize: Int32 read GetInputBlockSize;
+    property OutputBlockSize: Int32 read GetOutputBlockSize;
+
+  end;
+
+implementation
+
+{ TRsaCoreEngine }
+
+constructor TRsaCoreEngine.Create;
+begin
+  inherited Create();
+  FKey := nil;
+end;
+
+procedure TRsaCoreEngine.CheckInitialised;
+begin
+  if FKey = nil then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes(@SRsaEngineNotInitialised);
+  end;
+end;
+
+procedure TRsaCoreEngine.Init(forEncryption: Boolean;
+  const parameters: ICipherParameters);
+var
+  LParameters: ICipherParameters;
+begin
+  LParameters := parameters;
+  LParameters := TParameterUtilities.IgnoreRandom(LParameters);
+
+  FKey := LParameters as IRsaKeyParameters;
+  FForEncryption := forEncryption;
+  FBitSize := FKey.Modulus.BitLength;
+end;
+
+function TRsaCoreEngine.GetInputBlockSize: Int32;
+begin
+  CheckInitialised;
+
+  if FForEncryption then
+  begin
+    Result := (FBitSize - 1) div 8;
+  end
+  else
+  begin
+    Result := (FBitSize + 7) div 8;
+  end;
+end;
+
+function TRsaCoreEngine.GetOutputBlockSize: Int32;
+begin
+  CheckInitialised;
+
+  if FForEncryption then
+  begin
+    Result := (FBitSize + 7) div 8;
+  end
+  else
+  begin
+    Result := (FBitSize - 1) div 8;
+  end;
+end;
+
+function TRsaCoreEngine.ConvertInput(const buf: TCryptoLibByteArray;
+  off, len: Int32): TBigInteger;
+var
+  maxLength: Int32;
+begin
+  CheckInitialised;
+
+  maxLength := (FBitSize + 7) div 8;
+
+  if len > maxLength then
+  begin
+    raise EDataLengthCryptoLibException.CreateRes(@SInputTooLargeForRsa);
+  end;
+
+  Result := TBigInteger.Create(1, buf, off, len);
+
+  if Result.CompareTo(TBigInteger.One) <= 0 then
+  begin
+    raise EDataLengthCryptoLibException.CreateRes(@SInputTooSmallForRsa);
+  end;
+
+  if Result.CompareTo(FKey.Modulus.Subtract(TBigInteger.One)) >= 0 then
+  begin
+    raise EDataLengthCryptoLibException.CreateRes(@SInputTooLargeForRsa);
+  end;
+end;
+
+function TRsaCoreEngine.ConvertOutput(const res: TBigInteger): TCryptoLibByteArray;
+begin
+  CheckInitialised;
+
+  if FForEncryption then
+  begin
+    Result := TBigIntegers.AsUnsignedByteArray(GetOutputBlockSize, res);
+  end
+  else
+  begin
+    Result := TBigIntegers.AsUnsignedByteArray(res);
+  end;
+end;
+
+function TRsaCoreEngine.ProcessBlock(const input: TBigInteger): TBigInteger;
+var
+  crtKey: IRsaPrivateCrtKeyParameters;
+  p, q, dP, dQ, qInv: TBigInteger;
+  mP, mQ, h, m, check: TBigInteger;
+begin
+  CheckInitialised;
+
+  // Check if we have CRT parameters for private key operations
+  if not Supports(FKey, IRsaPrivateCrtKeyParameters, crtKey) then
+  begin
+    Result := input.ModPow(FKey.Exponent, FKey.Modulus);
+    Exit;
+  end;
+
+  // Use Chinese Remainder Theorem for faster decryption
+  p := crtKey.P;
+  q := crtKey.Q;
+  dP := crtKey.DP;
+  dQ := crtKey.DQ;
+  qInv := crtKey.QInv;
+
+  // mP = ((input Mod p) ^ dP) Mod p
+  mP := input.Remainder(p).ModPow(dP, p);
+
+  // mQ = ((input Mod q) ^ dQ) Mod q
+  mQ := input.Remainder(q).ModPow(dQ, q);
+
+  // h = qInv * (mP - mQ) Mod p
+  h := mP.Subtract(mQ).Multiply(qInv).&Mod(p);
+
+  // m = h * q + mQ
+  m := h.Multiply(q).Add(mQ);
+
+  // Defence against Arjen Lenstra's CRT attack
+  check := m.ModPow(crtKey.PublicExponent, crtKey.Modulus);
+  if not check.Equals(input) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes(@SFaultyDecryption);
+  end;
+
+  Result := m;
+end;
+
+end.

+ 113 - 0
CryptoLib/src/Crypto/Engines/ClpRsaEngine.pas

@@ -0,0 +1,113 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpRsaEngine;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpBigInteger,
+  ClpICipherParameters,
+  ClpIRsa,
+  ClpIRsaCoreEngine,
+  ClpRsaCoreEngine,
+  ClpIAsymmetricBlockCipher,
+  ClpIRsaEngine,
+  ClpCryptoLibTypes;
+
+type
+  /// <summary>
+  /// Basic RSA engine implementing IAsymmetricBlockCipher.
+  /// Wraps an IRsa implementation for byte[] processing.
+  /// </summary>
+  TRsaEngine = class(TInterfacedObject, IAsymmetricBlockCipher, IRsaEngine)
+
+  strict private
+  var
+    FCore: IRsa;
+
+  strict protected
+    function GetAlgorithmName: String;
+    function GetInputBlockSize: Int32;
+    function GetOutputBlockSize: Int32;
+
+  public
+    constructor Create(); overload;
+    constructor Create(const rsa: IRsa); overload;
+
+    procedure Init(forEncryption: Boolean;
+      const parameters: ICipherParameters);
+
+    function ProcessBlock(const inBuf: TCryptoLibByteArray;
+      inOff, inLen: Int32): TCryptoLibByteArray;
+
+    property AlgorithmName: String read GetAlgorithmName;
+    property InputBlockSize: Int32 read GetInputBlockSize;
+    property OutputBlockSize: Int32 read GetOutputBlockSize;
+
+  end;
+
+implementation
+
+{ TRsaEngine }
+
+constructor TRsaEngine.Create;
+begin
+  Create(TRsaCoreEngine.Create() as IRsa);
+end;
+
+constructor TRsaEngine.Create(const rsa: IRsa);
+begin
+  inherited Create();
+  FCore := rsa;
+end;
+
+function TRsaEngine.GetAlgorithmName: String;
+begin
+  Result := 'RSA';
+end;
+
+procedure TRsaEngine.Init(forEncryption: Boolean;
+  const parameters: ICipherParameters);
+begin
+  FCore.Init(forEncryption, parameters);
+end;
+
+function TRsaEngine.GetInputBlockSize: Int32;
+begin
+  Result := FCore.InputBlockSize;
+end;
+
+function TRsaEngine.GetOutputBlockSize: Int32;
+begin
+  Result := FCore.OutputBlockSize;
+end;
+
+function TRsaEngine.ProcessBlock(const inBuf: TCryptoLibByteArray;
+  inOff, inLen: Int32): TCryptoLibByteArray;
+var
+  input, output: TBigInteger;
+begin
+  input := FCore.ConvertInput(inBuf, inOff, inLen);
+  output := FCore.ProcessBlock(input);
+  Result := FCore.ConvertOutput(output);
+end;
+
+end.

+ 112 - 0
CryptoLib/src/Crypto/Generators/ClpRsaBlindingFactorGenerator.pas

@@ -0,0 +1,112 @@
+{ *********************************************************************************** }
+{ *                              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 ClpRsaBlindingFactorGenerator;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpBigInteger,
+  ClpBigIntegers,
+  ClpICipherParameters,
+  ClpParameterUtilities,
+  ClpIParametersWithRandom,
+  ClpIRsaKeyParameters,
+  ClpIRsaBlindingFactorGenerator,
+  ClpISecureRandom,
+  ClpSecureRandom,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SGeneratorNotInit = 'Generator not initialised';
+  SPublicKeyRequired = 'Generator requires RSA public key';
+
+type
+  /// <summary>
+  /// Generate a random factor suitable for use with RSA blind signatures.
+  /// </summary>
+  TRsaBlindingFactorGenerator = class(TInterfacedObject, IRsaBlindingFactorGenerator)
+
+  strict private
+  var
+    FKey: IRsaKeyParameters;
+    FRandom: ISecureRandom;
+
+  public
+    constructor Create();
+
+    procedure Init(const param: ICipherParameters);
+    function GenerateBlindingFactor: TBigInteger;
+
+  end;
+
+implementation
+
+{ TRsaBlindingFactorGenerator }
+
+constructor TRsaBlindingFactorGenerator.Create;
+begin
+  inherited Create();
+  FKey := nil;
+  FRandom := nil;
+end;
+
+procedure TRsaBlindingFactorGenerator.Init(const param: ICipherParameters);
+var
+  LParameters: ICipherParameters;
+  providedRandom: ISecureRandom;
+begin
+  LParameters := TParameterUtilities.GetRandom(param, providedRandom);
+  FKey := LParameters as IRsaKeyParameters;
+
+  if providedRandom <> nil then
+    FRandom := providedRandom
+  else
+    FRandom := TSecureRandom.Create();
+
+  if FKey.IsPrivate then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SPublicKeyRequired);
+  end;
+end;
+
+function TRsaBlindingFactorGenerator.GenerateBlindingFactor: TBigInteger;
+var
+  m: TBigInteger;
+  len: Int32;
+  factor: TBigInteger;
+begin
+  if FKey = nil then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes(@SGeneratorNotInit);
+  end;
+
+  m := FKey.Modulus;
+  len := m.BitLength - 1; // must be less than m.BitLength
+
+  repeat
+    factor := TBigInteger.Create(len, FRandom);
+  until (factor.CompareTo(TBigInteger.Two) >= 0) and
+    TBigIntegers.ModOddIsCoprimeVar(m, factor);
+
+  Result := factor;
+end;
+
+end.

+ 264 - 0
CryptoLib/src/Crypto/Generators/ClpRsaKeyPairGenerator.pas

@@ -0,0 +1,264 @@
+{ *********************************************************************************** }
+{ *                              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 ClpRsaKeyPairGenerator;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpBigInteger,
+  ClpBigIntegers,
+  ClpIKeyGenerationParameters,
+  ClpIRsaKeyGenerationParameters,
+  ClpRsaKeyGenerationParameters,
+  ClpIRsaKeyParameters,
+  ClpRsaKeyParameters,
+  ClpIRsaPrivateCrtKeyParameters,
+  ClpRsaPrivateCrtKeyParameters,
+  ClpIAsymmetricCipherKeyPair,
+  ClpAsymmetricCipherKeyPair,
+  ClpIAsymmetricCipherKeyPairGenerator,
+  ClpIRsaKeyPairGenerator,
+  ClpISecureRandom,
+  ClpECCompUtilities,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SRsaKeyGenNotInit = 'RSA key pair generator not initialised';
+
+type
+  /// <summary>
+  /// RSA key pair generator.
+  /// </summary>
+  TRsaKeyPairGenerator = class(TInterfacedObject,
+    IAsymmetricCipherKeyPairGenerator, IRsaKeyPairGenerator)
+
+  strict private
+  class var
+    FDefaultPublicExponent: TBigInteger;
+
+  const
+    DefaultTests = 100;
+
+  class var
+    FSpecialEValues: TCryptoLibInt32Array;
+    FSpecialEHighest: Int32;
+    FSpecialEBits: Int32;
+
+  var
+    FParam: IRsaKeyGenerationParameters;
+
+    class constructor CreateRsaKeyPairGenerator;
+
+    function ChooseRandomPrime(bitLength: Int32;
+      const e: TBigInteger): TBigInteger;
+
+
+    class function ArrayContains(const arr: TCryptoLibInt32Array; value: Int32): Boolean; static;
+
+  public
+    constructor Create();
+
+    procedure Init(const parameters: IKeyGenerationParameters);
+    function GenerateKeyPair(): IAsymmetricCipherKeyPair;
+
+  end;
+
+implementation
+
+{ TRsaKeyPairGenerator }
+
+class constructor TRsaKeyPairGenerator.CreateRsaKeyPairGenerator;
+begin
+  FSpecialEValues := TCryptoLibInt32Array.Create(3, 5, 17, 257, 65537);
+  FSpecialEHighest := 65537;
+  FSpecialEBits := TBigInteger.ValueOf(FSpecialEHighest).BitLength;
+  FDefaultPublicExponent := TBigInteger.ValueOf($10001);  // 65537
+end;
+
+constructor TRsaKeyPairGenerator.Create;
+begin
+  inherited Create();
+  FParam := nil;
+end;
+
+procedure TRsaKeyPairGenerator.Init(const parameters: IKeyGenerationParameters);
+begin
+  if Supports(parameters, IRsaKeyGenerationParameters) then
+    FParam := parameters as IRsaKeyGenerationParameters
+  else
+    // Create default RSA parameters if not provided
+    FParam := TRsaKeyGenerationParameters.Create(
+      FDefaultPublicExponent, parameters.Random, parameters.Strength, DefaultTests);
+end;
+
+class function TRsaKeyPairGenerator.ArrayContains(const arr: TArray<Int32>;
+  value: Int32): Boolean;
+var
+  i: Int32;
+begin
+  for i := 0 to System.Length(arr) - 1 do
+  begin
+    if arr[i] = value then
+    begin
+      Result := True;
+      Exit;
+    end;
+  end;
+  Result := False;
+end;
+
+
+
+function TRsaKeyPairGenerator.ChooseRandomPrime(bitLength: Int32;
+  const e: TBigInteger): TBigInteger;
+var
+  p, pSub1: TBigInteger;
+  eIsKnownOddPrime: Boolean;
+begin
+  eIsKnownOddPrime := (e.BitLength <= FSpecialEBits) and ArrayContains(FSpecialEValues, e.Int32Value);
+
+  while True do
+  begin
+    // Generate random odd number
+    p := TBigInteger.Create(bitLength, 1, FParam.Random);
+
+    // Check p mod e != 1
+    if p.&Mod(e).Equals(TBigInteger.One) then
+      Continue;
+
+    // Check primality
+    if not p.IsProbablePrime(FParam.Certainty, True) then
+      Continue;
+
+    // If e is not a known small prime, check gcd(e, p-1) = 1
+    if not eIsKnownOddPrime then
+    begin
+      pSub1 := p.Subtract(TBigInteger.One);
+      if not e.Gcd(pSub1).Equals(TBigInteger.One) then
+        Continue;
+    end;
+
+    Result := p;
+    Exit;
+  end;
+end;
+
+function TRsaKeyPairGenerator.GenerateKeyPair: IAsymmetricCipherKeyPair;
+var
+  strength, pBitLength, qBitLength, minDiffBits, minWeight: Int32;
+  e, p, q, pSub1, qSub1: TBigInteger;
+  n, d, dP, dQ, qInv: TBigInteger;
+  diff, gcd, lcm, tmp: TBigInteger;
+  pubKey: IRsaKeyParameters;
+  privKey: IRsaPrivateCrtKeyParameters;
+begin
+  if FParam = nil then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes(@SRsaKeyGenNotInit);
+  end;
+
+  while True do
+  begin
+    strength := FParam.Strength;
+    e := FParam.PublicExponent;
+
+    // p and q bit lengths
+    pBitLength := (strength + 1) div 2;
+    qBitLength := strength - pBitLength;
+    minDiffBits := strength div 3;
+    minWeight := strength shr 2;
+
+    // Generate p
+    p := ChooseRandomPrime(pBitLength, e);
+
+    // Generate q and modulus
+    while True do
+    begin
+      q := ChooseRandomPrime(qBitLength, e);
+
+      // p and q should not be too close together (or equal!)
+      diff := q.Subtract(p).Abs();
+      if diff.BitLength < minDiffBits then
+        Continue;
+
+      // Calculate the modulus
+      n := p.Multiply(q);
+
+      if n.BitLength <> strength then
+      begin
+        // If we get here our primes aren't big enough, make the largest
+        // of the two p and try again
+        p := p.Max(q);
+        Continue;
+      end;
+
+      // Require a minimum weight of the NAF representation, since low-weight
+      // composites may be weak against a version of the number-field-sieve
+      // for factoring.
+      // See "The number field sieve for integers of low weight", Oliver Schirokauer.
+      if TWNafUtilities.GetNafWeight(n) < minWeight then
+      begin
+        p := ChooseRandomPrime(pBitLength, e);
+        Continue;
+      end;
+
+      Break;
+    end;
+
+    // Ensure p > q (for CRT)
+    if p.CompareTo(q) < 0 then
+    begin
+      tmp := p;
+      p := q;
+      q := tmp;
+    end;
+
+    // Calculate phi components
+    pSub1 := p.Subtract(TBigInteger.One);
+    qSub1 := q.Subtract(TBigInteger.One);
+
+    // Calculate LCM(p-1, q-1) = (p-1) * (q-1) / gcd(p-1, q-1)
+    gcd := pSub1.Gcd(qSub1);
+    lcm := pSub1.Divide(gcd).Multiply(qSub1);
+
+    // Calculate the private exponent d = e^(-1) mod lcm
+    d := e.ModInverse(lcm);
+
+    // Check d has sufficient bit length
+    if d.BitLength <= qBitLength then
+      Continue;
+
+    // Calculate CRT parameters
+    dP := d.Remainder(pSub1);
+    dQ := d.Remainder(qSub1);
+    qInv := TBigIntegers.ModOddInverse(p, q);
+
+    // Create key pair
+    pubKey := TRsaKeyParameters.Create(False, n, e) as IRsaKeyParameters;
+    privKey := TRsaPrivateCrtKeyParameters.Create(n, e, d, p, q, dP, dQ, qInv)
+      as IRsaPrivateCrtKeyParameters;
+
+    Result := TAsymmetricCipherKeyPair.Create(pubKey, privKey);
+    Exit;
+  end;
+end;
+
+end.

+ 86 - 0
CryptoLib/src/Crypto/Parameters/ClpRsaBlindingParameters.pas

@@ -0,0 +1,86 @@
+{ *********************************************************************************** }
+{ *                              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 ClpRsaBlindingParameters;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpBigInteger,
+  ClpIRsaKeyParameters,
+  ClpIRsaBlindingParameters,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SPublicKeyRequired = 'RSA parameters should be for a public key';
+
+type
+  /// <summary>
+  /// Parameters for RSA blinding operations.
+  /// </summary>
+  TRsaBlindingParameters = class(TInterfacedObject, IRsaBlindingParameters)
+
+  strict private
+  var
+    FPublicKey: IRsaKeyParameters;
+    FBlindingFactor: TBigInteger;
+
+  strict protected
+    function GetPublicKey: IRsaKeyParameters;
+    function GetBlindingFactor: TBigInteger;
+
+  public
+    constructor Create(const publicKey: IRsaKeyParameters;
+      const blindingFactor: TBigInteger);
+
+    property PublicKey: IRsaKeyParameters read GetPublicKey;
+    property BlindingFactor: TBigInteger read GetBlindingFactor;
+
+  end;
+
+implementation
+
+{ TRsaBlindingParameters }
+
+constructor TRsaBlindingParameters.Create(const publicKey: IRsaKeyParameters;
+  const blindingFactor: TBigInteger);
+begin
+  inherited Create();
+
+  if publicKey.IsPrivate then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SPublicKeyRequired);
+  end;
+
+  FPublicKey := publicKey;
+  FBlindingFactor := blindingFactor;
+end;
+
+function TRsaBlindingParameters.GetBlindingFactor: TBigInteger;
+begin
+  Result := FBlindingFactor;
+end;
+
+function TRsaBlindingParameters.GetPublicKey: IRsaKeyParameters;
+begin
+  Result := FPublicKey;
+end;
+
+end.

+ 139 - 0
CryptoLib/src/Crypto/Parameters/ClpRsaKeyGenerationParameters.pas

@@ -0,0 +1,139 @@
+{ *********************************************************************************** }
+{ *                              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 ClpRsaKeyGenerationParameters;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpBigInteger,
+  ClpIRsaKeyGenerationParameters,
+  ClpKeyGenerationParameters,
+  ClpISecureRandom,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SPublicExponentNil = 'publicExponent';
+  SPublicExponentNotOdd = 'Public exponent must be an odd number';
+
+type
+  /// <summary>
+  /// RSA key generation parameters.
+  /// </summary>
+  TRsaKeyGenerationParameters = class(TKeyGenerationParameters,
+    IRsaKeyGenerationParameters)
+
+  strict private
+  const
+    DefaultTests = 100;
+
+  var
+    FPublicExponent: TBigInteger;
+    FCertainty: Int32;
+
+  strict protected
+    function GetPublicExponent: TBigInteger;
+    function GetCertainty: Int32;
+
+  public
+    /// <summary>
+    /// Create RSA key generation parameters.
+    /// </summary>
+    /// <param name="publicExponent">
+    /// The public exponent for generated keys, typically 0x10001 (65537).
+    /// </param>
+    /// <param name="random">
+    /// The random source for key generation.
+    /// </param>
+    /// <param name="strength">
+    /// The key size in bits.
+    /// </param>
+    /// <param name="certainty">
+    /// The certainty (number of iterations) for primality testing.
+    /// </param>
+    constructor Create(const publicExponent: TBigInteger;
+      const random: ISecureRandom; strength, certainty: Int32);
+
+    function Equals(const other: IRsaKeyGenerationParameters): Boolean;
+      reintroduce; overload;
+    function GetHashCode: {$IFDEF DELPHI}Int32;{$ELSE}PtrInt;{$ENDIF DELPHI} override;
+
+    property PublicExponent: TBigInteger read GetPublicExponent;
+    property Certainty: Int32 read GetCertainty;
+
+  end;
+
+implementation
+
+{ TRsaKeyGenerationParameters }
+
+constructor TRsaKeyGenerationParameters.Create(const publicExponent: TBigInteger;
+  const random: ISecureRandom; strength, certainty: Int32);
+begin
+  inherited Create(random, strength);
+
+  if not publicExponent.IsInitialized then
+  begin
+    raise EArgumentNilCryptoLibException.CreateRes(@SPublicExponentNil);
+  end;
+
+  if not publicExponent.TestBit(0) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SPublicExponentNotOdd);
+  end;
+
+  FPublicExponent := publicExponent;
+  FCertainty := certainty;
+end;
+
+function TRsaKeyGenerationParameters.GetCertainty: Int32;
+begin
+  Result := FCertainty;
+end;
+
+function TRsaKeyGenerationParameters.GetPublicExponent: TBigInteger;
+begin
+  Result := FPublicExponent;
+end;
+
+function TRsaKeyGenerationParameters.Equals(const other: IRsaKeyGenerationParameters): Boolean;
+begin
+  if other = nil then
+  begin
+    Result := False;
+    Exit;
+  end;
+
+  if (Self as IRsaKeyGenerationParameters) = other then
+  begin
+    Result := True;
+    Exit;
+  end;
+
+  Result := (FCertainty = other.Certainty) and
+    FPublicExponent.Equals(other.PublicExponent);
+end;
+
+function TRsaKeyGenerationParameters.GetHashCode: {$IFDEF DELPHI}Int32;{$ELSE}PtrInt;{$ENDIF DELPHI}
+begin
+  Result := FCertainty xor FPublicExponent.GetHashCode();
+end;
+
+end.

+ 207 - 0
CryptoLib/src/Crypto/Parameters/ClpRsaKeyParameters.pas

@@ -0,0 +1,207 @@
+{ *********************************************************************************** }
+{ *                              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 ClpRsaKeyParameters;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpBigInteger,
+  ClpBigIntegers,
+  ClpIRsaKeyParameters,
+  ClpAsymmetricKeyParameter,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SModulusNil = 'modulus';
+  SExponentNil = 'exponent';
+  SNotValidRsaModulus = 'Not a valid RSA modulus';
+  SNotValidRsaExponent = 'Not a valid RSA exponent';
+  SRsaModulusIsEven = 'RSA modulus is even';
+  SRsaModulusOutOfRange = 'RSA modulus out of range';
+  SRsaModulusHasSmallPrimeFactor = 'RSA modulus has a small prime factor';
+  SRsaPublicExponentIsEven = 'RSA publicExponent is even';
+
+type
+  TRsaKeyParameters = class(TAsymmetricKeyParameter, IRsaKeyParameters)
+
+  strict private
+  class var
+    FSmallPrimesProduct: TBigInteger;
+
+    class constructor CreateRsaKeyParameters();
+
+    class function HasAnySmallFactors(const modulus: TBigInteger): Boolean; static;
+    class function Validate(const modulus: TBigInteger): TBigInteger; static;
+
+  strict private
+  var
+    FModulus: TBigInteger;
+    FExponent: TBigInteger;
+
+  strict protected
+    function GetModulus: TBigInteger;
+    function GetExponent: TBigInteger;
+
+  public
+    constructor Create(isPrivate: Boolean;
+      const modulus, exponent: TBigInteger);
+
+    function Equals(const other: IRsaKeyParameters): Boolean;
+      reintroduce; overload;
+    function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}override;
+
+    property Modulus: TBigInteger read GetModulus;
+    property Exponent: TBigInteger read GetExponent;
+
+  end;
+
+implementation
+
+const
+  // Hexadecimal value of the product of the 131 smallest odd primes from 3 to 743
+  SmallPrimesProductHex =
+    '8138e8a0fcf3a4e84a771d40fd305d7f4aa59306d7251de54d98af8fe95729a1f' +
+    '73d893fa424cd2edc8636a6c3285e022b0e3866a565ae8108eed8591cd4fe8d2' +
+    'ce86165a978d719ebf647f362d33fca29cd179fb42401cbaf3df0c614056f9c8' +
+    'f3cfd51e474afb6bc6974f78db8aba8e9e517fded658591ab7502bd41849462f';
+
+  DefaultMaxBitLength = 16384;
+
+{ TRsaKeyParameters }
+
+class constructor TRsaKeyParameters.CreateRsaKeyParameters;
+begin
+  FSmallPrimesProduct := TBigInteger.Create(SmallPrimesProductHex, 16);
+end;
+
+class function TRsaKeyParameters.HasAnySmallFactors(
+  const modulus: TBigInteger): Boolean;
+var
+  M, X: TBigInteger;
+begin
+  // Check if modulus shares any factors with the product of small primes
+  if modulus.BitLength < FSmallPrimesProduct.BitLength then
+  begin
+    M := FSmallPrimesProduct;
+    X := modulus;
+  end
+  else
+  begin
+    M := modulus;
+    X := FSmallPrimesProduct;
+  end;
+
+  Result := not TBigIntegers.ModOddIsCoprimeVar(M, X);
+end;
+
+class function TRsaKeyParameters.Validate(
+  const modulus: TBigInteger): TBigInteger;
+begin
+  if (modulus.IsEven) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SRsaModulusIsEven);
+  end;
+
+  if (modulus.BitLength > DefaultMaxBitLength) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SRsaModulusOutOfRange);
+  end;
+
+  if HasAnySmallFactors(modulus) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SRsaModulusHasSmallPrimeFactor);
+  end;
+
+  Result := modulus;
+end;
+
+constructor TRsaKeyParameters.Create(isPrivate: Boolean;
+  const modulus, exponent: TBigInteger);
+begin
+  inherited Create(isPrivate);
+
+  if not modulus.IsInitialized then
+  begin
+    raise EArgumentNilCryptoLibException.CreateRes(@SModulusNil);
+  end;
+
+  if not exponent.IsInitialized then
+  begin
+    raise EArgumentNilCryptoLibException.CreateRes(@SExponentNil);
+  end;
+
+  if modulus.SignValue <= 0 then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SNotValidRsaModulus);
+  end;
+
+  if exponent.SignValue <= 0 then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SNotValidRsaExponent);
+  end;
+
+  if (not isPrivate) and (exponent.IsEven) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SRsaPublicExponentIsEven);
+  end;
+
+  FModulus := Validate(modulus);
+  FExponent := exponent;
+end;
+
+function TRsaKeyParameters.Equals(const other: IRsaKeyParameters): Boolean;
+begin
+  if other = nil then
+  begin
+    Result := False;
+    Exit;
+  end;
+
+  if ((Self as IRsaKeyParameters) = other) then
+  begin
+    Result := True;
+    Exit;
+  end;
+
+  Result := (IsPrivate = other.IsPrivate) and
+    FModulus.Equals(other.Modulus) and
+    FExponent.Equals(other.Exponent);
+end;
+
+function TRsaKeyParameters.GetExponent: TBigInteger;
+begin
+  Result := FExponent;
+end;
+
+function TRsaKeyParameters.GetHashCode: {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}
+begin
+  Result := FModulus.GetHashCode() xor FExponent.GetHashCode() xor
+    Ord(IsPrivate);
+end;
+
+function TRsaKeyParameters.GetModulus: TBigInteger;
+begin
+  Result := FModulus;
+end;
+
+end.

+ 183 - 0
CryptoLib/src/Crypto/Parameters/ClpRsaPrivateCrtKeyParameters.pas

@@ -0,0 +1,183 @@
+{ *********************************************************************************** }
+{ *                              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 ClpRsaPrivateCrtKeyParameters;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpBigInteger,
+  ClpIRsaKeyParameters,
+  ClpIRsaPrivateCrtKeyParameters,
+  ClpRsaKeyParameters,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SNotValidRsaExponent = 'Not a valid RSA exponent';
+  SNotValidRsaPValue = 'Not a valid RSA P value';
+  SNotValidRsaQValue = 'Not a valid RSA Q value';
+  SNotValidRsaDPValue = 'Not a valid RSA DP value';
+  SNotValidRsaDQValue = 'Not a valid RSA DQ value';
+  SNotValidRsaInverseQValue = 'Not a valid RSA InverseQ value';
+
+type
+  TRsaPrivateCrtKeyParameters = class(TRsaKeyParameters, IRsaPrivateCrtKeyParameters)
+
+  strict private
+  var
+    Fe: TBigInteger;  // publicExponent
+    Fp: TBigInteger;
+    Fq: TBigInteger;
+    FdP: TBigInteger;
+    FdQ: TBigInteger;
+    FqInv: TBigInteger;
+
+    class procedure ValidateValue(const x: TBigInteger;
+      const paramName, desc: String); static;
+
+  strict protected
+    function GetPublicExponent: TBigInteger;
+    function GetP: TBigInteger;
+    function GetQ: TBigInteger;
+    function GetDP: TBigInteger;
+    function GetDQ: TBigInteger;
+    function GetQInv: TBigInteger;
+
+  public
+    constructor Create(const modulus, publicExponent, privateExponent,
+      p, q, dP, dQ, qInv: TBigInteger);
+
+    function Equals(const other: IRsaPrivateCrtKeyParameters): Boolean;
+      reintroduce; overload;
+    function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}override;
+
+    property PublicExponent: TBigInteger read GetPublicExponent;
+    property P: TBigInteger read GetP;
+    property Q: TBigInteger read GetQ;
+    property DP: TBigInteger read GetDP;
+    property DQ: TBigInteger read GetDQ;
+    property QInv: TBigInteger read GetQInv;
+
+  end;
+
+implementation
+
+{ TRsaPrivateCrtKeyParameters }
+
+class procedure TRsaPrivateCrtKeyParameters.ValidateValue(const x: TBigInteger;
+  const paramName, desc: String);
+begin
+  if not x.IsInitialized then
+  begin
+    raise EArgumentNilCryptoLibException.Create(paramName);
+  end;
+
+  if x.SignValue <= 0 then
+  begin
+    raise EArgumentCryptoLibException.Create('Not a valid RSA ' + desc);
+  end;
+end;
+
+constructor TRsaPrivateCrtKeyParameters.Create(const modulus, publicExponent,
+  privateExponent, p, q, dP, dQ, qInv: TBigInteger);
+begin
+  inherited Create(True, modulus, privateExponent);
+
+  ValidateValue(publicExponent, 'publicExponent', 'exponent');
+  ValidateValue(p, 'p', 'P value');
+  ValidateValue(q, 'q', 'Q value');
+  ValidateValue(dP, 'dP', 'DP value');
+  ValidateValue(dQ, 'dQ', 'DQ value');
+  ValidateValue(qInv, 'qInv', 'InverseQ value');
+
+  Fe := publicExponent;
+  Fp := p;
+  Fq := q;
+  FdP := dP;
+  FdQ := dQ;
+  FqInv := qInv;
+end;
+
+function TRsaPrivateCrtKeyParameters.Equals(
+  const other: IRsaPrivateCrtKeyParameters): Boolean;
+begin
+  if other = nil then
+  begin
+    Result := False;
+    Exit;
+  end;
+
+  if ((Self as IRsaPrivateCrtKeyParameters) = other) then
+  begin
+    Result := True;
+    Exit;
+  end;
+
+  Result := FdP.Equals(other.DP) and
+    FdQ.Equals(other.DQ) and
+    Exponent.Equals(other.Exponent) and
+    Modulus.Equals(other.Modulus) and
+    Fp.Equals(other.P) and
+    Fq.Equals(other.Q) and
+    Fe.Equals(other.PublicExponent) and
+    FqInv.Equals(other.QInv);
+end;
+
+function TRsaPrivateCrtKeyParameters.GetDP: TBigInteger;
+begin
+  Result := FdP;
+end;
+
+function TRsaPrivateCrtKeyParameters.GetDQ: TBigInteger;
+begin
+  Result := FdQ;
+end;
+
+function TRsaPrivateCrtKeyParameters.GetHashCode: {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}
+begin
+  Result := FdP.GetHashCode() xor FdQ.GetHashCode() xor
+    Exponent.GetHashCode() xor Modulus.GetHashCode() xor
+    Fp.GetHashCode() xor Fq.GetHashCode() xor
+    Fe.GetHashCode() xor FqInv.GetHashCode();
+end;
+
+function TRsaPrivateCrtKeyParameters.GetP: TBigInteger;
+begin
+  Result := Fp;
+end;
+
+function TRsaPrivateCrtKeyParameters.GetPublicExponent: TBigInteger;
+begin
+  Result := Fe;
+end;
+
+function TRsaPrivateCrtKeyParameters.GetQ: TBigInteger;
+begin
+  Result := Fq;
+end;
+
+function TRsaPrivateCrtKeyParameters.GetQInv: TBigInteger;
+begin
+  Result := FqInv;
+end;
+
+end.

+ 390 - 0
CryptoLib/src/Crypto/Signers/ClpRsaDigestSigner.pas

@@ -0,0 +1,390 @@
+{ *********************************************************************************** }
+{ *                              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 ClpRsaDigestSigner;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  Generics.Collections,
+  ClpICipherParameters,
+  ClpIAsymmetricKeyParameter,
+  ClpIParametersWithRandom,
+  ClpParameterUtilities,
+  ClpIDigest,
+  ClpIRsa,
+  ClpIAsymmetricBlockCipher,
+  ClpISigner,
+  ClpIRsaDigestSigner,
+  ClpIRsaCoreEngine,
+  ClpRsaCoreEngine,
+  ClpIRsaBlindedEngine,
+  ClpRsaBlindedEngine,
+  ClpIPkcs1Encoding,
+  ClpPkcs1Encoding,
+  ClpIAlgorithmIdentifier,
+  ClpAlgorithmIdentifier,
+  ClpIDigestInfo,
+  ClpDigestInfo,
+  ClpIAsn1Objects,
+  ClpAsn1Objects,
+  ClpX509ObjectIdentifiers,
+  ClpNistObjectIdentifiers,
+  ClpPkcsObjectIdentifiers,
+  ClpTeleTrusTObjectIdentifiers,
+  ClpArrayUtils,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SSigningRequiresPrivateKey = 'Signing requires private key.';
+  SVerificationRequiresPublicKey = 'Verification requires public key.';
+  SNotInitForSignature = 'RsaDigestSigner not initialised for signature generation.';
+  SNotInitForVerification = 'RsaDigestSigner not initialised for verification';
+  SUnableToEncode = 'unable to encode signature: ';
+
+type
+  /// <summary>
+  /// RSA signer that uses a digest algorithm and PKCS#1 v1.5 padding.
+  /// </summary>
+  TRsaDigestSigner = class(TInterfacedObject, ISigner, IRsaDigestSigner)
+
+  strict private
+  class var
+    FOidMap: TDictionary<String, IDerObjectIdentifier>;
+
+  var
+    FEngine: IAsymmetricBlockCipher;
+    FDigestAlgID: IAlgorithmIdentifier;
+    FDigest: IDigest;
+    FForSigning: Boolean;
+
+    class constructor CreateRsaDigestSigner();
+    class destructor DestroyRsaDigestSigner();
+
+    class function CheckDerEncoded(const hash: TCryptoLibByteArray): TCryptoLibByteArray; static;
+    function DerEncode(const digestAlgID: IAlgorithmIdentifier;
+      const hash: TCryptoLibByteArray): TCryptoLibByteArray;
+    class function TryGetAltAlgID(const algID: IAlgorithmIdentifier;
+      out altAlgID: IAlgorithmIdentifier): Boolean; static;
+
+  strict protected
+    function GetAlgorithmName: String;
+
+  public
+    constructor Create(const digest: IDigest); overload;
+    constructor Create(const digest: IDigest;
+      const digestOid: IDerObjectIdentifier); overload;
+    constructor Create(const digest: IDigest;
+      const algId: IAlgorithmIdentifier); overload;
+    constructor Create(const rsa: IRsa; const digest: IDigest;
+      const digestOid: IDerObjectIdentifier); overload;
+    constructor Create(const rsa: IRsa; const digest: IDigest;
+      const algId: IAlgorithmIdentifier); overload;
+    constructor Create(const rsaEngine: IAsymmetricBlockCipher;
+      const digest: IDigest;
+      const algId: IAlgorithmIdentifier); overload;
+
+    procedure Init(forSigning: Boolean; const parameters: ICipherParameters);
+    procedure Update(input: Byte);
+    procedure BlockUpdate(const input: TCryptoLibByteArray; inOff, len: Int32);
+    function GetMaxSignatureSize: Int32;
+    function GenerateSignature(): TCryptoLibByteArray;
+    function VerifySignature(const signature: TCryptoLibByteArray): Boolean;
+    procedure Reset();
+
+    property AlgorithmName: String read GetAlgorithmName;
+
+  end;
+
+implementation
+
+{ TRsaDigestSigner }
+
+class constructor TRsaDigestSigner.CreateRsaDigestSigner;
+begin
+  FOidMap := TDictionary<String, IDerObjectIdentifier>.Create();
+
+  FOidMap.Add('RIPEMD128', TTeleTrusTObjectIdentifiers.RipeMD128);
+  FOidMap.Add('RIPEMD160', TTeleTrusTObjectIdentifiers.RipeMD160);
+  FOidMap.Add('RIPEMD256', TTeleTrusTObjectIdentifiers.RipeMD256);
+
+  FOidMap.Add('SHA-1', TX509ObjectIdentifiers.IdSha1);
+  FOidMap.Add('SHA-224', TNistObjectIdentifiers.IdSha224);
+  FOidMap.Add('SHA-256', TNistObjectIdentifiers.IdSha256);
+  FOidMap.Add('SHA-384', TNistObjectIdentifiers.IdSha384);
+  FOidMap.Add('SHA-512', TNistObjectIdentifiers.IdSha512);
+  FOidMap.Add('SHA-512/224', TNistObjectIdentifiers.IdSha512_224);
+  FOidMap.Add('SHA-512/256', TNistObjectIdentifiers.IdSha512_256);
+  FOidMap.Add('SHA3-224', TNistObjectIdentifiers.IdSha3_224);
+  FOidMap.Add('SHA3-256', TNistObjectIdentifiers.IdSha3_256);
+  FOidMap.Add('SHA3-384', TNistObjectIdentifiers.IdSha3_384);
+  FOidMap.Add('SHA3-512', TNistObjectIdentifiers.IdSha3_512);
+
+  FOidMap.Add('MD2', TPkcsObjectIdentifiers.MD2);
+  FOidMap.Add('MD4', TPkcsObjectIdentifiers.MD4);
+  FOidMap.Add('MD5', TPkcsObjectIdentifiers.MD5);
+end;
+
+class destructor TRsaDigestSigner.DestroyRsaDigestSigner;
+begin
+  FOidMap.Free;
+end;
+
+constructor TRsaDigestSigner.Create(const digest: IDigest);
+var
+  oid: IDerObjectIdentifier;
+begin
+  if FOidMap.TryGetValue(digest.AlgorithmName, oid) then
+    Create(digest, oid)
+  else
+  begin
+    oid := nil;
+    Create(digest, oid);
+  end;
+end;
+
+constructor TRsaDigestSigner.Create(const digest: IDigest;
+  const digestOid: IDerObjectIdentifier);
+var
+  algId: IAlgorithmIdentifier;
+begin
+  if digestOid <> nil then
+    algId := TAlgorithmIdentifier.Create(digestOid, TDerNull.Instance)
+  else
+    algId := nil;
+
+  Create(digest, algId);
+end;
+
+constructor TRsaDigestSigner.Create(const digest: IDigest;
+  const algId: IAlgorithmIdentifier);
+begin
+  Create(TRsaCoreEngine.Create() as IRsa, digest, algId);
+end;
+
+constructor TRsaDigestSigner.Create(const rsa: IRsa; const digest: IDigest;
+  const digestOid: IDerObjectIdentifier);
+var
+  algId: IAlgorithmIdentifier;
+begin
+  if digestOid <> nil then
+    algId := TAlgorithmIdentifier.Create(digestOid, TDerNull.Instance)
+  else
+    algId := nil;
+
+  Create(rsa, digest, algId);
+end;
+
+constructor TRsaDigestSigner.Create(const rsa: IRsa; const digest: IDigest;
+  const algId: IAlgorithmIdentifier);
+begin
+  Create(TRsaBlindedEngine.Create(rsa) as IAsymmetricBlockCipher, digest, algId);
+end;
+
+constructor TRsaDigestSigner.Create(const rsaEngine: IAsymmetricBlockCipher;
+  const digest: IDigest; const algId: IAlgorithmIdentifier);
+begin
+  inherited Create();
+  FEngine := TPkcs1Encoding.Create(rsaEngine) as IAsymmetricBlockCipher;
+  FDigest := digest;
+  FDigestAlgID := algId;
+end;
+
+function TRsaDigestSigner.GetAlgorithmName: String;
+begin
+  Result := FDigest.AlgorithmName + 'withRSA';
+end;
+
+procedure TRsaDigestSigner.Init(forSigning: Boolean;
+  const parameters: ICipherParameters);
+var
+  key: IAsymmetricKeyParameter;
+begin
+  FForSigning := forSigning;
+
+  key := TParameterUtilities.IgnoreRandom(parameters) as IAsymmetricKeyParameter;
+
+  if forSigning and (not key.IsPrivate) then
+  begin
+    raise EInvalidKeyCryptoLibException.CreateRes(@SSigningRequiresPrivateKey);
+  end;
+
+  if (not forSigning) and key.IsPrivate then
+  begin
+    raise EInvalidKeyCryptoLibException.CreateRes(@SVerificationRequiresPublicKey);
+  end;
+
+  Reset();
+  FEngine.Init(forSigning, parameters);
+end;
+
+procedure TRsaDigestSigner.Update(input: Byte);
+begin
+  FDigest.Update(input);
+end;
+
+procedure TRsaDigestSigner.BlockUpdate(const input: TCryptoLibByteArray;
+  inOff, len: Int32);
+begin
+  FDigest.BlockUpdate(input, inOff, len);
+end;
+
+function TRsaDigestSigner.GetMaxSignatureSize: Int32;
+begin
+  Result := FEngine.OutputBlockSize;
+end;
+
+class function TRsaDigestSigner.CheckDerEncoded(
+  const hash: TCryptoLibByteArray): TCryptoLibByteArray;
+begin
+  // Validate that hash is a valid DER-encoded DigestInfo
+  TDigestInfo.GetInstance(hash);
+  Result := hash;
+end;
+
+function TRsaDigestSigner.GenerateSignature: TCryptoLibByteArray;
+var
+  hash, data: TCryptoLibByteArray;
+begin
+  if not FForSigning then
+    raise EInvalidOperationCryptoLibException.CreateRes(@SNotInitForSignature);
+
+  //SetLength(hash, FDigest.GetDigestSize);
+  //FDigest.DoFinal(hash, 0);
+  hash := FDigest.DoFinal();
+
+  try
+    if FDigestAlgID = nil then
+      data := CheckDerEncoded(hash)
+    else
+      data := DerEncode(FDigestAlgID, hash);
+
+    Result := FEngine.ProcessBlock(data, 0, System.Length(data));
+  except
+    on E: EIOCryptoLibException do
+    begin
+      // IO errors should be reported as encoding failures
+      raise ECryptoLibException.Create(SUnableToEncode + E.Message);
+    end;
+
+    on E: ECryptoLibException do
+    begin
+      // All other CryptoLib exceptions propagate unchanged
+      raise;
+    end;
+
+    on E: Exception do
+    begin
+      // Non-crypto exceptions get wrapped
+      raise ECryptoLibException.Create(SUnableToEncode + E.Message);
+    end;
+  end;
+end;
+
+function TRsaDigestSigner.VerifySignature(
+  const signature: TCryptoLibByteArray): Boolean;
+var
+  sig, hash, expected: TCryptoLibByteArray;
+  altAlgID: IAlgorithmIdentifier;
+begin
+  if FForSigning then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes(@SNotInitForVerification);
+  end;
+
+  try
+    sig := FEngine.ProcessBlock(signature, 0, System.Length(signature));
+  except
+    Result := False;
+    Exit;
+  end;
+
+  //SetLength(hash, FDigest.GetDigestSize);
+  //FDigest.DoFinal(hash, 0);
+  hash := FDigest.DoFinal();
+
+  if FDigestAlgID = nil then
+  begin
+    Result := TArrayUtils.ConstantTimeAreEqual(sig, CheckDerEncoded(hash));
+    Exit;
+  end;
+
+  expected := DerEncode(FDigestAlgID, hash);
+  if TArrayUtils.ConstantTimeAreEqual(sig, expected) then
+  begin
+    Result := True;
+    Exit;
+  end;
+
+  // Try alternate algorithm identifier encoding (with/without DerNull)
+  if TryGetAltAlgID(FDigestAlgID, altAlgID) then
+  begin
+    expected := DerEncode(altAlgID, hash);
+    if TArrayUtils.ConstantTimeAreEqual(sig, expected) then
+    begin
+      Result := True;
+      Exit;
+    end;
+  end;
+
+  Result := False;
+end;
+
+procedure TRsaDigestSigner.Reset;
+begin
+  FDigest.Reset();
+end;
+
+function TRsaDigestSigner.DerEncode(const digestAlgID: IAlgorithmIdentifier;
+  const hash: TCryptoLibByteArray): TCryptoLibByteArray;
+var
+  digestInfo: IDigestInfo;
+  digestOctetString: IDerOctetString;
+begin
+  if System.Length(hash) < 1 then
+    digestOctetString := TDerOctetString.Create(nil)
+  else
+    digestOctetString := TDerOctetString.Create(hash);
+
+  digestInfo := TDigestInfo.Create(digestAlgID, digestOctetString as IAsn1OctetString);
+  Result := digestInfo.GetDerEncoded();
+end;
+
+class function TRsaDigestSigner.TryGetAltAlgID(const algID: IAlgorithmIdentifier;
+  out altAlgID: IAlgorithmIdentifier): Boolean;
+begin
+  if algID.Parameters = nil then
+  begin
+    altAlgID := TAlgorithmIdentifier.Create(algID.Algorithm, TDerNull.Instance);
+    Result := True;
+  end
+  else if TDerNull.Instance.Equals(algID.Parameters) then
+  begin
+    altAlgID := TAlgorithmIdentifier.Create(algID.Algorithm, nil);
+    Result := True;
+  end
+  else
+  begin
+    altAlgID := nil;
+    Result := False;
+  end;
+end;
+
+end.

+ 50 - 0
CryptoLib/src/Interfaces/ClpIAlgorithmIdentifier.pas

@@ -0,0 +1,50 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIAlgorithmIdentifier;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIAsn1Objects;
+
+type
+  /// <summary>
+  /// Interface for the AlgorithmIdentifier object.
+  /// <code>
+  /// AlgorithmIdentifier ::= SEQUENCE {
+  ///   algorithm OBJECT IDENTIFIER,
+  ///   parameters ANY DEFINED BY algorithm OPTIONAL
+  /// }
+  /// </code>
+  /// </summary>
+  IAlgorithmIdentifier = interface(IAsn1Encodable)
+    ['{E7F8A9B0-C1D2-E3F4-A5B6-C7D8E9F0A1B2}']
+
+    function GetAlgorithm: IDerObjectIdentifier;
+    function GetParameters: IAsn1Encodable;
+
+    property Algorithm: IDerObjectIdentifier read GetAlgorithm;
+    property Parameters: IAsn1Encodable read GetParameters;
+
+  end;
+
+implementation
+
+end.

+ 79 - 0
CryptoLib/src/Interfaces/ClpIAsymmetricBlockCipher.pas

@@ -0,0 +1,79 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIAsymmetricBlockCipher;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpICipherParameters,
+  ClpCryptoLibTypes;
+
+type
+  /// <summary>
+  /// Base interface for a public/private key block cipher.
+  /// </summary>
+  IAsymmetricBlockCipher = interface(IInterface)
+    ['{D4E5F6A7-B8C9-0123-DEF0-123456789ABC}']
+
+    /// <summary>
+    /// The name of the algorithm this cipher implements.
+    /// </summary>
+    function GetAlgorithmName: String;
+
+    /// <summary>
+    /// Initialise the cipher.
+    /// </summary>
+    /// <param name="forEncryption">
+    /// Initialise for encryption if true, for decryption if false.
+    /// </param>
+    /// <param name="parameters">
+    /// The key or other data required by the cipher.
+    /// </param>
+    procedure Init(forEncryption: Boolean; const parameters: ICipherParameters);
+
+    /// <summary>
+    /// The maximum size, in bytes, an input block may be.
+    /// </summary>
+    function GetInputBlockSize: Int32;
+
+    /// <summary>
+    /// The maximum size, in bytes, an output block will be.
+    /// </summary>
+    function GetOutputBlockSize: Int32;
+
+    /// <summary>
+    /// Process a block.
+    /// </summary>
+    /// <param name="inBuf">The input buffer.</param>
+    /// <param name="inOff">The offset into inBuf that the input block begins.</param>
+    /// <param name="inLen">The length of the input block.</param>
+    /// <returns>The processed block.</returns>
+    function ProcessBlock(const inBuf: TCryptoLibByteArray;
+      inOff, inLen: Int32): TCryptoLibByteArray;
+
+    property AlgorithmName: String read GetAlgorithmName;
+    property InputBlockSize: Int32 read GetInputBlockSize;
+    property OutputBlockSize: Int32 read GetOutputBlockSize;
+
+  end;
+
+implementation
+
+end.

+ 37 - 0
CryptoLib/src/Interfaces/ClpIBufferedAsymmetricBlockCipher.pas

@@ -0,0 +1,37 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIBufferedAsymmetricBlockCipher;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIBufferedCipher;
+
+type
+  /// <summary>
+  /// Interface for a buffer wrapper for an asymmetric block cipher.
+  /// </summary>
+  IBufferedAsymmetricBlockCipher = interface(IBufferedCipher)
+    ['{B2C4D6E8-F0A2-4B3C-9D5E-7F0A2B4C6D8E}']
+  end;
+
+implementation
+
+end.

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

@@ -71,6 +71,8 @@ type
     /// </param>
     /// </param>
     procedure BlockUpdate(const input: TCryptoLibByteArray; inOff, len: Int32);
     procedure BlockUpdate(const input: TCryptoLibByteArray; inOff, len: Int32);
 
 
+    function DoFinal: TCryptoLibByteArray; overload;
+
     /// <summary>
     /// <summary>
     /// Close the digest, producing the final digest value. The doFinal call
     /// Close the digest, producing the final digest value. The doFinal call
     /// leaves the digest reset.
     /// leaves the digest reset.
@@ -81,7 +83,7 @@ type
     /// <param name="outOff">
     /// <param name="outOff">
     /// the offset into the out array the digest is to start at.
     /// the offset into the out array the digest is to start at.
     /// </param>
     /// </param>
-    function DoFinal(const output: TCryptoLibByteArray; outOff: Int32): Int32;
+    function DoFinal(const output: TCryptoLibByteArray; outOff: Int32): Int32; overload;
 
 
     /// <summary>
     /// <summary>
     /// Resets the digest back to it's initial state.
     /// Resets the digest back to it's initial state.

+ 52 - 0
CryptoLib/src/Interfaces/ClpIDigestInfo.pas

@@ -0,0 +1,52 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIDigestInfo;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIAlgorithmIdentifier,
+  ClpIAsn1Objects,
+  ClpCryptoLibTypes;
+
+type
+  /// <summary>
+  /// Interface for the DigestInfo object.
+  /// DigestInfo ::= SEQUENCE {
+  ///   digestAlgorithm AlgorithmIdentifier,
+  ///   digest OCTET STRING
+  /// }
+  /// </summary>
+  IDigestInfo = interface(IAsn1Encodable)
+    ['{A1B2C3D4-E5F6-7890-ABCD-0123456789AB}']
+
+    function GetDigestAlgorithm: IAlgorithmIdentifier;
+    function GetDigest: IAsn1OctetString;
+    function GetDigestBytes: TCryptoLibByteArray;
+    function GetDerEncoded: TCryptoLibByteArray;
+
+    property DigestAlgorithm: IAlgorithmIdentifier read GetDigestAlgorithm;
+    property Digest: IAsn1OctetString read GetDigest;
+
+  end;
+
+implementation
+
+end.

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

@@ -0,0 +1,45 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpIISO9796d1Encoding;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIAsymmetricBlockCipher;
+
+type
+  /// <summary>
+  /// Interface for ISO 9796-1 encoding.
+  /// </summary>
+  IISO9796d1Encoding = interface(IAsymmetricBlockCipher)
+    ['{E1F2A3B4-C5D6-7890-1234-56789ABCDEF0}']
+
+    function GetUnderlyingCipher: IAsymmetricBlockCipher;
+    procedure SetPadBits(padBits: Int32);
+    function GetPadBits: Int32;
+
+    property UnderlyingCipher: IAsymmetricBlockCipher read GetUnderlyingCipher;
+    property PadBits: Int32 read GetPadBits write SetPadBits;
+
+  end;
+
+implementation
+
+end.

+ 41 - 0
CryptoLib/src/Interfaces/ClpIOaepEncoding.pas

@@ -0,0 +1,41 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIOaepEncoding;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIAsymmetricBlockCipher;
+
+type
+  /// <summary>
+  /// Interface for OAEP encoding.
+  /// </summary>
+  IOaepEncoding = interface(IAsymmetricBlockCipher)
+    ['{C9D0E1F2-A3B4-5678-9012-3456789ABCDE}']
+
+    function GetUnderlyingCipher: IAsymmetricBlockCipher;
+    property UnderlyingCipher: IAsymmetricBlockCipher read GetUnderlyingCipher;
+
+  end;
+
+implementation
+
+end.

+ 41 - 0
CryptoLib/src/Interfaces/ClpIPkcs1Encoding.pas

@@ -0,0 +1,41 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIPkcs1Encoding;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIAsymmetricBlockCipher;
+
+type
+  /// <summary>
+  /// Interface for PKCS#1 v1.5 encoding.
+  /// </summary>
+  IPkcs1Encoding = interface(IAsymmetricBlockCipher)
+    ['{B8C9D0E1-F2A3-4567-8901-23456789ABCD}']
+
+    function GetUnderlyingCipher: IAsymmetricBlockCipher;
+    property UnderlyingCipher: IAsymmetricBlockCipher read GetUnderlyingCipher;
+
+  end;
+
+implementation
+
+end.

+ 50 - 0
CryptoLib/src/Interfaces/ClpIRsa.pas

@@ -0,0 +1,50 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIRsa;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpBigInteger,
+  ClpICipherParameters,
+  ClpCryptoLibTypes;
+
+type
+  /// <summary>
+  /// Base interface for RSA engine implementations.
+  /// </summary>
+  IRsa = interface(IInterface)
+    ['{D4E5F6A7-B8C9-0123-4567-89ABCDEF0123}']
+
+    procedure Init(forEncryption: Boolean; const parameters: ICipherParameters);
+    function GetInputBlockSize: Int32;
+    function GetOutputBlockSize: Int32;
+    function ConvertInput(const buf: TCryptoLibByteArray; off, len: Int32): TBigInteger;
+    function ProcessBlock(const input: TBigInteger): TBigInteger;
+    function ConvertOutput(const result: TBigInteger): TCryptoLibByteArray;
+
+    property InputBlockSize: Int32 read GetInputBlockSize;
+    property OutputBlockSize: Int32 read GetOutputBlockSize;
+
+  end;
+
+implementation
+
+end.

+ 38 - 0
CryptoLib/src/Interfaces/ClpIRsaBlindedEngine.pas

@@ -0,0 +1,38 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIRsaBlindedEngine;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIAsymmetricBlockCipher;
+
+type
+  /// <summary>
+  /// Interface for blinded RSA engine implementing IAsymmetricBlockCipher.
+  /// Wraps IRsa with random blinding for side-channel protection.
+  /// </summary>
+  IRsaBlindedEngine = interface(IAsymmetricBlockCipher)
+    ['{F6A7B8C9-D0E1-2345-F012-3456789ABCDE}']
+  end;
+
+implementation
+
+end.

+ 37 - 0
CryptoLib/src/Interfaces/ClpIRsaBlindingEngine.pas

@@ -0,0 +1,37 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIRsaBlindingEngine;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIAsymmetricBlockCipher;
+
+type
+  /// <summary>
+  /// Interface for RSA Blinding Engine - used for Chaum's blind signatures.
+  /// </summary>
+  IRsaBlindingEngine = interface(IAsymmetricBlockCipher)
+    ['{A1B3C5D7-E9F1-4A3B-8C5D-7E9F1A3B5C7D}']
+  end;
+
+implementation
+
+end.

+ 42 - 0
CryptoLib/src/Interfaces/ClpIRsaBlindingFactorGenerator.pas

@@ -0,0 +1,42 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIRsaBlindingFactorGenerator;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpBigInteger,
+  ClpICipherParameters;
+
+type
+  /// <summary>
+  /// Interface for RSA blinding factor generator.
+  /// </summary>
+  IRsaBlindingFactorGenerator = interface(IInterface)
+    ['{A3B4C5D6-E7F8-9012-3456-789ABCDEF012}']
+
+    procedure Init(const param: ICipherParameters);
+    function GenerateBlindingFactor: TBigInteger;
+
+  end;
+
+implementation
+
+end.

+ 46 - 0
CryptoLib/src/Interfaces/ClpIRsaBlindingParameters.pas

@@ -0,0 +1,46 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIRsaBlindingParameters;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpBigInteger,
+  ClpIRsaKeyParameters,
+  ClpICipherParameters;
+
+type
+  /// <summary>
+  /// Interface for RSA blinding parameters.
+  /// </summary>
+  IRsaBlindingParameters = interface(ICipherParameters)
+    ['{F2A3B4C5-D6E7-8901-2345-6789ABCDEF01}']
+
+    function GetPublicKey: IRsaKeyParameters;
+    function GetBlindingFactor: TBigInteger;
+
+    property PublicKey: IRsaKeyParameters read GetPublicKey;
+    property BlindingFactor: TBigInteger read GetBlindingFactor;
+
+  end;
+
+implementation
+
+end.

+ 37 - 0
CryptoLib/src/Interfaces/ClpIRsaCoreEngine.pas

@@ -0,0 +1,37 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIRsaCoreEngine;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIRsa;
+
+type
+  /// <summary>
+  /// Interface for the core RSA engine.
+  /// </summary>
+  IRsaCoreEngine = interface(IRsa)
+    ['{E5F6A7B8-C9D0-1234-EF01-23456789ABCD}']
+  end;
+
+implementation
+
+end.

+ 37 - 0
CryptoLib/src/Interfaces/ClpIRsaDigestSigner.pas

@@ -0,0 +1,37 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIRsaDigestSigner;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpISigner;
+
+type
+  /// <summary>
+  /// Interface for RSA digest signer.
+  /// </summary>
+  IRsaDigestSigner = interface(ISigner)
+    ['{D0E1F2A3-B4C5-6789-0123-456789ABCDEF}']
+  end;
+
+implementation
+
+end.

+ 38 - 0
CryptoLib/src/Interfaces/ClpIRsaEngine.pas

@@ -0,0 +1,38 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIRsaEngine;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIAsymmetricBlockCipher;
+
+type
+  /// <summary>
+  /// Interface for RSA engine implementing IAsymmetricBlockCipher.
+  /// This is a wrapper around IRsa that provides byte[] processing.
+  /// </summary>
+  IRsaEngine = interface(IAsymmetricBlockCipher)
+    ['{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}']
+  end;
+
+implementation
+
+end.

+ 44 - 0
CryptoLib/src/Interfaces/ClpIRsaKeyGenerationParameters.pas

@@ -0,0 +1,44 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIRsaKeyGenerationParameters;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpBigInteger,
+  ClpIKeyGenerationParameters;
+
+type
+  IRsaKeyGenerationParameters = interface(IKeyGenerationParameters)
+    ['{C3D4E5F6-A7B8-9012-CDEF-123456789012}']
+
+    function GetPublicExponent: TBigInteger;
+    function GetCertainty: Int32;
+
+    function Equals(const other: IRsaKeyGenerationParameters): Boolean;
+
+    property PublicExponent: TBigInteger read GetPublicExponent;
+    property Certainty: Int32 read GetCertainty;
+
+  end;
+
+implementation
+
+end.

+ 34 - 0
CryptoLib/src/Interfaces/ClpIRsaKeyPairGenerator.pas

@@ -0,0 +1,34 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIRsaKeyPairGenerator;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIAsymmetricCipherKeyPairGenerator;
+
+type
+  IRsaKeyPairGenerator = interface(IAsymmetricCipherKeyPairGenerator)
+    ['{A7B8C9D0-E1F2-3456-0123-456789ABCDEF}']
+  end;
+
+implementation
+
+end.

+ 44 - 0
CryptoLib/src/Interfaces/ClpIRsaKeyParameters.pas

@@ -0,0 +1,44 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIRsaKeyParameters;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpBigInteger,
+  ClpIAsymmetricKeyParameter;
+
+type
+  IRsaKeyParameters = interface(IAsymmetricKeyParameter)
+    ['{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}']
+
+    function GetModulus: TBigInteger;
+    function GetExponent: TBigInteger;
+
+    function Equals(const other: IRsaKeyParameters): Boolean; overload;
+
+    property Modulus: TBigInteger read GetModulus;
+    property Exponent: TBigInteger read GetExponent;
+
+  end;
+
+implementation
+
+end.

+ 50 - 0
CryptoLib/src/Interfaces/ClpIRsaPrivateCrtKeyParameters.pas

@@ -0,0 +1,50 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIRsaPrivateCrtKeyParameters;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpBigInteger,
+  ClpIRsaKeyParameters;
+
+type
+  IRsaPrivateCrtKeyParameters = interface(IRsaKeyParameters)
+    ['{B2C3D4E5-F6A7-8901-BCDE-F12345678901}']
+
+    function GetPublicExponent: TBigInteger;
+    function GetP: TBigInteger;
+    function GetQ: TBigInteger;
+    function GetDP: TBigInteger;
+    function GetDQ: TBigInteger;
+    function GetQInv: TBigInteger;
+
+    property PublicExponent: TBigInteger read GetPublicExponent;
+    property P: TBigInteger read GetP;
+    property Q: TBigInteger read GetQ;
+    property DP: TBigInteger read GetDP;
+    property DQ: TBigInteger read GetDQ;
+    property QInv: TBigInteger read GetQInv;
+
+  end;
+
+implementation
+
+end.

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

@@ -393,6 +393,44 @@ contains
   ClpIMultipliers in '..\..\Interfaces\ClpIMultipliers.pas',
   ClpIMultipliers in '..\..\Interfaces\ClpIMultipliers.pas',
   ClpECCompUtilities in '..\..\Math\EC\ClpECCompUtilities.pas',
   ClpECCompUtilities in '..\..\Math\EC\ClpECCompUtilities.pas',
   ClpIKMac in '..\..\Interfaces\ClpIKMac.pas',
   ClpIKMac in '..\..\Interfaces\ClpIKMac.pas',
-  ClpKMac in '..\..\Crypto\Macs\ClpKMac.pas';
+  ClpKMac in '..\..\Crypto\Macs\ClpKMac.pas',
+  { RSA Implementation }
+  ClpIRsa in '..\..\Interfaces\ClpIRsa.pas',
+  ClpIRsaKeyParameters in '..\..\Interfaces\ClpIRsaKeyParameters.pas',
+  ClpRsaKeyParameters in '..\..\Crypto\Parameters\ClpRsaKeyParameters.pas',
+  ClpIRsaPrivateCrtKeyParameters in '..\..\Interfaces\ClpIRsaPrivateCrtKeyParameters.pas',
+  ClpRsaPrivateCrtKeyParameters in '..\..\Crypto\Parameters\ClpRsaPrivateCrtKeyParameters.pas',
+  ClpIRsaKeyGenerationParameters in '..\..\Interfaces\ClpIRsaKeyGenerationParameters.pas',
+  ClpRsaKeyGenerationParameters in '..\..\Crypto\Parameters\ClpRsaKeyGenerationParameters.pas',
+  ClpIAsymmetricBlockCipher in '..\..\Interfaces\ClpIAsymmetricBlockCipher.pas',
+  ClpIRsaCoreEngine in '..\..\Interfaces\ClpIRsaCoreEngine.pas',
+  ClpRsaCoreEngine in '..\..\Crypto\Engines\ClpRsaCoreEngine.pas',
+  ClpIRsaBlindedEngine in '..\..\Interfaces\ClpIRsaBlindedEngine.pas',
+  ClpRsaBlindedEngine in '..\..\Crypto\Engines\ClpRsaBlindedEngine.pas',
+  ClpIRsaEngine in '..\..\Interfaces\ClpIRsaEngine.pas',
+  ClpRsaEngine in '..\..\Crypto\Engines\ClpRsaEngine.pas',
+  ClpIRsaKeyPairGenerator in '..\..\Interfaces\ClpIRsaKeyPairGenerator.pas',
+  ClpRsaKeyPairGenerator in '..\..\Crypto\Generators\ClpRsaKeyPairGenerator.pas',
+  ClpIPkcs1Encoding in '..\..\Interfaces\ClpIPkcs1Encoding.pas',
+  ClpPkcs1Encoding in '..\..\Crypto\Encodings\ClpPkcs1Encoding.pas',
+  ClpIOaepEncoding in '..\..\Interfaces\ClpIOaepEncoding.pas',
+  ClpOaepEncoding in '..\..\Crypto\Encodings\ClpOaepEncoding.pas',
+  ClpIISO9796d1Encoding in '..\..\Interfaces\ClpIISO9796d1Encoding.pas',
+  ClpISO9796d1Encoding in '..\..\Crypto\Encodings\ClpISO9796d1Encoding.pas',
+  ClpIRsaDigestSigner in '..\..\Interfaces\ClpIRsaDigestSigner.pas',
+  ClpRsaDigestSigner in '..\..\Crypto\Signers\ClpRsaDigestSigner.pas',
+  ClpIRsaBlindingParameters in '..\..\Interfaces\ClpIRsaBlindingParameters.pas',
+  ClpRsaBlindingParameters in '..\..\Crypto\Parameters\ClpRsaBlindingParameters.pas',
+  ClpIRsaBlindingFactorGenerator in '..\..\Interfaces\ClpIRsaBlindingFactorGenerator.pas',
+  ClpRsaBlindingFactorGenerator in '..\..\Crypto\Generators\ClpRsaBlindingFactorGenerator.pas',
+  ClpIAlgorithmIdentifier in '..\..\Interfaces\ClpIAlgorithmIdentifier.pas',
+  ClpAlgorithmIdentifier in '..\..\Asn1\X509\ClpAlgorithmIdentifier.pas',
+  ClpIDigestInfo in '..\..\Interfaces\ClpIDigestInfo.pas',
+  ClpDigestInfo in '..\..\Asn1\X509\ClpDigestInfo.pas',
+  ClpX509ObjectIdentifiers in '..\..\Asn1\X509\ClpX509ObjectIdentifiers.pas',
+  ClpIRsaBlindingEngine in '..\..\Interfaces\ClpIRsaBlindingEngine.pas',
+  ClpRsaBlindingEngine in '..\..\Crypto\Engines\ClpRsaBlindingEngine.pas',
+  ClpIBufferedAsymmetricBlockCipher in '..\..\Interfaces\ClpIBufferedAsymmetricBlockCipher.pas',
+  ClpBufferedAsymmetricBlockCipher in '..\..\Crypto\ClpBufferedAsymmetricBlockCipher.pas';
 
 
 end.
 end.

+ 70 - 5
CryptoLib/src/Security/ClpCipherUtilities.pas

@@ -35,9 +35,12 @@ uses
   ClpIBufferedBlockCipher,
   ClpIBufferedBlockCipher,
   ClpBufferedStreamCipher,
   ClpBufferedStreamCipher,
   ClpIBufferedStreamCipher,
   ClpIBufferedStreamCipher,
+  ClpBufferedAsymmetricBlockCipher,
+  ClpIBufferedAsymmetricBlockCipher,
   ClpPaddedBufferedBlockCipher,
   ClpPaddedBufferedBlockCipher,
   ClpIPaddedBufferedBlockCipher,
   ClpIPaddedBufferedBlockCipher,
   ClpNistObjectIdentifiers,
   ClpNistObjectIdentifiers,
+  ClpPkcsObjectIdentifiers,
   ClpIAsn1Objects,
   ClpIAsn1Objects,
   ClpIBufferedCipher,
   ClpIBufferedCipher,
   ClpIBlockCipher,
   ClpIBlockCipher,
@@ -50,6 +53,16 @@ uses
   ClpISalsa20Engine,
   ClpISalsa20Engine,
   ClpRijndaelEngine,
   ClpRijndaelEngine,
   ClpIRijndaelEngine,
   ClpIRijndaelEngine,
+  ClpPkcs1Encoding,
+  ClpIPkcs1Encoding,
+  ClpOaepEncoding,
+  ClpIOaepEncoding,
+  ClpISO9796d1Encoding,
+  ClpIISO9796d1Encoding,
+  ClpRsaBlindedEngine,
+  ClpIRsaBlindedEngine,
+  ClpIAsymmetricBlockCipher,
+  ClpDigestUtilities,
   ClpIBlockCipherPadding;
   ClpIBlockCipherPadding;
 
 
 resourcestring
 resourcestring
@@ -72,12 +85,14 @@ type
 
 
   type
   type
 {$SCOPEDENUMS ON}
 {$SCOPEDENUMS ON}
-    TCipherAlgorithm = (AES, BLOWFISH, SALSA20, RIJNDAEL);
+    TCipherAlgorithm = (AES, BLOWFISH, SALSA20, RIJNDAEL, RSA);
     TCipherMode = (NONE, CBC, CFB, CTR, CTS, ECB, OFB, SIC);
     TCipherMode = (NONE, CBC, CFB, CTR, CTS, ECB, OFB, SIC);
-    TCipherPadding = (NOPADDING, ISO10126PADDING, ISO10126D2PADDING,
-      ISO10126_2PADDING, ISO7816_4PADDING, ISO9797_1PADDING, PKCS5,
-      PKCS5PADDING, PKCS7, PKCS7PADDING, TBCPADDING, WITHCTS, X923PADDING,
-      ZEROBYTEPADDING);
+    TCipherPadding = (NOPADDING, RAW, ISO10126PADDING, ISO10126D2PADDING,
+      ISO10126_2PADDING, ISO7816_4PADDING, ISO9797_1PADDING, ISO9796_1,
+      ISO9796_1PADDING, OAEP, OAEPPADDING, OAEPWITHSHA1ANDMGF1PADDING,
+      OAEPWITHSHA_1ANDMGF1PADDING, OAEPWITHSHA256ANDMGF1PADDING,
+      OAEPWITHSHA_256ANDMGF1PADDING, PKCS1, PKCS1PADDING, PKCS5, PKCS5PADDING,
+      PKCS7, PKCS7PADDING, TBCPADDING, WITHCTS, X923PADDING, ZEROBYTEPADDING);
 {$SCOPEDENUMS OFF}
 {$SCOPEDENUMS OFF}
 
 
   class var
   class var
@@ -150,6 +165,14 @@ begin
 
 
   Falgorithms.Add('1.3.6.1.4.1.3029.1.2', 'BLOWFISH/CBC');
   Falgorithms.Add('1.3.6.1.4.1.3029.1.2', 'BLOWFISH/CBC');
 
 
+  TPkcsObjectIdentifiers.Boot;
+
+  // RSA
+  Falgorithms.Add('RSA/ECB/PKCS1', 'RSA//PKCS1PADDING');
+  Falgorithms.Add('RSA/ECB/PKCS1PADDING', 'RSA//PKCS1PADDING');
+  Falgorithms.Add(TPkcsObjectIdentifiers.RsaEncryption.Id, 'RSA//PKCS1PADDING');
+  Falgorithms.Add(TPkcsObjectIdentifiers.IdRsaesOaep.Id, 'RSA//OAEPPADDING');
+
 end;
 end;
 
 
 class constructor TCipherUtilities.CreateCipherUtilities;
 class constructor TCipherUtilities.CreateCipherUtilities;
@@ -196,6 +219,7 @@ var
   cipherPadding: TCipherPadding;
   cipherPadding: TCipherPadding;
   cipherMode: TCipherMode;
   cipherMode: TCipherMode;
   blockCipher: IBlockCipher;
   blockCipher: IBlockCipher;
+  asymBlockCipher: IAsymmetricBlockCipher;
   streamCipher: IStreamCipher;
   streamCipher: IStreamCipher;
   padding: IBlockCipherPadding;
   padding: IBlockCipherPadding;
 begin
 begin
@@ -213,6 +237,7 @@ begin
   parts := TStringUtils.SplitString(algorithm, '/');
   parts := TStringUtils.SplitString(algorithm, '/');
 
 
   blockCipher := Nil;
   blockCipher := Nil;
+  asymBlockCipher := Nil;
   streamCipher := Nil;
   streamCipher := Nil;
 
 
   algorithmName := parts[0];
   algorithmName := parts[0];
@@ -245,6 +270,10 @@ begin
     TCipherAlgorithm.SALSA20:
     TCipherAlgorithm.SALSA20:
       begin
       begin
         streamCipher := TSalsa20Engine.Create() as ISalsa20Engine;
         streamCipher := TSalsa20Engine.Create() as ISalsa20Engine;
+      end;
+    TCipherAlgorithm.RSA:
+      begin
+        asymBlockCipher := TRsaBlindedEngine.Create() as IRsaBlindedEngine;
       end
       end
   else
   else
     begin
     begin
@@ -287,6 +316,11 @@ begin
           padded := False;
           padded := False;
         end;
         end;
 
 
+      TCipherPadding.RAW:
+        begin
+          // Raw padding - do nothing
+        end;
+
       TCipherPadding.ISO10126PADDING, TCipherPadding.ISO10126D2PADDING,
       TCipherPadding.ISO10126PADDING, TCipherPadding.ISO10126D2PADDING,
         TCipherPadding.ISO10126_2PADDING:
         TCipherPadding.ISO10126_2PADDING:
         begin
         begin
@@ -298,6 +332,31 @@ begin
           padding := TISO7816d4Padding.Create() as IISO7816d4Padding;
           padding := TISO7816d4Padding.Create() as IISO7816d4Padding;
         end;
         end;
 
 
+      TCipherPadding.ISO9796_1, TCipherPadding.ISO9796_1PADDING:
+        begin
+          asymBlockCipher := TISO9796d1Encoding.Create(asymBlockCipher) as IISO9796d1Encoding;
+        end;
+
+      TCipherPadding.OAEP, TCipherPadding.OAEPPADDING:
+        begin
+          asymBlockCipher := TOaepEncoding.Create(asymBlockCipher) as IOaepEncoding;
+        end;
+
+      TCipherPadding.OAEPWITHSHA1ANDMGF1PADDING, TCipherPadding.OAEPWITHSHA_1ANDMGF1PADDING:
+        begin
+          asymBlockCipher := TOaepEncoding.Create(asymBlockCipher, TDigestUtilities.GetDigest('SHA-1')) as IOaepEncoding;
+        end;
+
+      TCipherPadding.OAEPWITHSHA256ANDMGF1PADDING, TCipherPadding.OAEPWITHSHA_256ANDMGF1PADDING:
+        begin
+          asymBlockCipher := TOaepEncoding.Create(asymBlockCipher, TDigestUtilities.GetDigest('SHA-256')) as IOaepEncoding;
+        end;
+
+      TCipherPadding.PKCS1, TCipherPadding.PKCS1PADDING:
+        begin
+          asymBlockCipher := TPkcs1Encoding.Create(asymBlockCipher) as IPkcs1Encoding;
+        end;
+
       TCipherPadding.PKCS5, TCipherPadding.PKCS5PADDING, TCipherPadding.PKCS7,
       TCipherPadding.PKCS5, TCipherPadding.PKCS5PADDING, TCipherPadding.PKCS7,
         TCipherPadding.PKCS7PADDING:
         TCipherPadding.PKCS7PADDING:
         begin
         begin
@@ -461,6 +520,12 @@ begin
     Exit;
     Exit;
   end;
   end;
 
 
+  if (asymBlockCipher <> Nil) then
+  begin
+    Result := TBufferedAsymmetricBlockCipher.Create(asymBlockCipher) as IBufferedAsymmetricBlockCipher;
+    Exit;
+  end;
+
   raise ESecurityUtilityCryptoLibException.CreateResFmt(@SUnRecognizedCipher,
   raise ESecurityUtilityCryptoLibException.CreateResFmt(@SUnRecognizedCipher,
     [algorithm]);
     [algorithm]);
 end;
 end;

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

@@ -59,7 +59,7 @@ type
       KECCAK_384, KECCAK_512, MD2, MD4, MD5, NONE, RIPEMD128, RIPEMD160,
       KECCAK_384, KECCAK_512, MD2, MD4, MD5, NONE, RIPEMD128, RIPEMD160,
       RIPEMD256, RIPEMD320, SHA_1, SHA_224, SHA_256, SHA_384, SHA_512,
       RIPEMD256, RIPEMD320, SHA_1, SHA_224, SHA_256, SHA_384, SHA_512,
       SHA_512_224, SHA_512_256, SHA3_224, SHA3_256, SHA3_384, SHA3_512,
       SHA_512_224, SHA_512_256, SHA3_224, SHA3_256, SHA3_384, SHA3_512,
-      SHAKE128, SHAKE256, TIGER, WHIRLPOOL);
+      SHAKE128_256, SHAKE256_512, TIGER, WHIRLPOOL);
 {$SCOPEDENUMS OFF}
 {$SCOPEDENUMS OFF}
   class procedure Boot(); static;
   class procedure Boot(); static;
   class constructor CreateDigestUtilities();
   class constructor CreateDigestUtilities();
@@ -343,15 +343,15 @@ begin
         Exit;
         Exit;
       end;
       end;
 
 
-    TDigestAlgorithm.SHAKE128:
+    TDigestAlgorithm.SHAKE128_256:
       begin
       begin
-        result := TDigest.Create(THashFactory.TXOF.CreateShake_128(128));
+        result := TDigest.Create(THashFactory.TXOF.CreateShake_128(256));
         Exit;
         Exit;
       end;
       end;
 
 
-    TDigestAlgorithm.SHAKE256:
+    TDigestAlgorithm.SHAKE256_512:
       begin
       begin
-        result := TDigest.Create(THashFactory.TXOF.CreateShake_256(256));
+        result := TDigest.Create(THashFactory.TXOF.CreateShake_256(512));
         Exit;
         Exit;
       end;
       end;
 
 
@@ -395,21 +395,35 @@ begin
 
 
     Falgorithms.Add('SHA1', 'SHA-1');
     Falgorithms.Add('SHA1', 'SHA-1');
     Falgorithms.Add(TOiwObjectIdentifiers.IdSha1.id, 'SHA-1');
     Falgorithms.Add(TOiwObjectIdentifiers.IdSha1.id, 'SHA-1');
+    Falgorithms.Add(TPkcsObjectIdentifiers.IdHmacWithSha1.id, 'SHA-1');
 
 
     TNistObjectIdentifiers.Boot;
     TNistObjectIdentifiers.Boot;
 
 
     Falgorithms.Add('SHA224', 'SHA-224');
     Falgorithms.Add('SHA224', 'SHA-224');
     Falgorithms.Add(TNistObjectIdentifiers.IdSha224.id, 'SHA-224');
     Falgorithms.Add(TNistObjectIdentifiers.IdSha224.id, 'SHA-224');
+    Falgorithms.Add(TPkcsObjectIdentifiers.IdHmacWithSha224.id, 'SHA-224');
     Falgorithms.Add('SHA256', 'SHA-256');
     Falgorithms.Add('SHA256', 'SHA-256');
     Falgorithms.Add(TNistObjectIdentifiers.IdSha256.id, 'SHA-256');
     Falgorithms.Add(TNistObjectIdentifiers.IdSha256.id, 'SHA-256');
+    Falgorithms.Add(TPkcsObjectIdentifiers.IdHmacWithSha256.id, 'SHA-256');
     Falgorithms.Add('SHA384', 'SHA-384');
     Falgorithms.Add('SHA384', 'SHA-384');
     Falgorithms.Add(TNistObjectIdentifiers.IdSha384.id, 'SHA-384');
     Falgorithms.Add(TNistObjectIdentifiers.IdSha384.id, 'SHA-384');
+    Falgorithms.Add(TPkcsObjectIdentifiers.IdHmacWithSha384.id, 'SHA-384');
     Falgorithms.Add('SHA512', 'SHA-512');
     Falgorithms.Add('SHA512', 'SHA-512');
     Falgorithms.Add(TNistObjectIdentifiers.IdSha512.id, 'SHA-512');
     Falgorithms.Add(TNistObjectIdentifiers.IdSha512.id, 'SHA-512');
+    Falgorithms.Add(TPkcsObjectIdentifiers.IdHmacWithSha512.id, 'SHA-512');
+
     Falgorithms.Add('SHA512/224', 'SHA-512/224');
     Falgorithms.Add('SHA512/224', 'SHA-512/224');
+    Falgorithms.Add('SHA512-224', 'SHA-512/224');
+    Falgorithms.Add('SHA512(224)', 'SHA-512/224');
+    Falgorithms.Add('SHA-512(224)', 'SHA-512/224');
     Falgorithms.Add(TNistObjectIdentifiers.IdSha512_224.id, 'SHA-512/224');
     Falgorithms.Add(TNistObjectIdentifiers.IdSha512_224.id, 'SHA-512/224');
+    Falgorithms.Add(TPkcsObjectIdentifiers.IdHmacWithSha512_224.id, 'SHA-512/224');
     Falgorithms.Add('SHA512/256', 'SHA-512/256');
     Falgorithms.Add('SHA512/256', 'SHA-512/256');
+    Falgorithms.Add('SHA512-256', 'SHA-512/256');
+    Falgorithms.Add('SHA512(256)', 'SHA-512/256');
+    Falgorithms.Add('SHA-512(256)', 'SHA-512/256');
     Falgorithms.Add(TNistObjectIdentifiers.IdSha512_256.id, 'SHA-512/256');
     Falgorithms.Add(TNistObjectIdentifiers.IdSha512_256.id, 'SHA-512/256');
+    Falgorithms.Add(TPkcsObjectIdentifiers.IdHmacWithSha512_256.id, 'SHA-512/256');
 
 
     TTeleTrusTObjectIdentifiers.Boot;
     TTeleTrusTObjectIdentifiers.Boot;
 
 
@@ -433,11 +447,19 @@ begin
     Falgorithms.Add('KECCAK512', 'KECCAK-512');
     Falgorithms.Add('KECCAK512', 'KECCAK-512');
 
 
     Falgorithms.Add(TNistObjectIdentifiers.IdSha3_224.id, 'SHA3-224');
     Falgorithms.Add(TNistObjectIdentifiers.IdSha3_224.id, 'SHA3-224');
+    Falgorithms.Add(TNistObjectIdentifiers.IdHMacWithSha3_224.id, 'SHA3-224');
     Falgorithms.Add(TNistObjectIdentifiers.IdSha3_256.id, 'SHA3-256');
     Falgorithms.Add(TNistObjectIdentifiers.IdSha3_256.id, 'SHA3-256');
+    Falgorithms.Add(TNistObjectIdentifiers.IdHMacWithSha3_256.id, 'SHA3-256');
     Falgorithms.Add(TNistObjectIdentifiers.IdSha3_384.id, 'SHA3-384');
     Falgorithms.Add(TNistObjectIdentifiers.IdSha3_384.id, 'SHA3-384');
+    Falgorithms.Add(TNistObjectIdentifiers.IdHMacWithSha3_384.id, 'SHA3-384');
     Falgorithms.Add(TNistObjectIdentifiers.IdSha3_512.id, 'SHA3-512');
     Falgorithms.Add(TNistObjectIdentifiers.IdSha3_512.id, 'SHA3-512');
-    Falgorithms.Add(TNistObjectIdentifiers.IdShake128.id, 'SHAKE128');
-    Falgorithms.Add(TNistObjectIdentifiers.IdShake256.id, 'SHAKE256');
+    Falgorithms.Add(TNistObjectIdentifiers.IdHMacWithSha3_512.id, 'SHA3-512');
+    Falgorithms.Add('SHAKE128', 'SHAKE128-256');
+    Falgorithms.Add('SHAKE-128', 'SHAKE128-256');
+    Falgorithms.Add(TNistObjectIdentifiers.IdShake128.id, 'SHAKE128-256');
+    Falgorithms.Add('SHAKE256', 'SHAKE256-512');
+    Falgorithms.Add('SHAKE-256', 'SHAKE256-512');
+    Falgorithms.Add(TNistObjectIdentifiers.IdShake256.id, 'SHAKE256-512');
 
 
     TMiscObjectIdentifiers.Boot;
     TMiscObjectIdentifiers.Boot;
 
 
@@ -471,8 +493,8 @@ begin
     Foids.Add('SHA3-256', TNistObjectIdentifiers.IdSha3_256);
     Foids.Add('SHA3-256', TNistObjectIdentifiers.IdSha3_256);
     Foids.Add('SHA3-384', TNistObjectIdentifiers.IdSha3_384);
     Foids.Add('SHA3-384', TNistObjectIdentifiers.IdSha3_384);
     Foids.Add('SHA3-512', TNistObjectIdentifiers.IdSha3_512);
     Foids.Add('SHA3-512', TNistObjectIdentifiers.IdSha3_512);
-    Foids.Add('SHAKE128', TNistObjectIdentifiers.IdShake128);
-    Foids.Add('SHAKE256', TNistObjectIdentifiers.IdShake256);
+    Foids.Add('SHAKE128-256', TNistObjectIdentifiers.IdShake128);
+    Foids.Add('SHAKE256-512', TNistObjectIdentifiers.IdShake256);
     Foids.Add('RIPEMD128', TTeleTrusTObjectIdentifiers.RIPEMD128);
     Foids.Add('RIPEMD128', TTeleTrusTObjectIdentifiers.RIPEMD128);
     Foids.Add('RIPEMD160', TTeleTrusTObjectIdentifiers.RIPEMD160);
     Foids.Add('RIPEMD160', TTeleTrusTObjectIdentifiers.RIPEMD160);
     Foids.Add('RIPEMD256', TTeleTrusTObjectIdentifiers.RIPEMD256);
     Foids.Add('RIPEMD256', TTeleTrusTObjectIdentifiers.RIPEMD256);

+ 10 - 0
CryptoLib/src/Security/ClpGeneratorUtilities.pas

@@ -35,6 +35,8 @@ uses
   ClpIDsaKeyPairGenerator,
   ClpIDsaKeyPairGenerator,
   ClpDHKeyPairGenerator,
   ClpDHKeyPairGenerator,
   ClpIDHKeyPairGenerator,
   ClpIDHKeyPairGenerator,
+  ClpRsaKeyPairGenerator,
+  ClpIRsaKeyPairGenerator,
   ClpEd25519KeyPairGenerator,
   ClpEd25519KeyPairGenerator,
   ClpIEd25519KeyPairGenerator,
   ClpIEd25519KeyPairGenerator,
   ClpX25519KeyPairGenerator,
   ClpX25519KeyPairGenerator,
@@ -258,6 +260,8 @@ begin
 
 
   AddKpgAlgorithm('DH', ['DIFFIEHELLMAN']);
   AddKpgAlgorithm('DH', ['DIFFIEHELLMAN']);
   AddKpgAlgorithm('DSA', []);
   AddKpgAlgorithm('DSA', []);
+  AddKpgAlgorithm('RSA', [TPkcsObjectIdentifiers.RsaEncryption.ID]);
+  AddKpgAlgorithm('RSASSA-PSS', []);
   AddKpgAlgorithm('ECDH', ['ECIES']);
   AddKpgAlgorithm('ECDH', ['ECIES']);
   AddKpgAlgorithm('ECDHC', []);
   AddKpgAlgorithm('ECDHC', []);
   AddKpgAlgorithm('ECDSA', []);
   AddKpgAlgorithm('ECDSA', []);
@@ -400,6 +404,12 @@ begin
     Exit;
     Exit;
   end;
   end;
 
 
+  if ((canonicalName = 'RSA') or (canonicalName = 'RSASSA-PSS')) then
+  begin
+    result := TRsaKeyPairGenerator.Create() as IRsaKeyPairGenerator;
+    Exit;
+  end;
+
   // "EC", "ECDH", "ECDHC", "ECDSA", "ECGOST3410", "ECMQV"
   // "EC", "ECDH", "ECDHC", "ECDSA", "ECGOST3410", "ECMQV"
   if TStringUtils.BeginsWith(canonicalName, 'EC', True) then
   if TStringUtils.BeginsWith(canonicalName, 'EC', True) then
   begin
   begin

+ 34 - 0
CryptoLib/src/Security/ClpParameterUtilities.pas

@@ -31,6 +31,7 @@ uses
   ClpIAsn1Objects,
   ClpIAsn1Objects,
   ClpNistObjectIdentifiers,
   ClpNistObjectIdentifiers,
   ClpParametersWithRandom,
   ClpParametersWithRandom,
+  ClpIParametersWithRandom,
   ClpCryptoLibTypes;
   ClpCryptoLibTypes;
 
 
 resourcestring
 resourcestring
@@ -78,6 +79,10 @@ type
     class function WithRandom(const cp: ICipherParameters;
     class function WithRandom(const cp: ICipherParameters;
       const random: ISecureRandom): ICipherParameters; static; inline;
       const random: ISecureRandom): ICipherParameters; static; inline;
 
 
+    class function IgnoreRandom(const CipherParameters: ICipherParameters): ICipherParameters;
+
+    class function GetRandom(const CipherParameters: ICipherParameters; out Random: ISecureRandom): ICipherParameters;
+
   end;
   end;
 
 
 implementation
 implementation
@@ -159,6 +164,35 @@ begin
   result := Lcp;
   result := Lcp;
 end;
 end;
 
 
+class function TParameterUtilities.GetRandom(
+  const CipherParameters: ICipherParameters;
+  out Random: ISecureRandom): ICipherParameters;
+var
+  WithRandom: IParametersWithRandom;
+begin
+  if Supports(CipherParameters, IParametersWithRandom, WithRandom) then
+  begin
+    Random := WithRandom.Random;
+    Result := WithRandom.Parameters;
+  end
+  else
+  begin
+    Random := nil;
+    Result := CipherParameters;
+  end;
+end;
+
+
+class function TParameterUtilities.IgnoreRandom(const CipherParameters: ICipherParameters): ICipherParameters;
+var
+  WithRandom: IParametersWithRandom;
+begin
+  if Supports(CipherParameters, IParametersWithRandom, WithRandom) then
+    Result := WithRandom.Parameters
+  else
+    Result := CipherParameters;
+end;
+
 class function TParameterUtilities.CreateKeyParameter(const algorithm: String;
 class function TParameterUtilities.CreateKeyParameter(const algorithm: String;
   const keyBytes: TCryptoLibByteArray): IKeyParameter;
   const keyBytes: TCryptoLibByteArray): IKeyParameter;
 begin
 begin

+ 119 - 0
CryptoLib/src/Security/ClpSignerUtilities.pas

@@ -58,6 +58,9 @@ uses
   ClpSchnorrDigestSigner,
   ClpSchnorrDigestSigner,
   ClpECSchnorrSipaSigner,
   ClpECSchnorrSipaSigner,
   ClpIECSchnorrSipaSigner,
   ClpIECSchnorrSipaSigner,
+  ClpRsaDigestSigner,
+  ClpIRsaDigestSigner,
+  ClpPkcsObjectIdentifiers,
   ClpStringUtils,
   ClpStringUtils,
   ClpCryptoLibTypes;
   ClpCryptoLibTypes;
 
 
@@ -361,6 +364,96 @@ begin
   Falgorithms.Add('ED25519BLAKE2BCTX', 'Ed25519Blake2Bctx');
   Falgorithms.Add('ED25519BLAKE2BCTX', 'Ed25519Blake2Bctx');
   Falgorithms.Add('ED25519BLAKE2BPH', 'Ed25519Blake2Bph');
   Falgorithms.Add('ED25519BLAKE2BPH', 'Ed25519Blake2Bph');
 
 
+  // RSA
+  TPkcsObjectIdentifiers.Boot;
+  Falgorithms.Add('RSA', 'SHA-1withRSA');
+  Falgorithms.Add('RSAWITHSHA1', 'SHA-1withRSA');
+  Falgorithms.Add('RSAWITHSHA-1', 'SHA-1withRSA');
+  Falgorithms.Add('SHA1/RSA', 'SHA-1withRSA');
+  Falgorithms.Add('SHA-1/RSA', 'SHA-1withRSA');
+  Falgorithms.Add('SHA1WITHRSA', 'SHA-1withRSA');
+  Falgorithms.Add('SHA-1WITHRSA', 'SHA-1withRSA');
+  Falgorithms.Add(TPkcsObjectIdentifiers.Sha1WithRsaEncryption.id, 'SHA-1withRSA');
+
+  Falgorithms.Add('SHA224/RSA', 'SHA-224withRSA');
+  Falgorithms.Add('SHA-224/RSA', 'SHA-224withRSA');
+  Falgorithms.Add('SHA224WITHRSA', 'SHA-224withRSA');
+  Falgorithms.Add('SHA-224WITHRSA', 'SHA-224withRSA');
+  Falgorithms.Add(TPkcsObjectIdentifiers.Sha224WithRsaEncryption.id, 'SHA-224withRSA');
+
+  Falgorithms.Add('SHA256/RSA', 'SHA-256withRSA');
+  Falgorithms.Add('SHA-256/RSA', 'SHA-256withRSA');
+  Falgorithms.Add('SHA256WITHRSA', 'SHA-256withRSA');
+  Falgorithms.Add('SHA-256WITHRSA', 'SHA-256withRSA');
+  Falgorithms.Add(TPkcsObjectIdentifiers.Sha256WithRsaEncryption.id, 'SHA-256withRSA');
+
+  Falgorithms.Add('SHA384/RSA', 'SHA-384withRSA');
+  Falgorithms.Add('SHA-384/RSA', 'SHA-384withRSA');
+  Falgorithms.Add('SHA384WITHRSA', 'SHA-384withRSA');
+  Falgorithms.Add('SHA-384WITHRSA', 'SHA-384withRSA');
+  Falgorithms.Add(TPkcsObjectIdentifiers.Sha384WithRsaEncryption.id, 'SHA-384withRSA');
+
+  Falgorithms.Add('SHA512/RSA', 'SHA-512withRSA');
+  Falgorithms.Add('SHA-512/RSA', 'SHA-512withRSA');
+  Falgorithms.Add('SHA512WITHRSA', 'SHA-512withRSA');
+  Falgorithms.Add('SHA-512WITHRSA', 'SHA-512withRSA');
+  Falgorithms.Add(TPkcsObjectIdentifiers.Sha512WithRsaEncryption.id, 'SHA-512withRSA');
+
+  Falgorithms.Add('MD5/RSA', 'MD5withRSA');
+  Falgorithms.Add('MD5WITHRSA', 'MD5withRSA');
+  Falgorithms.Add(TPkcsObjectIdentifiers.MD5WithRsaEncryption.id, 'MD5withRSA');
+
+  Falgorithms.Add('RIPEMD160/RSA', 'RIPEMD160withRSA');
+  Falgorithms.Add('RIPEMD160WITHRSA', 'RIPEMD160withRSA');
+  Falgorithms.Add('RIPEMD160WITHRSAENCRYPTION', 'RIPEMD160withRSA');
+  Falgorithms.Add(TTeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160.id, 'RIPEMD160withRSA');
+
+  Falgorithms.Add('RIPEMD128WITHRSA', 'RIPEMD128withRSA');
+  Falgorithms.Add('RIPEMD128WITHRSAENCRYPTION', 'RIPEMD128withRSA');
+  Falgorithms.Add(TTeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128.id, 'RIPEMD128withRSA');
+
+  Falgorithms.Add('RIPEMD256WITHRSA', 'RIPEMD256withRSA');
+  Falgorithms.Add('RIPEMD256WITHRSAENCRYPTION', 'RIPEMD256withRSA');
+  Falgorithms.Add(TTeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256.id, 'RIPEMD256withRSA');
+
+  // MD2/MD4 with RSA
+  Falgorithms.Add('MD2WITHRSA', 'MD2withRSA');
+  Falgorithms.Add('MD2WITHRSAENCRYPTION', 'MD2withRSA');
+  Falgorithms.Add(TPkcsObjectIdentifiers.MD2WithRsaEncryption.id, 'MD2withRSA');
+
+  Falgorithms.Add('MD4WITHRSA', 'MD4withRSA');
+  Falgorithms.Add('MD4WITHRSAENCRYPTION', 'MD4withRSA');
+  Falgorithms.Add(TPkcsObjectIdentifiers.MD4WithRsaEncryption.id, 'MD4withRSA');
+
+  // Extended MD5 with RSA aliases
+  Falgorithms.Add('MD5WITHRSAENCRYPTION', 'MD5withRSA');
+
+  // Extended SHA with RSA aliases
+  Falgorithms.Add('SHA1WITHRSAENCRYPTION', 'SHA-1withRSA');
+  Falgorithms.Add('SHA-1WITHRSAENCRYPTION', 'SHA-1withRSA');
+  Falgorithms.Add('SHA224WITHRSAENCRYPTION', 'SHA-224withRSA');
+  Falgorithms.Add('SHA-224WITHRSAENCRYPTION', 'SHA-224withRSA');
+  Falgorithms.Add('SHA256WITHRSAENCRYPTION', 'SHA-256withRSA');
+  Falgorithms.Add('SHA-256WITHRSAENCRYPTION', 'SHA-256withRSA');
+  Falgorithms.Add('SHA384WITHRSAENCRYPTION', 'SHA-384withRSA');
+  Falgorithms.Add('SHA-384WITHRSAENCRYPTION', 'SHA-384withRSA');
+  Falgorithms.Add('SHA512WITHRSAENCRYPTION', 'SHA-512withRSA');
+  Falgorithms.Add('SHA-512WITHRSAENCRYPTION', 'SHA-512withRSA');
+
+  // SHA-512/224 and SHA-512/256 with RSA
+  Falgorithms.Add('SHA512(224)WITHRSA', 'SHA-512(224)withRSA');
+  Falgorithms.Add('SHA-512(224)WITHRSA', 'SHA-512(224)withRSA');
+  Falgorithms.Add('SHA512(224)WITHRSAENCRYPTION', 'SHA-512(224)withRSA');
+  Falgorithms.Add('SHA-512(224)WITHRSAENCRYPTION', 'SHA-512(224)withRSA');
+  Falgorithms.Add(TPkcsObjectIdentifiers.Sha512_224WithRSAEncryption.id, 'SHA-512(224)withRSA');
+
+  Falgorithms.Add('SHA512(256)WITHRSA', 'SHA-512(256)withRSA');
+  Falgorithms.Add('SHA-512(256)WITHRSA', 'SHA-512(256)withRSA');
+  Falgorithms.Add('SHA512(256)WITHRSAENCRYPTION', 'SHA-512(256)withRSA');
+  Falgorithms.Add('SHA-512(256)WITHRSAENCRYPTION', 'SHA-512(256)withRSA');
+  Falgorithms.Add(TPkcsObjectIdentifiers.Sha512_256WithRSAEncryption.id, 'SHA-512(256)withRSA');
+
+
   // ECSCHNORR SIPA
   // ECSCHNORR SIPA
 
 
   Falgorithms.Add('SHA1/ECSCHNORR/SIPA', 'SHA-1withECSCHNORRSIPA');
   Falgorithms.Add('SHA1/ECSCHNORR/SIPA', 'SHA-1withECSCHNORRSIPA');
@@ -432,6 +525,22 @@ begin
   // TCryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
   // TCryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
 
 
   Foids.Add('Ed25519', TEdECObjectIdentifiers.id_Ed25519);
   Foids.Add('Ed25519', TEdECObjectIdentifiers.id_Ed25519);
+
+  // RSA signature OIDs
+  Foids.Add('MD2withRSA', TPkcsObjectIdentifiers.MD2WithRsaEncryption);
+  Foids.Add('MD4withRSA', TPkcsObjectIdentifiers.MD4WithRsaEncryption);
+  Foids.Add('MD5withRSA', TPkcsObjectIdentifiers.MD5WithRsaEncryption);
+  Foids.Add('SHA-1withRSA', TPkcsObjectIdentifiers.Sha1WithRsaEncryption);
+  Foids.Add('SHA-224withRSA', TPkcsObjectIdentifiers.Sha224WithRsaEncryption);
+  Foids.Add('SHA-256withRSA', TPkcsObjectIdentifiers.Sha256WithRsaEncryption);
+  Foids.Add('SHA-384withRSA', TPkcsObjectIdentifiers.Sha384WithRsaEncryption);
+  Foids.Add('SHA-512withRSA', TPkcsObjectIdentifiers.Sha512WithRsaEncryption);
+  Foids.Add('SHA-512(224)withRSA', TPkcsObjectIdentifiers.Sha512_224WithRSAEncryption);
+  Foids.Add('SHA-512(256)withRSA', TPkcsObjectIdentifiers.Sha512_256WithRSAEncryption);
+
+  Foids.Add('RIPEMD128withRSA', TTeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128);
+  Foids.Add('RIPEMD160withRSA', TTeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160);
+  Foids.Add('RIPEMD256withRSA', TTeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256);
 end;
 end;
 
 
 class constructor TSignerUtilities.CreateSignerUtilities;
 class constructor TSignerUtilities.CreateSignerUtilities;
@@ -600,6 +709,16 @@ begin
     Exit;
     Exit;
   end;
   end;
 
 
+  if TStringUtils.EndsWith(mechanism, 'withRSA', True) then
+  begin
+    DigestName := System.Copy(mechanism, 1, TStringUtils.LastIndexOf(mechanism,
+      'with', True));
+
+    DigestInstance := TDigestUtilities.GetDigest(DigestName);
+    Result := TRsaDigestSigner.Create(DigestInstance) as IRsaDigestSigner;
+    Exit;
+  end;
+
   raise ESecurityUtilityCryptoLibException.CreateResFmt(@SUnRecognizedAlgorithm,
   raise ESecurityUtilityCryptoLibException.CreateResFmt(@SUnRecognizedAlgorithm,
     [algorithm]);
     [algorithm]);
 
 

+ 77 - 0
CryptoLib/src/Utils/ClpBigIntegers.pas

@@ -116,6 +116,24 @@ type
     class function GetUnsignedByteLength(const n: TBigInteger): Int32;
     class function GetUnsignedByteLength(const n: TBigInteger): Int32;
       static; inline;
       static; inline;
 
 
+    /// <summary>
+    /// Calculate the modular inverse of X mod M where M is odd.
+    /// </summary>
+    /// <param name="M">The odd modulus (must be positive and odd)</param>
+    /// <param name="X">The value to invert</param>
+    /// <returns>X^(-1) mod M</returns>
+    /// <exception cref="EArithmeticCryptoLibException">If M is not positive, not odd, or X is not invertible</exception>
+    class function ModOddInverse(const M, X: TBigInteger): TBigInteger; static;
+
+    /// <summary>
+    /// Check if two BigIntegers are coprime (gcd = 1) for an odd modulus.
+    /// Uses GCD-based calculation - variable time but simpler than constant-time approach.
+    /// </summary>
+    /// <param name="M">The odd modulus (must be positive and odd)</param>
+    /// <param name="X">The value to check for coprimality</param>
+    /// <returns>True if gcd(M, X) = 1, False otherwise</returns>
+    class function ModOddIsCoprimeVar(const M, X: TBigInteger): Boolean; static;
+
   end;
   end;
 
 
 implementation
 implementation
@@ -222,4 +240,63 @@ begin
   Result := (n.BitLength + 7) shr 3;
   Result := (n.BitLength + 7) shr 3;
 end;
 end;
 
 
+class function TBigIntegers.ModOddIsCoprimeVar(const M, X: TBigInteger): Boolean;
+var
+  xMod, gcd: TBigInteger;
+begin
+  // Validate M is odd and positive
+  if not M.TestBit(0) then
+  begin
+    raise EArgumentCryptoLibException.Create('Modulus must be odd');
+  end;
+
+  if M.SignValue <> 1 then
+  begin
+    raise EArithmeticCryptoLibException.Create('Modulus must be positive');
+  end;
+
+  // If X is 1, it's always coprime
+  if X.Equals(TBigInteger.One) then
+  begin
+    Result := True;
+    Exit;
+  end;
+
+  // Reduce X mod M if necessary
+  if (X.SignValue < 0) or (X.BitLength > M.BitLength) then
+    xMod := X.&Mod(M)
+  else
+    xMod := X;
+
+  // Check if GCD(M, X) = 1
+  gcd := M.Gcd(xMod);
+  Result := gcd.Equals(TBigInteger.One);
+end;
+
+class function TBigIntegers.ModOddInverse(const M, X: TBigInteger): TBigInteger;
+var
+  xMod: TBigInteger;
+begin
+  // Validate M is odd
+  if not M.TestBit(0) then
+  begin
+    raise EArgumentCryptoLibException.Create('Modulus must be odd');
+  end;
+
+  // Validate M is positive
+  if M.SignValue <> 1 then
+  begin
+    raise EArithmeticCryptoLibException.Create('BigInteger: modulus not positive');
+  end;
+
+  // Reduce X mod M if necessary
+  if (X.SignValue < 0) or (X.BitLength > M.BitLength) then
+    xMod := X.&Mod(M)
+  else
+    xMod := X;
+
+  // Use BigInteger's built-in ModInverse
+  Result := xMod.ModInverse(M);
+end;
+
 end.
 end.