Browse Source

Merge branch 'master' into travis

Ugochukwu Mmaduekwe 7 years ago
parent
commit
e267967f83
92 changed files with 16260 additions and 1178 deletions
  1. 40 2
      CryptoLib.Samples/Delphi.Samples/UsageSamples.dpr
  2. 11 6
      CryptoLib.Samples/src/UsageExamples.pas
  3. 48 2
      CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.dpr
  4. 33 1
      CryptoLib.Tests/FreePascal.Tests/CryptoLib.Tests.lpi
  5. 8 0
      CryptoLib.Tests/FreePascal.Tests/CryptoLib.lpr
  6. 33 1
      CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.Tests.lpi
  7. 8 0
      CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.lpr
  8. 34 1
      CryptoLib.Tests/src/Crypto/AESTestVectors.pas
  9. 11 12
      CryptoLib.Tests/src/Crypto/AESTests.pas
  10. 194 0
      CryptoLib.Tests/src/Crypto/BlockCipherMonteCarloTests.pas
  11. 52 6
      CryptoLib.Tests/src/Crypto/BlockCipherVectorTests.pas
  12. 162 0
      CryptoLib.Tests/src/Crypto/RIPEMD128HMacTests.pas
  13. 167 0
      CryptoLib.Tests/src/Crypto/RIPEMD160HMacTests.pas
  14. 168 0
      CryptoLib.Tests/src/Crypto/SHA1HMacTests.pas
  15. 169 0
      CryptoLib.Tests/src/Crypto/SHA224HMacTests.pas
  16. 169 0
      CryptoLib.Tests/src/Crypto/SHA256HMacTests.pas
  17. 169 0
      CryptoLib.Tests/src/Crypto/SHA384HMacTests.pas
  18. 169 0
      CryptoLib.Tests/src/Crypto/SHA512HMacTests.pas
  19. 3 2
      CryptoLib.Tests/src/Math/EC/Custom/Sec/SecP384R1FieldTests.pas
  20. 18 17
      CryptoLib.Tests/src/Math/EC/FixedPointTests.pas
  21. 11 8
      CryptoLib.Tests/src/Math/ECAlgorithmsTests.pas
  22. 63 61
      CryptoLib.Tests/src/Math/ECPointTests.pas
  23. 1 1
      CryptoLib.Tests/src/Others/NamedCurveTests.pas
  24. 2 2
      CryptoLib/src/Asn1/ClpDerObjectIdentifier.pas
  25. 68 58
      CryptoLib/src/Asn1/CryptoPro/ClpCryptoProObjectIdentifiers.pas
  26. 267 258
      CryptoLib/src/Asn1/CryptoPro/ClpECGost3410NamedCurves.pas
  27. 14 8
      CryptoLib/src/Asn1/Iana/ClpIanaObjectIdentifiers.pas
  28. 23 16
      CryptoLib/src/Asn1/Misc/ClpMiscObjectIdentifiers.pas
  29. 187 0
      CryptoLib/src/Asn1/Nist/ClpNistNamedCurves.pas
  30. 63 57
      CryptoLib/src/Asn1/Nist/ClpNistObjectIdentifiers.pas
  31. 9 4
      CryptoLib/src/Asn1/Oiw/ClpOiwObjectIdentifiers.pas
  32. 16 10
      CryptoLib/src/Asn1/Pkcs/ClpPkcsObjectIdentifiers.pas
  33. 34 26
      CryptoLib/src/Asn1/RossStandart/ClpRosstandartObjectIdentifiers.pas
  34. 1701 151
      CryptoLib/src/Asn1/Sec/ClpSecNamedCurves.pas
  35. 54 47
      CryptoLib/src/Asn1/Sec/ClpSecObjectIdentifiers.pas
  36. 15 9
      CryptoLib/src/Asn1/TeleTrust/ClpTeleTrusTObjectIdentifiers.pas
  37. 32 15
      CryptoLib/src/Asn1/X9/ClpECNamedCurveTable.pas
  38. 65 59
      CryptoLib/src/Asn1/X9/ClpX9ObjectIdentifiers.pas
  39. 2 2
      CryptoLib/src/Crypto/ClpBufferedCipherBase.pas
  40. 455 0
      CryptoLib/src/Crypto/EC/ClpCustomNamedCurves.pas
  41. 13 2
      CryptoLib/src/Crypto/Engines/ClpAesEngine.pas
  42. 725 0
      CryptoLib/src/Crypto/Engines/ClpAesLightEngine.pas
  43. 6 6
      CryptoLib/src/Crypto/Generators/ClpECKeyPairGenerator.pas
  44. 36 0
      CryptoLib/src/Interfaces/ClpIAesLightEngine.pas
  45. 2 2
      CryptoLib/src/Interfaces/ClpIECInterface.pas
  46. 44 0
      CryptoLib/src/Interfaces/ClpISecP256K1Curve.pas
  47. 38 0
      CryptoLib/src/Interfaces/ClpISecP256K1FieldElement.pas
  48. 35 0
      CryptoLib/src/Interfaces/ClpISecP256K1Point.pas
  49. 44 0
      CryptoLib/src/Interfaces/ClpISecP384R1Curve.pas
  50. 38 0
      CryptoLib/src/Interfaces/ClpISecP384R1FieldElement.pas
  51. 35 0
      CryptoLib/src/Interfaces/ClpISecP384R1Point.pas
  52. 44 0
      CryptoLib/src/Interfaces/ClpISecP521R1Curve.pas
  53. 38 0
      CryptoLib/src/Interfaces/ClpISecP521R1FieldElement.pas
  54. 35 0
      CryptoLib/src/Interfaces/ClpISecP521R1Point.pas
  55. 51 0
      CryptoLib/src/Interfaces/ClpISecT283FieldElement.pas
  56. 55 0
      CryptoLib/src/Interfaces/ClpISecT283K1Curve.pas
  57. 35 0
      CryptoLib/src/Interfaces/ClpISecT283K1Point.pas
  58. 181 112
      CryptoLib/src/Math/ClpBigInteger.pas
  59. 12 12
      CryptoLib/src/Math/EC/ClpECAlgorithms.pas
  60. 27 25
      CryptoLib/src/Math/EC/ClpECCurve.pas
  61. 42 29
      CryptoLib/src/Math/EC/ClpECFieldElement.pas
  62. 259 0
      CryptoLib/src/Math/EC/Custom/Sec/ClpSecP256K1Curve.pas
  63. 285 0
      CryptoLib/src/Math/EC/Custom/Sec/ClpSecP256K1Field.pas
  64. 347 0
      CryptoLib/src/Math/EC/Custom/Sec/ClpSecP256K1FieldElement.pas
  65. 391 0
      CryptoLib/src/Math/EC/Custom/Sec/ClpSecP256K1Point.pas
  66. 269 0
      CryptoLib/src/Math/EC/Custom/Sec/ClpSecP384R1Curve.pas
  67. 417 0
      CryptoLib/src/Math/EC/Custom/Sec/ClpSecP384R1Field.pas
  68. 342 0
      CryptoLib/src/Math/EC/Custom/Sec/ClpSecP384R1FieldElement.pas
  69. 406 0
      CryptoLib/src/Math/EC/Custom/Sec/ClpSecP384R1Point.pas
  70. 269 0
      CryptoLib/src/Math/EC/Custom/Sec/ClpSecP521R1Curve.pas
  71. 258 0
      CryptoLib/src/Math/EC/Custom/Sec/ClpSecP521R1Field.pas
  72. 299 0
      CryptoLib/src/Math/EC/Custom/Sec/ClpSecP521R1FieldElement.pas
  73. 400 0
      CryptoLib/src/Math/EC/Custom/Sec/ClpSecP521R1Point.pas
  74. 533 0
      CryptoLib/src/Math/EC/Custom/Sec/ClpSecT283Field.pas
  75. 381 0
      CryptoLib/src/Math/EC/Custom/Sec/ClpSecT283FieldElement.pas
  76. 283 0
      CryptoLib/src/Math/EC/Custom/Sec/ClpSecT283K1Curve.pas
  77. 476 0
      CryptoLib/src/Math/EC/Custom/Sec/ClpSecT283K1Point.pas
  78. 7 0
      CryptoLib/src/Math/Field/ClpGF2Polynomial.pas
  79. 235 0
      CryptoLib/src/Math/Raw/ClpInterleave.pas
  80. 103 107
      CryptoLib/src/Math/Raw/ClpNat.pas
  81. 1414 0
      CryptoLib/src/Math/Raw/ClpNat192.pas
  82. 1768 0
      CryptoLib/src/Math/Raw/ClpNat256.pas
  83. 181 0
      CryptoLib/src/Math/Raw/ClpNat320.pas
  84. 95 0
      CryptoLib/src/Math/Raw/ClpNat384.pas
  85. 96 0
      CryptoLib/src/Math/Raw/ClpNat512.pas
  86. 173 19
      CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.lpk
  87. 14 2
      CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.pas
  88. 12 5
      CryptoLib/src/Security/ClpSecureRandom.pas
  89. 114 1
      CryptoLib/src/Utils/ClpArrayUtils.pas
  90. 42 0
      CryptoLib/src/Utils/ClpBigIntegers.pas
  91. 107 8
      CryptoLib/src/Utils/ClpBits.pas
  92. 0 6
      CryptoLib/src/Utils/ClpConverters.pas

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

@@ -7,8 +7,8 @@ program UsageSamples;
 
 uses
   SysUtils,
-  ClpCryptoProObjectIdentifiers in '..\..\CryptoLib\src\Asn1\CryptoPro\ClpCryptoProObjectIdentifiers.pas',
   ClpECGost3410NamedCurves in '..\..\CryptoLib\src\Asn1\CryptoPro\ClpECGost3410NamedCurves.pas',
+  ClpCryptoProObjectIdentifiers in '..\..\CryptoLib\src\Asn1\CryptoPro\ClpCryptoProObjectIdentifiers.pas',
   ClpNistObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Nist\ClpNistObjectIdentifiers.pas',
   ClpOiwObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Oiw\ClpOiwObjectIdentifiers.pas',
   ClpPkcsObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Pkcs\ClpPkcsObjectIdentifiers.pas',
@@ -410,7 +410,45 @@ uses
   ClpIDsaParametersGenerator in '..\..\CryptoLib\src\Interfaces\ClpIDsaParametersGenerator.pas',
   ClpDsaParameter in '..\..\CryptoLib\src\Asn1\X509\ClpDsaParameter.pas',
   ClpIDsaParameter in '..\..\CryptoLib\src\Interfaces\ClpIDsaParameter.pas',
-  ClpIPreCompCallBack in '..\..\CryptoLib\src\Interfaces\ClpIPreCompCallBack.pas';
+  ClpIPreCompCallBack in '..\..\CryptoLib\src\Interfaces\ClpIPreCompCallBack.pas',
+  ClpNistNamedCurves in '..\..\CryptoLib\src\Asn1\Nist\ClpNistNamedCurves.pas',
+  ClpNat320 in '..\..\CryptoLib\src\Math\Raw\ClpNat320.pas',
+  ClpNat256 in '..\..\CryptoLib\src\Math\Raw\ClpNat256.pas',
+  ClpAesLightEngine in '..\..\CryptoLib\src\Crypto\Engines\ClpAesLightEngine.pas',
+  ClpIAesLightEngine in '..\..\CryptoLib\src\Interfaces\ClpIAesLightEngine.pas',
+  ClpCustomNamedCurves in '..\..\CryptoLib\src\Crypto\EC\ClpCustomNamedCurves.pas',
+  ClpSecP256K1Field in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP256K1Field.pas',
+  ClpSecP256K1FieldElement in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP256K1FieldElement.pas',
+  ClpISecP256K1FieldElement in '..\..\CryptoLib\src\Interfaces\ClpISecP256K1FieldElement.pas',
+  ClpSecP256K1Point in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP256K1Point.pas',
+  ClpISecP256K1Point in '..\..\CryptoLib\src\Interfaces\ClpISecP256K1Point.pas',
+  ClpSecP256K1Curve in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP256K1Curve.pas',
+  ClpISecP256K1Curve in '..\..\CryptoLib\src\Interfaces\ClpISecP256K1Curve.pas',
+  ClpSecP384R1Field in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP384R1Field.pas',
+  ClpNat384 in '..\..\CryptoLib\src\Math\Raw\ClpNat384.pas',
+  ClpSecP384R1FieldElement in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP384R1FieldElement.pas',
+  ClpISecP384R1FieldElement in '..\..\CryptoLib\src\Interfaces\ClpISecP384R1FieldElement.pas',
+  ClpSecP384R1Point in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP384R1Point.pas',
+  ClpISecP384R1Point in '..\..\CryptoLib\src\Interfaces\ClpISecP384R1Point.pas',
+  ClpSecP384R1Curve in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP384R1Curve.pas',
+  ClpISecP384R1Curve in '..\..\CryptoLib\src\Interfaces\ClpISecP384R1Curve.pas',
+  ClpNat192 in '..\..\CryptoLib\src\Math\Raw\ClpNat192.pas',
+  ClpSecP521R1Field in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP521R1Field.pas',
+  ClpNat512 in '..\..\CryptoLib\src\Math\Raw\ClpNat512.pas',
+  ClpSecP521R1FieldElement in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP521R1FieldElement.pas',
+  ClpISecP521R1FieldElement in '..\..\CryptoLib\src\Interfaces\ClpISecP521R1FieldElement.pas',
+  ClpSecP521R1Point in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP521R1Point.pas',
+  ClpISecP521R1Point in '..\..\CryptoLib\src\Interfaces\ClpISecP521R1Point.pas',
+  ClpSecP521R1Curve in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP521R1Curve.pas',
+  ClpISecP521R1Curve in '..\..\CryptoLib\src\Interfaces\ClpISecP521R1Curve.pas',
+  ClpInterleave in '..\..\CryptoLib\src\Math\Raw\ClpInterleave.pas',
+  ClpSecT283Field in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecT283Field.pas',
+  ClpSecT283FieldElement in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecT283FieldElement.pas',
+  ClpISecT283FieldElement in '..\..\CryptoLib\src\Interfaces\ClpISecT283FieldElement.pas',
+  ClpSecT283K1Point in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecT283K1Point.pas',
+  ClpISecT283K1Point in '..\..\CryptoLib\src\Interfaces\ClpISecT283K1Point.pas',
+  ClpISecT283K1Curve in '..\..\CryptoLib\src\Interfaces\ClpISecT283K1Curve.pas',
+  ClpSecT283K1Curve in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecT283K1Curve.pas';
 
 begin
   try

+ 11 - 6
CryptoLib.Samples/src/UsageExamples.pas

@@ -82,7 +82,8 @@ uses
   ClpIAsymmetricCipherKeyPairGenerator,
   ClpArrayUtils,
   ClpHex,
-  ClpSecNamedCurves;
+  // ClpSecNamedCurves,
+  ClpCustomNamedCurves;
 
 type
   TUsageExamples = class sealed(TObject)
@@ -376,7 +377,8 @@ begin
   System.Assert(PayloadToEncodeBytes <> Nil,
     'PayloadToDecodeBytes Cannot be Nil');
 
-  Lcurve := TSecNamedCurves.GetByName(ACurveName);
+  // Lcurve := TSecNamedCurves.GetByName(ACurveName);
+  Lcurve := TCustomNamedCurves.GetByName(ACurveName);
   System.Assert(Lcurve <> Nil, 'Lcurve Cannot be Nil');
 
   // Set Up Asymmetric Key Pair from known public key ByteArray
@@ -438,7 +440,8 @@ begin
   System.Assert(PayloadToDecodeBytes <> Nil,
     'PayloadToDecodeBytes Cannot be Nil');
 
-  Lcurve := TSecNamedCurves.GetByName(ACurveName);
+  // Lcurve := TSecNamedCurves.GetByName(ACurveName);
+  Lcurve := TCustomNamedCurves.GetByName(ACurveName);
   System.Assert(Lcurve <> Nil, 'Lcurve Cannot be Nil');
 
   // Set Up Asymmetric Key Pair from known private key ByteArray
@@ -687,7 +690,8 @@ const
 begin
   // Full Generation Method
 
-  Lcurve := TSecNamedCurves.GetByName(CurveName);
+  // Lcurve := TSecNamedCurves.GetByName(CurveName);
+  Lcurve := TCustomNamedCurves.GetByName(CurveName);
   KeyPairGeneratorInstance := TGeneratorUtilities.GetKeyPairGenerator('ECDSA');
   domain := TECDomainParameters.Create(Lcurve.Curve, Lcurve.G, Lcurve.N,
     Lcurve.H, Lcurve.GetSeed);
@@ -884,7 +888,7 @@ begin
       sLineBreak);
   end;
 
-  PrivD := TBigInteger.Create(PrivateKeyByteArray);
+  PrivD := TBigInteger.Create(1, PrivateKeyByteArray);
   RegeneratedPrivateKey := TECPrivateKeyParameters.Create('ECDSA',
     PrivD, domain);
 
@@ -980,7 +984,8 @@ end;
 class constructor TUsageExamples.UsageExamples;
 begin
   FRandom := TSecureRandom.Create();
-  FCurve := TSecNamedCurves.GetByName(CurveName);
+  // FCurve := TSecNamedCurves.GetByName(CurveName);
+  FCurve := TCustomNamedCurves.GetByName(CurveName);
 end;
 
 end.

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

@@ -20,8 +20,8 @@ uses
   TestFramework,
   GUITestRunner,
   TextTestRunner,
-  ClpCryptoProObjectIdentifiers in '..\..\CryptoLib\src\Asn1\CryptoPro\ClpCryptoProObjectIdentifiers.pas',
   ClpECGost3410NamedCurves in '..\..\CryptoLib\src\Asn1\CryptoPro\ClpECGost3410NamedCurves.pas',
+  ClpCryptoProObjectIdentifiers in '..\..\CryptoLib\src\Asn1\CryptoPro\ClpCryptoProObjectIdentifiers.pas',
   ClpNistObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Nist\ClpNistObjectIdentifiers.pas',
   ClpOiwObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Oiw\ClpOiwObjectIdentifiers.pas',
   ClpPkcsObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Pkcs\ClpPkcsObjectIdentifiers.pas',
@@ -454,7 +454,53 @@ uses
   ClpDsaParameter in '..\..\CryptoLib\src\Asn1\X509\ClpDsaParameter.pas',
   ClpIDsaParameter in '..\..\CryptoLib\src\Interfaces\ClpIDsaParameter.pas',
   ClpIPreCompCallBack in '..\..\CryptoLib\src\Interfaces\ClpIPreCompCallBack.pas',
-  DeterministicDsaTests in '..\src\Crypto\DeterministicDsaTests.pas';
+  DeterministicDsaTests in '..\src\Crypto\DeterministicDsaTests.pas',
+  ClpNistNamedCurves in '..\..\CryptoLib\src\Asn1\Nist\ClpNistNamedCurves.pas',
+  ClpNat320 in '..\..\CryptoLib\src\Math\Raw\ClpNat320.pas',
+  ClpNat256 in '..\..\CryptoLib\src\Math\Raw\ClpNat256.pas',
+  ClpAesLightEngine in '..\..\CryptoLib\src\Crypto\Engines\ClpAesLightEngine.pas',
+  ClpIAesLightEngine in '..\..\CryptoLib\src\Interfaces\ClpIAesLightEngine.pas',
+  BlockCipherMonteCarloTests in '..\src\Crypto\BlockCipherMonteCarloTests.pas',
+  SHA1HMacTests in '..\src\Crypto\SHA1HMacTests.pas',
+  SHA224HMacTests in '..\src\Crypto\SHA224HMacTests.pas',
+  SHA256HMacTests in '..\src\Crypto\SHA256HMacTests.pas',
+  SHA384HMacTests in '..\src\Crypto\SHA384HMacTests.pas',
+  SHA512HMacTests in '..\src\Crypto\SHA512HMacTests.pas',
+  RIPEMD128HMacTests in '..\src\Crypto\RIPEMD128HMacTests.pas',
+  RIPEMD160HMacTests in '..\src\Crypto\RIPEMD160HMacTests.pas',
+  ClpCustomNamedCurves in '..\..\CryptoLib\src\Crypto\EC\ClpCustomNamedCurves.pas',
+  ClpSecP256K1Field in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP256K1Field.pas',
+  ClpSecP256K1FieldElement in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP256K1FieldElement.pas',
+  ClpISecP256K1FieldElement in '..\..\CryptoLib\src\Interfaces\ClpISecP256K1FieldElement.pas',
+  ClpSecP256K1Point in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP256K1Point.pas',
+  ClpISecP256K1Point in '..\..\CryptoLib\src\Interfaces\ClpISecP256K1Point.pas',
+  ClpSecP256K1Curve in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP256K1Curve.pas',
+  ClpISecP256K1Curve in '..\..\CryptoLib\src\Interfaces\ClpISecP256K1Curve.pas',
+  ClpSecP384R1Field in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP384R1Field.pas',
+  ClpNat384 in '..\..\CryptoLib\src\Math\Raw\ClpNat384.pas',
+  ClpSecP384R1FieldElement in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP384R1FieldElement.pas',
+  ClpISecP384R1FieldElement in '..\..\CryptoLib\src\Interfaces\ClpISecP384R1FieldElement.pas',
+  ClpSecP384R1Point in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP384R1Point.pas',
+  ClpISecP384R1Point in '..\..\CryptoLib\src\Interfaces\ClpISecP384R1Point.pas',
+  ClpSecP384R1Curve in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP384R1Curve.pas',
+  ClpISecP384R1Curve in '..\..\CryptoLib\src\Interfaces\ClpISecP384R1Curve.pas',
+  ClpNat192 in '..\..\CryptoLib\src\Math\Raw\ClpNat192.pas',
+  ClpSecP521R1Field in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP521R1Field.pas',
+  ClpNat512 in '..\..\CryptoLib\src\Math\Raw\ClpNat512.pas',
+  ClpSecP521R1FieldElement in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP521R1FieldElement.pas',
+  ClpISecP521R1FieldElement in '..\..\CryptoLib\src\Interfaces\ClpISecP521R1FieldElement.pas',
+  ClpSecP521R1Point in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP521R1Point.pas',
+  ClpISecP521R1Point in '..\..\CryptoLib\src\Interfaces\ClpISecP521R1Point.pas',
+  ClpSecP521R1Curve in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecP521R1Curve.pas',
+  ClpISecP521R1Curve in '..\..\CryptoLib\src\Interfaces\ClpISecP521R1Curve.pas',
+  ClpInterleave in '..\..\CryptoLib\src\Math\Raw\ClpInterleave.pas',
+  ClpSecT283Field in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecT283Field.pas',
+  ClpSecT283FieldElement in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecT283FieldElement.pas',
+  ClpISecT283FieldElement in '..\..\CryptoLib\src\Interfaces\ClpISecT283FieldElement.pas',
+  ClpSecT283K1Point in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecT283K1Point.pas',
+  ClpISecT283K1Point in '..\..\CryptoLib\src\Interfaces\ClpISecT283K1Point.pas',
+  ClpISecT283K1Curve in '..\..\CryptoLib\src\Interfaces\ClpISecT283K1Curve.pas',
+  ClpSecT283K1Curve in '..\..\CryptoLib\src\Math\EC\Custom\Sec\ClpSecT283K1Curve.pas';
 
 begin
 

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

@@ -36,7 +36,7 @@
         <PackageName Value="FCL"/>
       </Item4>
     </RequiredPackages>
-    <Units Count="33">
+    <Units Count="41">
       <Unit0>
         <Filename Value="CryptoLib.lpr"/>
         <IsPartOfProject Value="True"/>
@@ -170,6 +170,38 @@
         <Filename Value="..\src\Crypto\DSATests.pas"/>
         <IsPartOfProject Value="True"/>
       </Unit32>
+      <Unit33>
+        <Filename Value="..\src\Crypto\BlockCipherMonteCarloTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit33>
+      <Unit34>
+        <Filename Value="..\src\Crypto\SHA1HMacTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit34>
+      <Unit35>
+        <Filename Value="..\src\Crypto\SHA224HMacTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit35>
+      <Unit36>
+        <Filename Value="..\src\Crypto\SHA256HMacTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit36>
+      <Unit37>
+        <Filename Value="..\src\Crypto\SHA384HMacTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit37>
+      <Unit38>
+        <Filename Value="..\src\Crypto\SHA512HMacTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit38>
+      <Unit39>
+        <Filename Value="..\src\Crypto\RIPEMD128HMacTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit39>
+      <Unit40>
+        <Filename Value="..\src\Crypto\RIPEMD160HMacTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit40>
     </Units>
   </ProjectOptions>
   <CompilerOptions>

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

@@ -24,10 +24,18 @@ uses
   FixedPointTests,
   AESTests,
   BlockCipherVectorTests,
+  BlockCipherMonteCarloTests,
   AESTestVectors,
   AESSICTests,
   IESCipherTests,
   MD5HMacTests,
+  SHA1HMacTests,
+  SHA224HMacTests,
+  SHA256HMacTests,
+  SHA384HMacTests,
+  SHA512HMacTests,
+  RIPEMD128HMacTests,
+  RIPEMD160HMacTests,
   HMacTests,
   Pkcs5Tests,
   HkdfGeneratorTests,

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

@@ -37,7 +37,7 @@
         <PackageName Value="FCL"/>
       </Item2>
     </RequiredPackages>
-    <Units Count="33">
+    <Units Count="41">
       <Unit0>
         <Filename Value="CryptoLibConsole.lpr"/>
         <IsPartOfProject Value="True"/>
@@ -170,6 +170,38 @@
         <Filename Value="..\src\Crypto\DSATests.pas"/>
         <IsPartOfProject Value="True"/>
       </Unit32>
+      <Unit33>
+        <Filename Value="..\src\Crypto\BlockCipherMonteCarloTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit33>
+      <Unit34>
+        <Filename Value="..\src\Crypto\SHA1HMacTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit34>
+      <Unit35>
+        <Filename Value="..\src\Crypto\SHA224HMacTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit35>
+      <Unit36>
+        <Filename Value="..\src\Crypto\SHA256HMacTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit36>
+      <Unit37>
+        <Filename Value="..\src\Crypto\SHA384HMacTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit37>
+      <Unit38>
+        <Filename Value="..\src\Crypto\SHA512HMacTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit38>
+      <Unit39>
+        <Filename Value="..\src\Crypto\RIPEMD128HMacTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit39>
+      <Unit40>
+        <Filename Value="..\src\Crypto\RIPEMD160HMacTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit40>
     </Units>
   </ProjectOptions>
   <CompilerOptions>

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

@@ -22,10 +22,18 @@ uses
   FixedPointTests,
   AESTests,
   BlockCipherVectorTests,
+  BlockCipherMonteCarloTests,
   AESTestVectors,
   AESSICTests,
   IESCipherTests,
   MD5HMacTests,
+  SHA1HMacTests,
+  SHA224HMacTests,
+  SHA256HMacTests,
+  SHA384HMacTests,
+  SHA512HMacTests,
+  RIPEMD128HMacTests,
+  RIPEMD160HMacTests,
  // HMacTests, stalling on x64 windows on travis ci
   Pkcs5Tests,
   HkdfGeneratorTests,

+ 34 - 1
CryptoLib.Tests/src/Crypto/AESTestVectors.pas

@@ -34,7 +34,9 @@ type
     class var
 
       FBlockCipherVectorKeys, FBlockCipherVectorInputs,
-      FBlockCipherVectorOutputs, FOfficialVectorKeys_AES_CBC,
+      FBlockCipherVectorOutputs, FBlockCipherMonteCarloIterations,
+      FBlockCipherMonteCarloKeys, FBlockCipherMonteCarloInputs,
+      FBlockCipherMonteCarloOutputs, FOfficialVectorKeys_AES_CBC,
       FOfficialVectorIVs_AES_CBC, FOfficialVectorInputs_AES_CBC,
       FOfficialVectorOutputs_AES_CBC, FOfficialVectorKeys_AES_CFB,
       FOfficialVectorIVs_AES_CFB, FOfficialVectorInputs_AES_CFB,
@@ -84,6 +86,37 @@ begin
 
     'DDC6BF790C15760D8D9AEB6F9A75FD4E');
 
+  FBlockCipherMonteCarloIterations := TCryptoLibStringArray.Create('10000',
+    '10000', '10000', '10000', '10000', '10000', '10000', '10000', '10000',
+    '10000', '10000', '10000');
+
+  FBlockCipherMonteCarloKeys := TCryptoLibStringArray.Create
+    ('00000000000000000000000000000000', '5F060D3716B345C253F6749ABAC10917',
+    'AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114',
+    '28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386',
+    '00000000000000000000000000000000', '5F060D3716B345C253F6749ABAC10917',
+    'AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114',
+    '28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386',
+    '00000000000000000000000000000000', '5F060D3716B345C253F6749ABAC10917',
+    'AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114',
+    '28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386');
+
+  FBlockCipherMonteCarloInputs := TCryptoLibStringArray.Create
+    ('00000000000000000000000000000000', '355F697E8B868B65B25A04E18D782AFA',
+    'F3F6752AE8D7831138F041560631B114', 'C737317FE0846F132B23C8C2A672CE22',
+    '00000000000000000000000000000000', '355F697E8B868B65B25A04E18D782AFA',
+    'F3F6752AE8D7831138F041560631B114', 'C737317FE0846F132B23C8C2A672CE22',
+    '00000000000000000000000000000000', '355F697E8B868B65B25A04E18D782AFA',
+    'F3F6752AE8D7831138F041560631B114', 'C737317FE0846F132B23C8C2A672CE22');
+
+  FBlockCipherMonteCarloOutputs := TCryptoLibStringArray.Create
+    ('C34C052CC0DA8D73451AFE5F03BE297F', 'ACC863637868E3E068D2FD6E3508454A',
+    '77BA00ED5412DFF27C8ED91F3C376172', 'E58B82BFBA53C0040DC610C642121168',
+    'C34C052CC0DA8D73451AFE5F03BE297F', 'ACC863637868E3E068D2FD6E3508454A',
+    '77BA00ED5412DFF27C8ED91F3C376172', 'E58B82BFBA53C0040DC610C642121168',
+    'C34C052CC0DA8D73451AFE5F03BE297F', 'ACC863637868E3E068D2FD6E3508454A',
+    '77BA00ED5412DFF27C8ED91F3C376172', 'E58B82BFBA53C0040DC610C642121168');
+
   // test vectors gotten from here
   // https://github.com/ircmaxell/quality-checker/blob/master/tmp/gh_18/PHP-PasswordLib-master/test/Data/Vectors/aes-cbc.test-vectors
 

+ 11 - 12
CryptoLib.Tests/src/Crypto/AESTests.pas

@@ -104,6 +104,7 @@ procedure TTestAES.doAESTest(const cipher: IBufferedCipher;
   withpadding: Boolean);
 var
   LInput, LOutput, EncryptionResult, DecryptionResult: TBytes;
+  // len1, len2: Int32;
 begin
   LInput := THex.Decode(input);
   LOutput := THex.Decode(output);
@@ -114,15 +115,6 @@ begin
   // Single Pass
   EncryptionResult := cipher.DoFinal(LInput);
 
-  if not withpadding then
-  begin
-    if (not TArrayUtils.AreEqual(LOutput, EncryptionResult)) then
-    begin
-      Fail(Format('Encryption Failed - Expected %s but got %s',
-        [THex.Encode(LOutput), THex.Encode(EncryptionResult)]));
-    end;
-  end;
-
   { *
     // Multi Pass
     System.SetLength(EncryptionResult,
@@ -131,9 +123,18 @@ begin
     len1 := cipher.ProcessBytes(LInput, 0, System.Length(LInput),
     EncryptionResult, 0);
 
-    len1 := cipher.DoFinal(EncryptionResult, len1);
+    len1 := len1 + cipher.DoFinal(EncryptionResult, len1);
     * }
 
+  if not withpadding then
+  begin
+    if (not TArrayUtils.AreEqual(LOutput, EncryptionResult)) then
+    begin
+      Fail(Format('Encryption Failed - Expected %s but got %s',
+        [THex.Encode(LOutput), THex.Encode(EncryptionResult)]));
+    end;
+  end;
+
   cipher.Init(False, param);
 
   // Decryption
@@ -150,8 +151,6 @@ begin
     len2 := len2 + cipher.DoFinal(DecryptionResult, len2);
 
     // remove padding important!!!
-    System.Move(DecryptionResult[0], DecryptionResult[0],
-    len2 * System.SizeOf(Byte));
     System.SetLength(DecryptionResult, len2);
     * }
 

+ 194 - 0
CryptoLib.Tests/src/Crypto/BlockCipherMonteCarloTests.pas

@@ -0,0 +1,194 @@
+{ *********************************************************************************** }
+{ *                              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 BlockCipherMonteCarloTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+uses
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  AESTestVectors,
+  ClpIBlockCipher,
+  ClpICipherParameters,
+  ClpAesEngine,
+  ClpIAesEngine,
+  ClpAesLightEngine,
+  ClpIAesLightEngine,
+  ClpKeyParameter,
+  ClpIKeyParameter,
+  ClpBufferedBlockCipher,
+  ClpIBufferedBlockCipher,
+  ClpHex,
+  ClpArrayUtils,
+  ClpCryptoLibTypes;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  /// <summary>
+  /// a basic test that takes a cipher, key parameter, and an input and
+  /// output string. This test wraps the engine in a buffered block cipher
+  /// with padding disabled.
+  /// </summary>
+  TTestBlockCipherMonteCarlo = class(TCryptoLibTestCase)
+  private
+
+    procedure DoBlockCipherMonteCarloTest(const iteration: string;
+      const engine: IBlockCipher; const param: ICipherParameters;
+      const input, output: String);
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+
+    procedure TestBlockCipherAESEngine;
+    procedure TestBlockCipherAESLightEngine;
+
+  end;
+
+implementation
+
+{ TTestBlockCipherMonteCarlo }
+
+procedure TTestBlockCipherMonteCarlo.DoBlockCipherMonteCarloTest(const iteration
+  : string; const engine: IBlockCipher; const param: ICipherParameters;
+  const input, output: String);
+var
+  cipher: IBufferedBlockCipher;
+  len1, len2, i, iterations: Int32;
+  LInput, LOutput, outBytes: TBytes;
+begin
+  LInput := THex.Decode(input);
+  LOutput := THex.Decode(output);
+  iterations := StrToInt(iteration);
+
+  cipher := TBufferedBlockCipher.Create(engine);
+
+  cipher.Init(true, param);
+
+  System.SetLength(outBytes, System.Length(LInput));
+
+  System.Move(LInput[0], outBytes[0], System.Length(outBytes) *
+    System.SizeOf(Byte));
+
+  i := 0;
+  while i <> iterations do
+  begin
+    len1 := cipher.ProcessBytes(outBytes, 0, System.Length(outBytes),
+      outBytes, 0);
+
+    cipher.DoFinal(outBytes, len1);
+    System.Inc(i);
+  end;
+
+  if (not TArrayUtils.AreEqual(outBytes, LOutput)) then
+  begin
+    Fail(Format('Encryption Failed - Expected %s but got %s',
+      [THex.Encode(LOutput), THex.Encode(outBytes)]));
+  end;
+
+  cipher.Init(false, param);
+
+  i := 0;
+  while i <> iterations do
+  begin
+    len2 := cipher.ProcessBytes(outBytes, 0, System.Length(outBytes),
+      outBytes, 0);
+
+    cipher.DoFinal(outBytes, len2);
+    System.Inc(i);
+  end;
+
+  if (not TArrayUtils.AreEqual(LInput, outBytes)) then
+  begin
+    Fail(Format('Decryption Failed - Expected %s but got %s',
+      [THex.Encode(LInput), THex.Encode(outBytes)]));
+  end;
+end;
+
+procedure TTestBlockCipherMonteCarlo.SetUp;
+begin
+  inherited;
+end;
+
+procedure TTestBlockCipherMonteCarlo.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestBlockCipherMonteCarlo.TestBlockCipherAESEngine;
+var
+  i: Int32;
+begin
+  for i := System.Low(TAESTestVectors.FBlockCipherMonteCarloKeys)
+    to System.High(TAESTestVectors.FBlockCipherMonteCarloKeys) do
+  begin
+    DoBlockCipherMonteCarloTest(TAESTestVectors.FBlockCipherMonteCarloIterations
+      [i], TAesEngine.Create() as IAesEngine,
+      TKeyParameter.Create
+      (THex.Decode(TAESTestVectors.FBlockCipherMonteCarloKeys[i]))
+      as IKeyParameter, TAESTestVectors.FBlockCipherMonteCarloInputs[i],
+      TAESTestVectors.FBlockCipherMonteCarloOutputs[i]);
+  end;
+
+end;
+
+procedure TTestBlockCipherMonteCarlo.TestBlockCipherAESLightEngine;
+var
+  i: Int32;
+begin
+  for i := System.Low(TAESTestVectors.FBlockCipherMonteCarloKeys)
+    to System.High(TAESTestVectors.FBlockCipherMonteCarloKeys) do
+  begin
+    DoBlockCipherMonteCarloTest(TAESTestVectors.FBlockCipherMonteCarloIterations
+      [i], TAesLightEngine.Create() as IAesLightEngine,
+      TKeyParameter.Create
+      (THex.Decode(TAESTestVectors.FBlockCipherMonteCarloKeys[i]))
+      as IKeyParameter, TAESTestVectors.FBlockCipherMonteCarloInputs[i],
+      TAESTestVectors.FBlockCipherMonteCarloOutputs[i]);
+  end;
+
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestBlockCipherMonteCarlo);
+{$ELSE}
+  RegisterTest(TTestBlockCipherMonteCarlo.Suite);
+{$ENDIF FPC}
+
+end.

+ 52 - 6
CryptoLib.Tests/src/Crypto/BlockCipherVectorTests.pas

@@ -36,6 +36,8 @@ uses
   ClpICipherParameters,
   ClpAesEngine,
   ClpIAesEngine,
+  ClpAesLightEngine,
+  ClpIAesLightEngine,
   ClpKeyParameter,
   ClpIKeyParameter,
   ClpParametersWithIV,
@@ -62,7 +64,7 @@ type
   TTestBlockCipherVector = class(TCryptoLibTestCase)
   private
 
-    procedure doBlockCipherVectorTest(const engine: IBlockCipher;
+    procedure DoBlockCipherVectorTest(const engine: IBlockCipher;
       const param: ICipherParameters; const input, output: String);
 
   protected
@@ -71,6 +73,7 @@ type
   published
 
     procedure TestBlockCipherAESEngine;
+    procedure TestBlockCipherAESLightEngine;
     procedure TestBadParameters;
 
   end;
@@ -79,7 +82,7 @@ implementation
 
 { TTestBlockCipherVector }
 
-procedure TTestBlockCipherVector.doBlockCipherVectorTest
+procedure TTestBlockCipherVector.DoBlockCipherVectorTest
   (const engine: IBlockCipher; const param: ICipherParameters;
   const input, output: String);
 var
@@ -96,9 +99,7 @@ begin
 
   System.SetLength(outBytes, System.Length(LInput));
 
-  // len1 := cipher.ProcessBytes(LInput, 0, System.Length(LInput), outBytes, 0);
-  len1 := cipher.ProcessBytes(LInput, 0,
-    cipher.GetOutputSize(System.Length(LInput)), outBytes, 0);
+  len1 := cipher.ProcessBytes(LInput, 0, System.Length(LInput), outBytes, 0);
 
   cipher.DoFinal(outBytes, len1);
 
@@ -136,6 +137,7 @@ procedure TTestBlockCipherVector.TestBadParameters;
 var
   dudKey, iv: TBytes;
   engine: IAesEngine;
+  engine2: IAesLightEngine;
 begin
 
   engine := TAesEngine.Create();
@@ -166,6 +168,35 @@ begin
     end;
 
   end;
+
+  engine2 := TAesLightEngine.Create();
+  //
+  // init tests
+  //
+
+  try
+    System.SetLength(dudKey, 6);
+    engine2.Init(true, TKeyParameter.Create(dudKey) as IKeyParameter);
+    Fail('failed key length check');
+  except
+    on e: EArgumentCryptoLibException do
+    begin
+      // expected
+    end;
+
+  end;
+
+  try
+    System.SetLength(iv, 16);
+    engine2.Init(true, TParametersWithIV.Create(nil, iv) as IParametersWithIV);
+    Fail('failed parameter check');
+  except
+    on e: EArgumentCryptoLibException do
+    begin
+      // expected
+    end;
+
+  end;
 end;
 
 procedure TTestBlockCipherVector.TestBlockCipherAESEngine;
@@ -175,7 +206,22 @@ begin
   for I := System.Low(TAESTestVectors.FBlockCipherVectorKeys)
     to System.High(TAESTestVectors.FBlockCipherVectorKeys) do
   begin
-    doBlockCipherVectorTest(TAesEngine.Create() as IAesEngine,
+    DoBlockCipherVectorTest(TAesEngine.Create() as IAesEngine,
+      TKeyParameter.Create(THex.Decode(TAESTestVectors.FBlockCipherVectorKeys[I]
+      )) as IKeyParameter, TAESTestVectors.FBlockCipherVectorInputs[I],
+      TAESTestVectors.FBlockCipherVectorOutputs[I]);
+  end;
+
+end;
+
+procedure TTestBlockCipherVector.TestBlockCipherAESLightEngine;
+var
+  I: Int32;
+begin
+  for I := System.Low(TAESTestVectors.FBlockCipherVectorKeys)
+    to System.High(TAESTestVectors.FBlockCipherVectorKeys) do
+  begin
+    DoBlockCipherVectorTest(TAesLightEngine.Create() as IAesLightEngine,
       TKeyParameter.Create(THex.Decode(TAESTestVectors.FBlockCipherVectorKeys[I]
       )) as IKeyParameter, TAESTestVectors.FBlockCipherVectorInputs[I],
       TAESTestVectors.FBlockCipherVectorOutputs[I]);

+ 162 - 0
CryptoLib.Tests/src/Crypto/RIPEMD128HMacTests.pas

@@ -0,0 +1,162 @@
+{ *********************************************************************************** }
+{ *                              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 RIPEMD128HMacTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+uses
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpKeyParameter,
+  ClpHMac,
+  ClpIMac,
+  ClpDigestUtilities,
+  ClpHex,
+  ClpArrayUtils,
+  ClpStringUtils,
+  ClpCryptoLibTypes;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  /// <summary>
+  /// RIPEMD128 HMac Test, test vectors from RFC 2202
+  /// </summary>
+  TTestRIPEMD128HMac = class(TCryptoLibTestCase)
+  private
+  var
+    Fkeys, Fdigests, Fmessages: TCryptoLibStringArray;
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+
+    procedure TestRIPEMD128HMac;
+
+  end;
+
+implementation
+
+{ TTestRIPEMD128HMac }
+
+procedure TTestRIPEMD128HMac.SetUp;
+begin
+  inherited;
+  Fkeys := TCryptoLibStringArray.Create('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b',
+    '4a656665', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
+    '0102030405060708090a0b0c0d0e0f10111213141516171819',
+    '0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c',
+    'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
+    'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
+
+  Fdigests := TCryptoLibStringArray.Create('fbf61f9492aa4bbf81c172e84e0734db',
+    '875f828862b6b334b427c55f9f7ff09b', '09f0b2846d2f543da363cbec8d62a38d',
+    'bdbbd7cf03e44b5aa60af815be4d2294', 'e79808f24b25fd031c155f0d551d9a3a',
+    'dc732928de98104a1f59d373c150acbb', '5c6bec96793e16d40690c237635f30c5');
+
+  Fmessages := TCryptoLibStringArray.Create('Hi There',
+    'what do ya want for nothing?',
+    '0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd',
+    '0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd',
+    'Test With Truncation',
+    'Test Using Larger Than Block-Size Key - Hash Key First',
+    'Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data');
+end;
+
+procedure TTestRIPEMD128HMac.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestRIPEMD128HMac.TestRIPEMD128HMac;
+var
+  hmac: IMac;
+  resBuf, m, m2: TBytes;
+  i, vector: Int32;
+begin
+  hmac := THMac.Create(TDigestUtilities.GetDigest('RIPEMD128'));
+  System.SetLength(resBuf, hmac.GetMacSize());
+
+  for i := 0 to System.Pred(System.Length(Fmessages)) do
+  begin
+    m := TEncoding.ASCII.GetBytes(UnicodeString(Fmessages[i]));
+    if (TStringUtils.BeginsWith(Fmessages[i], '0x', True)) then
+    begin
+      m := THex.Decode(System.Copy(Fmessages[i], 3,
+        System.Length(Fmessages[i]) - 2));
+    end;
+    hmac.Init(TKeyParameter.Create(THex.Decode(Fkeys[i])));
+    hmac.BlockUpdate(m, 0, System.Length(m));
+    hmac.DoFinal(resBuf, 0);
+
+    if (not TArrayUtils.AreEqual(resBuf, THex.Decode(Fdigests[i]))) then
+    begin
+      Fail('Vector ' + IntToStr(i) + ' failed');
+    end;
+  end;
+
+  // test reset
+  vector := 0; // vector used for test
+  m2 := TEncoding.ASCII.GetBytes(UnicodeString(Fmessages[vector]));
+
+  if (TStringUtils.BeginsWith(Fmessages[vector], '0x', True)) then
+  begin
+    m2 := THex.Decode(System.Copy(Fmessages[vector], 3,
+      System.Length(Fmessages[vector]) - 2));
+  end;
+
+  hmac.Init(TKeyParameter.Create(THex.Decode(Fkeys[vector])));
+  hmac.BlockUpdate(m2, 0, System.Length(m2));
+  hmac.DoFinal(resBuf, 0);
+  hmac.Reset();
+  hmac.BlockUpdate(m2, 0, System.Length(m2));
+  hmac.DoFinal(resBuf, 0);
+
+  if (not TArrayUtils.AreEqual(resBuf, THex.Decode(Fdigests[vector]))) then
+  begin
+    Fail('Reset with vector ' + IntToStr(vector) + ' failed');
+  end;
+
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestRIPEMD128HMac);
+{$ELSE}
+  RegisterTest(TTestRIPEMD128HMac.Suite);
+{$ENDIF FPC}
+
+end.

+ 167 - 0
CryptoLib.Tests/src/Crypto/RIPEMD160HMacTests.pas

@@ -0,0 +1,167 @@
+{ *********************************************************************************** }
+{ *                              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 RIPEMD160HMacTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+uses
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpKeyParameter,
+  ClpHMac,
+  ClpIMac,
+  ClpDigestUtilities,
+  ClpHex,
+  ClpArrayUtils,
+  ClpStringUtils,
+  ClpCryptoLibTypes;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  /// <summary>
+  /// RIPEMD160 HMac Test, test vectors from RFC 2202
+  /// </summary>
+  TTestRIPEMD160HMac = class(TCryptoLibTestCase)
+  private
+  var
+    Fkeys, Fdigests, Fmessages: TCryptoLibStringArray;
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+
+    procedure TestRIPEMD160HMac;
+
+  end;
+
+implementation
+
+{ TTestRIPEMD160HMac }
+
+procedure TTestRIPEMD160HMac.SetUp;
+begin
+  inherited;
+  Fkeys := TCryptoLibStringArray.Create
+    ('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b', '4a656665',
+    'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
+    '0102030405060708090a0b0c0d0e0f10111213141516171819',
+    '0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c',
+    'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
+    'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
+
+  Fdigests := TCryptoLibStringArray.Create
+    ('24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668',
+    'dda6c0213a485a9e24f4742064a7f033b43c4069',
+    'b0b105360de759960ab4f35298e116e295d8e7c1',
+    'd5ca862f4d21d5e610e18b4cf1beb97a4365ecf4',
+    '7619693978f91d90539ae786500ff3d8e0518e39',
+    '6466ca07ac5eac29e1bd523e5ada7605b791fd8b',
+    '69ea60798d71616cce5fd0871e23754cd75d5a0a');
+
+  Fmessages := TCryptoLibStringArray.Create('Hi There',
+    'what do ya want for nothing?',
+    '0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd',
+    '0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd',
+    'Test With Truncation',
+    'Test Using Larger Than Block-Size Key - Hash Key First',
+    'Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data');
+end;
+
+procedure TTestRIPEMD160HMac.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestRIPEMD160HMac.TestRIPEMD160HMac;
+var
+  hmac: IMac;
+  resBuf, m, m2: TBytes;
+  i, vector: Int32;
+begin
+  hmac := THMac.Create(TDigestUtilities.GetDigest('RIPEMD160'));
+  System.SetLength(resBuf, hmac.GetMacSize());
+
+  for i := 0 to System.Pred(System.Length(Fmessages)) do
+  begin
+    m := TEncoding.ASCII.GetBytes(UnicodeString(Fmessages[i]));
+    if (TStringUtils.BeginsWith(Fmessages[i], '0x', True)) then
+    begin
+      m := THex.Decode(System.Copy(Fmessages[i], 3,
+        System.Length(Fmessages[i]) - 2));
+    end;
+    hmac.Init(TKeyParameter.Create(THex.Decode(Fkeys[i])));
+    hmac.BlockUpdate(m, 0, System.Length(m));
+    hmac.DoFinal(resBuf, 0);
+
+    if (not TArrayUtils.AreEqual(resBuf, THex.Decode(Fdigests[i]))) then
+    begin
+      Fail('Vector ' + IntToStr(i) + ' failed');
+    end;
+  end;
+
+  // test reset
+  vector := 0; // vector used for test
+  m2 := TEncoding.ASCII.GetBytes(UnicodeString(Fmessages[vector]));
+
+  if (TStringUtils.BeginsWith(Fmessages[vector], '0x', True)) then
+  begin
+    m2 := THex.Decode(System.Copy(Fmessages[vector], 3,
+      System.Length(Fmessages[vector]) - 2));
+  end;
+
+  hmac.Init(TKeyParameter.Create(THex.Decode(Fkeys[vector])));
+  hmac.BlockUpdate(m2, 0, System.Length(m2));
+  hmac.DoFinal(resBuf, 0);
+  hmac.Reset();
+  hmac.BlockUpdate(m2, 0, System.Length(m2));
+  hmac.DoFinal(resBuf, 0);
+
+  if (not TArrayUtils.AreEqual(resBuf, THex.Decode(Fdigests[vector]))) then
+  begin
+    Fail('Reset with vector ' + IntToStr(vector) + ' failed');
+  end;
+
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestRIPEMD160HMac);
+{$ELSE}
+  RegisterTest(TTestRIPEMD160HMac.Suite);
+{$ENDIF FPC}
+
+end.

+ 168 - 0
CryptoLib.Tests/src/Crypto/SHA1HMacTests.pas

@@ -0,0 +1,168 @@
+{ *********************************************************************************** }
+{ *                              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 SHA1HMacTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+uses
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpKeyParameter,
+  ClpHMac,
+  ClpIMac,
+  ClpDigestUtilities,
+  ClpHex,
+  ClpArrayUtils,
+  ClpStringUtils,
+  ClpCryptoLibTypes;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  /// <summary>
+  /// SHA1 HMac Test, test vectors from RFC 2202
+  /// </summary>
+  TTestSHA1HMac = class(TCryptoLibTestCase)
+  private
+  var
+    Fkeys, Fdigests, Fmessages: TCryptoLibStringArray;
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+
+    procedure TestSHA1HMac;
+
+  end;
+
+implementation
+
+{ TTestSHA1HMac }
+
+procedure TTestSHA1HMac.SetUp;
+begin
+  inherited;
+  Fkeys := TCryptoLibStringArray.Create
+    ('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b', '4a656665',
+    'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
+    '0102030405060708090a0b0c0d0e0f10111213141516171819',
+    '0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c',
+    'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
+    'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
+  Fdigests := TCryptoLibStringArray.Create
+    ('b617318655057264e28bc0b6fb378c8ef146be00',
+    'effcdf6ae5eb2fa2d27416d5f184df9c259a7c79',
+    '125d7342b9ac11cd91a39af48aa17b4f63f175d3',
+    '4c9007f4026250c6bc8414f9bf50c86c2d7235da',
+    '4c1a03424b55e07fe7f27be1d58bb9324a9a5a04',
+    'aa4ae5e15272d00e95705637ce8a3b55ed402112',
+    'e8e99d0f45237d786d6bbaa7965c7808bbff1a91',
+    '4c1a03424b55e07fe7f27be1d58bb9324a9a5a04',
+    'aa4ae5e15272d00e95705637ce8a3b55ed402112',
+    'e8e99d0f45237d786d6bbaa7965c7808bbff1a91');
+  Fmessages := TCryptoLibStringArray.Create('Hi There',
+    'what do ya want for nothing?',
+    '0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd',
+    '0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd',
+    'Test With Truncation',
+    'Test Using Larger Than Block-Size Key - Hash Key First',
+    'Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data');
+end;
+
+procedure TTestSHA1HMac.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestSHA1HMac.TestSHA1HMac;
+var
+  hmac: IMac;
+  resBuf, m, m2: TBytes;
+  i, vector: Int32;
+begin
+  hmac := THMac.Create(TDigestUtilities.GetDigest('SHA-1'));
+  System.SetLength(resBuf, hmac.GetMacSize());
+
+  for i := 0 to System.Pred(System.Length(Fmessages)) do
+  begin
+    m := TEncoding.ASCII.GetBytes(UnicodeString(Fmessages[i]));
+    if (TStringUtils.BeginsWith(Fmessages[i], '0x', True)) then
+    begin
+      m := THex.Decode(System.Copy(Fmessages[i], 3,
+        System.Length(Fmessages[i]) - 2));
+    end;
+    hmac.Init(TKeyParameter.Create(THex.Decode(Fkeys[i])));
+    hmac.BlockUpdate(m, 0, System.Length(m));
+    hmac.DoFinal(resBuf, 0);
+
+    if (not TArrayUtils.AreEqual(resBuf, THex.Decode(Fdigests[i]))) then
+    begin
+      Fail('Vector ' + IntToStr(i) + ' failed');
+    end;
+  end;
+
+  // test reset
+  vector := 0; // vector used for test
+  m2 := TEncoding.ASCII.GetBytes(UnicodeString(Fmessages[vector]));
+
+  if (TStringUtils.BeginsWith(Fmessages[vector], '0x', True)) then
+  begin
+    m2 := THex.Decode(System.Copy(Fmessages[vector], 3,
+      System.Length(Fmessages[vector]) - 2));
+  end;
+
+  hmac.Init(TKeyParameter.Create(THex.Decode(Fkeys[vector])));
+  hmac.BlockUpdate(m2, 0, System.Length(m2));
+  hmac.DoFinal(resBuf, 0);
+  hmac.Reset();
+  hmac.BlockUpdate(m2, 0, System.Length(m2));
+  hmac.DoFinal(resBuf, 0);
+
+  if (not TArrayUtils.AreEqual(resBuf, THex.Decode(Fdigests[vector]))) then
+  begin
+    Fail('Reset with vector ' + IntToStr(vector) + ' failed');
+  end;
+
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestSHA1HMac);
+{$ELSE}
+  RegisterTest(TTestSHA1HMac.Suite);
+{$ENDIF FPC}
+
+end.

+ 169 - 0
CryptoLib.Tests/src/Crypto/SHA224HMacTests.pas

@@ -0,0 +1,169 @@
+{ *********************************************************************************** }
+{ *                              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 SHA224HMacTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+uses
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpKeyParameter,
+  ClpHMac,
+  ClpIMac,
+  ClpDigestUtilities,
+  ClpHex,
+  ClpArrayUtils,
+  ClpStringUtils,
+  ClpCryptoLibTypes;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  /// <summary>
+  /// SHA224 HMac Test, test vectors from RFC 2202
+  /// </summary>
+  TTestSHA224HMac = class(TCryptoLibTestCase)
+  private
+  var
+    Fkeys, Fdigests, Fmessages: TCryptoLibStringArray;
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+
+    procedure TestSHA224HMac;
+
+  end;
+
+implementation
+
+{ TTestSHA224HMac }
+
+procedure TTestSHA224HMac.SetUp;
+begin
+  inherited;
+  Fkeys := TCryptoLibStringArray.Create
+    ('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b', '4a656665',
+    'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
+    '0102030405060708090a0b0c0d0e0f10111213141516171819',
+    '0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c',
+    'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
+    + 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
+    'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
+    + 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
+
+  Fdigests := TCryptoLibStringArray.Create
+    ('896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22',
+    'a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44',
+    '7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea',
+    '6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a',
+    '0e2aea68a90c8d37c988bcdb9fca6fa8099cd857c7ec4a1815cac54c',
+    '95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e',
+    '3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1');
+
+  Fmessages := TCryptoLibStringArray.Create('Hi There',
+    'what do ya want for nothing?',
+    '0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd',
+    '0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd',
+    'Test With Truncation',
+    'Test Using Larger Than Block-Size Key - Hash Key First',
+    'This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.');
+end;
+
+procedure TTestSHA224HMac.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestSHA224HMac.TestSHA224HMac;
+var
+  hmac: IMac;
+  resBuf, m, m2: TBytes;
+  i, vector: Int32;
+begin
+  hmac := THMac.Create(TDigestUtilities.GetDigest('SHA-224'));
+  System.SetLength(resBuf, hmac.GetMacSize());
+
+  for i := 0 to System.Pred(System.Length(Fmessages)) do
+  begin
+    m := TEncoding.ASCII.GetBytes(UnicodeString(Fmessages[i]));
+    if (TStringUtils.BeginsWith(Fmessages[i], '0x', True)) then
+    begin
+      m := THex.Decode(System.Copy(Fmessages[i], 3,
+        System.Length(Fmessages[i]) - 2));
+    end;
+    hmac.Init(TKeyParameter.Create(THex.Decode(Fkeys[i])));
+    hmac.BlockUpdate(m, 0, System.Length(m));
+    hmac.DoFinal(resBuf, 0);
+
+    if (not TArrayUtils.AreEqual(resBuf, THex.Decode(Fdigests[i]))) then
+    begin
+      Fail('Vector ' + IntToStr(i) + ' failed');
+    end;
+  end;
+
+  // test reset
+  vector := 0; // vector used for test
+  m2 := TEncoding.ASCII.GetBytes(UnicodeString(Fmessages[vector]));
+
+  if (TStringUtils.BeginsWith(Fmessages[vector], '0x', True)) then
+  begin
+    m2 := THex.Decode(System.Copy(Fmessages[vector], 3,
+      System.Length(Fmessages[vector]) - 2));
+  end;
+
+  hmac.Init(TKeyParameter.Create(THex.Decode(Fkeys[vector])));
+  hmac.BlockUpdate(m2, 0, System.Length(m2));
+  hmac.DoFinal(resBuf, 0);
+  hmac.Reset();
+  hmac.BlockUpdate(m2, 0, System.Length(m2));
+  hmac.DoFinal(resBuf, 0);
+
+  if (not TArrayUtils.AreEqual(resBuf, THex.Decode(Fdigests[vector]))) then
+  begin
+    Fail('Reset with vector ' + IntToStr(vector) + ' failed');
+  end;
+
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestSHA224HMac);
+{$ELSE}
+  RegisterTest(TTestSHA224HMac.Suite);
+{$ENDIF FPC}
+
+end.

+ 169 - 0
CryptoLib.Tests/src/Crypto/SHA256HMacTests.pas

@@ -0,0 +1,169 @@
+{ *********************************************************************************** }
+{ *                              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 SHA256HMacTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+uses
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpKeyParameter,
+  ClpHMac,
+  ClpIMac,
+  ClpDigestUtilities,
+  ClpHex,
+  ClpArrayUtils,
+  ClpStringUtils,
+  ClpCryptoLibTypes;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  /// <summary>
+  /// SHA256 HMac Test, test vectors from RFC 2202
+  /// </summary>
+  TTestSHA256HMac = class(TCryptoLibTestCase)
+  private
+  var
+    Fkeys, Fdigests, Fmessages: TCryptoLibStringArray;
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+
+    procedure TestSHA256HMac;
+
+  end;
+
+implementation
+
+{ TTestSHA256HMac }
+
+procedure TTestSHA256HMac.SetUp;
+begin
+  inherited;
+  Fkeys := TCryptoLibStringArray.Create
+    ('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b', '4a656665',
+    'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
+    '0102030405060708090a0b0c0d0e0f10111213141516171819',
+    '0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c',
+    'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
+    + 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
+    'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
+    + 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
+
+  Fdigests := TCryptoLibStringArray.Create
+    ('b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7',
+    '5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843',
+    '773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe',
+    '82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b',
+    'a3b6167473100ee06e0c796c2955552bfa6f7c0a6a8aef8b93f860aab0cd20c5',
+    '60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54',
+    '9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2');
+
+  Fmessages := TCryptoLibStringArray.Create('Hi There',
+    'what do ya want for nothing?',
+    '0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd',
+    '0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd',
+    'Test With Truncation',
+    'Test Using Larger Than Block-Size Key - Hash Key First',
+    'This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.');
+end;
+
+procedure TTestSHA256HMac.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestSHA256HMac.TestSHA256HMac;
+var
+  hmac: IMac;
+  resBuf, m, m2: TBytes;
+  i, vector: Int32;
+begin
+  hmac := THMac.Create(TDigestUtilities.GetDigest('SHA-256'));
+  System.SetLength(resBuf, hmac.GetMacSize());
+
+  for i := 0 to System.Pred(System.Length(Fmessages)) do
+  begin
+    m := TEncoding.ASCII.GetBytes(UnicodeString(Fmessages[i]));
+    if (TStringUtils.BeginsWith(Fmessages[i], '0x', True)) then
+    begin
+      m := THex.Decode(System.Copy(Fmessages[i], 3,
+        System.Length(Fmessages[i]) - 2));
+    end;
+    hmac.Init(TKeyParameter.Create(THex.Decode(Fkeys[i])));
+    hmac.BlockUpdate(m, 0, System.Length(m));
+    hmac.DoFinal(resBuf, 0);
+
+    if (not TArrayUtils.AreEqual(resBuf, THex.Decode(Fdigests[i]))) then
+    begin
+      Fail('Vector ' + IntToStr(i) + ' failed');
+    end;
+  end;
+
+  // test reset
+  vector := 0; // vector used for test
+  m2 := TEncoding.ASCII.GetBytes(UnicodeString(Fmessages[vector]));
+
+  if (TStringUtils.BeginsWith(Fmessages[vector], '0x', True)) then
+  begin
+    m2 := THex.Decode(System.Copy(Fmessages[vector], 3,
+      System.Length(Fmessages[vector]) - 2));
+  end;
+
+  hmac.Init(TKeyParameter.Create(THex.Decode(Fkeys[vector])));
+  hmac.BlockUpdate(m2, 0, System.Length(m2));
+  hmac.DoFinal(resBuf, 0);
+  hmac.Reset();
+  hmac.BlockUpdate(m2, 0, System.Length(m2));
+  hmac.DoFinal(resBuf, 0);
+
+  if (not TArrayUtils.AreEqual(resBuf, THex.Decode(Fdigests[vector]))) then
+  begin
+    Fail('Reset with vector ' + IntToStr(vector) + ' failed');
+  end;
+
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestSHA256HMac);
+{$ELSE}
+  RegisterTest(TTestSHA256HMac.Suite);
+{$ENDIF FPC}
+
+end.

+ 169 - 0
CryptoLib.Tests/src/Crypto/SHA384HMacTests.pas

@@ -0,0 +1,169 @@
+{ *********************************************************************************** }
+{ *                              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 SHA384HMacTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+uses
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpKeyParameter,
+  ClpHMac,
+  ClpIMac,
+  ClpDigestUtilities,
+  ClpHex,
+  ClpArrayUtils,
+  ClpStringUtils,
+  ClpCryptoLibTypes;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  /// <summary>
+  /// SHA384 HMac Test, test vectors from RFC 2202
+  /// </summary>
+  TTestSHA384HMac = class(TCryptoLibTestCase)
+  private
+  var
+    Fkeys, Fdigests, Fmessages: TCryptoLibStringArray;
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+
+    procedure TestSHA384HMac;
+
+  end;
+
+implementation
+
+{ TTestSHA384HMac }
+
+procedure TTestSHA384HMac.SetUp;
+begin
+  inherited;
+  Fkeys := TCryptoLibStringArray.Create
+    ('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b', '4a656665',
+    'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
+    '0102030405060708090a0b0c0d0e0f10111213141516171819',
+    '0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c',
+    'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
+    + 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
+    'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
+    + 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
+
+  Fdigests := TCryptoLibStringArray.Create
+    ('afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59cfaea9ea9076ede7f4af152e8b2fa9cb6',
+    'af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649',
+    '88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b2a5ab39dc13814b94e3ab6e101a34f27',
+    '3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e6801dd23c4a7d679ccf8a386c674cffb',
+    '3abf34c3503b2a23a46efc619baef897f4c8e42c934ce55ccbae9740fcbc1af4ca62269e2a37cd88ba926341efe4aeea',
+    '4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c60c2ef6ab4030fe8296248df163f44952',
+    '6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5a678cc31e799176d3860e6110c46523e');
+
+  Fmessages := TCryptoLibStringArray.Create('Hi There',
+    'what do ya want for nothing?',
+    '0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd',
+    '0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd',
+    'Test With Truncation',
+    'Test Using Larger Than Block-Size Key - Hash Key First',
+    'This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.');
+end;
+
+procedure TTestSHA384HMac.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestSHA384HMac.TestSHA384HMac;
+var
+  hmac: IMac;
+  resBuf, m, m2: TBytes;
+  i, vector: Int32;
+begin
+  hmac := THMac.Create(TDigestUtilities.GetDigest('SHA-384'));
+  System.SetLength(resBuf, hmac.GetMacSize());
+
+  for i := 0 to System.Pred(System.Length(Fmessages)) do
+  begin
+    m := TEncoding.ASCII.GetBytes(UnicodeString(Fmessages[i]));
+    if (TStringUtils.BeginsWith(Fmessages[i], '0x', True)) then
+    begin
+      m := THex.Decode(System.Copy(Fmessages[i], 3,
+        System.Length(Fmessages[i]) - 2));
+    end;
+    hmac.Init(TKeyParameter.Create(THex.Decode(Fkeys[i])));
+    hmac.BlockUpdate(m, 0, System.Length(m));
+    hmac.DoFinal(resBuf, 0);
+
+    if (not TArrayUtils.AreEqual(resBuf, THex.Decode(Fdigests[i]))) then
+    begin
+      Fail('Vector ' + IntToStr(i) + ' failed');
+    end;
+  end;
+
+  // test reset
+  vector := 0; // vector used for test
+  m2 := TEncoding.ASCII.GetBytes(UnicodeString(Fmessages[vector]));
+
+  if (TStringUtils.BeginsWith(Fmessages[vector], '0x', True)) then
+  begin
+    m2 := THex.Decode(System.Copy(Fmessages[vector], 3,
+      System.Length(Fmessages[vector]) - 2));
+  end;
+
+  hmac.Init(TKeyParameter.Create(THex.Decode(Fkeys[vector])));
+  hmac.BlockUpdate(m2, 0, System.Length(m2));
+  hmac.DoFinal(resBuf, 0);
+  hmac.Reset();
+  hmac.BlockUpdate(m2, 0, System.Length(m2));
+  hmac.DoFinal(resBuf, 0);
+
+  if (not TArrayUtils.AreEqual(resBuf, THex.Decode(Fdigests[vector]))) then
+  begin
+    Fail('Reset with vector ' + IntToStr(vector) + ' failed');
+  end;
+
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestSHA384HMac);
+{$ELSE}
+  RegisterTest(TTestSHA384HMac.Suite);
+{$ENDIF FPC}
+
+end.

+ 169 - 0
CryptoLib.Tests/src/Crypto/SHA512HMacTests.pas

@@ -0,0 +1,169 @@
+{ *********************************************************************************** }
+{ *                              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 SHA512HMacTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+uses
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpKeyParameter,
+  ClpHMac,
+  ClpIMac,
+  ClpDigestUtilities,
+  ClpHex,
+  ClpArrayUtils,
+  ClpStringUtils,
+  ClpCryptoLibTypes;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  /// <summary>
+  /// SHA512 HMac Test, test vectors from RFC 2202
+  /// </summary>
+  TTestSHA512HMac = class(TCryptoLibTestCase)
+  private
+  var
+    Fkeys, Fdigests, Fmessages: TCryptoLibStringArray;
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+
+    procedure TestSHA512HMac;
+
+  end;
+
+implementation
+
+{ TTestSHA512HMac }
+
+procedure TTestSHA512HMac.SetUp;
+begin
+  inherited;
+  Fkeys := TCryptoLibStringArray.Create
+    ('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b', '4a656665',
+    'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
+    '0102030405060708090a0b0c0d0e0f10111213141516171819',
+    '0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c',
+    'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
+    + 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
+    'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
+    + 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
+
+  Fdigests := TCryptoLibStringArray.Create
+    ('87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854',
+    '164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737',
+    'fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb',
+    'b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd',
+    '415fad6271580a531d4179bc891d87a650188707922a4fbb36663a1eb16da008711c5b50ddd0fc235084eb9d3364a1454fb2ef67cd1d29fe6773068ea266e96b',
+    '80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598',
+    'e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58');
+
+  Fmessages := TCryptoLibStringArray.Create('Hi There',
+    'what do ya want for nothing?',
+    '0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd',
+    '0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd',
+    'Test With Truncation',
+    'Test Using Larger Than Block-Size Key - Hash Key First',
+    'This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.');
+end;
+
+procedure TTestSHA512HMac.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestSHA512HMac.TestSHA512HMac;
+var
+  hmac: IMac;
+  resBuf, m, m2: TBytes;
+  i, vector: Int32;
+begin
+  hmac := THMac.Create(TDigestUtilities.GetDigest('SHA-512'));
+  System.SetLength(resBuf, hmac.GetMacSize());
+
+  for i := 0 to System.Pred(System.Length(Fmessages)) do
+  begin
+    m := TEncoding.ASCII.GetBytes(UnicodeString(Fmessages[i]));
+    if (TStringUtils.BeginsWith(Fmessages[i], '0x', True)) then
+    begin
+      m := THex.Decode(System.Copy(Fmessages[i], 3,
+        System.Length(Fmessages[i]) - 2));
+    end;
+    hmac.Init(TKeyParameter.Create(THex.Decode(Fkeys[i])));
+    hmac.BlockUpdate(m, 0, System.Length(m));
+    hmac.DoFinal(resBuf, 0);
+
+    if (not TArrayUtils.AreEqual(resBuf, THex.Decode(Fdigests[i]))) then
+    begin
+      Fail('Vector ' + IntToStr(i) + ' failed');
+    end;
+  end;
+
+  // test reset
+  vector := 0; // vector used for test
+  m2 := TEncoding.ASCII.GetBytes(UnicodeString(Fmessages[vector]));
+
+  if (TStringUtils.BeginsWith(Fmessages[vector], '0x', True)) then
+  begin
+    m2 := THex.Decode(System.Copy(Fmessages[vector], 3,
+      System.Length(Fmessages[vector]) - 2));
+  end;
+
+  hmac.Init(TKeyParameter.Create(THex.Decode(Fkeys[vector])));
+  hmac.BlockUpdate(m2, 0, System.Length(m2));
+  hmac.DoFinal(resBuf, 0);
+  hmac.Reset();
+  hmac.BlockUpdate(m2, 0, System.Length(m2));
+  hmac.DoFinal(resBuf, 0);
+
+  if (not TArrayUtils.AreEqual(resBuf, THex.Decode(Fdigests[vector]))) then
+  begin
+    Fail('Reset with vector ' + IntToStr(vector) + ' failed');
+  end;
+
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestSHA512HMac);
+{$ELSE}
+  RegisterTest(TTestSHA512HMac.Suite);
+{$ENDIF FPC}
+
+end.

+ 3 - 2
CryptoLib.Tests/src/Math/EC/Custom/Sec/SecP384R1FieldTests.pas

@@ -38,7 +38,7 @@ uses
   ClpIX9ECParameters,
   ClpSecObjectIdentifiers,
   ClpConverters,
-  ClpSecNamedCurves,
+  ClpCustomNamedCurves,
   ClpIECFieldElement,
   ClpBigInteger;
 
@@ -148,7 +148,8 @@ procedure TTestSecP384R1Field.SetUp;
 begin
   inherited;
   FRandom := TSecureRandom.Create();
-  FDP := TSecNamedCurves.GetByOid(TSecObjectIdentifiers.SecP384r1);
+  FDP := TCustomNamedCurves.GetByOid(TSecObjectIdentifiers.SecP384r1);
+
   FQ := FDP.Curve.Field.Characteristic;
 end;
 

+ 18 - 17
CryptoLib.Tests/src/Math/EC/FixedPointTests.pas

@@ -36,6 +36,7 @@ uses
   ClpIECInterface,
   ClpBigInteger,
   ClpECNamedCurveTable,
+  ClpCustomNamedCurves,
   ClpFixedPointCombMultiplier,
   ClpIFixedPointCombMultiplier,
   ClpECAlgorithms,
@@ -89,10 +90,10 @@ var
   tempList: TList<String>;
   tempDict: TDictionary<String, String>;
   names: TCryptoLibStringArray;
-  x9, X9A: IX9ECParameters;
+  x9, X9A, X9B: IX9ECParameters;
   M: IFixedPointCombMultiplier;
   k: TBigInteger;
-  pRef, pA: IECPoint;
+  pRef, pA, pB: IECPoint;
 
 begin
   M := TFixedPointCombMultiplier.Create();
@@ -100,7 +101,7 @@ begin
   tempList := TList<String>.Create();
   try
     tempList.AddRange(TECNamedCurveTable.names); // get all collections
-    // tempList.AddRange(TCustomNamedCurves.Names);
+    tempList.AddRange(TCustomNamedCurves.names);
     tempDict := TDictionary<String, String>.Create();
     try
       for s in tempList do
@@ -118,15 +119,15 @@ begin
   for name in names do
   begin
     X9A := TECNamedCurveTable.GetByName(name);
-    // x9B := CustomNamedCurves.GetByName(name);
-    // if (x9B <> Nil) then
-    // begin
-    // x9 := x9B
-    // end
-    // else
-    // begin
-    x9 := X9A;
-    // end;
+    X9B := TCustomNamedCurves.GetByName(name);
+    if (X9B <> Nil) then
+    begin
+      x9 := X9B
+    end
+    else
+    begin
+      x9 := X9A;
+    end;
 
     i := 0;
     while i < TestsPerCurve do
@@ -140,11 +141,11 @@ begin
         AssertPointsEqual('Standard curve fixed-point failure', pRef, pA);
       end;
 
-      // if (x9B <> Nil) then
-      // begin
-      // pB := M.Multiply(x9B.G, k);
-      // AssertPointsEqual('Custom curve fixed-point failure', pRef, pB);
-      // end;
+      if (X9B <> Nil) then
+      begin
+        pB := M.Multiply(X9B.G, k);
+        AssertPointsEqual('Custom curve fixed-point failure', pRef, pB);
+      end;
       System.Inc(i);
     end;
 

+ 11 - 8
CryptoLib.Tests/src/Math/ECAlgorithmsTests.pas

@@ -42,6 +42,7 @@ uses
   ClpIECInterface,
   ClpBigInteger,
   ClpECNamedCurveTable,
+  ClpCustomNamedCurves,
   ClpECAlgorithms,
   ClpX9ECParameters,
   ClpIX9ECParameters,
@@ -243,7 +244,7 @@ begin
     tempList := TList<String>.Create();
     try
       tempList.AddRange(TECNamedCurveTable.names); // get all collections
-      // tempList.AddRange(TCustomNamedCurves.Names);
+      tempList.AddRange(TCustomNamedCurves.names);
       tempDict := TDictionary<String, String>.Create();
       try
         for s in tempList do
@@ -266,11 +267,11 @@ begin
         AddTestCurves(x9s, x9);
       end;
 
-      // x9 := TCustomNamedCurves.GetByName(name);
-      // if (x9 <> Nil) then
-      // begin
-      // AddTestCurves(x9s, x9);
-      // end;
+      x9 := TCustomNamedCurves.GetByName(name);
+      if (x9 <> Nil) then
+      begin
+        AddTestCurves(x9s, x9);
+      end;
     end;
     Result := x9s.ToArray;
   finally
@@ -294,7 +295,8 @@ var
   x9: IX9ECParameters;
 begin
   // x9 := TCustomNamedCurves.GetByName('secp256r1'); // original
-  x9 := TECNamedCurveTable.GetByName('secp256k1');
+  // x9 := TECNamedCurveTable.GetByName('secp256k1');
+  x9 := TCustomNamedCurves.GetByName('secp256k1');
   CheckNotNull(x9);
   DoTestSumOfMultiplies(x9);
 end;
@@ -314,7 +316,8 @@ var
   x9: IX9ECParameters;
 begin
   // x9 := TCustomNamedCurves.GetByName('secp256r1');  // original
-  x9 := TECNamedCurveTable.GetByName('secp256k1');
+  // x9 := TECNamedCurveTable.GetByName('secp256k1');
+  x9 := TCustomNamedCurves.GetByName('secp256k1');
   CheckNotNull(x9);
   DoTestSumOfTwoMultiplies(x9);
 end;

+ 63 - 61
CryptoLib.Tests/src/Math/ECPointTests.pas

@@ -33,6 +33,7 @@ uses
   TestFramework,
 {$ENDIF FPC}
   Generics.Collections,
+  ClpCustomNamedCurves,
   ClpECNamedCurveTable,
   ClpCryptoLibTypes,
   ClpSecureRandom,
@@ -44,7 +45,8 @@ uses
   ClpIFiniteField,
   ClpIX9ECParameters,
   ClpIECFieldElement,
-  ClpIECInterface;
+  ClpIECInterface,
+  ClpArrayUtils;
 
 type
 
@@ -111,10 +113,10 @@ type
     F2mInstance: TF2m;
 
     procedure AssertPointsEqual(const msg: String; const a, b: IECPoint);
-    // procedure AssertBigIntegersEqual(a, b: TBigInteger);
-    // procedure AssertIFiniteFieldsEqual(a, b: IFiniteField);
-    // procedure AssertOptionalValuesAgree(a, b: TBigInteger); overload;
-    // procedure AssertOptionalValuesAgree(a, b: TCryptoLibByteArray); overload;
+    procedure AssertBigIntegersEqual(a, b: TBigInteger);
+    procedure AssertIFiniteFieldsEqual(a, b: IFiniteField);
+    procedure AssertOptionalValuesAgree(a, b: TBigInteger); overload;
+    procedure AssertOptionalValuesAgree(a, b: TCryptoLibByteArray); overload;
 
     procedure AssertECFieldElementsEqual(const a, b: IECFieldElement);
 
@@ -261,31 +263,31 @@ begin
   CheckEquals(True, a.Equals(b));
 end;
 
-// procedure TTestECPoint.AssertBigIntegersEqual(a, b: TBigInteger);
-// begin
-// CheckEquals(True, a.Equals(b));
-// end;
-
-// procedure TTestECPoint.AssertIFiniteFieldsEqual(a, b: IFiniteField);
-// begin
-// CheckEquals(True, (a as TObject).Equals(b as TObject));
-// end;
-//
-// procedure TTestECPoint.AssertOptionalValuesAgree(a, b: TBigInteger);
-// begin
-// if ((a.IsInitialized) and (b.IsInitialized)) then
-// begin
-// AssertBigIntegersEqual(a, b);
-// end;
-// end;
-//
-// procedure TTestECPoint.AssertOptionalValuesAgree(a, b: TCryptoLibByteArray);
-// begin
-// if ((a <> Nil) and (b <> Nil)) then
-// begin
-// CheckTrue(TArrayUtils.AreEqual(a, b));
-// end;
-// end;
+procedure TTestECPoint.AssertBigIntegersEqual(a, b: TBigInteger);
+begin
+  CheckEquals(True, a.Equals(b));
+end;
+
+procedure TTestECPoint.AssertIFiniteFieldsEqual(a, b: IFiniteField);
+begin
+  CheckEquals(True, (a as TObject).Equals(b as TObject));
+end;
+
+procedure TTestECPoint.AssertOptionalValuesAgree(a, b: TBigInteger);
+begin
+  if ((a.IsInitialized) and (b.IsInitialized)) then
+  begin
+    AssertBigIntegersEqual(a, b);
+  end;
+end;
+
+procedure TTestECPoint.AssertOptionalValuesAgree(a, b: TCryptoLibByteArray);
+begin
+  if ((a <> Nil) and (b <> Nil)) then
+  begin
+    CheckTrue(TArrayUtils.AreEqual(a, b));
+  end;
+end;
 
 procedure TTestECPoint.AssertPointsEqual(const msg: String;
   const a, b: IECPoint);
@@ -581,15 +583,15 @@ var
   tempDict: TDictionary<String, String>;
   uniqNames: TCryptoLibStringArray;
   s, name: string;
-  x9A { , x9B } : IX9ECParameters;
-  // pA, pB: IECPoint;
-  // k: TBigInteger;
+  x9A, x9B: IX9ECParameters;
+  pA, pB: IECPoint;
+  k: TBigInteger;
 begin
 
   tempList := TList<String>.Create();
   try
     tempList.AddRange(TECNamedCurveTable.names); // get all collections
-    // tempList.AddRange(CustomNamedCurves.Names);
+    tempList.AddRange(TCustomNamedCurves.names);
     tempDict := TDictionary<String, String>.Create();
     try
       for s in tempList do
@@ -607,39 +609,39 @@ begin
   for name in uniqNames do
   begin
     x9A := TECNamedCurveTable.GetByName(name);
-    // x9B := TCustomNamedCurves.GetByName(name);
-
-    // if ((x9A <> Nil) and (x9B <> Nil)) then
-    // begin
-    // AssertIFiniteFieldsEqual(x9A.curve.Field, x9B.curve.Field);
-    // AssertBigIntegersEqual(x9A.curve.a.ToBigInteger(),
-    // x9B.curve.a.ToBigInteger());
-    // AssertBigIntegersEqual(x9A.curve.b.ToBigInteger(),
-    // x9B.curve.b.ToBigInteger());
-    // AssertOptionalValuesAgree(x9A.curve.Cofactor, x9B.curve.Cofactor);
-    // AssertOptionalValuesAgree(x9A.curve.Order, x9B.curve.Order);
-    //
-    // AssertPointsEqual('Custom curve base-point inconsistency', x9A.G, x9B.G);
-    //
-    // AssertBigIntegersEqual(x9A.H, x9B.H);
-    // AssertBigIntegersEqual(x9A.n, x9B.n);
-    // AssertOptionalValuesAgree(x9A.GetSeed(), x9B.GetSeed());
-    //
-    // k := TBigInteger.Create(x9A.n.BitLength, FRandom);
-    // pA := x9A.G.Multiply(k);
-    // pB := x9B.G.Multiply(k);
-    // AssertPointsEqual('Custom curve multiplication inconsistency', pA, pB);
-    // end;
+    x9B := TCustomNamedCurves.GetByName(name);
+
+    if ((x9A <> Nil) and (x9B <> Nil)) then
+    begin
+      AssertIFiniteFieldsEqual(x9A.curve.Field, x9B.curve.Field);
+      AssertBigIntegersEqual(x9A.curve.a.ToBigInteger(),
+        x9B.curve.a.ToBigInteger());
+      AssertBigIntegersEqual(x9A.curve.b.ToBigInteger(),
+        x9B.curve.b.ToBigInteger());
+      AssertOptionalValuesAgree(x9A.curve.Cofactor, x9B.curve.Cofactor);
+      AssertOptionalValuesAgree(x9A.curve.Order, x9B.curve.Order);
+
+      AssertPointsEqual('Custom curve base-point inconsistency', x9A.g, x9B.g);
+
+      AssertBigIntegersEqual(x9A.h, x9B.h);
+      AssertBigIntegersEqual(x9A.n, x9B.n);
+      AssertOptionalValuesAgree(x9A.GetSeed(), x9B.GetSeed());
+
+      k := TBigInteger.Create(x9A.n.BitLength, FRandom);
+      pA := x9A.g.Multiply(k);
+      pB := x9B.g.Multiply(k);
+      AssertPointsEqual('Custom curve multiplication inconsistency', pA, pB);
+    end;
 
     if (x9A <> Nil) then
     begin
       ImplAddSubtractMultiplyTwiceEncodingTestAllCoords(x9A);
     end;
 
-    // if (x9B <> Nil) then
-    // begin
-    // ImplAddSubtractMultiplyTwiceEncodingTestAllCoords(x9B);
-    // end;
+    if (x9B <> Nil) then
+    begin
+      ImplAddSubtractMultiplyTwiceEncodingTestAllCoords(x9B);
+    end;
   end;
 end;
 

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

@@ -144,7 +144,7 @@ end;
 //
 // g := TECKeyPairGenerator.Create(keyAlgorithm);
 //
-// g.Init(TECKeyGenerationParameters.Create(ecSpec, TSecureRandom.Create() as ISecureRandom));
+// g.Init(TECKeyGenerationParameters.Create(ecSpec, TSecureRandom.Create() as ISecureRandom) as IECKeyGenerationParameters);
 //
 // pair := g.GenerateKeyPair();
 // sKey := pair.Private;

+ 2 - 2
CryptoLib/src/Asn1/ClpDerObjectIdentifier.pas

@@ -383,7 +383,7 @@ begin
     // TODO Leading zeroes?
     if (CharInSet(ch, ['0' .. '9'])) then
     begin
-      periodAllowed := true;
+      periodAllowed := True;
       System.Dec(pos);
       continue;
     end;
@@ -445,7 +445,7 @@ var
 begin
   value := 0;
   bigValue := Default (TBigInteger);
-  first := true;
+  first := True;
   objId := TStringList.Create();
   objId.LineBreak := '';
   try

+ 68 - 58
CryptoLib/src/Asn1/CryptoPro/ClpCryptoProObjectIdentifiers.pas

@@ -26,12 +26,19 @@ uses
   ClpIDerObjectIdentifier;
 
 type
-  TCryptoProObjectIdentifiers = class abstract(TObject)
+  TCryptoProObjectIdentifiers = class sealed(TObject)
 
   strict private
-    class var
 
-      FGostR3411, FGostR3410x2001, FGostR3410x94, FGostR28147Cbc,
+  const
+    // GOST Algorithms OBJECT IDENTIFIERS :
+    // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2)}
+    GostID: String = '1.2.643.2.2';
+
+  class var
+
+    FIsBooted: Boolean;
+    FGostR3411, FGostR3410x2001, FGostR3410x94, FGostR28147Cbc,
       FID_Gost28147_89_CryptoPro_A_ParamSet, FGostR3411x94CryptoProParam,
       FGostR3411Hmac, FGostR3410x2001CryptoProA, FGostElSgDH3410Default,
       FGostR3410x94CryptoProXchB, FGostR3410x94CryptoProXchC,
@@ -42,8 +49,6 @@ type
       FGostR3410x2001CryptoProXchA, FGostR3410x2001CryptoProB,
       FGostR3410x2001CryptoProC, FGostElSgDH3410x1: IDerObjectIdentifier;
 
-    class constructor CryptoProObjectIdentifiers();
-
     class function GetGostR3411: IDerObjectIdentifier; static; inline;
 
     class function GetGostR28147Cbc: IDerObjectIdentifier; static; inline;
@@ -89,12 +94,9 @@ type
     class function GetGostR3411x94CryptoProParamSet: IDerObjectIdentifier;
       static; inline;
 
-  public
+    class constructor CryptoProObjectIdentifiers();
 
-    const
-    // GOST Algorithms OBJECT IDENTIFIERS :
-    // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2)}
-    GostID: String = '1.2.643.2.2';
+  public
 
     class property GostR3411: IDerObjectIdentifier read GetGostR3411;
     class property GostR3411Hmac: IDerObjectIdentifier read GetGostR3411Hmac;
@@ -157,54 +159,6 @@ implementation
 
 { TCryptoProObjectIdentifiers }
 
-class procedure TCryptoProObjectIdentifiers.Boot;
-begin
-  FGostR3411 := TDerObjectIdentifier.Create(GostID + '.9');
-  FGostR3411Hmac := TDerObjectIdentifier.Create(GostID + '.10');
-
-  FGostR28147Cbc := TDerObjectIdentifier.Create(GostID + '.21');
-
-  FID_Gost28147_89_CryptoPro_A_ParamSet := TDerObjectIdentifier.Create
-    (GostID + '.31.1');
-
-  FGostR3410x94 := TDerObjectIdentifier.Create(GostID + '.20');
-  FGostR3410x2001 := TDerObjectIdentifier.Create(GostID + '.19');
-  FGostR3411x94WithGostR3410x94 := TDerObjectIdentifier.Create(GostID + '.4');
-  FGostR3411x94WithGostR3410x2001 := TDerObjectIdentifier.Create(GostID + '.3');
-
-  // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) hashes(30) }
-  FGostR3411x94CryptoProParamSet := TDerObjectIdentifier.Create
-    (GostID + '.30.1');
-
-  // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) signs(32) }
-  FGostR3410x94CryptoProA := TDerObjectIdentifier.Create(GostID + '.32.2');
-  FGostR3410x94CryptoProB := TDerObjectIdentifier.Create(GostID + '.32.3');
-  FGostR3410x94CryptoProC := TDerObjectIdentifier.Create(GostID + '.32.4');
-  FGostR3410x94CryptoProD := TDerObjectIdentifier.Create(GostID + '.32.5');
-
-  // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) exchanges(33) }
-  FGostR3410x94CryptoProXchA := TDerObjectIdentifier.Create(GostID + '.33.1');
-  FGostR3410x94CryptoProXchB := TDerObjectIdentifier.Create(GostID + '.33.2');
-  FGostR3410x94CryptoProXchC := TDerObjectIdentifier.Create(GostID + '.33.3');
-
-  // { iso(1) member-body(2)ru(643) rans(2) cryptopro(2) ecc-signs(35) }
-  FGostR3410x2001CryptoProA := TDerObjectIdentifier.Create(GostID + '.35.1');
-  FGostR3410x2001CryptoProB := TDerObjectIdentifier.Create(GostID + '.35.2');
-  FGostR3410x2001CryptoProC := TDerObjectIdentifier.Create(GostID + '.35.3');
-
-  // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) ecc-exchanges(36) }
-  FGostR3410x2001CryptoProXchA := TDerObjectIdentifier.Create(GostID + '.36.0');
-  FGostR3410x2001CryptoProXchB := TDerObjectIdentifier.Create(GostID + '.36.1');
-
-  FGostElSgDH3410Default := TDerObjectIdentifier.Create(GostID + '.36.0');
-  FGostElSgDH3410x1 := TDerObjectIdentifier.Create(GostID + '.36.1');
-end;
-
-class constructor TCryptoProObjectIdentifiers.CryptoProObjectIdentifiers;
-begin
-  TCryptoProObjectIdentifiers.Boot;
-end;
-
 class function TCryptoProObjectIdentifiers.GetGostR3411: IDerObjectIdentifier;
 begin
   result := FGostR3411;
@@ -348,4 +302,60 @@ begin
   result := FID_Gost28147_89_CryptoPro_A_ParamSet;
 end;
 
+class procedure TCryptoProObjectIdentifiers.Boot;
+begin
+  if not FIsBooted then
+  begin
+    FGostR3411 := TDerObjectIdentifier.Create(GostID + '.9');
+    FGostR3411Hmac := TDerObjectIdentifier.Create(GostID + '.10');
+
+    FGostR28147Cbc := TDerObjectIdentifier.Create(GostID + '.21');
+
+    FID_Gost28147_89_CryptoPro_A_ParamSet := TDerObjectIdentifier.Create
+      (GostID + '.31.1');
+
+    FGostR3410x94 := TDerObjectIdentifier.Create(GostID + '.20');
+    FGostR3410x2001 := TDerObjectIdentifier.Create(GostID + '.19');
+    FGostR3411x94WithGostR3410x94 := TDerObjectIdentifier.Create(GostID + '.4');
+    FGostR3411x94WithGostR3410x2001 := TDerObjectIdentifier.Create
+      (GostID + '.3');
+
+    // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) hashes(30) }
+    FGostR3411x94CryptoProParamSet := TDerObjectIdentifier.Create
+      (GostID + '.30.1');
+
+    // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) signs(32) }
+    FGostR3410x94CryptoProA := TDerObjectIdentifier.Create(GostID + '.32.2');
+    FGostR3410x94CryptoProB := TDerObjectIdentifier.Create(GostID + '.32.3');
+    FGostR3410x94CryptoProC := TDerObjectIdentifier.Create(GostID + '.32.4');
+    FGostR3410x94CryptoProD := TDerObjectIdentifier.Create(GostID + '.32.5');
+
+    // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) exchanges(33) }
+    FGostR3410x94CryptoProXchA := TDerObjectIdentifier.Create(GostID + '.33.1');
+    FGostR3410x94CryptoProXchB := TDerObjectIdentifier.Create(GostID + '.33.2');
+    FGostR3410x94CryptoProXchC := TDerObjectIdentifier.Create(GostID + '.33.3');
+
+    // { iso(1) member-body(2)ru(643) rans(2) cryptopro(2) ecc-signs(35) }
+    FGostR3410x2001CryptoProA := TDerObjectIdentifier.Create(GostID + '.35.1');
+    FGostR3410x2001CryptoProB := TDerObjectIdentifier.Create(GostID + '.35.2');
+    FGostR3410x2001CryptoProC := TDerObjectIdentifier.Create(GostID + '.35.3');
+
+    // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) ecc-exchanges(36) }
+    FGostR3410x2001CryptoProXchA := TDerObjectIdentifier.Create
+      (GostID + '.36.0');
+    FGostR3410x2001CryptoProXchB := TDerObjectIdentifier.Create
+      (GostID + '.36.1');
+
+    FGostElSgDH3410Default := TDerObjectIdentifier.Create(GostID + '.36.0');
+    FGostElSgDH3410x1 := TDerObjectIdentifier.Create(GostID + '.36.1');
+
+    FIsBooted := True;
+  end;
+end;
+
+class constructor TCryptoProObjectIdentifiers.CryptoProObjectIdentifiers;
+begin
+  TCryptoProObjectIdentifiers.Boot;
+end;
+
 end.

+ 267 - 258
CryptoLib/src/Asn1/CryptoPro/ClpECGost3410NamedCurves.pas

@@ -41,6 +41,7 @@ type
 
   strict private
   class var
+    FIsBooted: Boolean;
     Fparameters: TDictionary<IDerObjectIdentifier, IECDomainParameters>;
     FobjIds: TDictionary<String, IDerObjectIdentifier>;
     Fnames: TDictionary<IDerObjectIdentifier, String>;
@@ -96,264 +97,272 @@ var
   curve: IFPCurve;
   ecParams: IECDomainParameters;
 begin
-  TBigInteger.Boot;
-  Fparameters := TDictionary<IDerObjectIdentifier,
-    IECDomainParameters>.Create();
-  FobjIds := TDictionary<String, IDerObjectIdentifier>.Create();
-  Fnames := TDictionary<IDerObjectIdentifier, String>.Create();
-
-  mod_p := TBigInteger.Create
-    ('115792089237316195423570985008687907853269984665640564039457584007913129639319');
-  mod_q := TBigInteger.Create
-    ('115792089237316195423570985008687907853073762908499243225378155805079068850323');
-
-  curve := TFpCurve.Create(mod_p, // p
-    TBigInteger.Create
-    ('115792089237316195423570985008687907853269984665640564039457584007913129639316'),
-    // a
-    TBigInteger.Create('166'), // b
-    mod_q, TBigInteger.One);
-
-  ecParams := TECDomainParameters.Create(curve,
-    curve.CreatePoint(TBigInteger.Create('1'), // x
-    TBigInteger.Create
-    ('64033881142927202683649881450433473985931760268884941288852745803908878638612')
-    ), // y
-    mod_q);
-
-  Fparameters.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProA,
-    ecParams);
-
-  mod_p := TBigInteger.Create
-    ('115792089237316195423570985008687907853269984665640564039457584007913129639319');
-  mod_q := TBigInteger.Create
-    ('115792089237316195423570985008687907853073762908499243225378155805079068850323');
-
-  curve := TFpCurve.Create(mod_p, // p
-    TBigInteger.Create
-    ('115792089237316195423570985008687907853269984665640564039457584007913129639316'),
-    TBigInteger.Create('166'), mod_q, TBigInteger.One);
-
-  ecParams := TECDomainParameters.Create(curve,
-    curve.CreatePoint(TBigInteger.Create('1'), // x
-    TBigInteger.Create
-    ('64033881142927202683649881450433473985931760268884941288852745803908878638612')
-    ), // y
-    mod_q);
-
-  Fparameters.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProXchA,
-    ecParams);
-
-  mod_p := TBigInteger.Create
-    ('57896044618658097711785492504343953926634992332820282019728792003956564823193');
-  // p
-  mod_q := TBigInteger.Create
-    ('57896044618658097711785492504343953927102133160255826820068844496087732066703');
-  // q
-
-  curve := TFpCurve.Create(mod_p, // p
-    TBigInteger.Create
-    ('57896044618658097711785492504343953926634992332820282019728792003956564823190'),
-    // a
-    TBigInteger.Create
-    ('28091019353058090096996979000309560759124368558014865957655842872397301267595'),
-    // b
-    mod_q, TBigInteger.One);
-
-  ecParams := TECDomainParameters.Create(curve,
-    curve.CreatePoint(TBigInteger.Create('1'), // x
-    TBigInteger.Create
-    ('28792665814854611296992347458380284135028636778229113005756334730996303888124')
-    ), // y
-    mod_q); // q
-
-  Fparameters.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProB,
-    ecParams);
-
-  mod_p := TBigInteger.Create
-    ('70390085352083305199547718019018437841079516630045180471284346843705633502619');
-  mod_q := TBigInteger.Create
-    ('70390085352083305199547718019018437840920882647164081035322601458352298396601');
-
-  curve := TFpCurve.Create(mod_p, // p
-    TBigInteger.Create
-    ('70390085352083305199547718019018437841079516630045180471284346843705633502616'),
-    TBigInteger.Create('32858'), mod_q, TBigInteger.One);
-
-  ecParams := TECDomainParameters.Create(curve,
-    curve.CreatePoint(TBigInteger.Create('0'),
-    TBigInteger.Create
-    ('29818893917731240733471273240314769927240550812383695689146495261604565990247')
-    ), mod_q);
-
-  Fparameters.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProXchB,
-    ecParams);
-
-  mod_p := TBigInteger.Create
-    ('70390085352083305199547718019018437841079516630045180471284346843705633502619');
-  // p
-  mod_q := TBigInteger.Create
-    ('70390085352083305199547718019018437840920882647164081035322601458352298396601');
-  // q
-  curve := TFpCurve.Create(mod_p, // p
-    TBigInteger.Create
-    ('70390085352083305199547718019018437841079516630045180471284346843705633502616'),
-    // a
-    TBigInteger.Create('32858'), // b
-    mod_q, TBigInteger.One);
-
-  ecParams := TECDomainParameters.Create(curve,
-    curve.CreatePoint(TBigInteger.Create('0'), // x
-    TBigInteger.Create
-    ('29818893917731240733471273240314769927240550812383695689146495261604565990247')
-    ), // y
-    mod_q); // q
-
-  Fparameters.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProC,
-    ecParams);
-
-  // GOST34.10 2012
-  mod_p := TBigInteger.Create
-    ('115792089237316195423570985008687907853269984665640564039457584007913129639319');
-  // p
-  mod_q := TBigInteger.Create
-    ('115792089237316195423570985008687907853073762908499243225378155805079068850323');
-  // q
-  curve := TFpCurve.Create(mod_p, // p
-    TBigInteger.Create
-    ('115792089237316195423570985008687907853269984665640564039457584007913129639316'),
-    // a
-    TBigInteger.Create('166'), // b
-    mod_q, TBigInteger.One);
-
-  ecParams := TECDomainParameters.Create(curve,
-    curve.CreatePoint(TBigInteger.Create('1'), // x
-    TBigInteger.Create
-    ('64033881142927202683649881450433473985931760268884941288852745803908878638612')
-    ), // y
-    mod_q); // q
-
-  Fparameters.Add(TRosstandartObjectIdentifiers.
-    id_tc26_gost_3410_12_256_paramSetA, ecParams);
-
-  mod_p := TBigInteger.Create
-    ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7',
-    16); // p
-  mod_q := TBigInteger.Create
-    ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27E69532F48D89116FF22B8D4E0560609B4B38ABFAD2B85DCACDB1411F10B275',
-    16); // q
-  curve := TFpCurve.Create(mod_p, // p
-    TBigInteger.Create
-    ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC4',
-    16), // a
-    TBigInteger.Create
-    ('E8C2505DEDFC86DDC1BD0B2B6667F1DA34B82574761CB0E879BD081CFD0B6265EE3CB090F30D27614CB4574010DA90DD862EF9D4EBEE4761503190785A71C760',
-    16), // b
-    mod_q, TBigInteger.One);
-
-  ecParams := TECDomainParameters.Create(curve,
-    curve.CreatePoint(TBigInteger.Create
-    ('00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003'),
-    // x
-    TBigInteger.Create
-    ('7503CFE87A836AE3A61B8816E25450E6CE5E1C93ACF1ABC1778064FDCBEFA921DF1626BE4FD036E93D75E6A50E3A41E98028FE5FC235F5B889A589CB5215F2A4',
-    16)), // y
-    mod_q); // q
-
-  Fparameters.Add(TRosstandartObjectIdentifiers.
-    id_tc26_gost_3410_12_512_paramSetA, ecParams);
-
-  mod_p := TBigInteger.Create
-    ('8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006F',
-    16); // p
-  mod_q := TBigInteger.Create
-    ('800000000000000000000000000000000000000000000000000000000000000149A1EC142565A545ACFDB77BD9D40CFA8B996712101BEA0EC6346C54374F25BD',
-    16); // q
-  curve := TFpCurve.Create(mod_p, // p
-    TBigInteger.Create
-    ('8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006C',
-    16), // a
-    TBigInteger.Create
-    ('687D1B459DC841457E3E06CF6F5E2517B97C7D614AF138BCBF85DC806C4B289F3E965D2DB1416D217F8B276FAD1AB69C50F78BEE1FA3106EFB8CCBC7C5140116',
-    16), // b
-    mod_q, TBigInteger.One);
-
-  ecParams := TECDomainParameters.Create(curve,
-    curve.CreatePoint(TBigInteger.Create
-    ('00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002'),
-    // x
-    TBigInteger.Create
-    ('1A8F7EDA389B094C2C071E3647A8940F3C123B697578C213BE6DD9E6C8EC7335DCB228FD1EDF4A39152CBCAAF8C0398828041055F94CEEEC7E21340780FE41BD',
-    16)), // y
-    mod_q); // q
-
-  Fparameters.Add(TRosstandartObjectIdentifiers.
-    id_tc26_gost_3410_12_512_paramSetB, ecParams);
-
-  mod_p := TBigInteger.Create
-    ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7',
-    16); // p
-  mod_q := TBigInteger.Create
-    ('3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC98CDBA46506AB004C33A9FF5147502CC8EDA9E7A769A12694623CEF47F023ED',
-    16); // q
-  curve := TFpCurve.Create(mod_p, // p
-    TBigInteger.Create
-    ('DC9203E514A721875485A529D2C722FB187BC8980EB866644DE41C68E143064546E861C0E2C9EDD92ADE71F46FCF50FF2AD97F951FDA9F2A2EB6546F39689BD3',
-    16), // a
-    TBigInteger.Create
-    ('B4C4EE28CEBC6C2C8AC12952CF37F16AC7EFB6A9F69F4B57FFDA2E4F0DE5ADE038CBC2FFF719D2C18DE0284B8BFEF3B52B8CC7A5F5BF0A3C8D2319A5312557E1',
-    16), // b
-    mod_q, TBigInteger.One);
-
-  ecParams := TECDomainParameters.Create(curve,
-    curve.CreatePoint(TBigInteger.Create
-    ('E2E31EDFC23DE7BDEBE241CE593EF5DE2295B7A9CBAEF021D385F7074CEA043AA27272A7AE602BF2A7B9033DB9ED3610C6FB85487EAE97AAC5BC7928C1950148',
-    16), // x
-    TBigInteger.Create
-    ('F5CE40D95B5EB899ABBCCFF5911CB8577939804D6527378B8C108C3D2090FF9BE18E2D33E3021ED2EF32D85822423B6304F726AA854BAE07D0396E9A9ADDC40F',
-    16)), // y
-    mod_q); // q
-
-  Fparameters.Add(TRosstandartObjectIdentifiers.
-    id_tc26_gost_3410_12_512_paramSetC, ecParams);
-
-  FobjIds.Add('GostR3410-2001-CryptoPro-A',
-    TCryptoProObjectIdentifiers.GostR3410x2001CryptoProA);
-  FobjIds.Add('GostR3410-2001-CryptoPro-B',
-    TCryptoProObjectIdentifiers.GostR3410x2001CryptoProB);
-  FobjIds.Add('GostR3410-2001-CryptoPro-C',
-    TCryptoProObjectIdentifiers.GostR3410x2001CryptoProC);
-  FobjIds.Add('GostR3410-2001-CryptoPro-XchA',
-    TCryptoProObjectIdentifiers.GostR3410x2001CryptoProXchA);
-  FobjIds.Add('GostR3410-2001-CryptoPro-XchB',
-    TCryptoProObjectIdentifiers.GostR3410x2001CryptoProXchB);
-  FobjIds.Add('Tc26-Gost-3410-12-256-paramSetA',
-    TRosstandartObjectIdentifiers.id_tc26_gost_3410_12_256_paramSetA);
-  FobjIds.Add('Tc26-Gost-3410-12-512-paramSetA',
-    TRosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetA);
-  FobjIds.Add('Tc26-Gost-3410-12-512-paramSetB',
-    TRosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetB);
-  FobjIds.Add('Tc26-Gost-3410-12-512-paramSetC',
-    TRosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetC);
-
-  Fnames.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProA,
-    'GostR3410-2001-CryptoPro-A');
-  Fnames.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProB,
-    'GostR3410-2001-CryptoPro-B');
-  Fnames.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProC,
-    'GostR3410-2001-CryptoPro-C');
-  Fnames.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProXchA,
-    'GostR3410-2001-CryptoPro-XchA');
-  Fnames.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProXchB,
-    'GostR3410-2001-CryptoPro-XchB');
-  Fnames.Add(TRosstandartObjectIdentifiers.id_tc26_gost_3410_12_256_paramSetA,
-    'Tc26-Gost-3410-12-256-paramSetA');
-  Fnames.Add(TRosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetA,
-    'Tc26-Gost-3410-12-512-paramSetA');
-  Fnames.Add(TRosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetB,
-    'Tc26-Gost-3410-12-512-paramSetB');
-  Fnames.Add(TRosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetC,
-    'Tc26-Gost-3410-12-512-paramSetC');
+  if not FIsBooted then
+  begin
+    TBigInteger.Boot;
+    TCryptoProObjectIdentifiers.Boot;
+    TRosstandartObjectIdentifiers.Boot;
+
+    Fparameters := TDictionary<IDerObjectIdentifier,
+      IECDomainParameters>.Create();
+    FobjIds := TDictionary<String, IDerObjectIdentifier>.Create();
+    Fnames := TDictionary<IDerObjectIdentifier, String>.Create();
+
+    mod_p := TBigInteger.Create
+      ('115792089237316195423570985008687907853269984665640564039457584007913129639319');
+    mod_q := TBigInteger.Create
+      ('115792089237316195423570985008687907853073762908499243225378155805079068850323');
+
+    curve := TFpCurve.Create(mod_p, // p
+      TBigInteger.Create
+      ('115792089237316195423570985008687907853269984665640564039457584007913129639316'),
+      // a
+      TBigInteger.Create('166'), // b
+      mod_q, TBigInteger.One);
+
+    ecParams := TECDomainParameters.Create(curve,
+      curve.CreatePoint(TBigInteger.Create('1'), // x
+      TBigInteger.Create
+      ('64033881142927202683649881450433473985931760268884941288852745803908878638612')
+      ), // y
+      mod_q);
+
+    Fparameters.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProA,
+      ecParams);
+
+    mod_p := TBigInteger.Create
+      ('115792089237316195423570985008687907853269984665640564039457584007913129639319');
+    mod_q := TBigInteger.Create
+      ('115792089237316195423570985008687907853073762908499243225378155805079068850323');
+
+    curve := TFpCurve.Create(mod_p, // p
+      TBigInteger.Create
+      ('115792089237316195423570985008687907853269984665640564039457584007913129639316'),
+      TBigInteger.Create('166'), mod_q, TBigInteger.One);
+
+    ecParams := TECDomainParameters.Create(curve,
+      curve.CreatePoint(TBigInteger.Create('1'), // x
+      TBigInteger.Create
+      ('64033881142927202683649881450433473985931760268884941288852745803908878638612')
+      ), // y
+      mod_q);
+
+    Fparameters.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProXchA,
+      ecParams);
+
+    mod_p := TBigInteger.Create
+      ('57896044618658097711785492504343953926634992332820282019728792003956564823193');
+    // p
+    mod_q := TBigInteger.Create
+      ('57896044618658097711785492504343953927102133160255826820068844496087732066703');
+    // q
+
+    curve := TFpCurve.Create(mod_p, // p
+      TBigInteger.Create
+      ('57896044618658097711785492504343953926634992332820282019728792003956564823190'),
+      // a
+      TBigInteger.Create
+      ('28091019353058090096996979000309560759124368558014865957655842872397301267595'),
+      // b
+      mod_q, TBigInteger.One);
+
+    ecParams := TECDomainParameters.Create(curve,
+      curve.CreatePoint(TBigInteger.Create('1'), // x
+      TBigInteger.Create
+      ('28792665814854611296992347458380284135028636778229113005756334730996303888124')
+      ), // y
+      mod_q); // q
+
+    Fparameters.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProB,
+      ecParams);
+
+    mod_p := TBigInteger.Create
+      ('70390085352083305199547718019018437841079516630045180471284346843705633502619');
+    mod_q := TBigInteger.Create
+      ('70390085352083305199547718019018437840920882647164081035322601458352298396601');
+
+    curve := TFpCurve.Create(mod_p, // p
+      TBigInteger.Create
+      ('70390085352083305199547718019018437841079516630045180471284346843705633502616'),
+      TBigInteger.Create('32858'), mod_q, TBigInteger.One);
+
+    ecParams := TECDomainParameters.Create(curve,
+      curve.CreatePoint(TBigInteger.Create('0'),
+      TBigInteger.Create
+      ('29818893917731240733471273240314769927240550812383695689146495261604565990247')
+      ), mod_q);
+
+    Fparameters.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProXchB,
+      ecParams);
+
+    mod_p := TBigInteger.Create
+      ('70390085352083305199547718019018437841079516630045180471284346843705633502619');
+    // p
+    mod_q := TBigInteger.Create
+      ('70390085352083305199547718019018437840920882647164081035322601458352298396601');
+    // q
+    curve := TFpCurve.Create(mod_p, // p
+      TBigInteger.Create
+      ('70390085352083305199547718019018437841079516630045180471284346843705633502616'),
+      // a
+      TBigInteger.Create('32858'), // b
+      mod_q, TBigInteger.One);
+
+    ecParams := TECDomainParameters.Create(curve,
+      curve.CreatePoint(TBigInteger.Create('0'), // x
+      TBigInteger.Create
+      ('29818893917731240733471273240314769927240550812383695689146495261604565990247')
+      ), // y
+      mod_q); // q
+
+    Fparameters.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProC,
+      ecParams);
+
+    // GOST34.10 2012
+    mod_p := TBigInteger.Create
+      ('115792089237316195423570985008687907853269984665640564039457584007913129639319');
+    // p
+    mod_q := TBigInteger.Create
+      ('115792089237316195423570985008687907853073762908499243225378155805079068850323');
+    // q
+    curve := TFpCurve.Create(mod_p, // p
+      TBigInteger.Create
+      ('115792089237316195423570985008687907853269984665640564039457584007913129639316'),
+      // a
+      TBigInteger.Create('166'), // b
+      mod_q, TBigInteger.One);
+
+    ecParams := TECDomainParameters.Create(curve,
+      curve.CreatePoint(TBigInteger.Create('1'), // x
+      TBigInteger.Create
+      ('64033881142927202683649881450433473985931760268884941288852745803908878638612')
+      ), // y
+      mod_q); // q
+
+    Fparameters.Add(TRosstandartObjectIdentifiers.
+      id_tc26_gost_3410_12_256_paramSetA, ecParams);
+
+    mod_p := TBigInteger.Create
+      ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7',
+      16); // p
+    mod_q := TBigInteger.Create
+      ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27E69532F48D89116FF22B8D4E0560609B4B38ABFAD2B85DCACDB1411F10B275',
+      16); // q
+    curve := TFpCurve.Create(mod_p, // p
+      TBigInteger.Create
+      ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC4',
+      16), // a
+      TBigInteger.Create
+      ('E8C2505DEDFC86DDC1BD0B2B6667F1DA34B82574761CB0E879BD081CFD0B6265EE3CB090F30D27614CB4574010DA90DD862EF9D4EBEE4761503190785A71C760',
+      16), // b
+      mod_q, TBigInteger.One);
+
+    ecParams := TECDomainParameters.Create(curve,
+      curve.CreatePoint(TBigInteger.Create
+      ('00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003'),
+      // x
+      TBigInteger.Create
+      ('7503CFE87A836AE3A61B8816E25450E6CE5E1C93ACF1ABC1778064FDCBEFA921DF1626BE4FD036E93D75E6A50E3A41E98028FE5FC235F5B889A589CB5215F2A4',
+      16)), // y
+      mod_q); // q
+
+    Fparameters.Add(TRosstandartObjectIdentifiers.
+      id_tc26_gost_3410_12_512_paramSetA, ecParams);
+
+    mod_p := TBigInteger.Create
+      ('8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006F',
+      16); // p
+    mod_q := TBigInteger.Create
+      ('800000000000000000000000000000000000000000000000000000000000000149A1EC142565A545ACFDB77BD9D40CFA8B996712101BEA0EC6346C54374F25BD',
+      16); // q
+    curve := TFpCurve.Create(mod_p, // p
+      TBigInteger.Create
+      ('8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006C',
+      16), // a
+      TBigInteger.Create
+      ('687D1B459DC841457E3E06CF6F5E2517B97C7D614AF138BCBF85DC806C4B289F3E965D2DB1416D217F8B276FAD1AB69C50F78BEE1FA3106EFB8CCBC7C5140116',
+      16), // b
+      mod_q, TBigInteger.One);
+
+    ecParams := TECDomainParameters.Create(curve,
+      curve.CreatePoint(TBigInteger.Create
+      ('00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002'),
+      // x
+      TBigInteger.Create
+      ('1A8F7EDA389B094C2C071E3647A8940F3C123B697578C213BE6DD9E6C8EC7335DCB228FD1EDF4A39152CBCAAF8C0398828041055F94CEEEC7E21340780FE41BD',
+      16)), // y
+      mod_q); // q
+
+    Fparameters.Add(TRosstandartObjectIdentifiers.
+      id_tc26_gost_3410_12_512_paramSetB, ecParams);
+
+    mod_p := TBigInteger.Create
+      ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7',
+      16); // p
+    mod_q := TBigInteger.Create
+      ('3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC98CDBA46506AB004C33A9FF5147502CC8EDA9E7A769A12694623CEF47F023ED',
+      16); // q
+    curve := TFpCurve.Create(mod_p, // p
+      TBigInteger.Create
+      ('DC9203E514A721875485A529D2C722FB187BC8980EB866644DE41C68E143064546E861C0E2C9EDD92ADE71F46FCF50FF2AD97F951FDA9F2A2EB6546F39689BD3',
+      16), // a
+      TBigInteger.Create
+      ('B4C4EE28CEBC6C2C8AC12952CF37F16AC7EFB6A9F69F4B57FFDA2E4F0DE5ADE038CBC2FFF719D2C18DE0284B8BFEF3B52B8CC7A5F5BF0A3C8D2319A5312557E1',
+      16), // b
+      mod_q, TBigInteger.One);
+
+    ecParams := TECDomainParameters.Create(curve,
+      curve.CreatePoint(TBigInteger.Create
+      ('E2E31EDFC23DE7BDEBE241CE593EF5DE2295B7A9CBAEF021D385F7074CEA043AA27272A7AE602BF2A7B9033DB9ED3610C6FB85487EAE97AAC5BC7928C1950148',
+      16), // x
+      TBigInteger.Create
+      ('F5CE40D95B5EB899ABBCCFF5911CB8577939804D6527378B8C108C3D2090FF9BE18E2D33E3021ED2EF32D85822423B6304F726AA854BAE07D0396E9A9ADDC40F',
+      16)), // y
+      mod_q); // q
+
+    Fparameters.Add(TRosstandartObjectIdentifiers.
+      id_tc26_gost_3410_12_512_paramSetC, ecParams);
+
+    FobjIds.Add('GostR3410-2001-CryptoPro-A',
+      TCryptoProObjectIdentifiers.GostR3410x2001CryptoProA);
+    FobjIds.Add('GostR3410-2001-CryptoPro-B',
+      TCryptoProObjectIdentifiers.GostR3410x2001CryptoProB);
+    FobjIds.Add('GostR3410-2001-CryptoPro-C',
+      TCryptoProObjectIdentifiers.GostR3410x2001CryptoProC);
+    FobjIds.Add('GostR3410-2001-CryptoPro-XchA',
+      TCryptoProObjectIdentifiers.GostR3410x2001CryptoProXchA);
+    FobjIds.Add('GostR3410-2001-CryptoPro-XchB',
+      TCryptoProObjectIdentifiers.GostR3410x2001CryptoProXchB);
+    FobjIds.Add('Tc26-Gost-3410-12-256-paramSetA',
+      TRosstandartObjectIdentifiers.id_tc26_gost_3410_12_256_paramSetA);
+    FobjIds.Add('Tc26-Gost-3410-12-512-paramSetA',
+      TRosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetA);
+    FobjIds.Add('Tc26-Gost-3410-12-512-paramSetB',
+      TRosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetB);
+    FobjIds.Add('Tc26-Gost-3410-12-512-paramSetC',
+      TRosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetC);
+
+    Fnames.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProA,
+      'GostR3410-2001-CryptoPro-A');
+    Fnames.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProB,
+      'GostR3410-2001-CryptoPro-B');
+    Fnames.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProC,
+      'GostR3410-2001-CryptoPro-C');
+    Fnames.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProXchA,
+      'GostR3410-2001-CryptoPro-XchA');
+    Fnames.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProXchB,
+      'GostR3410-2001-CryptoPro-XchB');
+    Fnames.Add(TRosstandartObjectIdentifiers.id_tc26_gost_3410_12_256_paramSetA,
+      'Tc26-Gost-3410-12-256-paramSetA');
+    Fnames.Add(TRosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetA,
+      'Tc26-Gost-3410-12-512-paramSetA');
+    Fnames.Add(TRosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetB,
+      'Tc26-Gost-3410-12-512-paramSetB');
+    Fnames.Add(TRosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetC,
+      'Tc26-Gost-3410-12-512-paramSetC');
+
+    FIsBooted := True;
+  end;
 
 end;
 

+ 14 - 8
CryptoLib/src/Asn1/Iana/ClpIanaObjectIdentifiers.pas

@@ -34,9 +34,9 @@ type
     // {iso(1) identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) ipsec(8) isakmpOakley(1)}
     //
 
-    class var
-
-      FIsakmpOakley, FHmacMD5, FHmacSha1, FHmacTiger, FHmacRipeMD160
+  class var
+    FIsBooted: Boolean;
+    FIsakmpOakley, FHmacMD5, FHmacSha1, FHmacTiger, FHmacRipeMD160
       : IDerObjectIdentifier;
 
     class function GetIsakmpOakley: IDerObjectIdentifier; static; inline;
@@ -95,14 +95,20 @@ end;
 
 class procedure TIanaObjectIdentifiers.Boot;
 begin
-  FIsakmpOakley := TDerObjectIdentifier.Create('1.3.6.1.5.5.8.1');
+  if not FIsBooted then
+  begin
+
+    FIsakmpOakley := TDerObjectIdentifier.Create('1.3.6.1.5.5.8.1');
 
-  FHmacMD5 := TDerObjectIdentifier.Create(IsakmpOakley.ID + '.1');
-  FHmacSha1 := TDerObjectIdentifier.Create(IsakmpOakley.ID + '.2');
+    FHmacMD5 := TDerObjectIdentifier.Create(IsakmpOakley.ID + '.1');
+    FHmacSha1 := TDerObjectIdentifier.Create(IsakmpOakley.ID + '.2');
 
-  FHmacTiger := TDerObjectIdentifier.Create(IsakmpOakley.ID + '.3');
+    FHmacTiger := TDerObjectIdentifier.Create(IsakmpOakley.ID + '.3');
 
-  FHmacRipeMD160 := TDerObjectIdentifier.Create(IsakmpOakley.ID + '.4');
+    FHmacRipeMD160 := TDerObjectIdentifier.Create(IsakmpOakley.ID + '.4');
+
+    FIsBooted := True;
+  end;
 end;
 
 class constructor TIanaObjectIdentifiers.IanaObjectIdentifiers;

+ 23 - 16
CryptoLib/src/Asn1/Misc/ClpMiscObjectIdentifiers.pas

@@ -30,9 +30,10 @@ type
 
   strict private
 
-    class var
+  class var
 
-      Fblake2, Fid_blake2b160, Fid_blake2b256, Fid_blake2b384, Fid_blake2b512,
+    FIsBooted: Boolean;
+    Fblake2, Fid_blake2b160, Fid_blake2b256, Fid_blake2b384, Fid_blake2b512,
       Fid_blake2s128, Fid_blake2s160, Fid_blake2s224, Fid_blake2s256
       : IDerObjectIdentifier;
 
@@ -119,20 +120,26 @@ end;
 
 class procedure TMiscObjectIdentifiers.Boot;
 begin
-  //
-  // Blake2b and Blake2s
-  //
-  Fblake2 := TDerObjectIdentifier.Create('1.3.6.1.4.1.1722.12.2');
-
-  Fid_blake2b160 := blake2.Branch('1.5');
-  Fid_blake2b256 := blake2.Branch('1.8');
-  Fid_blake2b384 := blake2.Branch('1.12');
-  Fid_blake2b512 := blake2.Branch('1.16');
-
-  Fid_blake2s128 := blake2.Branch('2.4');
-  Fid_blake2s160 := blake2.Branch('2.5');
-  Fid_blake2s224 := blake2.Branch('2.7');
-  Fid_blake2s256 := blake2.Branch('2.8');
+
+  if not FIsBooted then
+  begin
+    //
+    // Blake2b and Blake2s
+    //
+    Fblake2 := TDerObjectIdentifier.Create('1.3.6.1.4.1.1722.12.2');
+
+    Fid_blake2b160 := blake2.Branch('1.5');
+    Fid_blake2b256 := blake2.Branch('1.8');
+    Fid_blake2b384 := blake2.Branch('1.12');
+    Fid_blake2b512 := blake2.Branch('1.16');
+
+    Fid_blake2s128 := blake2.Branch('2.4');
+    Fid_blake2s160 := blake2.Branch('2.5');
+    Fid_blake2s224 := blake2.Branch('2.7');
+    Fid_blake2s256 := blake2.Branch('2.8');
+
+    FIsBooted := True;
+  end;
 end;
 
 class constructor TMiscObjectIdentifiers.MiscObjectIdentifiers;

+ 187 - 0
CryptoLib/src/Asn1/Nist/ClpNistNamedCurves.pas

@@ -0,0 +1,187 @@
+{ *********************************************************************************** }
+{ *                              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 ClpNistNamedCurves;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  Generics.Collections,
+  ClpIX9ECParameters,
+  ClpSecNamedCurves,
+  ClpCryptoLibTypes,
+  ClpIDerObjectIdentifier,
+  ClpSecObjectIdentifiers;
+
+type
+
+  /// <summary>
+  /// Utility class for fetching curves using their NIST names as published
+  /// in FIPS-PUB 186-3
+  /// </summary>
+  TNistNamedCurves = class sealed(TObject)
+
+  strict private
+
+  class var
+    FIsBooted: Boolean;
+    FobjIds: TDictionary<String, IDerObjectIdentifier>;
+    Fnames: TDictionary<IDerObjectIdentifier, String>;
+
+    class function GetNames: TCryptoLibStringArray; static; inline;
+
+    class procedure DefineCurveAlias(const name: String;
+      const oid: IDerObjectIdentifier); static; inline;
+
+    class constructor CreateNistNamedCurves();
+    class destructor DestroyNistNamedCurves();
+
+  public
+
+    class function GetByName(const name: String): IX9ECParameters;
+      static; inline;
+    // /**
+    // * return the X9ECParameters object for the named curve represented by
+    // * the passed in object identifier. Null if the curve isn't present.
+    // *
+    // * @param oid an object identifier representing a named curve, if present.
+    // */
+    class function GetByOid(const oid: IDerObjectIdentifier): IX9ECParameters;
+      static; inline;
+    // /**
+    // * return the object identifier signified by the passed in name. Null
+    // * if there is no object identifier associated with name.
+    // *
+    // * @return the object identifier associated with name, if present.
+    // */
+    class function GetOid(const name: String): IDerObjectIdentifier;
+      static; inline;
+    // /**
+    // * return the named curve name represented by the given object identifier.
+    // */
+    class function GetName(const oid: IDerObjectIdentifier): String;
+      static; inline;
+    // /**
+    // * returns an enumeration containing the name strings for curves
+    // * contained in this structure.
+    // */
+    class property Names: TCryptoLibStringArray read GetNames;
+
+    class procedure Boot; static;
+
+  end;
+
+implementation
+
+{ TNistNamedCurves }
+
+class procedure TNistNamedCurves.DefineCurveAlias(const name: String;
+  const oid: IDerObjectIdentifier);
+begin
+  FobjIds.Add(UpperCase(name), oid);
+  Fnames.Add(oid, name);
+end;
+
+class function TNistNamedCurves.GetByOid(const oid: IDerObjectIdentifier)
+  : IX9ECParameters;
+begin
+  result := TSecNamedCurves.GetByOid(oid);
+end;
+
+class function TNistNamedCurves.GetOid(const name: String)
+  : IDerObjectIdentifier;
+begin
+  if not(FobjIds.TryGetValue(UpperCase(name), result)) then
+  begin
+    result := Nil;
+  end;
+end;
+
+class function TNistNamedCurves.GetByName(const name: String): IX9ECParameters;
+var
+  oid: IDerObjectIdentifier;
+begin
+  oid := GetOid(name);
+  if oid = Nil then
+  begin
+    result := Nil;
+  end
+  else
+  begin
+    result := GetByOid(oid);
+  end;
+
+end;
+
+class function TNistNamedCurves.GetName(const oid
+  : IDerObjectIdentifier): String;
+begin
+  if not(Fnames.TryGetValue(oid, result)) then
+  begin
+    result := '';
+  end;
+end;
+
+class function TNistNamedCurves.GetNames: TCryptoLibStringArray;
+begin
+  result := Fnames.Values.ToArray();
+end;
+
+class procedure TNistNamedCurves.Boot;
+begin
+  if not FIsBooted then
+  begin
+    FobjIds := TDictionary<String, IDerObjectIdentifier>.Create();
+    Fnames := TDictionary<IDerObjectIdentifier, String>.Create();
+
+    DefineCurveAlias('B-163', TSecObjectIdentifiers.SecT163r2);
+    DefineCurveAlias('B-233', TSecObjectIdentifiers.SecT233r1);
+    DefineCurveAlias('B-283', TSecObjectIdentifiers.SecT283r1);
+    DefineCurveAlias('B-409', TSecObjectIdentifiers.SecT409r1);
+    DefineCurveAlias('B-571', TSecObjectIdentifiers.SecT571r1);
+
+    DefineCurveAlias('K-163', TSecObjectIdentifiers.SecT163k1);
+    DefineCurveAlias('K-233', TSecObjectIdentifiers.SecT233k1);
+    DefineCurveAlias('K-283', TSecObjectIdentifiers.SecT283k1);
+    DefineCurveAlias('K-409', TSecObjectIdentifiers.SecT409k1);
+    DefineCurveAlias('K-571', TSecObjectIdentifiers.SecT571k1);
+
+    DefineCurveAlias('P-192', TSecObjectIdentifiers.SecP192r1);
+    DefineCurveAlias('P-224', TSecObjectIdentifiers.SecP224r1);
+    DefineCurveAlias('P-256', TSecObjectIdentifiers.SecP256r1);
+    DefineCurveAlias('P-384', TSecObjectIdentifiers.SecP384r1);
+    DefineCurveAlias('P-521', TSecObjectIdentifiers.SecP521r1);
+
+    FIsBooted := True;
+  end;
+end;
+
+class constructor TNistNamedCurves.CreateNistNamedCurves;
+begin
+  TNistNamedCurves.Boot;
+end;
+
+class destructor TNistNamedCurves.DestroyNistNamedCurves;
+begin
+  FobjIds.Free;
+  Fnames.Free;
+end;
+
+end.

+ 63 - 57
CryptoLib/src/Asn1/Nist/ClpNistObjectIdentifiers.pas

@@ -30,9 +30,10 @@ type
 
   strict private
 
-    class var
+  class var
 
-      FNistAlgorithm, FHashAlgs, FSigAlgs, FIdSha256, FIdSha384, FIdSha512,
+    FIsBooted: Boolean;
+    FNistAlgorithm, FHashAlgs, FSigAlgs, FIdSha256, FIdSha384, FIdSha512,
       FIdSha224, FIdSha512_224, FIdSha512_256, FIdSha3_224, FIdSha3_256,
       FIdSha3_384, FIdSha3_512, FIdHMacWithSha3_224, FIdHMacWithSha3_256,
       FIdHMacWithSha3_384, FIdHMacWithSha3_512, FAES, FIdAES128Ecb,
@@ -411,61 +412,66 @@ end;
 
 class procedure TNistObjectIdentifiers.Boot;
 begin
-  FNistAlgorithm := TDerObjectIdentifier.Create('2.16.840.1.101.3.4');
-  FHashAlgs := NistAlgorithm.Branch('2');
-
-  FIdSha256 := HashAlgs.Branch('1');
-  FIdSha384 := HashAlgs.Branch('2');
-  FIdSha512 := HashAlgs.Branch('3');
-  FIdSha224 := HashAlgs.Branch('4');
-  FIdSha512_224 := HashAlgs.Branch('5');
-  FIdSha512_256 := HashAlgs.Branch('6');
-  FIdSha3_224 := HashAlgs.Branch('7');
-  FIdSha3_256 := HashAlgs.Branch('8');
-  FIdSha3_384 := HashAlgs.Branch('9');
-  FIdSha3_512 := HashAlgs.Branch('10');
-
-  FIdHMacWithSha3_224 := HashAlgs.Branch('13');
-  FIdHMacWithSha3_256 := HashAlgs.Branch('14');
-  FIdHMacWithSha3_384 := HashAlgs.Branch('15');
-  FIdHMacWithSha3_512 := HashAlgs.Branch('16');
-
-  FAES := TDerObjectIdentifier.Create(NistAlgorithm.id + '.1');
-
-  FIdAES128Ecb := TDerObjectIdentifier.Create(AES.id + '.1');
-  FIdAes128Cbc := TDerObjectIdentifier.Create(AES.id + '.2');
-  FIdAes128Ofb := TDerObjectIdentifier.Create(AES.id + '.3');
-  FIdAes128Cfb := TDerObjectIdentifier.Create(AES.id + '.4');
-  FidAes192Ecb := TDerObjectIdentifier.Create(AES.id + '.21');
-  FIdAes192Cbc := TDerObjectIdentifier.Create(AES.id + '.22');
-  FIdAes192Ofb := TDerObjectIdentifier.Create(AES.id + '.23');
-  FIdAes192Cfb := TDerObjectIdentifier.Create(AES.id + '.24');
-  FIdAes256Ecb := TDerObjectIdentifier.Create(AES.id + '.41');
-  FIdAes256Cbc := TDerObjectIdentifier.Create(AES.id + '.42');
-  FIdAes256Ofb := TDerObjectIdentifier.Create(AES.id + '.43');
-  FIdAes256Cfb := TDerObjectIdentifier.Create(AES.id + '.44');
-
-  //
-  // signatures
-  //
-  FSigAlgs := NistAlgorithm.Branch('3');
-  FIdDsaWithSha2 := SigAlgs;
-
-  FDsaWithSha224 := TDerObjectIdentifier.Create(SigAlgs.id + '.1');
-  FDsaWithSha256 := TDerObjectIdentifier.Create(SigAlgs.id + '.2');
-  FDsaWithSha384 := TDerObjectIdentifier.Create(SigAlgs.id + '.3');
-  FDsaWithSha512 := TDerObjectIdentifier.Create(SigAlgs.id + '.4');
-
-  FIdDsaWithSha3_224 := TDerObjectIdentifier.Create(SigAlgs.id + '.5');
-  FIdDsaWithSha3_256 := TDerObjectIdentifier.Create(SigAlgs.id + '.6');
-  FIdDsaWithSha3_384 := TDerObjectIdentifier.Create(SigAlgs.id + '.7');
-  FIdDsaWithSha3_512 := TDerObjectIdentifier.Create(SigAlgs.id + '.8');
-
-  // ECDSA with SHA-3
-  FIdECDsaWithSha3_224 := TDerObjectIdentifier.Create(SigAlgs.id + '.9');
-  FIdECDsaWithSha3_256 := TDerObjectIdentifier.Create(SigAlgs.id + '.10');
-  FIdECDsaWithSha3_384 := TDerObjectIdentifier.Create(SigAlgs.id + '.11');
-  FIdECDsaWithSha3_512 := TDerObjectIdentifier.Create(SigAlgs.id + '.12');
+  if not FIsBooted then
+  begin
+    FNistAlgorithm := TDerObjectIdentifier.Create('2.16.840.1.101.3.4');
+    FHashAlgs := NistAlgorithm.Branch('2');
+
+    FIdSha256 := HashAlgs.Branch('1');
+    FIdSha384 := HashAlgs.Branch('2');
+    FIdSha512 := HashAlgs.Branch('3');
+    FIdSha224 := HashAlgs.Branch('4');
+    FIdSha512_224 := HashAlgs.Branch('5');
+    FIdSha512_256 := HashAlgs.Branch('6');
+    FIdSha3_224 := HashAlgs.Branch('7');
+    FIdSha3_256 := HashAlgs.Branch('8');
+    FIdSha3_384 := HashAlgs.Branch('9');
+    FIdSha3_512 := HashAlgs.Branch('10');
+
+    FIdHMacWithSha3_224 := HashAlgs.Branch('13');
+    FIdHMacWithSha3_256 := HashAlgs.Branch('14');
+    FIdHMacWithSha3_384 := HashAlgs.Branch('15');
+    FIdHMacWithSha3_512 := HashAlgs.Branch('16');
+
+    FAES := TDerObjectIdentifier.Create(NistAlgorithm.id + '.1');
+
+    FIdAES128Ecb := TDerObjectIdentifier.Create(AES.id + '.1');
+    FIdAes128Cbc := TDerObjectIdentifier.Create(AES.id + '.2');
+    FIdAes128Ofb := TDerObjectIdentifier.Create(AES.id + '.3');
+    FIdAes128Cfb := TDerObjectIdentifier.Create(AES.id + '.4');
+    FidAes192Ecb := TDerObjectIdentifier.Create(AES.id + '.21');
+    FIdAes192Cbc := TDerObjectIdentifier.Create(AES.id + '.22');
+    FIdAes192Ofb := TDerObjectIdentifier.Create(AES.id + '.23');
+    FIdAes192Cfb := TDerObjectIdentifier.Create(AES.id + '.24');
+    FIdAes256Ecb := TDerObjectIdentifier.Create(AES.id + '.41');
+    FIdAes256Cbc := TDerObjectIdentifier.Create(AES.id + '.42');
+    FIdAes256Ofb := TDerObjectIdentifier.Create(AES.id + '.43');
+    FIdAes256Cfb := TDerObjectIdentifier.Create(AES.id + '.44');
+
+    //
+    // signatures
+    //
+    FSigAlgs := NistAlgorithm.Branch('3');
+    FIdDsaWithSha2 := SigAlgs;
+
+    FDsaWithSha224 := TDerObjectIdentifier.Create(SigAlgs.id + '.1');
+    FDsaWithSha256 := TDerObjectIdentifier.Create(SigAlgs.id + '.2');
+    FDsaWithSha384 := TDerObjectIdentifier.Create(SigAlgs.id + '.3');
+    FDsaWithSha512 := TDerObjectIdentifier.Create(SigAlgs.id + '.4');
+
+    FIdDsaWithSha3_224 := TDerObjectIdentifier.Create(SigAlgs.id + '.5');
+    FIdDsaWithSha3_256 := TDerObjectIdentifier.Create(SigAlgs.id + '.6');
+    FIdDsaWithSha3_384 := TDerObjectIdentifier.Create(SigAlgs.id + '.7');
+    FIdDsaWithSha3_512 := TDerObjectIdentifier.Create(SigAlgs.id + '.8');
+
+    // ECDSA with SHA-3
+    FIdECDsaWithSha3_224 := TDerObjectIdentifier.Create(SigAlgs.id + '.9');
+    FIdECDsaWithSha3_256 := TDerObjectIdentifier.Create(SigAlgs.id + '.10');
+    FIdECDsaWithSha3_384 := TDerObjectIdentifier.Create(SigAlgs.id + '.11');
+    FIdECDsaWithSha3_512 := TDerObjectIdentifier.Create(SigAlgs.id + '.12');
+
+    FIsBooted := True;
+  end;
 
 end;
 

+ 9 - 4
CryptoLib/src/Asn1/Oiw/ClpOiwObjectIdentifiers.pas

@@ -30,9 +30,10 @@ type
 
   strict private
 
-    class var
+  class var
 
-      FIdSha1, FDsaWithSha1: IDerObjectIdentifier;
+    FIsBooted: Boolean;
+    FIdSha1, FDsaWithSha1: IDerObjectIdentifier;
 
     class function GetIdSha1: IDerObjectIdentifier; static; inline;
     class function GetDsaWithSha1: IDerObjectIdentifier; static; inline;
@@ -57,8 +58,12 @@ implementation
 
 class procedure TOiwObjectIdentifiers.Boot;
 begin
-  FIdSha1 := TDerObjectIdentifier.Create('1.3.14.3.2.26');
-  FDsaWithSha1 := TDerObjectIdentifier.Create('1.3.14.3.2.27');
+  if not FIsBooted then
+  begin
+    FIdSha1 := TDerObjectIdentifier.Create('1.3.14.3.2.26');
+    FDsaWithSha1 := TDerObjectIdentifier.Create('1.3.14.3.2.27');
+    FIsBooted := True;
+  end;
 end;
 
 class function TOiwObjectIdentifiers.GetDsaWithSha1: IDerObjectIdentifier;

+ 16 - 10
CryptoLib/src/Asn1/Pkcs/ClpPkcsObjectIdentifiers.pas

@@ -36,9 +36,10 @@ type
     //
     DigestAlgorithm: String = '1.2.840.113549.2';
 
-    class var
+  class var
 
-      FMD2, FMD4, FMD5, FIdHmacWithSha1, FIdHmacWithSha224, FIdHmacWithSha256,
+    FIsBooted: Boolean;
+    FMD2, FMD4, FMD5, FIdHmacWithSha1, FIdHmacWithSha224, FIdHmacWithSha256,
       FIdHmacWithSha384, FIdHmacWithSha512: IDerObjectIdentifier;
 
     class function GetMD2: IDerObjectIdentifier; static; inline;
@@ -91,14 +92,19 @@ implementation
 
 class procedure TPkcsObjectIdentifiers.Boot;
 begin
-  FMD2 := TDerObjectIdentifier.Create(DigestAlgorithm + '.2');
-  FMD4 := TDerObjectIdentifier.Create(DigestAlgorithm + '.4');
-  FMD5 := TDerObjectIdentifier.Create(DigestAlgorithm + '.5');
-  FIdHmacWithSha1 := TDerObjectIdentifier.Create(DigestAlgorithm + '.7');
-  FIdHmacWithSha224 := TDerObjectIdentifier.Create(DigestAlgorithm + '.8');
-  FIdHmacWithSha256 := TDerObjectIdentifier.Create(DigestAlgorithm + '.9');
-  FIdHmacWithSha384 := TDerObjectIdentifier.Create(DigestAlgorithm + '.10');
-  FIdHmacWithSha512 := TDerObjectIdentifier.Create(DigestAlgorithm + '.11');
+  if not FIsBooted then
+  begin
+    FMD2 := TDerObjectIdentifier.Create(DigestAlgorithm + '.2');
+    FMD4 := TDerObjectIdentifier.Create(DigestAlgorithm + '.4');
+    FMD5 := TDerObjectIdentifier.Create(DigestAlgorithm + '.5');
+    FIdHmacWithSha1 := TDerObjectIdentifier.Create(DigestAlgorithm + '.7');
+    FIdHmacWithSha224 := TDerObjectIdentifier.Create(DigestAlgorithm + '.8');
+    FIdHmacWithSha256 := TDerObjectIdentifier.Create(DigestAlgorithm + '.9');
+    FIdHmacWithSha384 := TDerObjectIdentifier.Create(DigestAlgorithm + '.10');
+    FIdHmacWithSha512 := TDerObjectIdentifier.Create(DigestAlgorithm + '.11');
+
+    FIsBooted := True;
+  end;
 end;
 
 class function TPkcsObjectIdentifiers.GetIdHmacWithSha1: IDerObjectIdentifier;

+ 34 - 26
CryptoLib/src/Asn1/RossStandart/ClpRosstandartObjectIdentifiers.pas

@@ -29,9 +29,10 @@ type
   TRosstandartObjectIdentifiers = class abstract(TObject)
   strict private
 
-    class var
+  class var
 
-      Frosstandart, Fid_tc26_gost_3410_12_512_paramSetC,
+    FIsBooted: Boolean;
+    Frosstandart, Fid_tc26_gost_3410_12_512_paramSetC,
       Fid_tc26_gost_3410_12_512_paramSetA, Fid_tc26_gost_28147_param_Z,
       Fid_tc26_gost_3410_12_256_paramSetA, Fid_tc26_hmac_gost_3411_12_512,
       Fid_tc26_hmac_gost_3411_12_256, Fid_tc26_agreement_gost_3410_12_512,
@@ -257,49 +258,56 @@ end;
 
 class procedure TRosstandartObjectIdentifiers.Boot;
 begin
-  Frosstandart := TDerObjectIdentifier.Create('1.2.643.7');
 
-  Fid_tc26 := rosstandart.Branch('1');
+  if not FIsBooted then
+  begin
 
-  Fid_tc26_gost_3411_12_256 := id_tc26.Branch('1.2.2');
+    Frosstandart := TDerObjectIdentifier.Create('1.2.643.7');
 
-  Fid_tc26_gost_3411_12_512 := id_tc26.Branch('1.2.3');
+    Fid_tc26 := rosstandart.Branch('1');
 
-  Fid_tc26_hmac_gost_3411_12_256 := id_tc26.Branch('1.4.1');
+    Fid_tc26_gost_3411_12_256 := id_tc26.Branch('1.2.2');
 
-  Fid_tc26_hmac_gost_3411_12_512 := id_tc26.Branch('1.4.2');
+    Fid_tc26_gost_3411_12_512 := id_tc26.Branch('1.2.3');
 
-  Fid_tc26_gost_3410_12_256 := id_tc26.Branch('1.1.1');
+    Fid_tc26_hmac_gost_3411_12_256 := id_tc26.Branch('1.4.1');
 
-  Fid_tc26_gost_3410_12_512 := id_tc26.Branch('1.1.2');
+    Fid_tc26_hmac_gost_3411_12_512 := id_tc26.Branch('1.4.2');
 
-  Fid_tc26_signwithdigest_gost_3410_12_256 := id_tc26.Branch('1.3.2');
+    Fid_tc26_gost_3410_12_256 := id_tc26.Branch('1.1.1');
 
-  Fid_tc26_signwithdigest_gost_3410_12_512 := id_tc26.Branch('1.3.3');
+    Fid_tc26_gost_3410_12_512 := id_tc26.Branch('1.1.2');
 
-  Fid_tc26_agreement := id_tc26.Branch('1.6');
+    Fid_tc26_signwithdigest_gost_3410_12_256 := id_tc26.Branch('1.3.2');
 
-  Fid_tc26_agreement_gost_3410_12_256 := id_tc26_agreement.Branch('1');
+    Fid_tc26_signwithdigest_gost_3410_12_512 := id_tc26.Branch('1.3.3');
 
-  Fid_tc26_agreement_gost_3410_12_512 := id_tc26_agreement.Branch('2');
+    Fid_tc26_agreement := id_tc26.Branch('1.6');
 
-  Fid_tc26_gost_3410_12_256_paramSet := id_tc26.Branch('2.1.1');
+    Fid_tc26_agreement_gost_3410_12_256 := id_tc26_agreement.Branch('1');
 
-  Fid_tc26_gost_3410_12_256_paramSetA :=
-    id_tc26_gost_3410_12_256_paramSet.Branch('1');
+    Fid_tc26_agreement_gost_3410_12_512 := id_tc26_agreement.Branch('2');
 
-  Fid_tc26_gost_3410_12_512_paramSet := id_tc26.Branch('2.1.2');
+    Fid_tc26_gost_3410_12_256_paramSet := id_tc26.Branch('2.1.1');
 
-  Fid_tc26_gost_3410_12_512_paramSetA :=
-    id_tc26_gost_3410_12_512_paramSet.Branch('1');
+    Fid_tc26_gost_3410_12_256_paramSetA :=
+      id_tc26_gost_3410_12_256_paramSet.Branch('1');
 
-  Fid_tc26_gost_3410_12_512_paramSetB :=
-    id_tc26_gost_3410_12_512_paramSet.Branch('2');
+    Fid_tc26_gost_3410_12_512_paramSet := id_tc26.Branch('2.1.2');
 
-  Fid_tc26_gost_3410_12_512_paramSetC :=
-    id_tc26_gost_3410_12_512_paramSet.Branch('3');
+    Fid_tc26_gost_3410_12_512_paramSetA :=
+      id_tc26_gost_3410_12_512_paramSet.Branch('1');
 
-  Fid_tc26_gost_28147_param_Z := id_tc26.Branch('2.5.1.1');
+    Fid_tc26_gost_3410_12_512_paramSetB :=
+      id_tc26_gost_3410_12_512_paramSet.Branch('2');
+
+    Fid_tc26_gost_3410_12_512_paramSetC :=
+      id_tc26_gost_3410_12_512_paramSet.Branch('3');
+
+    Fid_tc26_gost_28147_param_Z := id_tc26.Branch('2.5.1.1');
+
+    FIsBooted := True;
+  end;
 end;
 
 end.

File diff suppressed because it is too large
+ 1701 - 151
CryptoLib/src/Asn1/Sec/ClpSecNamedCurves.pas


+ 54 - 47
CryptoLib/src/Asn1/Sec/ClpSecObjectIdentifiers.pas

@@ -36,15 +36,15 @@ type
 
   strict private
 
-    class var
+  class var
 
-      FSecT193r1, FSecP112r2, FEllipticCurve, FSecP224r1, FSecP160r2,
-      FSecT233r1, FSecP112r1, FSecT409r1, FSecP192k1, FSecT131r2, FSecT283k1,
-      FSecT113r2, FSecT163r2, FSecP160r1, FSecT239k1, FSecP521r1, FSecP256r1,
-      FSecT131r1, FSecT113r1, FSecT163r1, FSecP224k1, FSecT233k1, FSecT409k1,
-      FSecP160k1, FSecT571r1, FSecP256k1, FSecT163k1, FSecP128r2, FSecT571k1,
-      FSecP128r1, FSecP192r1, FSecT283r1, FSecT193r2,
-      FSecP384r1: IDerObjectIdentifier;
+    FIsBooted: Boolean;
+    FSecT193r1, FSecP112r2, FEllipticCurve, FSecP224r1, FSecP160r2, FSecT233r1,
+      FSecP112r1, FSecT409r1, FSecP192k1, FSecT131r2, FSecT283k1, FSecT113r2,
+      FSecT163r2, FSecP160r1, FSecT239k1, FSecP521r1, FSecP256r1, FSecT131r1,
+      FSecT113r1, FSecT163r1, FSecP224k1, FSecT233k1, FSecT409k1, FSecP160k1,
+      FSecT571r1, FSecP256k1, FSecT163k1, FSecP128r2, FSecT571k1, FSecP128r1,
+      FSecP192r1, FSecT283r1, FSecT193r2, FSecP384r1: IDerObjectIdentifier;
 
     class constructor SecObjectIdentifiers();
 
@@ -302,45 +302,52 @@ end;
 
 class procedure TSecObjectIdentifiers.Boot;
 begin
-  FEllipticCurve := TDerObjectIdentifier.Create('1.3.132.0');
-
-  FSecT163k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.1');
-  FSecT163r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.2');
-  FSecT239k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.3');
-  FSecT113r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.4');
-  FSecT113r2 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.5');
-  FSecP112r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.6');
-  FSecP112r2 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.7');
-  FSecP160r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.8');
-  FSecP160k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.9');
-  FSecP256k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.10');
-  FSecT163r2 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.15');
-  FSecT283k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.16');
-  FSecT283r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.17');
-  FSecT131r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.22');
-  FSecT131r2 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.23');
-  FSecT193r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.24');
-  FSecT193r2 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.25');
-  FSecT233k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.26');
-  FSecT233r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.27');
-  FSecP128r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.28');
-  FSecP128r2 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.29');
-  FSecP160r2 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.30');
-  FSecP192k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.31');
-  FSecP224k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.32');
-  FSecP224r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.33');
-  FSecP384r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.34');
-  FSecP521r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.35');
-  FSecT409k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.36');
-  FSecT409r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.37');
-  FSecT571k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.38');
-  FSecT571r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.39');
-
-  TX9ObjectIdentifiers.Boot;
-
-  FSecP192r1 := TX9ObjectIdentifiers.Prime192v1;
-
-  FSecP256r1 := TX9ObjectIdentifiers.Prime256v1;
+
+  if not FIsBooted then
+  begin
+
+    FEllipticCurve := TDerObjectIdentifier.Create('1.3.132.0');
+
+    FSecT163k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.1');
+    FSecT163r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.2');
+    FSecT239k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.3');
+    FSecT113r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.4');
+    FSecT113r2 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.5');
+    FSecP112r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.6');
+    FSecP112r2 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.7');
+    FSecP160r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.8');
+    FSecP160k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.9');
+    FSecP256k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.10');
+    FSecT163r2 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.15');
+    FSecT283k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.16');
+    FSecT283r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.17');
+    FSecT131r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.22');
+    FSecT131r2 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.23');
+    FSecT193r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.24');
+    FSecT193r2 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.25');
+    FSecT233k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.26');
+    FSecT233r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.27');
+    FSecP128r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.28');
+    FSecP128r2 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.29');
+    FSecP160r2 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.30');
+    FSecP192k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.31');
+    FSecP224k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.32');
+    FSecP224r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.33');
+    FSecP384r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.34');
+    FSecP521r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.35');
+    FSecT409k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.36');
+    FSecT409r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.37');
+    FSecT571k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.38');
+    FSecT571r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.39');
+
+    TX9ObjectIdentifiers.Boot;
+
+    FSecP192r1 := TX9ObjectIdentifiers.Prime192v1;
+
+    FSecP256r1 := TX9ObjectIdentifiers.Prime256v1;
+
+    FIsBooted := True;
+  end;
 
 end;
 

+ 15 - 9
CryptoLib/src/Asn1/TeleTrust/ClpTeleTrusTObjectIdentifiers.pas

@@ -30,9 +30,10 @@ type
 
   strict private
 
-    class var
+  class var
 
-      FTeleTrusTAlgorithm, FRipeMD160, FRipeMD128, FRipeMD256, FECSign,
+    FIsBooted: Boolean;
+    FTeleTrusTAlgorithm, FRipeMD160, FRipeMD128, FRipeMD256, FECSign,
       FECSignWithSha1, FECSignWithRipeMD160: IDerObjectIdentifier;
 
     class function GetRipeMD128: IDerObjectIdentifier; static; inline;
@@ -105,15 +106,20 @@ end;
 
 class procedure TTeleTrusTObjectIdentifiers.Boot;
 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');
+  if not FIsBooted then
+  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');
+    FECSign := TDerObjectIdentifier.Create(TeleTrusTAlgorithm.ID + '.3.2');
 
-  FECSignWithSha1 := TDerObjectIdentifier.Create(ECSign.ID + '.1');
-  FECSignWithRipeMD160 := TDerObjectIdentifier.Create(ECSign.ID + '.2');
+    FECSignWithSha1 := TDerObjectIdentifier.Create(ECSign.ID + '.1');
+    FECSignWithRipeMD160 := TDerObjectIdentifier.Create(ECSign.ID + '.2');
+
+    FIsBooted := True;
+  end;
 
 end;
 

+ 32 - 15
CryptoLib/src/Asn1/X9/ClpECNamedCurveTable.pas

@@ -28,6 +28,7 @@ uses
   // ClpECGost3410NamedCurves,
   // ClpX9ECParameters,
   ClpSecNamedCurves,
+  ClpNistNamedCurves,
   // ClpIECDomainParameters,
   ClpIDerObjectIdentifier,
   ClpIX9ECParameters;
@@ -112,6 +113,11 @@ begin
   ecP := TSecNamedCurves.GetByName(name);
   // end;
 
+  if (ecP = Nil) then
+  begin
+    ecP := TNistNamedCurves.GetByName(name);
+  end;
+
   result := ecP;
 end;
 
@@ -125,6 +131,7 @@ begin
   // begin
   ecP := TSecNamedCurves.GetByOid(oid);
   // end;
+  // NOTE: All the NIST curves are currently from SEC, so no point in redundant OID lookup
   result := ecP;
 end;
 
@@ -134,26 +141,16 @@ var
   name: String;
 begin
   // name := TX962NamedCurves.GetName(oid);
-  // if (name = Nil) then
+  // if (name = '') then
   // begin
   name := TSecNamedCurves.GetName(oid);
   // end;
-  result := name;
-end;
 
-class function TECNamedCurveTable.GetNames: TCryptoLibStringArray;
-var
-  temp: TList<String>;
-begin
-  temp := TList<String>.Create();
-  try
-    temp.AddRange(TSecNamedCurves.Names);
-    // temp.AddRange(TECGost3410NamedCurves.Names);
-    result := temp.ToArray;
-  finally
-    temp.Free;
+  if (name = '') then
+  begin
+    name := TNistNamedCurves.GetName(oid);
   end;
-
+  result := name;
 end;
 
 class function TECNamedCurveTable.GetOid(const name: String)
@@ -167,7 +164,27 @@ begin
   oid := TSecNamedCurves.GetOid(name);
   // end;
 
+  if (oid = Nil) then
+  begin
+    oid := TNistNamedCurves.GetOid(name);
+  end;
+
   result := oid;
 end;
 
+class function TECNamedCurveTable.GetNames: TCryptoLibStringArray;
+var
+  temp: TList<String>;
+begin
+  temp := TList<String>.Create();
+  try
+    temp.AddRange(TSecNamedCurves.Names);
+    temp.AddRange(TNistNamedCurves.Names);
+    result := temp.ToArray;
+  finally
+    temp.Free;
+  end;
+
+end;
+
 end.

+ 65 - 59
CryptoLib/src/Asn1/X9/ClpX9ObjectIdentifiers.pas

@@ -39,9 +39,10 @@ type
 
     AnsiX962: String = '1.2.840.10045';
 
-    class var
+  class var
 
-      Fansi_X9_62, FIdFieldType, FPrimeField, FCharacteristicTwoField, FGNBasis,
+    FIsBooted: Boolean;
+    Fansi_X9_62, FIdFieldType, FPrimeField, FCharacteristicTwoField, FGNBasis,
       FTPBasis, FPPBasis, Fid_ecSigType, FECDsaWithSha1, Fid_publicKeyType,
       FIdECPublicKey, FECDsaWithSha2, FECDsaWithSha224, FECDsaWithSha256,
       FECDsaWithSha384, FECDsaWithSha512, FEllipticCurve, FPrimeCurve,
@@ -270,63 +271,68 @@ end;
 
 class procedure TX9ObjectIdentifiers.Boot;
 begin
-  Fansi_X9_62 := TDerObjectIdentifier.Create(AnsiX962);
-
-  FIdFieldType := ansi_X9_62.Branch('1');
-
-  FPrimeField := IdFieldType.Branch('1');
-
-  FCharacteristicTwoField := IdFieldType.Branch('2');
-
-  FGNBasis := CharacteristicTwoField.Branch('3.1');
-  FTPBasis := CharacteristicTwoField.Branch('3.2');
-  FPPBasis := CharacteristicTwoField.Branch('3.3');
-
-  Fid_ecSigType := ansi_X9_62.Branch('4');
-  //
-  FECDsaWithSha1 := id_ecSigType.Branch('1');
-
-  Fid_publicKeyType := ansi_X9_62.Branch('2');
-
-  FIdECPublicKey := id_publicKeyType.Branch('1');
-
-  FECDsaWithSha2 := id_ecSigType.Branch('3');
-
-  FECDsaWithSha224 := ECDsaWithSha2.Branch('1');
-  FECDsaWithSha256 := ECDsaWithSha2.Branch('2');
-  FECDsaWithSha384 := ECDsaWithSha2.Branch('3');
-  FECDsaWithSha512 := ECDsaWithSha2.Branch('4');
-  //
-  //
-  // named curves
-  //
-  FEllipticCurve := ansi_X9_62.Branch('3');
-
-  //
-  // Prime
-  //
-  FPrimeCurve := EllipticCurve.Branch('1');
-
-  FPrime192v1 := PrimeCurve.Branch('1');
-  FPrime192v2 := PrimeCurve.Branch('2');
-  FPrime192v3 := PrimeCurve.Branch('3');
-  FPrime239v1 := PrimeCurve.Branch('4');
-  FPrime239v2 := PrimeCurve.Branch('5');
-  FPrime239v3 := PrimeCurve.Branch('6');
-  FPrime256v1 := PrimeCurve.Branch('7');
-
-  //
-  // DSA
-  //
-  // dsapublicnumber OBJECT IDENTIFIER ::= { iso(1) member-body(2)
-  // us(840) ansi-x957(10040) number-type(4) 1 }
-  FIdDsa := TDerObjectIdentifier.Create('1.2.840.10040.4.1');
-
-  // /**
-  // *   id-dsa-with-sha1 OBJECT IDENTIFIER ::=  { iso(1) member-body(2)
-  // *         us(840) x9-57 (10040) x9cm(4) 3 }
-  // */
-  FIdDsaWithSha1 := TDerObjectIdentifier.Create('1.2.840.10040.4.3');
+  if not FIsBooted then
+  begin
+    Fansi_X9_62 := TDerObjectIdentifier.Create(AnsiX962);
+
+    FIdFieldType := ansi_X9_62.Branch('1');
+
+    FPrimeField := IdFieldType.Branch('1');
+
+    FCharacteristicTwoField := IdFieldType.Branch('2');
+
+    FGNBasis := CharacteristicTwoField.Branch('3.1');
+    FTPBasis := CharacteristicTwoField.Branch('3.2');
+    FPPBasis := CharacteristicTwoField.Branch('3.3');
+
+    Fid_ecSigType := ansi_X9_62.Branch('4');
+    //
+    FECDsaWithSha1 := id_ecSigType.Branch('1');
+
+    Fid_publicKeyType := ansi_X9_62.Branch('2');
+
+    FIdECPublicKey := id_publicKeyType.Branch('1');
+
+    FECDsaWithSha2 := id_ecSigType.Branch('3');
+
+    FECDsaWithSha224 := ECDsaWithSha2.Branch('1');
+    FECDsaWithSha256 := ECDsaWithSha2.Branch('2');
+    FECDsaWithSha384 := ECDsaWithSha2.Branch('3');
+    FECDsaWithSha512 := ECDsaWithSha2.Branch('4');
+    //
+    //
+    // named curves
+    //
+    FEllipticCurve := ansi_X9_62.Branch('3');
+
+    //
+    // Prime
+    //
+    FPrimeCurve := EllipticCurve.Branch('1');
+
+    FPrime192v1 := PrimeCurve.Branch('1');
+    FPrime192v2 := PrimeCurve.Branch('2');
+    FPrime192v3 := PrimeCurve.Branch('3');
+    FPrime239v1 := PrimeCurve.Branch('4');
+    FPrime239v2 := PrimeCurve.Branch('5');
+    FPrime239v3 := PrimeCurve.Branch('6');
+    FPrime256v1 := PrimeCurve.Branch('7');
+
+    //
+    // DSA
+    //
+    // dsapublicnumber OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+    // us(840) ansi-x957(10040) number-type(4) 1 }
+    FIdDsa := TDerObjectIdentifier.Create('1.2.840.10040.4.1');
+
+    // /**
+    // *   id-dsa-with-sha1 OBJECT IDENTIFIER ::=  { iso(1) member-body(2)
+    // *         us(840) x9-57 (10040) x9cm(4) 3 }
+    // */
+    FIdDsaWithSha1 := TDerObjectIdentifier.Create('1.2.840.10040.4.3');
+
+    FIsBooted := True;
+  end;
 
 end;
 

+ 2 - 2
CryptoLib/src/Crypto/ClpBufferedCipherBase.pas

@@ -41,7 +41,7 @@ type
 
     class function GetEmptyBuffer: TCryptoLibByteArray; static; inline;
 
-    class constructor CreateBufferedCipherBase();
+    class constructor BufferedCipherBase();
 
   strict protected
 
@@ -104,7 +104,7 @@ implementation
 
 { TBufferedCipherBase }
 
-class constructor TBufferedCipherBase.CreateBufferedCipherBase;
+class constructor TBufferedCipherBase.BufferedCipherBase;
 begin
   System.SetLength(FEmptyBuffer, 0);
 end;

+ 455 - 0
CryptoLib/src/Crypto/EC/ClpCustomNamedCurves.pas

@@ -0,0 +1,455 @@
+{ *********************************************************************************** }
+{ *                              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 ClpCustomNamedCurves;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  Generics.Collections,
+  ClpHex,
+  ClpGlvTypeBParameters,
+  ClpIGlvTypeBEndomorphism,
+  ClpSecObjectIdentifiers,
+  ClpCryptoLibTypes,
+  ClpBigInteger,
+  ClpECCurve,
+  ClpSecP256K1Curve,
+  ClpISecP256K1Curve,
+  ClpSecP384R1Curve,
+  ClpISecP384R1Curve,
+  ClpSecP521R1Curve,
+  ClpISecP521R1Curve,
+  ClpSecT283K1Curve,
+  ClpISecT283K1Curve,
+  ClpIECInterface,
+  ClpX9ECPoint,
+  ClpIX9ECPoint,
+  ClpIDerObjectIdentifier,
+  ClpGlvTypeBEndomorphism,
+  ClpX9ECParameters,
+  ClpIX9ECParameters,
+  ClpX9ECParametersHolder,
+  ClpIX9ECParametersHolder,
+  ClpIGlvTypeBParameters;
+
+type
+  TCustomNamedCurves = class sealed(TObject)
+
+  strict private
+
+  class var
+
+    FIsBooted: Boolean;
+    FnameToCurve: TDictionary<String, IX9ECParametersHolder>;
+    FnameToOid: TDictionary<String, IDerObjectIdentifier>;
+    FoidToCurve: TDictionary<IDerObjectIdentifier, IX9ECParametersHolder>;
+    FoidToName: TDictionary<IDerObjectIdentifier, String>;
+
+    Fnames: TList<String>;
+
+    class function GetNames: TCryptoLibStringArray; static; inline;
+
+    // class procedure DefineCurve(const name: String;
+    // const holder: IX9ECParametersHolder); static; inline;
+
+    class procedure DefineCurveWithOid(const name: String;
+      const oid: IDerObjectIdentifier; const holder: IX9ECParametersHolder);
+      static; inline;
+
+    class procedure DefineCurveAlias(const name: String;
+      const oid: IDerObjectIdentifier); static; inline;
+
+    class function ConfigureCurve(const curve: IECCurve): IECCurve;
+      static; inline;
+    class function ConfigureCurveGlv(const c: IECCurve;
+      const p: IGlvTypeBParameters): IECCurve; static; inline;
+
+    class constructor CreateCustomNamedCurves();
+    class destructor DestroyCustomNamedCurves();
+
+  public
+    class function GetByName(const name: String): IX9ECParameters;
+      static; inline;
+    // /**
+    // * return the X9ECParameters object for the named curve represented by
+    // * the passed in object identifier. Null if the curve isn't present.
+    // *
+    // * @param oid an object identifier representing a named curve, if present.
+    // */
+    class function GetByOid(const oid: IDerObjectIdentifier): IX9ECParameters;
+      static; inline;
+    // /**
+    // * return the object identifier signified by the passed in name. Null
+    // * if there is no object identifier associated with name.
+    // *
+    // * @return the object identifier associated with name, if present.
+    // */
+    class function GetOid(const name: String): IDerObjectIdentifier;
+      static; inline;
+    // /**
+    // * return the named curve name represented by the given object identifier.
+    // */
+    class function GetName(const oid: IDerObjectIdentifier): String;
+      static; inline;
+    // /**
+    // * returns an enumeration containing the name strings for curves
+    // * contained in this structure.
+    // */
+    class property Names: TCryptoLibStringArray read GetNames;
+
+    class procedure Boot(); static;
+
+  type
+
+    /// <summary>
+    /// secp256k1
+    /// </summary>
+    TSecP256K1Holder = class sealed(TX9ECParametersHolder,
+      IX9ECParametersHolder)
+
+    strict protected
+      function CreateParameters(): IX9ECParameters; override;
+
+    public
+      class function Instance(): IX9ECParametersHolder; static;
+
+    end;
+
+  type
+
+    /// <summary>
+    /// secp384r1
+    /// </summary>
+    TSecP384R1Holder = class sealed(TX9ECParametersHolder,
+      IX9ECParametersHolder)
+
+    strict protected
+      function CreateParameters(): IX9ECParameters; override;
+
+    public
+      class function Instance(): IX9ECParametersHolder; static;
+
+    end;
+
+  type
+
+    /// <summary>
+    /// secp521r1
+    /// </summary>
+    TSecP521R1Holder = class sealed(TX9ECParametersHolder,
+      IX9ECParametersHolder)
+
+    strict protected
+      function CreateParameters(): IX9ECParameters; override;
+
+    public
+      class function Instance(): IX9ECParametersHolder; static;
+
+    end;
+
+  type
+
+    /// <summary>
+    /// sect283k1
+    /// </summary>
+    TSecT283K1Holder = class sealed(TX9ECParametersHolder,
+      IX9ECParametersHolder)
+
+    strict protected
+      function CreateParameters(): IX9ECParameters; override;
+
+    public
+      class function Instance(): IX9ECParametersHolder; static;
+
+    end;
+
+  end;
+
+implementation
+
+{ TCustomNamedCurves }
+
+// class procedure TCustomNamedCurves.DefineCurve(const name: String;
+// const holder: IX9ECParametersHolder);
+// var
+// LName: string;
+// begin
+// LName := name;
+// Fnames.Add(LName);
+// LName := UpperCase(LName);
+// FnameToCurve.Add(LName, holder);
+// end;
+
+class procedure TCustomNamedCurves.DefineCurveWithOid(const name: String;
+  const oid: IDerObjectIdentifier; const holder: IX9ECParametersHolder);
+var
+  LName: string;
+begin
+  LName := name;
+  Fnames.Add(LName);
+  FoidToName.Add(oid, LName);
+  FoidToCurve.Add(oid, holder);
+  LName := UpperCase(LName);
+  FnameToOid.Add(LName, oid);
+  FnameToCurve.Add(LName, holder);
+end;
+
+class procedure TCustomNamedCurves.DefineCurveAlias(const name: String;
+  const oid: IDerObjectIdentifier);
+var
+  curve: IX9ECParametersHolder;
+  LName: string;
+begin
+  LName := name;
+  if not(FoidToCurve.TryGetValue(oid, curve)) then
+  begin
+    raise EInvalidOperationCryptoLibException.Create('');
+  end;
+  LName := UpperCase(LName);
+  FnameToOid.Add(LName, oid);
+  FnameToCurve.Add(LName, curve);
+end;
+
+class function TCustomNamedCurves.ConfigureCurve(const curve: IECCurve)
+  : IECCurve;
+begin
+  result := curve;
+end;
+
+class function TCustomNamedCurves.ConfigureCurveGlv(const c: IECCurve;
+  const p: IGlvTypeBParameters): IECCurve;
+var
+  glv: IGlvTypeBEndomorphism;
+begin
+  glv := TGlvTypeBEndomorphism.Create(c, p);
+  result := c.Configure().SetEndomorphism(glv).CreateCurve();
+end;
+
+class function TCustomNamedCurves.GetByOid(const oid: IDerObjectIdentifier)
+  : IX9ECParameters;
+var
+  holder: IX9ECParametersHolder;
+begin
+  if FoidToCurve.TryGetValue(oid, holder) then
+  begin
+    result := holder.Parameters
+  end
+  else
+  begin
+    result := Nil;
+  end;
+end;
+
+class function TCustomNamedCurves.GetOid(const name: String)
+  : IDerObjectIdentifier;
+begin
+  if not(FnameToOid.TryGetValue(UpperCase(name), result)) then
+  begin
+    result := Nil;
+  end;
+end;
+
+class function TCustomNamedCurves.GetByName(const name: String)
+  : IX9ECParameters;
+var
+  holder: IX9ECParametersHolder;
+begin
+  if FnameToCurve.TryGetValue(UpperCase(name), holder) then
+  begin
+    result := holder.Parameters
+  end
+  else
+  begin
+    result := Nil;
+  end;
+end;
+
+class function TCustomNamedCurves.GetName
+  (const oid: IDerObjectIdentifier): String;
+begin
+  if not(FoidToName.TryGetValue(oid, result)) then
+  begin
+    result := '';
+  end;
+end;
+
+class function TCustomNamedCurves.GetNames: TCryptoLibStringArray;
+begin
+  result := Fnames.ToArray();
+end;
+
+class constructor TCustomNamedCurves.CreateCustomNamedCurves;
+begin
+  TCustomNamedCurves.Boot;
+end;
+
+class destructor TCustomNamedCurves.DestroyCustomNamedCurves;
+begin
+  FnameToCurve.Free;
+  FnameToOid.Free;
+  FoidToCurve.Free;
+  FoidToName.Free;
+  Fnames.Free;
+end;
+
+class procedure TCustomNamedCurves.Boot;
+begin
+  if not FIsBooted then
+  begin
+    FnameToCurve := TDictionary<String, IX9ECParametersHolder>.Create();
+    FnameToOid := TDictionary<String, IDerObjectIdentifier>.Create();
+    FoidToCurve := TDictionary<IDerObjectIdentifier,
+      IX9ECParametersHolder>.Create();
+    FoidToName := TDictionary<IDerObjectIdentifier, String>.Create();
+
+    Fnames := TList<String>.Create();
+
+    DefineCurveWithOid('secp256k1', TSecObjectIdentifiers.SecP256k1,
+      TSecP256K1Holder.Instance);
+
+    DefineCurveWithOid('secp384r1', TSecObjectIdentifiers.SecP384r1,
+      TSecP384R1Holder.Instance);
+
+    DefineCurveWithOid('secp521r1', TSecObjectIdentifiers.SecP521r1,
+      TSecP521R1Holder.Instance);
+
+    DefineCurveWithOid('sect283k1', TSecObjectIdentifiers.SecT283k1,
+      TSecT283K1Holder.Instance);
+
+    DefineCurveAlias('K-283', TSecObjectIdentifiers.SecT283k1);
+
+    DefineCurveAlias('P-384', TSecObjectIdentifiers.SecP384r1);
+    DefineCurveAlias('P-521', TSecObjectIdentifiers.SecP521r1);
+
+    FIsBooted := True;
+  end;
+end;
+
+{ TCustomNamedCurves.TSecP256K1Holder }
+
+function TCustomNamedCurves.TSecP256K1Holder.CreateParameters: IX9ECParameters;
+var
+  curve: IECCurve;
+  G: IX9ECPoint;
+  S: TCryptoLibByteArray;
+  glv: IGlvTypeBParameters;
+begin
+  S := Nil;
+  glv := TGlvTypeBParameters.Create
+    (TBigInteger.Create
+    ('7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee', 16),
+    TBigInteger.Create
+    ('5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72', 16),
+    TCryptoLibGenericArray<TBigInteger>.Create
+    (TBigInteger.Create('3086d221a7d46bcde86c90e49284eb15', 16),
+    TBigInteger.Create('-e4437ed6010e88286f547fa90abfe4c3', 16)),
+    TCryptoLibGenericArray<TBigInteger>.Create
+    (TBigInteger.Create('114ca50f7a8e2f3f657c1108d9d44cfd8', 16),
+    TBigInteger.Create('3086d221a7d46bcde86c90e49284eb15', 16)),
+    TBigInteger.Create('3086d221a7d46bcde86c90e49284eb153dab', 16),
+    TBigInteger.Create('e4437ed6010e88286f547fa90abfe4c42212', 16), 272);
+  curve := ConfigureCurveGlv(TSecP256K1Curve.Create() as ISecP256K1Curve, glv);
+  G := TX9ECPoint.Create(curve,
+    THex.Decode('04' +
+    '79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798' +
+    '483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8'));
+  result := TX9ECParameters.Create(curve, G, curve.Order, curve.Cofactor, S);
+end;
+
+class function TCustomNamedCurves.TSecP256K1Holder.Instance
+  : IX9ECParametersHolder;
+begin
+  result := TSecP256K1Holder.Create();
+end;
+
+{ TCustomNamedCurves.TSecP384R1Holder }
+
+function TCustomNamedCurves.TSecP384R1Holder.CreateParameters: IX9ECParameters;
+var
+  S: TCryptoLibByteArray;
+  curve: IECCurve;
+  G: IX9ECPoint;
+begin
+  S := THex.Decode('A335926AA319A27A1D00896A6773A4827ACDAC73');
+  curve := ConfigureCurve(TSecP384R1Curve.Create() as ISecP384R1Curve);
+  G := TX9ECPoint.Create(curve,
+    THex.Decode('04' +
+    'AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7'
+    + '3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F')
+    );
+  result := TX9ECParameters.Create(curve, G, curve.Order, curve.Cofactor, S);
+end;
+
+class function TCustomNamedCurves.TSecP384R1Holder.Instance
+  : IX9ECParametersHolder;
+begin
+  result := TSecP384R1Holder.Create();
+end;
+
+{ TCustomNamedCurves.TSecP521R1Holder }
+
+function TCustomNamedCurves.TSecP521R1Holder.CreateParameters: IX9ECParameters;
+var
+  S: TCryptoLibByteArray;
+  curve: IECCurve;
+  G: IX9ECPoint;
+begin
+  S := THex.Decode('D09E8800291CB85396CC6717393284AAA0DA64BA');
+  curve := ConfigureCurve(TSecP521R1Curve.Create() as ISecP521R1Curve);
+  G := TX9ECPoint.Create(curve,
+    THex.Decode('04' +
+    '00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66'
+    + '011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650')
+    );
+  result := TX9ECParameters.Create(curve, G, curve.Order, curve.Cofactor, S);
+end;
+
+class function TCustomNamedCurves.TSecP521R1Holder.Instance
+  : IX9ECParametersHolder;
+begin
+  result := TSecP521R1Holder.Create();
+end;
+
+{ TCustomNamedCurves.TSecT283K1Holder }
+
+function TCustomNamedCurves.TSecT283K1Holder.CreateParameters: IX9ECParameters;
+var
+  S: TCryptoLibByteArray;
+  curve: IECCurve;
+  G: IX9ECPoint;
+begin
+  S := Nil;
+  curve := ConfigureCurve(TSecT283K1Curve.Create() as ISecT283K1Curve);
+  G := TX9ECPoint.Create(curve,
+    THex.Decode('04' +
+    '0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836' +
+    '01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259')
+    );
+  result := TX9ECParameters.Create(curve, G, curve.Order, curve.Cofactor, S);
+end;
+
+class function TCustomNamedCurves.TSecT283K1Holder.Instance
+  : IX9ECParametersHolder;
+begin
+  result := TSecT283K1Holder.Create();
+end;
+
+end.

+ 13 - 2
CryptoLib/src/Crypto/Engines/ClpAesEngine.pas

@@ -53,6 +53,16 @@ type
   /// This implementation is based on optimizations from Dr. Brian
   /// Gladman's paper and C code at <see href="http://fp.gladman.plus.com/cryptography_technology/rijndael/" />
   /// </para>
+  /// <para>
+  /// This version uses only one 256 word table for each, for a total of
+  /// 2Kbytes, <br />adding 12 rotate operations per round to compute the
+  /// values contained in the other tables from <br />the contents of the
+  /// first.
+  /// </para>
+  /// <para>
+  /// This file contains the middle performance version with 2Kbytes of
+  /// static tables for round precomputation.
+  /// </para>
   /// </summary>
   TAesEngine = class sealed(TInterfacedObject, IAesEngine, IBlockCipher)
 
@@ -118,9 +128,10 @@ type
     // private int FFmulX(int x) { int u = x & m1; u |= (u >> 1); return ((x & m2) << 1) ^ ((u >>> 3) | (u >>> 6)); }
     // private static final int  m4 = 0x1b1b1b1b;
     // private int FFmulX(int x) { int u = x & m1; return ((x & m2) << 1) ^ ((u - (u >>> 7)) & m4); }
+
     class function Inv_Mcol(x: UInt32): UInt32; static; inline;
     class function SubWord(x: UInt32): UInt32; static; inline;
-    class constructor CreateAesEngine();
+    class constructor AesEngine();
 
   public
 
@@ -278,7 +289,7 @@ begin
 
 end;
 
-class constructor TAesEngine.CreateAesEngine;
+class constructor TAesEngine.AesEngine;
 begin
   TAesEngine.Boot;
 end;

+ 725 - 0
CryptoLib/src/Crypto/Engines/ClpAesLightEngine.pas

@@ -0,0 +1,725 @@
+{ *********************************************************************************** }
+{ *                              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 ClpAesLightEngine;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpIAesLightEngine,
+  ClpIBlockCipher,
+  ClpICipherParameters,
+  ClpIKeyParameter,
+  ClpCheck,
+  ClpBits,
+  ClpConverters,
+  ClpCryptoLibTypes;
+
+resourcestring
+  AESEngineNotInitialised = 'AES Engine not Initialised';
+  SInputBuffertooShort = 'Input Buffer too Short';
+  SOutputBuffertooShort = 'Output Buffer too Short';
+  SInvalidParameterAESInit = 'Invalid Parameter Passed to AES Init - "%s"';
+  SInvalidKeyLength = 'Key Length not 128/192/256 bits.';
+  SInvalidOperation = 'Should Never Get Here';
+
+type
+
+  /// <summary>
+  /// <para>
+  /// an implementation of the AES (Rijndael), from FIPS-197.
+  /// </para>
+  /// <para>
+  /// For further details see: <see href="http://csrc.nist.gov/encryption/aes/" />
+  /// </para>
+  /// <para>
+  /// This implementation is based on optimizations from Dr. Brian
+  /// Gladman's paper and C code at <see href="http://fp.gladman.plus.com/cryptography_technology/rijndael/" />
+  /// </para>
+  /// <para>
+  /// This version uses no static tables at all and computes the values
+  /// in each round.
+  /// </para>
+  /// <para>
+  /// This file contains the slowest performance version with no static
+  /// tables for round precomputation, but it has the smallest foot
+  /// print.
+  /// </para>
+  /// </summary>
+  TAesLightEngine = class sealed(TInterfacedObject, IAesLightEngine,
+    IBlockCipher)
+
+  strict private
+
+  const
+    // multiply four bytes in GF(2^8) by 'x' {02} in parallel //
+
+    m1 = UInt32($80808080);
+    m2 = UInt32($7F7F7F7F);
+    m3 = UInt32($0000001B);
+    m4 = UInt32($C0C0C0C0);
+    m5 = UInt32($3F3F3F3F);
+    BLOCK_SIZE = Int32(16);
+
+  var
+    FROUNDS: Int32;
+    FWorkingKey: TCryptoLibMatrixUInt32Array;
+    FC0, FC1, FC2, FC3: UInt32;
+    FforEncryption: Boolean;
+
+    function GetAlgorithmName: String; virtual;
+    function GetIsPartialBlockOkay: Boolean; virtual;
+    function GetBlockSize(): Int32; virtual;
+
+    /// <summary>
+    /// <para>
+    /// Calculate the necessary round keys
+    /// </para>
+    /// <para>
+    /// The number of calculations depends on key size and block size
+    /// </para>
+    /// <para>
+    /// AES specified a fixed block size of 128 bits and key sizes
+    /// 128/192/256 bits
+    /// </para>
+    /// <para>
+    /// This code is written assuming those are the only possible values
+    /// </para>
+    /// </summary>
+    function GenerateWorkingKey(key: TCryptoLibByteArray;
+      forEncryption: Boolean): TCryptoLibMatrixUInt32Array;
+
+    procedure UnPackBlock(bytes: TCryptoLibByteArray; off: Int32); inline;
+    procedure PackBlock(bytes: TCryptoLibByteArray; off: Int32); inline;
+
+    procedure EncryptBlock(KW: TCryptoLibMatrixUInt32Array);
+
+    procedure DecryptBlock(KW: TCryptoLibMatrixUInt32Array);
+
+    class var
+
+      Fs, FSi, Frcon: TCryptoLibByteArray;
+
+    class function Shift(r: UInt32; Shift: Int32): UInt32; static; inline;
+    class function FFmulX(x: UInt32): UInt32; static; inline;
+    class function FFmulX2(x: UInt32): UInt32; static; inline;
+
+    // The following defines provide alternative definitions of FFmulX that might
+    // give improved performance if a fast 32-bit multiply is not available.
+    //
+    // private int FFmulX(int x) { int u = x & m1; u |= (u >> 1); return ((x & m2) << 1) ^ ((u >>> 3) | (u >>> 6)); }
+    // private static final int  m4 = 0x1b1b1b1b;
+    // private int FFmulX(int x) { int u = x & m1; return ((x & m2) << 1) ^ ((u - (u >>> 7)) & m4); }
+
+    class function Mcol(x: UInt32): UInt32; static; inline;
+    class function Inv_Mcol(x: UInt32): UInt32; static; inline;
+    class function SubWord(x: UInt32): UInt32; static; inline;
+    class constructor AesLightEngine();
+
+  public
+    /// <summary>
+    /// initialise an AES cipher.
+    /// </summary>
+    /// <param name="forEncryption">
+    /// whether or not we are for encryption.
+    /// </param>
+    /// <param name="parameters">
+    /// the parameters required to set up the cipher.
+    /// </param>
+    /// <exception cref="EArgumentCryptoLibException">
+    /// if the parameters argument is inappropriate.
+    /// </exception>
+    procedure Init(forEncryption: Boolean;
+      const parameters: ICipherParameters); virtual;
+
+    function ProcessBlock(input: TCryptoLibByteArray; inOff: Int32;
+      output: TCryptoLibByteArray; outOff: Int32): Int32; virtual;
+
+    procedure Reset(); virtual;
+
+    property AlgorithmName: String read GetAlgorithmName;
+    property IsPartialBlockOkay: Boolean read GetIsPartialBlockOkay;
+    class procedure Boot; static;
+
+  end;
+
+implementation
+
+{ TAesLightEngine }
+
+class procedure TAesLightEngine.Boot;
+begin
+  // The S box
+  Fs := TCryptoLibByteArray.Create(99, 124, 119, 123, 242, 107, 111, 197, 48, 1,
+    103, 43, 254, 215, 171, 118, 202, 130, 201, 125, 250, 89, 71, 240, 173, 212,
+    162, 175, 156, 164, 114, 192, 183, 253, 147, 38, 54, 63, 247, 204, 52, 165,
+    229, 241, 113, 216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128,
+    226, 235, 39, 178, 117, 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179,
+    41, 227, 47, 132, 83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74,
+    76, 88, 207, 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60,
+    159, 168, 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255,
+    243, 210, 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25,
+    115, 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
+    224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, 231,
+    200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, 186,
+    120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, 112,
+    62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, 225, 248,
+    152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223, 140, 161,
+    137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22);
+
+  // The inverse S-box
+  FSi := TCryptoLibByteArray.Create(82, 9, 106, 213, 48, 54, 165, 56, 191, 64,
+    163, 158, 129, 243, 215, 251, 124, 227, 57, 130, 155, 47, 255, 135, 52, 142,
+    67, 68, 196, 222, 233, 203, 84, 123, 148, 50, 166, 194, 35, 61, 238, 76,
+    149, 11, 66, 250, 195, 78, 8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162,
+    73, 109, 139, 209, 37, 114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92,
+    204, 93, 101, 182, 146, 108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70,
+    87, 167, 141, 157, 132, 144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88,
+    5, 184, 179, 69, 6, 208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1,
+    19, 138, 107, 58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240,
+    180, 230, 115, 150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28,
+    117, 223, 110, 71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170,
+    24, 190, 27, 252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120,
+    205, 90, 244, 31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128,
+    236, 95, 96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201,
+    156, 239, 160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83,
+    153, 97, 23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85,
+    33, 12, 125);
+
+  // vector used in calculating key schedule (powers of x in GF(256))
+  Frcon := TCryptoLibByteArray.Create($01, $02, $04, $08, $10, $20, $40, $80,
+    $1B, $36, $6C, $D8, $AB, $4D, $9A, $2F, $5E, $BC, $63, $C6, $97, $35, $6A,
+    $D4, $B3, $7D, $FA, $EF, $C5, $91);
+end;
+
+class constructor TAesLightEngine.AesLightEngine;
+begin
+  TAesLightEngine.Boot;
+end;
+
+class function TAesLightEngine.Shift(r: UInt32; Shift: Int32): UInt32;
+begin
+  // result := (r shr shift) or (r shl (32 - shift));
+  result := TBits.RotateRight32(r, Shift);
+end;
+
+class function TAesLightEngine.SubWord(x: UInt32): UInt32;
+begin
+  result := UInt32(Fs[x and 255]) or (UInt32(Fs[(x shr 8) and 255]) shl 8) or
+    (UInt32(Fs[(x shr 16) and 255]) shl 16) or
+    (UInt32(Fs[(x shr 24) and 255]) shl 24);
+end;
+
+class function TAesLightEngine.FFmulX(x: UInt32): UInt32;
+begin
+  result := ((x and m2) shl 1) xor (((x and m1) shr 7) * m3);
+end;
+
+class function TAesLightEngine.FFmulX2(x: UInt32): UInt32;
+var
+  t0, t1: UInt32;
+begin
+  t0 := (x and m5) shl 2;
+  t1 := (x and m4);
+  t1 := t1 xor (t1 shr 1);
+  result := t0 xor (t1 shr 2) xor (t1 shr 5);
+end;
+
+class function TAesLightEngine.Mcol(x: UInt32): UInt32;
+var
+  t0, t1: UInt32;
+begin
+  t0 := Shift(x, 8);
+  t1 := x xor t0;
+  result := Shift(t1, 16) xor t0 xor FFmulX(t1);
+end;
+
+class function TAesLightEngine.Inv_Mcol(x: UInt32): UInt32;
+var
+  t0, t1: UInt32;
+begin
+  t0 := x;
+  t1 := t0 xor Shift(t0, 8);
+  t0 := t0 xor FFmulX(t1);
+  t1 := t1 xor FFmulX2(t0);
+  t0 := t0 xor (t1 xor Shift(t1, 16));
+  result := t0;
+end;
+
+procedure TAesLightEngine.EncryptBlock(KW: TCryptoLibMatrixUInt32Array);
+var
+  lkw: TCryptoLibUInt32Array;
+  lt0, lt1, lt2, lr0, lr1, lr2, lr3: UInt32;
+  lr: Int32;
+begin
+  lkw := KW[0];
+  lt0 := FC0 xor lkw[0];
+  lt1 := FC1 xor lkw[1];
+  lt2 := FC2 xor lkw[2];
+
+  lr3 := FC3 xor lkw[3];
+  lr := 1;
+
+  while (lr < FROUNDS - 1) do
+  begin
+    lkw := KW[lr];
+    System.Inc(lr);
+    lr0 := Mcol(UInt32(Fs[lt0 and 255]) xor ((UInt32(Fs[(lt1 shr 8) and 255]))
+      shl 8) xor ((UInt32(Fs[(lt2 shr 16) and 255])) shl 16)
+      xor ((UInt32(Fs[(lr3 shr 24) and 255])) shl 24)) xor lkw[0];
+    lr1 := Mcol(UInt32(Fs[lt1 and 255]) xor ((UInt32(Fs[(lt2 shr 8) and 255]))
+      shl 8) xor ((UInt32(Fs[(lr3 shr 16) and 255])) shl 16)
+      xor ((UInt32(Fs[(lt0 shr 24) and 255])) shl 24)) xor lkw[1];
+    lr2 := Mcol(UInt32(Fs[lt2 and 255]) xor ((UInt32(Fs[(lr3 shr 8) and 255]))
+      shl 8) xor ((UInt32(Fs[(lt0 shr 16) and 255])) shl 16)
+      xor ((UInt32(Fs[(lt1 shr 24) and 255])) shl 24)) xor lkw[2];
+    lr3 := Mcol(UInt32(Fs[lr3 and 255]) xor ((UInt32(Fs[(lt0 shr 8) and 255]))
+      shl 8) xor ((UInt32(Fs[(lt1 shr 16) and 255])) shl 16)
+      xor ((UInt32(Fs[(lt2 shr 24) and 255])) shl 24)) xor lkw[3];
+    lkw := KW[lr];
+    System.Inc(lr);
+    lt0 := Mcol(UInt32(Fs[lr0 and 255]) xor ((UInt32(Fs[(lr1 shr 8) and 255]))
+      shl 8) xor ((UInt32(Fs[(lr2 shr 16) and 255])) shl 16)
+      xor ((UInt32(Fs[(lr3 shr 24) and 255])) shl 24)) xor lkw[0];
+    lt1 := Mcol(UInt32(Fs[lr1 and 255]) xor ((UInt32(Fs[(lr2 shr 8) and 255]))
+      shl 8) xor ((UInt32(Fs[(lr3 shr 16) and 255])) shl 16)
+      xor ((UInt32(Fs[(lr0 shr 24) and 255])) shl 24)) xor lkw[1];
+    lt2 := Mcol(UInt32(Fs[lr2 and 255]) xor ((UInt32(Fs[(lr3 shr 8) and 255]))
+      shl 8) xor ((UInt32(Fs[(lr0 shr 16) and 255])) shl 16)
+      xor ((UInt32(Fs[(lr1 shr 24) and 255])) shl 24)) xor lkw[2];
+    lr3 := Mcol(UInt32(Fs[lr3 and 255]) xor ((UInt32(Fs[(lr0 shr 8) and 255]))
+      shl 8) xor ((UInt32(Fs[(lr1 shr 16) and 255])) shl 16)
+      xor ((UInt32(Fs[(lr2 shr 24) and 255])) shl 24)) xor lkw[3];
+  end;
+
+  lkw := KW[lr];
+  System.Inc(lr);
+  lr0 := Mcol(UInt32(Fs[lt0 and 255]) xor ((UInt32(Fs[(lt1 shr 8) and 255]))
+    shl 8) xor ((UInt32(Fs[(lt2 shr 16) and 255])) shl 16)
+    xor ((UInt32(Fs[(lr3 shr 24) and 255])) shl 24)) xor lkw[0];
+  lr1 := Mcol(UInt32(Fs[lt1 and 255]) xor ((UInt32(Fs[(lt2 shr 8) and 255]))
+    shl 8) xor ((UInt32(Fs[(lr3 shr 16) and 255])) shl 16)
+    xor ((UInt32(Fs[(lt0 shr 24) and 255])) shl 24)) xor lkw[1];
+  lr2 := Mcol(UInt32(Fs[lt2 and 255]) xor ((UInt32(Fs[(lr3 shr 8) and 255]))
+    shl 8) xor ((UInt32(Fs[(lt0 shr 16) and 255])) shl 16)
+    xor ((UInt32(Fs[(lt1 shr 24) and 255])) shl 24)) xor lkw[2];
+  lr3 := Mcol(UInt32(Fs[lr3 and 255]) xor ((UInt32(Fs[(lt0 shr 8) and 255]))
+    shl 8) xor ((UInt32(Fs[(lt1 shr 16) and 255])) shl 16)
+    xor ((UInt32(Fs[(lt2 shr 24) and 255])) shl 24)) xor lkw[3];
+
+  // the final round is a simple function of S
+
+  lkw := KW[lr];
+  FC0 := UInt32(Fs[lr0 and 255]) xor ((UInt32(Fs[(lr1 shr 8) and 255])) shl 8)
+    xor ((UInt32(Fs[(lr2 shr 16) and 255])) shl 16)
+    xor ((UInt32(Fs[(lr3 shr 24) and 255])) shl 24) xor lkw[0];
+  FC1 := UInt32(Fs[lr1 and 255]) xor ((UInt32(Fs[(lr2 shr 8) and 255])) shl 8)
+    xor ((UInt32(Fs[(lr3 shr 16) and 255])) shl 16)
+    xor ((UInt32(Fs[(lr0 shr 24) and 255])) shl 24) xor lkw[1];
+  FC2 := UInt32(Fs[lr2 and 255]) xor ((UInt32(Fs[(lr3 shr 8) and 255])) shl 8)
+    xor ((UInt32(Fs[(lr0 shr 16) and 255])) shl 16)
+    xor ((UInt32(Fs[(lr1 shr 24) and 255])) shl 24) xor lkw[2];
+  FC3 := UInt32(Fs[lr3 and 255]) xor ((UInt32(Fs[(lr0 shr 8) and 255])) shl 8)
+    xor ((UInt32(Fs[(lr1 shr 16) and 255])) shl 16)
+    xor ((UInt32(Fs[(lr2 shr 24) and 255])) shl 24) xor lkw[3];
+end;
+
+procedure TAesLightEngine.DecryptBlock(KW: TCryptoLibMatrixUInt32Array);
+var
+  lkw: TCryptoLibUInt32Array;
+  lt0, lt1, lt2, lr0, lr1, lr2, lr3: UInt32;
+  lr: Int32;
+begin
+  lkw := KW[FROUNDS];
+  lt0 := FC0 xor lkw[0];
+  lt1 := FC1 xor lkw[1];
+  lt2 := FC2 xor lkw[2];
+
+  lr3 := FC3 xor lkw[3];
+  lr := FROUNDS - 1;
+
+  while (lr > 1) do
+  begin
+    lkw := KW[lr];
+    System.Dec(lr);
+    lr0 := Inv_Mcol(UInt32(FSi[lt0 and 255])
+      xor ((UInt32(FSi[(lr3 shr 8) and 255])) shl 8)
+      xor ((UInt32(FSi[(lt2 shr 16) and 255])) shl 16)
+      xor (UInt32(FSi[(lt1 shr 24) and 255]) shl 24)) xor lkw[0];
+    lr1 := Inv_Mcol(UInt32(FSi[lt1 and 255])
+      xor ((UInt32(FSi[(lt0 shr 8) and 255])) shl 8)
+      xor ((UInt32(FSi[(lr3 shr 16) and 255])) shl 16)
+      xor (UInt32(FSi[(lt2 shr 24) and 255]) shl 24)) xor lkw[1];
+    lr2 := Inv_Mcol(UInt32(FSi[lt2 and 255])
+      xor ((UInt32(FSi[(lt1 shr 8) and 255])) shl 8)
+      xor ((UInt32(FSi[(lt0 shr 16) and 255])) shl 16)
+      xor (UInt32(FSi[(lr3 shr 24) and 255]) shl 24)) xor lkw[2];
+    lr3 := Inv_Mcol(UInt32(FSi[lr3 and 255])
+      xor ((UInt32(FSi[(lt2 shr 8) and 255])) shl 8)
+      xor ((UInt32(FSi[(lt1 shr 16) and 255])) shl 16)
+      xor (UInt32(FSi[(lt0 shr 24) and 255]) shl 24)) xor lkw[3];
+    lkw := KW[lr];
+    System.Dec(lr);
+    lt0 := Inv_Mcol(UInt32(FSi[lr0 and 255])
+      xor ((UInt32(FSi[(lr3 shr 8) and 255])) shl 8)
+      xor ((UInt32(FSi[(lr2 shr 16) and 255])) shl 16)
+      xor (UInt32(FSi[(lr1 shr 24) and 255]) shl 24)) xor lkw[0];
+    lt1 := Inv_Mcol(UInt32(FSi[lr1 and 255])
+      xor ((UInt32(FSi[(lr0 shr 8) and 255])) shl 8)
+      xor ((UInt32(FSi[(lr3 shr 16) and 255])) shl 16)
+      xor (UInt32(FSi[(lr2 shr 24) and 255]) shl 24)) xor lkw[1];
+    lt2 := Inv_Mcol(UInt32(FSi[lr2 and 255])
+      xor ((UInt32(FSi[(lr1 shr 8) and 255])) shl 8)
+      xor ((UInt32(FSi[(lr0 shr 16) and 255])) shl 16)
+      xor (UInt32(FSi[(lr3 shr 24) and 255]) shl 24)) xor lkw[2];
+    lr3 := Inv_Mcol(UInt32(FSi[lr3 and 255])
+      xor ((UInt32(FSi[(lr2 shr 8) and 255])) shl 8)
+      xor ((UInt32(FSi[(lr1 shr 16) and 255])) shl 16)
+      xor (UInt32(FSi[(lr0 shr 24) and 255]) shl 24)) xor lkw[3];
+  end;
+
+  lkw := KW[1];
+  lr0 := Inv_Mcol(UInt32(FSi[lt0 and 255])
+    xor ((UInt32(FSi[(lr3 shr 8) and 255])) shl 8)
+    xor ((UInt32(FSi[(lt2 shr 16) and 255])) shl 16)
+    xor (UInt32(FSi[(lt1 shr 24) and 255]) shl 24)) xor lkw[0];
+  lr1 := Inv_Mcol(UInt32(FSi[lt1 and 255])
+    xor ((UInt32(FSi[(lt0 shr 8) and 255])) shl 8)
+    xor ((UInt32(FSi[(lr3 shr 16) and 255])) shl 16)
+    xor (UInt32(FSi[(lt2 shr 24) and 255]) shl 24)) xor lkw[1];
+  lr2 := Inv_Mcol(UInt32(FSi[lt2 and 255])
+    xor ((UInt32(FSi[(lt1 shr 8) and 255])) shl 8)
+    xor ((UInt32(FSi[(lt0 shr 16) and 255])) shl 16)
+    xor (UInt32(FSi[(lr3 shr 24) and 255]) shl 24)) xor lkw[2];
+  lr3 := Inv_Mcol(UInt32(FSi[lr3 and 255])
+    xor ((UInt32(FSi[(lt2 shr 8) and 255])) shl 8)
+    xor ((UInt32(FSi[(lt1 shr 16) and 255])) shl 16)
+    xor (UInt32(FSi[(lt0 shr 24) and 255]) shl 24)) xor lkw[3];
+
+  // the final round's table is a simple function of Si
+
+  lkw := KW[0];
+  FC0 := UInt32(FSi[lr0 and 255]) xor ((UInt32(FSi[(lr3 shr 8) and 255])) shl 8)
+    xor ((UInt32(FSi[(lr2 shr 16) and 255])) shl 16)
+    xor ((UInt32(FSi[(lr1 shr 24) and 255])) shl 24) xor lkw[0];
+  FC1 := UInt32(FSi[lr1 and 255]) xor ((UInt32(FSi[(lr0 shr 8) and 255])) shl 8)
+    xor ((UInt32(FSi[(lr3 shr 16) and 255])) shl 16)
+    xor ((UInt32(FSi[(lr2 shr 24) and 255])) shl 24) xor lkw[1];
+  FC2 := UInt32(FSi[lr2 and 255]) xor ((UInt32(FSi[(lr1 shr 8) and 255])) shl 8)
+    xor ((UInt32(FSi[(lr0 shr 16) and 255])) shl 16)
+    xor ((UInt32(FSi[(lr3 shr 24) and 255])) shl 24) xor lkw[2];
+  FC3 := UInt32(FSi[lr3 and 255]) xor ((UInt32(FSi[(lr2 shr 8) and 255])) shl 8)
+    xor ((UInt32(FSi[(lr1 shr 16) and 255])) shl 16)
+    xor ((UInt32(FSi[(lr0 shr 24) and 255])) shl 24) xor lkw[3];
+end;
+
+function TAesLightEngine.GenerateWorkingKey(key: TCryptoLibByteArray;
+  forEncryption: Boolean): TCryptoLibMatrixUInt32Array;
+var
+  keyLen, KC, i, j: Int32;
+  smallw: TCryptoLibUInt32Array;
+  bigW: TCryptoLibMatrixUInt32Array;
+  u, rcon, t0, t1, t2, t3, t4, t5, t6, t7: UInt32;
+
+begin
+  keyLen := System.Length(key);
+  if ((keyLen < 16) or (keyLen > 32) or ((keyLen and 7) <> 0)) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SInvalidKeyLength);
+  end;
+
+  KC := keyLen shr 2; // KC := keyLen div 4;
+  FROUNDS := KC + 6;
+  // This is not always true for the generalized Rijndael that allows larger block sizes
+  System.SetLength(bigW, FROUNDS + 1); // 4 words in a block
+
+  for i := 0 to FROUNDS do
+  begin
+    System.SetLength(bigW[i], 4);
+  end;
+
+  case KC of
+    4:
+      begin
+        t0 := TConverters.ReadBytesAsUInt32LE(PByte(key), 0);
+        bigW[0][0] := t0;
+        t1 := TConverters.ReadBytesAsUInt32LE(PByte(key), 4);
+        bigW[0][1] := t1;
+        t2 := TConverters.ReadBytesAsUInt32LE(PByte(key), 8);
+        bigW[0][2] := t2;
+        t3 := TConverters.ReadBytesAsUInt32LE(PByte(key), 12);
+        bigW[0][3] := t3;
+
+        for i := 1 to 10 do
+        begin
+          u := SubWord(Shift(t3, 8)) xor Frcon[i - 1];
+          t0 := t0 xor u;
+          bigW[i][0] := t0;
+          t1 := t1 xor t0;
+          bigW[i][1] := t1;
+          t2 := t2 xor t1;
+          bigW[i][2] := t2;
+          t3 := t3 xor t2;
+          bigW[i][3] := t3;
+        end;
+      end;
+
+    6:
+      begin
+        t0 := TConverters.ReadBytesAsUInt32LE(PByte(key), 0);
+        bigW[0][0] := t0;
+        t1 := TConverters.ReadBytesAsUInt32LE(PByte(key), 4);
+        bigW[0][1] := t1;
+        t2 := TConverters.ReadBytesAsUInt32LE(PByte(key), 8);
+        bigW[0][2] := t2;
+        t3 := TConverters.ReadBytesAsUInt32LE(PByte(key), 12);
+        bigW[0][3] := t3;
+        t4 := TConverters.ReadBytesAsUInt32LE(PByte(key), 16);
+        bigW[1][0] := t4;
+        t5 := TConverters.ReadBytesAsUInt32LE(PByte(key), 20);
+        bigW[1][1] := t5;
+
+        rcon := 1;
+        u := SubWord(Shift(t5, 8)) xor rcon;
+        rcon := rcon shl 1;
+        t0 := t0 xor u;
+        bigW[1][2] := t0;
+        t1 := t1 xor t0;
+        bigW[1][3] := t1;
+        t2 := t2 xor t1;
+        bigW[2][0] := t2;
+        t3 := t3 xor t2;
+        bigW[2][1] := t3;
+        t4 := t4 xor t3;
+        bigW[2][2] := t4;
+        t5 := t5 xor t4;
+        bigW[2][3] := t5;
+
+        i := 3;
+
+        while i < 12 do
+
+        begin
+          u := SubWord(Shift(t5, 8)) xor rcon;
+          rcon := rcon shl 1;
+          t0 := t0 xor u;
+          bigW[i][0] := t0;
+          t1 := t1 xor t0;
+          bigW[i][1] := t1;
+          t2 := t2 xor t1;
+          bigW[i][2] := t2;
+          t3 := t3 xor t2;
+          bigW[i][3] := t3;
+          t4 := t4 xor t3;
+          bigW[i + 1][0] := t4;
+          t5 := t5 xor t4;
+          bigW[i + 1][1] := t5;
+          u := SubWord(Shift(t5, 8)) xor rcon;
+          rcon := rcon shl 1;
+          t0 := t0 xor u;
+          bigW[i + 1][2] := t0;
+          t1 := t1 xor t0;
+          bigW[i + 1][3] := t1;
+          t2 := t2 xor t1;
+          bigW[i + 2][0] := t2;
+          t3 := t3 xor t2;
+          bigW[i + 2][1] := t3;
+          t4 := t4 xor t3;
+          bigW[i + 2][2] := t4;
+          t5 := t5 xor t4;
+          bigW[i + 2][3] := t5;
+          System.Inc(i, 3);
+        end;
+
+        u := SubWord(Shift(t5, 8)) xor rcon;
+        t0 := t0 xor u;
+        bigW[12][0] := t0;
+        t1 := t1 xor t0;
+        bigW[12][1] := t1;
+        t2 := t2 xor t1;
+        bigW[12][2] := t2;
+        t3 := t3 xor t2;
+        bigW[12][3] := t3;
+      end;
+
+    8:
+      begin
+        t0 := TConverters.ReadBytesAsUInt32LE(PByte(key), 0);
+        bigW[0][0] := t0;
+        t1 := TConverters.ReadBytesAsUInt32LE(PByte(key), 4);
+        bigW[0][1] := t1;
+        t2 := TConverters.ReadBytesAsUInt32LE(PByte(key), 8);
+        bigW[0][2] := t2;
+        t3 := TConverters.ReadBytesAsUInt32LE(PByte(key), 12);
+        bigW[0][3] := t3;
+        t4 := TConverters.ReadBytesAsUInt32LE(PByte(key), 16);
+        bigW[1][0] := t4;
+        t5 := TConverters.ReadBytesAsUInt32LE(PByte(key), 20);
+        bigW[1][1] := t5;
+        t6 := TConverters.ReadBytesAsUInt32LE(PByte(key), 24);
+        bigW[1][2] := t6;
+        t7 := TConverters.ReadBytesAsUInt32LE(PByte(key), 28);
+        bigW[1][3] := t7;
+
+        rcon := 1;
+
+        i := 2;
+
+        while i < 14 do
+
+        begin
+          u := SubWord(Shift(t7, 8)) xor rcon;
+          rcon := rcon shl 1;
+          t0 := t0 xor u;
+          bigW[i][0] := t0;
+          t1 := t1 xor t0;
+          bigW[i][1] := t1;
+          t2 := t2 xor t1;
+          bigW[i][2] := t2;
+          t3 := t3 xor t2;;
+          bigW[i][3] := t3;
+          u := SubWord(t3);
+          t4 := t4 xor u;
+          bigW[i + 1][0] := t4;
+          t5 := t5 xor t4;
+          bigW[i + 1][1] := t5;
+          t6 := t6 xor t5;
+          bigW[i + 1][2] := t6;
+          t7 := t7 xor t6;
+          bigW[i + 1][3] := t7;
+          System.Inc(i, 2);
+        end;
+
+        u := SubWord(Shift(t7, 8)) xor rcon;
+        t0 := t0 xor u;
+        bigW[14][0] := t0;
+        t1 := t1 xor t0;
+        bigW[14][1] := t1;
+        t2 := t2 xor t1;
+        bigW[14][2] := t2;
+        t3 := t3 xor t2;;
+        bigW[14][3] := t3;
+      end
+  else
+    begin
+      raise EInvalidOperationCryptoLibException.CreateRes(@SInvalidOperation);
+    end;
+  end;
+
+  if (not forEncryption) then
+  begin
+    for j := 1 to System.Pred(FROUNDS) do
+
+    begin
+      smallw := bigW[j];
+      for i := 0 to System.Pred(4) do
+
+      begin
+        smallw[i] := Inv_Mcol(smallw[i]);
+      end;
+    end;
+  end;
+
+  result := bigW;
+
+end;
+
+function TAesLightEngine.GetAlgorithmName: String;
+begin
+  result := 'AES';
+end;
+
+function TAesLightEngine.GetBlockSize: Int32;
+begin
+  result := BLOCK_SIZE;
+end;
+
+function TAesLightEngine.GetIsPartialBlockOkay: Boolean;
+begin
+  result := false;
+end;
+
+procedure TAesLightEngine.Init(forEncryption: Boolean;
+  const parameters: ICipherParameters);
+var
+  keyParameter: IKeyParameter;
+begin
+
+  if not Supports(parameters, IKeyParameter, keyParameter) then
+  begin
+    raise EArgumentCryptoLibException.CreateResFmt(@SInvalidParameterAESInit,
+      [(parameters as TObject).ToString]);
+  end;
+
+  FWorkingKey := GenerateWorkingKey(keyParameter.GetKey(), forEncryption);
+
+  FforEncryption := forEncryption;
+end;
+
+procedure TAesLightEngine.PackBlock(bytes: TCryptoLibByteArray; off: Int32);
+begin
+  TConverters.ReadUInt32AsBytesLE(FC0, bytes, off);
+  TConverters.ReadUInt32AsBytesLE(FC1, bytes, off + 4);
+  TConverters.ReadUInt32AsBytesLE(FC2, bytes, off + 8);
+  TConverters.ReadUInt32AsBytesLE(FC3, bytes, off + 12);
+end;
+
+procedure TAesLightEngine.UnPackBlock(bytes: TCryptoLibByteArray; off: Int32);
+begin
+  FC0 := TConverters.ReadBytesAsUInt32LE(PByte(bytes), off);
+  FC1 := TConverters.ReadBytesAsUInt32LE(PByte(bytes), off + 4);
+  FC2 := TConverters.ReadBytesAsUInt32LE(PByte(bytes), off + 8);
+  FC3 := TConverters.ReadBytesAsUInt32LE(PByte(bytes), off + 12);
+end;
+
+function TAesLightEngine.ProcessBlock(input: TCryptoLibByteArray; inOff: Int32;
+  output: TCryptoLibByteArray; outOff: Int32): Int32;
+begin
+  if (FWorkingKey = Nil) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes
+      (@AESEngineNotInitialised);
+  end;
+
+  TCheck.DataLength(input, inOff, 16, SInputBuffertooShort);
+  TCheck.OutputLength(output, outOff, 16, SOutputBuffertooShort);
+
+  UnPackBlock(input, inOff);
+
+  if (FforEncryption) then
+  begin
+    EncryptBlock(FWorkingKey);
+  end
+  else
+  begin
+    DecryptBlock(FWorkingKey);
+  end;
+
+  PackBlock(output, outOff);
+
+  result := BLOCK_SIZE;
+end;
+
+procedure TAesLightEngine.Reset;
+begin
+  // nothing to do.
+end;
+
+end.

+ 6 - 6
CryptoLib/src/Crypto/Generators/ClpECKeyPairGenerator.pas

@@ -37,7 +37,7 @@ uses
   ClpIECInterface,
   ClpIFixedPointCombMultiplier,
   ClpSecObjectIdentifiers,
-  // ClpCustomNamedCurves,
+  ClpCustomNamedCurves,
   ClpECNamedCurveTable,
   ClpX9ObjectIdentifiers,
   ClpIX9ECParameters,
@@ -119,11 +119,11 @@ var
 begin
   // TODO ECGost3410NamedCurves support (returns ECDomainParameters though)
 
-  // ecP := TCustomNamedCurves.GetByOid(oid);
-  // if (ecP = Nil) then
-  // begin
-  ecP := TECNamedCurveTable.GetByOid(oid);
-  // end;
+  ecP := TCustomNamedCurves.GetByOid(oid);
+  if (ecP = Nil) then
+  begin
+    ecP := TECNamedCurveTable.GetByOid(oid);
+  end;
 
   result := ecP;
 end;

+ 36 - 0
CryptoLib/src/Interfaces/ClpIAesLightEngine.pas

@@ -0,0 +1,36 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIAesLightEngine;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIBlockCipher;
+
+type
+
+  IAesLightEngine = interface(IBlockCipher)
+    ['{DC3E80FD-A8C7-454D-9727-C8E68B006BA6}']
+
+  end;
+
+implementation
+
+end.

+ 2 - 2
CryptoLib/src/Interfaces/ClpIECInterface.pas

@@ -294,8 +294,8 @@ type
     function DecompressPoint(yTilde: Int32; X1: TBigInteger): IECPoint;
 
     property FieldSize: Int32 read GetFieldSize;
-    function FromBigInteger(x: TBigInteger): IECFieldElement;
-    function IsValidFieldElement(x: TBigInteger): Boolean;
+    function FromBigInteger(const x: TBigInteger): IECFieldElement;
+    function IsValidFieldElement(const x: TBigInteger): Boolean;
 
     function Configure(): IConfig;
     function ValidatePoint(const x, y: TBigInteger): IECPoint; overload;

+ 44 - 0
CryptoLib/src/Interfaces/ClpISecP256K1Curve.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 ClpISecP256K1Curve;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIECInterface,
+  ClpBigInteger;
+
+type
+  ISecP256K1LookupTable = Interface(IECLookupTable)
+    ['{0E204483-F303-49FD-AF66-0F30CF855CA9}']
+  end;
+
+type
+  ISecP256K1Curve = Interface(IAbstractFpCurve)
+    ['{BBE4D704-8562-4C17-9149-CA33CFE7611F}']
+
+    function GetQ: TBigInteger;
+    property Q: TBigInteger read GetQ;
+
+  end;
+
+implementation
+
+end.

+ 38 - 0
CryptoLib/src/Interfaces/ClpISecP256K1FieldElement.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 ClpISecP256K1FieldElement;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIECFieldElement,
+  ClpCryptoLibTypes;
+
+type
+  ISecP256K1FieldElement = Interface(IAbstractFpFieldElement)
+    ['{F283DDDA-CB65-45E0-9239-2A202F2F1462}']
+
+    function GetX: TCryptoLibUInt32Array;
+    property X: TCryptoLibUInt32Array read GetX;
+  end;
+
+implementation
+
+end.

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

@@ -0,0 +1,35 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpISecP256K1Point;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIECInterface;
+
+type
+  ISecP256K1Point = Interface(IAbstractFpPoint)
+    ['{E3B94BCB-F6A0-4140-A04E-7C26B1D81B7F}']
+
+  end;
+
+implementation
+
+end.

+ 44 - 0
CryptoLib/src/Interfaces/ClpISecP384R1Curve.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 ClpISecP384R1Curve;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIECInterface,
+  ClpBigInteger;
+
+type
+  ISecP384R1LookupTable = Interface(IECLookupTable)
+    ['{F1354F0B-577F-402C-A363-7761CF82DA43}']
+  end;
+
+type
+  ISecP384R1Curve = Interface(IAbstractFpCurve)
+    ['{50639F3D-E15C-4C3C-A7AA-7A8ACA243341}']
+
+    function GetQ: TBigInteger;
+    property Q: TBigInteger read GetQ;
+
+  end;
+
+implementation
+
+end.

+ 38 - 0
CryptoLib/src/Interfaces/ClpISecP384R1FieldElement.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 ClpISecP384R1FieldElement;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIECFieldElement,
+  ClpCryptoLibTypes;
+
+type
+  ISecP384R1FieldElement = Interface(IAbstractFpFieldElement)
+    ['{EE28D1BA-2409-4915-99E9-EACD18C420DA}']
+
+    function GetX: TCryptoLibUInt32Array;
+    property X: TCryptoLibUInt32Array read GetX;
+  end;
+
+implementation
+
+end.

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

@@ -0,0 +1,35 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpISecP384R1Point;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIECInterface;
+
+type
+  ISecP384R1Point = Interface(IAbstractFpPoint)
+    ['{2F1900E8-0B35-414A-B2EE-EDCA9763E2E8}']
+
+  end;
+
+implementation
+
+end.

+ 44 - 0
CryptoLib/src/Interfaces/ClpISecP521R1Curve.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 ClpISecP521R1Curve;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIECInterface,
+  ClpBigInteger;
+
+type
+  ISecP521R1LookupTable = Interface(IECLookupTable)
+    ['{3A647191-94A9-483D-9AC5-57FEFDBA3060}']
+  end;
+
+type
+  ISecP521R1Curve = Interface(IAbstractFpCurve)
+    ['{B2AACD7E-6EF2-45E2-8126-FB87D6DB65B1}']
+
+    function GetQ: TBigInteger;
+    property Q: TBigInteger read GetQ;
+
+  end;
+
+implementation
+
+end.

+ 38 - 0
CryptoLib/src/Interfaces/ClpISecP521R1FieldElement.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 ClpISecP521R1FieldElement;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIECFieldElement,
+  ClpCryptoLibTypes;
+
+type
+  ISecP521R1FieldElement = Interface(IAbstractFpFieldElement)
+    ['{30C8C42B-5099-4387-BEC9-66D6D8901BB4}']
+
+    function GetX: TCryptoLibUInt32Array;
+    property X: TCryptoLibUInt32Array read GetX;
+  end;
+
+implementation
+
+end.

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

@@ -0,0 +1,35 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpISecP521R1Point;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIECInterface;
+
+type
+  ISecP521R1Point = Interface(IAbstractFpPoint)
+    ['{BBE6F8EB-1C56-4B69-B4DE-93EF3079939A}']
+
+  end;
+
+implementation
+
+end.

+ 51 - 0
CryptoLib/src/Interfaces/ClpISecT283FieldElement.pas

@@ -0,0 +1,51 @@
+{ *********************************************************************************** }
+{ *                              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 ClpISecT283FieldElement;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIECFieldElement,
+  ClpCryptoLibTypes;
+
+type
+  ISecT283FieldElement = Interface(IAbstractF2mFieldElement)
+    ['{8DD5CFAF-D879-4FC2-93D7-3C2D5D49E8D1}']
+
+    function GetM: Int32;
+    property M: Int32 read GetM;
+
+    function GetRepresentation: Int32;
+    property Representation: Int32 read GetRepresentation;
+
+    function GetK1: Int32;
+    property k1: Int32 read GetK1;
+    function GetK2: Int32;
+    property k2: Int32 read GetK2;
+    function GetK3: Int32;
+    property k3: Int32 read GetK3;
+
+    function GetX: TCryptoLibUInt64Array;
+    property X: TCryptoLibUInt64Array read GetX;
+  end;
+
+implementation
+
+end.

+ 55 - 0
CryptoLib/src/Interfaces/ClpISecT283K1Curve.pas

@@ -0,0 +1,55 @@
+{ *********************************************************************************** }
+{ *                              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 ClpISecT283K1Curve;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIECInterface;
+
+type
+  ISecT283K1LookupTable = Interface(IECLookupTable)
+    ['{3AF41553-A108-46D6-9CCC-AB1814A0A247}']
+  end;
+
+type
+  ISecT283K1Curve = Interface(IAbstractF2mCurve)
+    ['{1D88AF22-721F-4E89-82A2-1C1CFFB7830C}']
+
+    function GetM: Int32;
+    property M: Int32 read GetM;
+
+    function GetK1: Int32;
+    property K1: Int32 read GetK1;
+
+    function GetK2: Int32;
+    property K2: Int32 read GetK2;
+
+    function GetK3: Int32;
+    property K3: Int32 read GetK3;
+
+    function GetIsTrinomial: Boolean;
+    property IsTrinomial: Boolean read GetIsTrinomial;
+
+  end;
+
+implementation
+
+end.

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

@@ -0,0 +1,35 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpISecT283K1Point;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIECInterface;
+
+type
+  ISecT283K1Point = Interface(IAbstractF2mPoint)
+    ['{516DA5D2-430B-42FC-A3FB-691E77B76D8B}']
+
+  end;
+
+implementation
+
+end.

+ 181 - 112
CryptoLib/src/Math/ClpBigInteger.pas

@@ -103,6 +103,7 @@ type
 
   class var
 
+    FIsBooted: Boolean;
     FZero, FOne, FTwo, FThree, FFour, FTen: TBigInteger;
     // Each list has a product < 2^31
     FprimeLists: TCryptoLibMatrixInt32Array;
@@ -434,6 +435,8 @@ type
 
     class function Arbitrary(sizeInBits: Int32): TBigInteger; static;
 
+    class function Jacobi(const a, b: TBigInteger): Int32; static;
+
     class procedure Boot(); static;
 
   end;
@@ -797,129 +800,142 @@ var
   product, j: Int32;
 begin
 
-  System.SetLength(FZeroEncoding, 0);
-  System.SetLength(FZeroMagnitude, 0);
-  FprimeLists := TCryptoLibMatrixInt32Array.Create
-    (TCryptoLibInt32Array.Create(3, 5, 7, 11, 13, 17, 19, 23),
-    TCryptoLibInt32Array.Create(29, 31, 37, 41, 43),
-    TCryptoLibInt32Array.Create(47, 53, 59, 61, 67),
-    TCryptoLibInt32Array.Create(71, 73, 79, 83), TCryptoLibInt32Array.Create(89,
-    97, 101, 103),
-
-    TCryptoLibInt32Array.Create(107, 109, 113, 127),
-    TCryptoLibInt32Array.Create(131, 137, 139, 149),
-    TCryptoLibInt32Array.Create(151, 157, 163, 167),
-    TCryptoLibInt32Array.Create(173, 179, 181, 191),
-    TCryptoLibInt32Array.Create(193, 197, 199, 211),
-
-    TCryptoLibInt32Array.Create(223, 227, 229), TCryptoLibInt32Array.Create(233,
-    239, 241), TCryptoLibInt32Array.Create(251, 257, 263),
-    TCryptoLibInt32Array.Create(269, 271, 277), TCryptoLibInt32Array.Create(281,
-    283, 293),
-
-    TCryptoLibInt32Array.Create(307, 311, 313), TCryptoLibInt32Array.Create(317,
-    331, 337), TCryptoLibInt32Array.Create(347, 349, 353),
-    TCryptoLibInt32Array.Create(359, 367, 373), TCryptoLibInt32Array.Create(379,
-    383, 389),
-
-    TCryptoLibInt32Array.Create(397, 401, 409), TCryptoLibInt32Array.Create(419,
-    421, 431), TCryptoLibInt32Array.Create(433, 439, 443),
-    TCryptoLibInt32Array.Create(449, 457, 461), TCryptoLibInt32Array.Create(463,
-    467, 479),
-
-    TCryptoLibInt32Array.Create(487, 491, 499), TCryptoLibInt32Array.Create(503,
-    509, 521), TCryptoLibInt32Array.Create(523, 541, 547),
-    TCryptoLibInt32Array.Create(557, 563, 569), TCryptoLibInt32Array.Create(571,
-    577, 587),
-
-    TCryptoLibInt32Array.Create(593, 599, 601), TCryptoLibInt32Array.Create(607,
-    613, 617), TCryptoLibInt32Array.Create(619, 631, 641),
-    TCryptoLibInt32Array.Create(643, 647, 653), TCryptoLibInt32Array.Create(659,
-    661, 673),
-
-    TCryptoLibInt32Array.Create(677, 683, 691), TCryptoLibInt32Array.Create(701,
-    709, 719), TCryptoLibInt32Array.Create(727, 733, 739),
-    TCryptoLibInt32Array.Create(743, 751, 757), TCryptoLibInt32Array.Create(761,
-    769, 773),
-
-    TCryptoLibInt32Array.Create(787, 797, 809), TCryptoLibInt32Array.Create(811,
-    821, 823), TCryptoLibInt32Array.Create(827, 829, 839),
-    TCryptoLibInt32Array.Create(853, 857, 859), TCryptoLibInt32Array.Create(863,
-    877, 881),
-
-    TCryptoLibInt32Array.Create(883, 887, 907), TCryptoLibInt32Array.Create(911,
-    919, 929), TCryptoLibInt32Array.Create(937, 941, 947),
-    TCryptoLibInt32Array.Create(953, 967, 971), TCryptoLibInt32Array.Create(977,
-    983, 991),
-
-    TCryptoLibInt32Array.Create(997, 1009, 1013),
-    TCryptoLibInt32Array.Create(1019, 1021, 1031),
-    TCryptoLibInt32Array.Create(1033, 1039, 1049),
-    TCryptoLibInt32Array.Create(1051, 1061, 1063),
-    TCryptoLibInt32Array.Create(1069, 1087, 1091),
-
-    TCryptoLibInt32Array.Create(1093, 1097, 1103),
-    TCryptoLibInt32Array.Create(1109, 1117, 1123),
-    TCryptoLibInt32Array.Create(1129, 1151, 1153),
-    TCryptoLibInt32Array.Create(1163, 1171, 1181),
-    TCryptoLibInt32Array.Create(1187, 1193, 1201),
-
-    TCryptoLibInt32Array.Create(1213, 1217, 1223),
-    TCryptoLibInt32Array.Create(1229, 1231, 1237),
-    TCryptoLibInt32Array.Create(1249, 1259, 1277),
-    TCryptoLibInt32Array.Create(1279, 1283, 1289));
-
-  TSecureRandom.Boot;
-
-  FRandomSource := TSecureRandom.Create();
-
-  FZero := TBigInteger.Create(0, FZeroMagnitude, false);
-  FZero.FnBits := 0;
-  FZero.FnBitLength := 0;
-
-  System.SetLength(FSMALL_CONSTANTS, 17);
-
-  FSMALL_CONSTANTS[0] := FZero;
-
-  i := 1;
-
-  while i < UInt32(System.length(FSMALL_CONSTANTS)) do
-  begin
-    FSMALL_CONSTANTS[i] := CreateUValueOf(i);
-    System.Inc(i);
-  end;
+  if not FIsBooted then
+  begin
+    System.SetLength(FZeroEncoding, 0);
+    System.SetLength(FZeroMagnitude, 0);
+    FprimeLists := TCryptoLibMatrixInt32Array.Create
+      (TCryptoLibInt32Array.Create(3, 5, 7, 11, 13, 17, 19, 23),
+      TCryptoLibInt32Array.Create(29, 31, 37, 41, 43),
+      TCryptoLibInt32Array.Create(47, 53, 59, 61, 67),
+      TCryptoLibInt32Array.Create(71, 73, 79, 83),
+      TCryptoLibInt32Array.Create(89, 97, 101, 103),
+
+      TCryptoLibInt32Array.Create(107, 109, 113, 127),
+      TCryptoLibInt32Array.Create(131, 137, 139, 149),
+      TCryptoLibInt32Array.Create(151, 157, 163, 167),
+      TCryptoLibInt32Array.Create(173, 179, 181, 191),
+      TCryptoLibInt32Array.Create(193, 197, 199, 211),
+
+      TCryptoLibInt32Array.Create(223, 227, 229),
+      TCryptoLibInt32Array.Create(233, 239, 241),
+      TCryptoLibInt32Array.Create(251, 257, 263),
+      TCryptoLibInt32Array.Create(269, 271, 277),
+      TCryptoLibInt32Array.Create(281, 283, 293),
+
+      TCryptoLibInt32Array.Create(307, 311, 313),
+      TCryptoLibInt32Array.Create(317, 331, 337),
+      TCryptoLibInt32Array.Create(347, 349, 353),
+      TCryptoLibInt32Array.Create(359, 367, 373),
+      TCryptoLibInt32Array.Create(379, 383, 389),
+
+      TCryptoLibInt32Array.Create(397, 401, 409),
+      TCryptoLibInt32Array.Create(419, 421, 431),
+      TCryptoLibInt32Array.Create(433, 439, 443),
+      TCryptoLibInt32Array.Create(449, 457, 461),
+      TCryptoLibInt32Array.Create(463, 467, 479),
+
+      TCryptoLibInt32Array.Create(487, 491, 499),
+      TCryptoLibInt32Array.Create(503, 509, 521),
+      TCryptoLibInt32Array.Create(523, 541, 547),
+      TCryptoLibInt32Array.Create(557, 563, 569),
+      TCryptoLibInt32Array.Create(571, 577, 587),
+
+      TCryptoLibInt32Array.Create(593, 599, 601),
+      TCryptoLibInt32Array.Create(607, 613, 617),
+      TCryptoLibInt32Array.Create(619, 631, 641),
+      TCryptoLibInt32Array.Create(643, 647, 653),
+      TCryptoLibInt32Array.Create(659, 661, 673),
+
+      TCryptoLibInt32Array.Create(677, 683, 691),
+      TCryptoLibInt32Array.Create(701, 709, 719),
+      TCryptoLibInt32Array.Create(727, 733, 739),
+      TCryptoLibInt32Array.Create(743, 751, 757),
+      TCryptoLibInt32Array.Create(761, 769, 773),
+
+      TCryptoLibInt32Array.Create(787, 797, 809),
+      TCryptoLibInt32Array.Create(811, 821, 823),
+      TCryptoLibInt32Array.Create(827, 829, 839),
+      TCryptoLibInt32Array.Create(853, 857, 859),
+      TCryptoLibInt32Array.Create(863, 877, 881),
+
+      TCryptoLibInt32Array.Create(883, 887, 907),
+      TCryptoLibInt32Array.Create(911, 919, 929),
+      TCryptoLibInt32Array.Create(937, 941, 947),
+      TCryptoLibInt32Array.Create(953, 967, 971),
+      TCryptoLibInt32Array.Create(977, 983, 991),
+
+      TCryptoLibInt32Array.Create(997, 1009, 1013),
+      TCryptoLibInt32Array.Create(1019, 1021, 1031),
+      TCryptoLibInt32Array.Create(1033, 1039, 1049),
+      TCryptoLibInt32Array.Create(1051, 1061, 1063),
+      TCryptoLibInt32Array.Create(1069, 1087, 1091),
+
+      TCryptoLibInt32Array.Create(1093, 1097, 1103),
+      TCryptoLibInt32Array.Create(1109, 1117, 1123),
+      TCryptoLibInt32Array.Create(1129, 1151, 1153),
+      TCryptoLibInt32Array.Create(1163, 1171, 1181),
+      TCryptoLibInt32Array.Create(1187, 1193, 1201),
+
+      TCryptoLibInt32Array.Create(1213, 1217, 1223),
+      TCryptoLibInt32Array.Create(1229, 1231, 1237),
+      TCryptoLibInt32Array.Create(1249, 1259, 1277),
+      TCryptoLibInt32Array.Create(1279, 1283, 1289));
+
+    TSecureRandom.Boot;
+
+    FRandomSource := TSecureRandom.Create();
+
+    FZero := TBigInteger.Create(0, FZeroMagnitude, false);
+    FZero.FnBits := 0;
+    FZero.FnBitLength := 0;
+
+    System.SetLength(FSMALL_CONSTANTS, 17);
+
+    FSMALL_CONSTANTS[0] := FZero;
+
+    i := 1;
+
+    while i < UInt32(System.length(FSMALL_CONSTANTS)) do
+    begin
+      FSMALL_CONSTANTS[i] := CreateUValueOf(i);
+      System.Inc(i);
+    end;
 
-  FOne := FSMALL_CONSTANTS[1];
-  FTwo := FSMALL_CONSTANTS[2];
-  FThree := FSMALL_CONSTANTS[3];
-  FFour := FSMALL_CONSTANTS[4];
-  FTen := FSMALL_CONSTANTS[10];
+    FOne := FSMALL_CONSTANTS[1];
+    FTwo := FSMALL_CONSTANTS[2];
+    FThree := FSMALL_CONSTANTS[3];
+    FFour := FSMALL_CONSTANTS[4];
+    FTen := FSMALL_CONSTANTS[10];
 
-  Fradix2 := ValueOf(2);
-  Fradix2E := Fradix2.Pow(chunk2);
+    Fradix2 := ValueOf(2);
+    Fradix2E := Fradix2.Pow(chunk2);
 
-  Fradix8 := ValueOf(8);
-  Fradix8E := Fradix8.Pow(chunk8);
+    Fradix8 := ValueOf(8);
+    Fradix8E := Fradix8.Pow(chunk8);
 
-  Fradix10 := ValueOf(10);
+    Fradix10 := ValueOf(10);
 
-  Fradix10E := Fradix10.Pow(chunk10);
+    Fradix10E := Fradix10.Pow(chunk10);
 
-  Fradix16 := ValueOf(16);
-  Fradix16E := Fradix16.Pow(chunk16);
+    Fradix16 := ValueOf(16);
+    Fradix16E := Fradix16.Pow(chunk16);
 
-  System.SetLength(FprimeProducts, System.length(primeLists));
+    System.SetLength(FprimeProducts, System.length(primeLists));
 
-  for i := 0 to System.Pred(System.length(primeLists)) do
-  begin
-    primeList := primeLists[i];
-    product := primeList[0];
-    for j := 1 to System.Pred(System.length(primeList)) do
+    for i := 0 to System.Pred(System.length(primeLists)) do
     begin
-      product := product * primeList[j];
+      primeList := primeLists[i];
+      product := primeList[0];
+      for j := 1 to System.Pred(System.length(primeList)) do
+      begin
+        product := product * primeList[j];
+      end;
+
+      FprimeProducts[i] := product;
     end;
 
-    FprimeProducts[i] := product;
+    FIsBooted := True;
   end;
 
 end;
@@ -2165,6 +2181,59 @@ begin
   Result := n.CheckProbablePrime(certainty, RandomSource, randomlySelected);
 end;
 
+class function TBigInteger.Jacobi(const a, b: TBigInteger): Int32;
+var
+  totalS, e, bLsw, a1Lsw: Int32;
+  a1, La, Lb: TBigInteger;
+begin
+  La := a;
+  Lb := b;
+{$IFDEF DEBUG}
+  System.Assert(La.SignValue >= 0);
+  System.Assert(Lb.SignValue > 0);
+  System.Assert(Lb.TestBit(0));
+  System.Assert(La.CompareTo(Lb) < 0);
+{$ENDIF DEBUG}
+  totalS := 1;
+  while True do
+  begin
+    if (La.SignValue = 0) then
+    begin
+      Result := 0;
+      Exit;
+    end;
+
+    if (La.Equals(One)) then
+    begin
+      break;
+    end;
+
+    e := La.GetLowestSetBit();
+
+    bLsw := Lb.Fmagnitude[System.length(Lb.Fmagnitude) - 1];
+    if (((e and 1) <> 0) and (((bLsw and 7) = 3) or ((bLsw and 7) = 5))) then
+    begin
+      totalS := -totalS;
+    end;
+
+    if (La.BitLength = e + 1) then
+    begin
+      break;
+    end;
+    a1 := La.ShiftRight(e);
+
+    a1Lsw := a1.Fmagnitude[System.length(a1.Fmagnitude) - 1];
+    if (((bLsw and 3) = 3) and ((a1Lsw and 3) = 3)) then
+    begin
+      totalS := -totalS;
+    end;
+
+    La := Lb.Remainder(a1);
+    Lb := a1;
+  end;
+  Result := totalS;
+end;
+
 function TBigInteger.IsProbablePrime(certainty: Int32): Boolean;
 begin
   Result := IsProbablePrime(certainty, false);

+ 12 - 12
CryptoLib/src/Math/EC/ClpECAlgorithms.pas

@@ -281,10 +281,10 @@ begin
   result := ImplShamirsTrickWNaf(preCompP, preCompNegP, wnafP, preCompQ,
     preCompNegQ, wnafQ);
 
-  infoP.PreComp := Nil;
-  infoP.PreCompNeg := Nil;
-  infoQ.PreComp := Nil;
-  infoQ.PreCompNeg := Nil;
+  infoP.PreComp := Nil; // Review
+  infoP.PreCompNeg := Nil; // Review
+  infoQ.PreComp := Nil; // Review
+  infoQ.PreCompNeg := Nil; // Review
 
 end;
 
@@ -351,10 +351,10 @@ begin
 
   result := ImplShamirsTrickWNaf(preCompP, preCompNegP, wnafP, preCompQ,
     preCompNegQ, wnafQ);
-  infoP.PreComp := Nil;
-  infoP.PreCompNeg := Nil;
-  infoQ.PreComp := Nil;
-  infoQ.PreCompNeg := Nil;
+  infoP.PreComp := Nil; // Review
+  infoP.PreCompNeg := Nil; // Review
+  infoQ.PreComp := Nil; // Review
+  infoQ.PreCompNeg := Nil; // Review
 end;
 
 class function TECAlgorithms.ImplShamirsTrickWNaf(preCompP,
@@ -499,8 +499,8 @@ begin
 
   for i := System.Low(infos) to System.High(infos) do
   begin
-    infos[i].PreComp := Nil;
-    infos[i].PreCompNeg := Nil;
+    infos[i].PreComp := Nil; // Review
+    infos[i].PreCompNeg := Nil; // Review
   end;
 
 end;
@@ -537,8 +537,8 @@ begin
 
   for i := System.Low(infos) to System.High(infos) do
   begin
-    infos[i].PreComp := Nil;
-    infos[i].PreCompNeg := Nil;
+    infos[i].PreComp := Nil; // Review
+    infos[i].PreCompNeg := Nil; // Review
   end;
 
 end;

+ 27 - 25
CryptoLib/src/Math/EC/ClpECCurve.pas

@@ -112,6 +112,9 @@ type
 
     constructor Create(const field: IFiniteField);
 
+    function GetFieldSize: Int32; virtual; abstract;
+    function GetInfinity: IECPoint; virtual; abstract;
+
     function CloneCurve(): IECCurve; virtual; abstract;
 
     function CreateRawPoint(const x, y: IECFieldElement;
@@ -172,11 +175,10 @@ type
 
     end;
 
-  function GetFieldSize: Int32; virtual; abstract;
-  function GetInfinity: IECPoint; virtual; abstract;
-
-  function FromBigInteger(x: TBigInteger): IECFieldElement; virtual; abstract;
-  function IsValidFieldElement(x: TBigInteger): Boolean; virtual; abstract;
+  function FromBigInteger(const x: TBigInteger): IECFieldElement;
+    virtual; abstract;
+  function IsValidFieldElement(const x: TBigInteger): Boolean; virtual;
+    abstract;
 
   function Configure(): IConfig; virtual;
   function ValidatePoint(const x, y: TBigInteger): IECPoint; overload; virtual;
@@ -339,7 +341,7 @@ type
 
   public
     destructor Destroy; override;
-    function IsValidFieldElement(x: TBigInteger): Boolean; override;
+    function IsValidFieldElement(const x: TBigInteger): Boolean; override;
 
   end;
 
@@ -368,8 +370,6 @@ type
   const
     FP_DEFAULT_COORDS = Int32(TECCurve.COORD_JACOBIAN_MODIFIED);
 
-    function GetQ: TBigInteger; virtual;
-
   strict protected
   var
     Fm_q, Fm_r: TBigInteger;
@@ -381,6 +381,10 @@ type
     constructor Create(const q, r: TBigInteger; const A, B: IECFieldElement;
       const Order, Cofactor: TBigInteger); overload;
 
+    function GetQ: TBigInteger; virtual;
+    function GetInfinity: IECPoint; override;
+    function GetFieldSize: Int32; override;
+
     function CloneCurve(): IECCurve; override;
     function CreateRawPoint(const x, y: IECFieldElement;
       withCompression: Boolean): IECPoint; overload; override;
@@ -396,10 +400,7 @@ type
 
     destructor Destroy; override;
 
-    function GetInfinity: IECPoint; override;
-    function GetFieldSize: Int32; override;
-
-    function FromBigInteger(x: TBigInteger): IECFieldElement; override;
+    function FromBigInteger(const x: TBigInteger): IECFieldElement; override;
     function ImportPoint(const p: IECPoint): IECPoint; override;
 
     function SupportsCoordinateSystem(coord: Int32): Boolean; override;
@@ -421,6 +422,11 @@ type
     /// </summary>
     Fsi: TCryptoLibGenericArray<TBigInteger>;
 
+    class function BuildField(m, k1, k2, k3: Int32): IFiniteField; static;
+
+  strict protected
+    constructor Create(m, k1, k2, k3: Int32);
+
     /// <summary>
     /// Returns true if this is a Koblitz curve (ABC curve).
     /// </summary>
@@ -429,10 +435,6 @@ type
     /// </returns>
     function GetIsKoblitz: Boolean; virtual;
 
-    class function BuildField(m, k1, k2, k3: Int32): IFiniteField; static;
-
-  strict protected
-    constructor Create(m, k1, k2, k3: Int32);
     function DecompressPoint(yTilde: Int32; X1: TBigInteger): IECPoint;
       override;
 
@@ -452,7 +454,7 @@ type
 
     destructor Destroy; override;
 
-    function IsValidFieldElement(x: TBigInteger): Boolean; override;
+    function IsValidFieldElement(const x: TBigInteger): Boolean; override;
 
     function CreatePoint(const x, y: TBigInteger; withCompression: Boolean)
       : IECPoint; override;
@@ -529,6 +531,9 @@ type
     function GetK3: Int32; inline;
 
   strict protected
+    function GetFieldSize: Int32; override;
+    function GetInfinity: IECPoint; override;
+
     function CloneCurve(): IECCurve; override;
     function CreateDefaultMultiplier(): IECMultiplier; override;
 
@@ -627,11 +632,8 @@ type
 
     destructor Destroy; override;
 
-    function GetFieldSize: Int32; override;
-    function GetInfinity: IECPoint; override;
-
     function SupportsCoordinateSystem(coord: Int32): Boolean; override;
-    function FromBigInteger(x: TBigInteger): IECFieldElement; override;
+    function FromBigInteger(const x: TBigInteger): IECFieldElement; override;
 
     /// <summary>
     /// Return true if curve uses a Trinomial basis.
@@ -1253,7 +1255,7 @@ begin
   inherited Destroy;
 end;
 
-function TAbstractFpCurve.IsValidFieldElement(x: TBigInteger): Boolean;
+function TAbstractFpCurve.IsValidFieldElement(const x: TBigInteger): Boolean;
 begin
   Result := (x.IsInitialized) and (x.SignValue >= 0) and
     (x.CompareTo(field.Characteristic) < 0);
@@ -1324,7 +1326,7 @@ begin
   Result := TFpPoint.Create(Self as IECCurve, x, y, withCompression);
 end;
 
-function TFpCurve.FromBigInteger(x: TBigInteger): IECFieldElement;
+function TFpCurve.FromBigInteger(const x: TBigInteger): IECFieldElement;
 begin
   Result := TFpFieldElement.Create(Fm_q, Fm_r, x);
 end;
@@ -1528,7 +1530,7 @@ begin
   Result := TLongArray.Create(x).ModInverse(m, ks).ToBigInteger();
 end;
 
-function TAbstractF2mCurve.IsValidFieldElement(x: TBigInteger): Boolean;
+function TAbstractF2mCurve.IsValidFieldElement(const x: TBigInteger): Boolean;
 begin
   Result := (x.IsInitialized) and (x.SignValue >= 0) and
     (x.BitLength <= FieldSize);
@@ -1745,7 +1747,7 @@ begin
   inherited Destroy;
 end;
 
-function TF2mCurve.FromBigInteger(x: TBigInteger): IECFieldElement;
+function TF2mCurve.FromBigInteger(const x: TBigInteger): IECFieldElement;
 begin
   Result := TF2mFieldElement.Create(Fm, Fk1, Fk2, Fk3, x);
 end;

+ 42 - 29
CryptoLib/src/Math/EC/ClpECFieldElement.pas

@@ -51,16 +51,20 @@ resourcestring
 type
   TECFieldElement = class abstract(TInterfacedObject, IECFieldElement)
 
-  public
-
-    constructor Create();
-    destructor Destroy; override;
+  strict protected
 
     function GetBitLength: Int32; virtual;
     function GetIsOne: Boolean; virtual;
     function GetIsZero: Boolean; virtual;
+
     function GetFieldName: String; virtual; abstract;
     function GetFieldSize: Int32; virtual; abstract;
+
+  public
+
+    constructor Create();
+    destructor Destroy; override;
+
     function ToBigInteger(): TBigInteger; virtual; abstract;
     function Add(const b: IECFieldElement): IECFieldElement; virtual; abstract;
     function AddOne(): IECFieldElement; virtual; abstract;
@@ -91,7 +95,8 @@ type
 
     function TestBitZero(): Boolean; virtual;
 
-    function Equals(const other: IECFieldElement): Boolean; reintroduce;
+    function Equals(const other: IECFieldElement): Boolean;
+      reintroduce; virtual;
 
     function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
 {$ENDIF DELPHI}override;
@@ -136,14 +141,6 @@ type
     function ModReduce(x: TBigInteger): TBigInteger; virtual;
     function ModSubtract(const x1, x2: TBigInteger): TBigInteger; virtual;
 
-  public
-    constructor Create(const Q, x: TBigInteger); overload;
-      deprecated 'Use ECCurve.FromBigInteger to construct field elements';
-
-    constructor Create(const Q, r, x: TBigInteger); overload;
-
-    destructor Destroy; override;
-
     /// <summary>
     /// return the field name for this field.
     /// </summary>
@@ -153,6 +150,14 @@ type
     function GetFieldName: String; override;
     function GetFieldSize: Int32; override;
 
+  public
+    constructor Create(const Q, x: TBigInteger); overload;
+      deprecated 'Use ECCurve.FromBigInteger to construct field elements';
+
+    constructor Create(const Q, r, x: TBigInteger); overload;
+
+    destructor Destroy; override;
+
     function ToBigInteger(): TBigInteger; override;
 
     function Add(const b: IECFieldElement): IECFieldElement; override;
@@ -200,12 +205,12 @@ type
   end;
 
 type
-  TAbstract2mFieldElement = class abstract(TECFieldElement,
+  TAbstractF2mFieldElement = class abstract(TECFieldElement,
     IAbstractF2mFieldElement)
 
   public
-    function Trace(): Int32;
-    function HalfTrace(): IECFieldElement;
+    function Trace(): Int32; virtual;
+    function HalfTrace(): IECFieldElement; virtual;
 
   end;
 
@@ -217,7 +222,7 @@ type
   // * basis representations are supported. Gaussian normal basis (GNB)
   // * representation is not supported.
   // */
-  TF2mFieldElement = class(TAbstract2mFieldElement, IF2mFieldElement)
+  TF2mFieldElement = class(TAbstractF2mFieldElement, IF2mFieldElement)
 
   strict private
 
@@ -240,6 +245,15 @@ type
     function GetK2: Int32; inline;
     function GetK3: Int32; inline;
 
+  strict protected
+
+    function GetBitLength: Int32; override;
+    function GetIsOne: Boolean; override;
+    function GetIsZero: Boolean; override;
+
+    function GetFieldName: String; override;
+    function GetFieldSize: Int32; override;
+
   public
 
     const
@@ -296,13 +310,6 @@ type
 
     destructor Destroy; override;
 
-    function GetBitLength: Int32; override;
-    function GetIsOne: Boolean; override;
-    function GetIsZero: Boolean; override;
-
-    function GetFieldName: String; override;
-    function GetFieldSize: Int32; override;
-
     function TestBitZero(): Boolean; override;
     function ToBigInteger(): TBigInteger; override;
 
@@ -1017,7 +1024,8 @@ begin
     begin
       Qh := Ql;
       Uh := ModReduce(Uh.Multiply(Vl).Subtract(Ql));
-      Vh := ModReduce(Vl.Multiply(Vl).Subtract(Ql.ShiftLeft(1)));
+      Vh := ModReduce(Vh.Multiply(Vl).Subtract(P.Multiply(Ql)));
+      Vl := ModReduce(Vl.Multiply(Vl).Subtract(Ql.ShiftLeft(1)));
     end;
     System.Dec(j);
   end;
@@ -1233,6 +1241,7 @@ var
   u, v, K, e, t1, t2, t3, t4, y, legendreExponent, x, fourX, qMinusOne,
     P: TBigInteger;
   tempRes: TCryptoLibGenericArray<TBigInteger>;
+  CompareRes, ModReduceRes: Boolean;
 begin
   if (IsZero or IsOne) then
   begin
@@ -1294,8 +1303,12 @@ begin
 
     repeat
       P := TBigInteger.Arbitrary(Fq.BitLength);
-    until ((not P.CompareTo(Q) >= 0) or (ModReduce(P.Multiply(P).Subtract(fourX)
-      ).ModPow(legendreExponent, Q).Equals(qMinusOne)));
+
+      CompareRes := P.CompareTo(Q) >= 0;
+      ModReduceRes := (not ModReduce(P.Multiply(P).Subtract(fourX))
+        .ModPow(legendreExponent, Q).Equals(qMinusOne));
+
+    until ((not CompareRes) and (not ModReduceRes));
 
     tempRes := LucasSequence(P, x, K);
     u := tempRes[0];
@@ -1360,7 +1373,7 @@ end;
 
 { TAbstract2mFieldElement }
 
-function TAbstract2mFieldElement.HalfTrace: IECFieldElement;
+function TAbstractF2mFieldElement.HalfTrace: IECFieldElement;
 var
   m, i: Int32;
   fe, ht: IECFieldElement;
@@ -1384,7 +1397,7 @@ begin
   result := ht;
 end;
 
-function TAbstract2mFieldElement.Trace: Int32;
+function TAbstractF2mFieldElement.Trace: Int32;
 var
   m, i: Int32;
   fe, tr: IECFieldElement;

+ 259 - 0
CryptoLib/src/Math/EC/Custom/Sec/ClpSecP256K1Curve.pas

@@ -0,0 +1,259 @@
+{ *********************************************************************************** }
+{ *                              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 ClpSecP256K1Curve;
+
+{$I ..\..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpHex,
+  ClpBits,
+  ClpNat256,
+  ClpECCurve,
+  ClpIECInterface,
+  ClpISecP256K1FieldElement,
+  ClpSecP256K1Point,
+  ClpISecP256K1Curve,
+  ClpISecP256K1Point,
+  ClpIECFieldElement,
+  ClpBigInteger,
+  ClpCryptoLibTypes;
+
+type
+  TSecP256K1Curve = class sealed(TAbstractFpCurve, ISecP256K1Curve)
+
+  strict private
+
+  type
+    TSecP256K1LookupTable = class sealed(TInterfacedObject,
+      ISecP256K1LookupTable, IECLookupTable)
+
+    strict private
+    var
+      Fm_outer: ISecP256K1Curve;
+      Fm_table: TCryptoLibUInt32Array;
+      Fm_size: Int32;
+
+      function GetSize: Int32; virtual;
+
+    public
+
+      constructor Create(const outer: ISecP256K1Curve;
+        table: TCryptoLibUInt32Array; size: Int32);
+
+      function Lookup(index: Int32): IECPoint; virtual;
+
+      property size: Int32 read GetSize;
+
+    end;
+
+  const
+    SECP256K1_DEFAULT_COORDS = Int32(TECCurve.COORD_JACOBIAN);
+    SECP256K1_FE_INTS = Int32(8);
+
+    class var
+
+      Fq: TBigInteger;
+
+    class function GetSecP256K1Curve_Q: TBigInteger; static; inline;
+    class constructor SecP256K1Curve();
+
+  strict protected
+  var
+    Fm_infinity: ISecP256K1Point;
+
+    function GetQ: TBigInteger; virtual;
+    function GetFieldSize: Int32; override;
+    function GetInfinity: IECPoint; override;
+
+    function CloneCurve(): IECCurve; override;
+
+    function CreateRawPoint(const x, y: IECFieldElement;
+      withCompression: Boolean): IECPoint; overload; override;
+
+    function CreateRawPoint(const x, y: IECFieldElement;
+      zs: TCryptoLibGenericArray<IECFieldElement>; withCompression: Boolean)
+      : IECPoint; overload; override;
+
+  public
+    constructor Create();
+    function FromBigInteger(const x: TBigInteger): IECFieldElement; override;
+
+    function SupportsCoordinateSystem(coord: Int32): Boolean; override;
+
+    function CreateCacheSafeLookupTable
+      (points: TCryptoLibGenericArray<IECPoint>; off, len: Int32)
+      : IECLookupTable; override;
+
+    property Q: TBigInteger read GetQ;
+    property Infinity: IECPoint read GetInfinity;
+    property FieldSize: Int32 read GetFieldSize;
+
+    class property SecP256K1Curve_Q: TBigInteger read GetSecP256K1Curve_Q;
+
+  end;
+
+implementation
+
+uses
+  // included here to avoid circular dependency :)
+  ClpSecP256K1FieldElement;
+
+{ TSecP256K1Curve }
+
+class function TSecP256K1Curve.GetSecP256K1Curve_Q: TBigInteger;
+begin
+  result := Fq;
+end;
+
+class constructor TSecP256K1Curve.SecP256K1Curve;
+begin
+  Fq := TBigInteger.Create(1,
+    THex.Decode
+    ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F'));
+end;
+
+constructor TSecP256K1Curve.Create;
+begin
+  Inherited Create(Fq);
+  Fm_infinity := TSecP256K1Point.Create(Self as IECCurve, Nil, Nil);
+  Fm_a := FromBigInteger(TBigInteger.Zero);
+  Fm_b := FromBigInteger(TBigInteger.ValueOf(7));
+  Fm_order := TBigInteger.Create(1,
+    THex.Decode
+    ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141'));
+  Fm_cofactor := TBigInteger.One;
+  Fm_coord := SECP256K1_DEFAULT_COORDS;
+end;
+
+function TSecP256K1Curve.CloneCurve: IECCurve;
+begin
+  result := TSecP256K1Curve.Create();
+end;
+
+function TSecP256K1Curve.CreateCacheSafeLookupTable
+  (points: TCryptoLibGenericArray<IECPoint>; off, len: Int32): IECLookupTable;
+var
+  table: TCryptoLibUInt32Array;
+  pos, i: Int32;
+  p: IECPoint;
+begin
+  System.SetLength(table, len * SECP256K1_FE_INTS * 2);
+
+  pos := 0;
+  for i := 0 to System.Pred(len) do
+  begin
+    p := points[off + i];
+    TNat256.Copy((p.RawXCoord as ISecP256K1FieldElement).x, 0, table, pos);
+    pos := pos + SECP256K1_FE_INTS;
+    TNat256.Copy((p.RawYCoord as ISecP256K1FieldElement).x, 0, table, pos);
+    pos := pos + SECP256K1_FE_INTS;
+  end;
+
+  result := TSecP256K1LookupTable.Create(Self as ISecP256K1Curve, table, len);
+end;
+
+function TSecP256K1Curve.CreateRawPoint(const x, y: IECFieldElement;
+  withCompression: Boolean): IECPoint;
+begin
+  result := TSecP256K1Point.Create(Self as IECCurve, x, y, withCompression);
+end;
+
+function TSecP256K1Curve.CreateRawPoint(const x, y: IECFieldElement;
+  zs: TCryptoLibGenericArray<IECFieldElement>; withCompression: Boolean)
+  : IECPoint;
+begin
+  result := TSecP256K1Point.Create(Self as IECCurve, x, y, zs, withCompression);
+end;
+
+function TSecP256K1Curve.FromBigInteger(const x: TBigInteger): IECFieldElement;
+begin
+  result := TSecP256K1FieldElement.Create(x);
+end;
+
+function TSecP256K1Curve.GetFieldSize: Int32;
+begin
+  result := Fq.BitLength;
+end;
+
+function TSecP256K1Curve.GetInfinity: IECPoint;
+begin
+  result := Fm_infinity;
+end;
+
+function TSecP256K1Curve.GetQ: TBigInteger;
+begin
+  result := Fq;
+end;
+
+function TSecP256K1Curve.SupportsCoordinateSystem(coord: Int32): Boolean;
+begin
+  case coord of
+    COORD_JACOBIAN:
+      result := True
+  else
+    result := False;
+  end;
+end;
+
+{ TSecP256K1Curve.TSecP256K1LookupTable }
+
+constructor TSecP256K1Curve.TSecP256K1LookupTable.Create
+  (const outer: ISecP256K1Curve; table: TCryptoLibUInt32Array; size: Int32);
+begin
+  Inherited Create();
+  Fm_outer := outer;
+  Fm_table := table;
+  Fm_size := size;
+end;
+
+function TSecP256K1Curve.TSecP256K1LookupTable.GetSize: Int32;
+begin
+  result := Fm_size;
+end;
+
+function TSecP256K1Curve.TSecP256K1LookupTable.Lookup(index: Int32): IECPoint;
+var
+  x, y: TCryptoLibUInt32Array;
+  pos, i, J: Int32;
+  MASK: UInt32;
+begin
+  x := TNat256.Create();
+  y := TNat256.Create();
+  pos := 0;
+
+  for i := 0 to System.Pred(Fm_size) do
+  begin
+    MASK := UInt32(TBits.Asr32((i xor index) - 1, 31));
+
+    for J := 0 to System.Pred(SECP256K1_FE_INTS) do
+    begin
+      x[J] := x[J] xor (Fm_table[pos + J] and MASK);
+      y[J] := y[J] xor (Fm_table[pos + SECP256K1_FE_INTS + J] and MASK);
+    end;
+
+    pos := pos + (SECP256K1_FE_INTS * 2);
+  end;
+
+  result := Fm_outer.CreateRawPoint(TSecP256K1FieldElement.Create(x)
+    as ISecP256K1FieldElement, TSecP256K1FieldElement.Create(y)
+    as ISecP256K1FieldElement, False);
+end;
+
+end.

+ 285 - 0
CryptoLib/src/Math/EC/Custom/Sec/ClpSecP256K1Field.pas

@@ -0,0 +1,285 @@
+{ *********************************************************************************** }
+{ *                              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 ClpSecP256K1Field;
+
+{$I ..\..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpNat,
+  ClpNat256,
+  ClpBigInteger,
+  ClpCryptoLibTypes;
+
+type
+  // 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
+  TSecP256K1Field = class sealed(TObject)
+
+  strict private
+  const
+    P7 = UInt32($FFFFFFFF);
+    PExt15 = UInt32($FFFFFFFF);
+    PInv33 = UInt32($3D1);
+
+    class var
+
+      FP, FPExt, FPExtInv: TCryptoLibUInt32Array;
+
+    class function GetP: TCryptoLibUInt32Array; static; inline;
+
+    class constructor SecP256K1Field();
+
+  public
+    class procedure Add(x, y, z: TCryptoLibUInt32Array); static; inline;
+    class procedure AddExt(xx, yy, zz: TCryptoLibUInt32Array); static; inline;
+    class procedure AddOne(x, z: TCryptoLibUInt32Array); static; inline;
+    class function FromBigInteger(const x: TBigInteger): TCryptoLibUInt32Array;
+      static; inline;
+    class procedure Half(x, z: TCryptoLibUInt32Array); static; inline;
+    class procedure Multiply(x, y, z: TCryptoLibUInt32Array); static; inline;
+    class procedure MultiplyAddToExt(x, y, zz: TCryptoLibUInt32Array);
+      static; inline;
+    class procedure Negate(x, z: TCryptoLibUInt32Array); static; inline;
+    class procedure Reduce(xx, z: TCryptoLibUInt32Array); static; inline;
+    class procedure Reduce32(x: UInt32; z: TCryptoLibUInt32Array);
+      static; inline;
+    class procedure Square(x, z: TCryptoLibUInt32Array); static; inline;
+    class procedure SquareN(x: TCryptoLibUInt32Array; n: Int32;
+      z: TCryptoLibUInt32Array); static; inline;
+    class procedure Subtract(x, y, z: TCryptoLibUInt32Array); static; inline;
+    class procedure SubtractExt(xx, yy, zz: TCryptoLibUInt32Array);
+      static; inline;
+    class procedure Twice(x, z: TCryptoLibUInt32Array); static; inline;
+
+    class property P: TCryptoLibUInt32Array read GetP;
+  end;
+
+implementation
+
+{ TSecP256K1Field }
+
+class constructor TSecP256K1Field.SecP256K1Field;
+begin
+  FP := TCryptoLibUInt32Array.Create($FFFFFC2F, $FFFFFFFE, $FFFFFFFF, $FFFFFFFF,
+    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF);
+  FPExt := TCryptoLibUInt32Array.Create($000E90A1, $000007A2, $00000001,
+    $00000000, $00000000, $00000000, $00000000, $00000000, $FFFFF85E, $FFFFFFFD,
+    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF);
+  FPExtInv := TCryptoLibUInt32Array.Create($FFF16F5F, $FFFFF85D, $FFFFFFFE,
+    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $000007A1,
+    $00000002);
+end;
+
+class function TSecP256K1Field.GetP: TCryptoLibUInt32Array;
+begin
+  result := FP;
+end;
+
+class procedure TSecP256K1Field.Add(x, y, z: TCryptoLibUInt32Array);
+var
+  c: UInt32;
+begin
+  c := TNat256.Add(x, y, z);
+  if ((c <> 0) or ((z[7] = P7) and (TNat256.Gte(z, FP)))) then
+  begin
+    TNat.Add33To(8, PInv33, z);
+  end;
+end;
+
+class procedure TSecP256K1Field.AddExt(xx, yy, zz: TCryptoLibUInt32Array);
+var
+  c: UInt32;
+begin
+  c := TNat.Add(16, xx, yy, zz);
+  if ((c <> 0) or ((zz[15] = PExt15) and (TNat.Gte(16, zz, FPExt)))) then
+  begin
+    if (TNat.AddTo(System.Length(FPExtInv), FPExtInv, zz) <> 0) then
+    begin
+      TNat.IncAt(16, zz, System.Length(FPExtInv));
+    end;
+  end;
+end;
+
+class procedure TSecP256K1Field.AddOne(x, z: TCryptoLibUInt32Array);
+var
+  c: UInt32;
+begin
+  c := TNat.Inc(8, x, z);
+  if ((c <> 0) or ((z[7] = P7) and (TNat256.Gte(z, FP)))) then
+  begin
+    TNat.Add33To(8, PInv33, z);
+  end;
+end;
+
+class function TSecP256K1Field.FromBigInteger(const x: TBigInteger)
+  : TCryptoLibUInt32Array;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat256.FromBigInteger(x);
+  if ((z[7] = P7) and (TNat256.Gte(z, FP))) then
+  begin
+    TNat256.SubFrom(FP, z);
+  end;
+  result := z;
+end;
+
+class procedure TSecP256K1Field.Half(x, z: TCryptoLibUInt32Array);
+var
+  c: UInt32;
+begin
+  if ((x[0] and 1) = 0) then
+  begin
+    TNat.ShiftDownBit(8, x, 0, z);
+  end
+  else
+  begin
+    c := TNat256.Add(x, FP, z);
+    TNat.ShiftDownBit(8, z, c);
+  end;
+end;
+
+class procedure TSecP256K1Field.Reduce(xx, z: TCryptoLibUInt32Array);
+var
+  cc: UInt64;
+  c: UInt32;
+begin
+  cc := TNat256.Mul33Add(PInv33, xx, 8, xx, 0, z, 0);
+  c := TNat256.Mul33DWordAdd(PInv33, cc, z, 0);
+{$IFDEF DEBUG}
+  System.Assert((c = 0) or (c = 1));
+{$ENDIF DEBUG}
+  if ((c <> 0) or ((z[7] = P7) and (TNat256.Gte(z, FP)))) then
+  begin
+    TNat.Add33To(8, PInv33, z);
+  end;
+end;
+
+class procedure TSecP256K1Field.Multiply(x, y, z: TCryptoLibUInt32Array);
+var
+  tt: TCryptoLibUInt32Array;
+begin
+  tt := TNat256.CreateExt();
+  TNat256.Mul(x, y, tt);
+  Reduce(tt, z);
+end;
+
+class procedure TSecP256K1Field.MultiplyAddToExt(x, y,
+  zz: TCryptoLibUInt32Array);
+var
+  c: UInt32;
+begin
+  c := TNat256.MulAddTo(x, y, zz);
+  if ((c <> 0) or ((zz[15] = PExt15) and (TNat.Gte(16, zz, FPExt)))) then
+  begin
+    if (TNat.AddTo(System.Length(FPExtInv), FPExtInv, zz) <> 0) then
+    begin
+      TNat.IncAt(16, zz, System.Length(FPExtInv));
+    end;
+  end;
+end;
+
+class procedure TSecP256K1Field.Negate(x, z: TCryptoLibUInt32Array);
+begin
+  if (TNat256.IsZero(x)) then
+  begin
+    TNat256.Zero(z);
+  end
+  else
+  begin
+    TNat256.Sub(FP, x, z);
+  end;
+end;
+
+class procedure TSecP256K1Field.Reduce32(x: UInt32; z: TCryptoLibUInt32Array);
+begin
+  if (((x <> 0) and (TNat256.Mul33WordAdd(PInv33, x, z, 0) <> 0)) or
+    ((z[7] = P7) and (TNat256.Gte(z, FP)))) then
+  begin
+    TNat.Add33To(8, PInv33, z);
+  end;
+end;
+
+class procedure TSecP256K1Field.Square(x, z: TCryptoLibUInt32Array);
+var
+  tt: TCryptoLibUInt32Array;
+begin
+  tt := TNat256.CreateExt();
+  TNat256.Square(x, tt);
+  Reduce(tt, z);
+end;
+
+class procedure TSecP256K1Field.SquareN(x: TCryptoLibUInt32Array; n: Int32;
+  z: TCryptoLibUInt32Array);
+var
+  tt: TCryptoLibUInt32Array;
+begin
+{$IFDEF DEBUG}
+  System.Assert(n > 0);
+{$ENDIF DEBUG}
+  tt := TNat256.CreateExt();
+  TNat256.Square(x, tt);
+  Reduce(tt, z);
+
+  System.Dec(n);
+  while (n > 0) do
+  begin
+    TNat256.Square(z, tt);
+    Reduce(tt, z);
+    System.Dec(n);
+  end;
+end;
+
+class procedure TSecP256K1Field.Subtract(x, y, z: TCryptoLibUInt32Array);
+var
+  c: Int32;
+begin
+  c := TNat256.Sub(x, y, z);
+  if (c <> 0) then
+  begin
+    TNat.Sub33From(8, PInv33, z);
+  end;
+end;
+
+class procedure TSecP256K1Field.SubtractExt(xx, yy, zz: TCryptoLibUInt32Array);
+var
+  c: Int32;
+begin
+  c := TNat.Sub(16, xx, yy, zz);
+  if (c <> 0) then
+  begin
+    if (TNat.SubFrom(System.Length(FPExtInv), FPExtInv, zz) <> 0) then
+    begin
+      TNat.DecAt(16, zz, System.Length(FPExtInv));
+    end;
+  end;
+end;
+
+class procedure TSecP256K1Field.Twice(x, z: TCryptoLibUInt32Array);
+var
+  c: UInt32;
+begin
+  c := TNat.ShiftUpBit(8, x, 0, z);
+  if ((c <> 0) or ((z[7] = P7) and (TNat256.Gte(z, FP)))) then
+  begin
+    TNat.Add33To(8, PInv33, z);
+  end;
+end;
+
+end.

+ 347 - 0
CryptoLib/src/Math/EC/Custom/Sec/ClpSecP256K1FieldElement.pas

@@ -0,0 +1,347 @@
+{ *********************************************************************************** }
+{ *                              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 ClpSecP256K1FieldElement;
+
+{$I ..\..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpNat256,
+  ClpMod,
+  ClpSecP256K1Curve,
+  ClpECFieldElement,
+  ClpIECFieldElement,
+  ClpSecP256K1Field,
+  ClpISecP256K1FieldElement,
+  ClpBigInteger,
+  ClpArrayUtils,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SInvalidValueForSecP256K1FieldElement =
+    'Value Invalid for SecP256K1FieldElement "%s"';
+
+type
+  TSecP256K1FieldElement = class(TAbstractFpFieldElement,
+    ISecP256K1FieldElement)
+
+  strict private
+
+    function Equals(const other: ISecP256K1FieldElement): Boolean;
+      reintroduce; overload;
+
+    class function GetQ: TBigInteger; static; inline;
+
+  strict protected
+  var
+    Fx: TCryptoLibUInt32Array;
+
+    function GetFieldName: string; override;
+    function GetFieldSize: Int32; override;
+    function GetIsOne: Boolean; override;
+    function GetIsZero: Boolean; override;
+
+    function GetX: TCryptoLibUInt32Array; inline;
+    property X: TCryptoLibUInt32Array read GetX;
+
+  public
+    constructor Create(); overload;
+    constructor Create(const X: TBigInteger); overload;
+    constructor Create(X: TCryptoLibUInt32Array); overload;
+
+    function TestBitZero: Boolean; override;
+    function ToBigInteger(): TBigInteger; override;
+
+    function Add(const b: IECFieldElement): IECFieldElement; override;
+    function AddOne(): IECFieldElement; override;
+    function Subtract(const b: IECFieldElement): IECFieldElement; override;
+
+    function Multiply(const b: IECFieldElement): IECFieldElement; override;
+    function Divide(const b: IECFieldElement): IECFieldElement; override;
+    function Negate(): IECFieldElement; override;
+    function Square(): IECFieldElement; override;
+
+    function Invert(): IECFieldElement; override;
+
+    /// <summary>
+    /// return a sqrt root - the routine verifies that the calculation
+    /// returns the right value - if <br />none exists it returns null.
+    /// </summary>
+    function Sqrt(): IECFieldElement; override;
+
+    function Equals(const other: IECFieldElement): Boolean; overload; override;
+
+    function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}override;
+
+    property IsZero: Boolean read GetIsZero;
+    property IsOne: Boolean read GetIsOne;
+    property FieldName: string read GetFieldName;
+    property FieldSize: Int32 read GetFieldSize;
+
+    class property Q: TBigInteger read GetQ;
+  end;
+
+implementation
+
+{ TSecP256K1FieldElement }
+
+class function TSecP256K1FieldElement.GetQ: TBigInteger;
+begin
+  result := TSecP256K1Curve.SecP256K1Curve_Q;
+end;
+
+function TSecP256K1FieldElement.GetX: TCryptoLibUInt32Array;
+begin
+  result := Fx;
+end;
+
+constructor TSecP256K1FieldElement.Create;
+begin
+  Inherited Create();
+  Fx := TNat256.Create();
+end;
+
+constructor TSecP256K1FieldElement.Create(const X: TBigInteger);
+begin
+  if ((not(X.IsInitialized)) or (X.SignValue < 0) or (X.CompareTo(Q) >= 0)) then
+  begin
+    raise EArgumentCryptoLibException.CreateResFmt
+      (@SInvalidValueForSecP256K1FieldElement, ['x']);
+  end;
+  Inherited Create();
+  Fx := TSecP256K1Field.FromBigInteger(X);
+end;
+
+constructor TSecP256K1FieldElement.Create(X: TCryptoLibUInt32Array);
+begin
+  Inherited Create();
+  Fx := X;
+end;
+
+function TSecP256K1FieldElement.GetFieldName: string;
+begin
+  result := 'SecP256K1Field';
+end;
+
+function TSecP256K1FieldElement.GetFieldSize: Int32;
+begin
+  result := Q.BitLength;
+end;
+
+function TSecP256K1FieldElement.GetHashCode: {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}
+begin
+  result := Q.GetHashCode() xor TArrayUtils.GetArrayHashCode(Fx, 0, 8);
+end;
+
+function TSecP256K1FieldElement.GetIsOne: Boolean;
+begin
+  result := TNat256.IsOne(Fx);
+end;
+
+function TSecP256K1FieldElement.GetIsZero: Boolean;
+begin
+  result := TNat256.IsZero(Fx);
+end;
+
+function TSecP256K1FieldElement.Invert: IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat256.Create();
+  TMod.Invert(TSecP256K1Field.P, Fx, z);
+  result := TSecP256K1FieldElement.Create(z);
+end;
+
+function TSecP256K1FieldElement.Multiply(const b: IECFieldElement)
+  : IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat256.Create();
+  TSecP256K1Field.Multiply(Fx, (b as ISecP256K1FieldElement).X, z);
+  result := TSecP256K1FieldElement.Create(z);
+end;
+
+function TSecP256K1FieldElement.Negate: IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat256.Create();
+  TSecP256K1Field.Negate(Fx, z);
+  result := TSecP256K1FieldElement.Create(z);
+end;
+
+function TSecP256K1FieldElement.Sqrt: IECFieldElement;
+var
+  x1, x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1,
+    t2: TCryptoLibUInt32Array;
+begin
+  { *
+    * Raise this element to the exponent 2^254 - 2^30 - 2^7 - 2^6 - 2^5 - 2^4 - 2^2
+    *
+    * Breaking up the exponent's binary representation into "repunits", we get:
+    * ( 223 1s ) ( 1 0s ) ( 22 1s ) ( 4 0s ) ( 2 1s ) ( 2 0s)
+    *
+    * Therefore we need an addition chain containing 2, 22, 223 (the lengths of the repunits)
+    * We use: 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223]
+    * }
+
+  x1 := Fx;
+  if ((TNat256.IsZero(x1)) or (TNat256.IsOne(x1))) then
+  begin
+    result := Self as IECFieldElement;
+    Exit;
+  end;
+
+  x2 := TNat256.Create();
+  TSecP256K1Field.Square(x1, x2);
+  TSecP256K1Field.Multiply(x2, x1, x2);
+  x3 := TNat256.Create();
+  TSecP256K1Field.Square(x2, x3);
+  TSecP256K1Field.Multiply(x3, x1, x3);
+  x6 := TNat256.Create();
+  TSecP256K1Field.SquareN(x3, 3, x6);
+  TSecP256K1Field.Multiply(x6, x3, x6);
+  x9 := x6;
+  TSecP256K1Field.SquareN(x6, 3, x9);
+  TSecP256K1Field.Multiply(x9, x3, x9);
+  x11 := x9;
+  TSecP256K1Field.SquareN(x9, 2, x11);
+  TSecP256K1Field.Multiply(x11, x2, x11);
+  x22 := TNat256.Create();
+  TSecP256K1Field.SquareN(x11, 11, x22);
+  TSecP256K1Field.Multiply(x22, x11, x22);
+  x44 := x11;
+  TSecP256K1Field.SquareN(x22, 22, x44);
+  TSecP256K1Field.Multiply(x44, x22, x44);
+  x88 := TNat256.Create();
+  TSecP256K1Field.SquareN(x44, 44, x88);
+  TSecP256K1Field.Multiply(x88, x44, x88);
+  x176 := TNat256.Create();
+  TSecP256K1Field.SquareN(x88, 88, x176);
+  TSecP256K1Field.Multiply(x176, x88, x176);
+  x220 := x88;
+  TSecP256K1Field.SquareN(x176, 44, x220);
+  TSecP256K1Field.Multiply(x220, x44, x220);
+  x223 := x44;
+  TSecP256K1Field.SquareN(x220, 3, x223);
+  TSecP256K1Field.Multiply(x223, x3, x223);
+
+  t1 := x223;
+  TSecP256K1Field.SquareN(t1, 23, t1);
+  TSecP256K1Field.Multiply(t1, x22, t1);
+  TSecP256K1Field.SquareN(t1, 6, t1);
+  TSecP256K1Field.Multiply(t1, x2, t1);
+  TSecP256K1Field.SquareN(t1, 2, t1);
+
+  t2 := x2;
+  TSecP256K1Field.Square(t1, t2);
+
+  if TNat256.Eq(x1, t2) then
+  begin
+    result := TSecP256K1FieldElement.Create(t1);
+  end
+  else
+  begin
+    result := Nil;
+  end;
+end;
+
+function TSecP256K1FieldElement.Square: IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat256.Create();
+  TSecP256K1Field.Square(Fx, z);
+  result := TSecP256K1FieldElement.Create(z);
+end;
+
+function TSecP256K1FieldElement.Subtract(const b: IECFieldElement)
+  : IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat256.Create();
+  TSecP256K1Field.Subtract(Fx, (b as ISecP256K1FieldElement).X, z);
+  result := TSecP256K1FieldElement.Create(z);
+end;
+
+function TSecP256K1FieldElement.TestBitZero: Boolean;
+begin
+  result := TNat256.GetBit(Fx, 0) = 1;
+end;
+
+function TSecP256K1FieldElement.ToBigInteger: TBigInteger;
+begin
+  result := TNat256.ToBigInteger(Fx);
+end;
+
+function TSecP256K1FieldElement.Add(const b: IECFieldElement): IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat256.Create();
+  TSecP256K1Field.Add(Fx, (b as ISecP256K1FieldElement).X, z);
+  result := TSecP256K1FieldElement.Create(z);
+end;
+
+function TSecP256K1FieldElement.AddOne: IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat256.Create();
+  TSecP256K1Field.AddOne(Fx, z);
+  result := TSecP256K1FieldElement.Create(z);
+end;
+
+function TSecP256K1FieldElement.Divide(const b: IECFieldElement)
+  : IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat256.Create();
+  TMod.Invert(TSecP256K1Field.P, (b as ISecP256K1FieldElement).X, z);
+  TSecP256K1Field.Multiply(z, Fx, z);
+  result := TSecP256K1FieldElement.Create(z);
+end;
+
+function TSecP256K1FieldElement.Equals(const other
+  : ISecP256K1FieldElement): Boolean;
+begin
+  if ((Self as ISecP256K1FieldElement) = other) then
+  begin
+    result := true;
+    Exit;
+  end;
+  if (other = Nil) then
+  begin
+    result := false;
+    Exit;
+  end;
+  result := TNat256.Eq(Fx, other.X);
+end;
+
+function TSecP256K1FieldElement.Equals(const other: IECFieldElement): Boolean;
+begin
+  result := Equals(other as ISecP256K1FieldElement);
+end;
+
+end.

+ 391 - 0
CryptoLib/src/Math/EC/Custom/Sec/ClpSecP256K1Point.pas

@@ -0,0 +1,391 @@
+{ *********************************************************************************** }
+{ *                              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 ClpSecP256K1Point;
+
+{$I ..\..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpNat,
+  ClpNat256,
+  ClpECPoint,
+  ClpSecP256K1Field,
+  ClpISecP256K1Point,
+  ClpISecP256K1FieldElement,
+  ClpIECFieldElement,
+  ClpIECInterface,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SOneOfECFieldElementIsNil = 'Exactly One of the Field Elements is Nil';
+
+type
+  TSecP256K1Point = class sealed(TAbstractFpPoint, ISecP256K1Point)
+
+  strict protected
+    function Detach(): IECPoint; override;
+
+  public
+
+    /// <summary>
+    /// Create a point which encodes without point compression.
+    /// </summary>
+    /// <param name="curve">
+    /// the curve to use
+    /// </param>
+    /// <param name="x">
+    /// affine x co-ordinate
+    /// </param>
+    /// <param name="y">
+    /// affine y co-ordinate
+    /// </param>
+    constructor Create(const curve: IECCurve; const x, y: IECFieldElement);
+      overload; deprecated 'Use ECCurve.createPoint to construct points';
+
+    /// <summary>
+    /// Create a point that encodes with or without point compresion.
+    /// </summary>
+    /// <param name="curve">
+    /// the curve to use
+    /// </param>
+    /// <param name="x">
+    /// affine x co-ordinate
+    /// </param>
+    /// <param name="y">
+    /// affine y co-ordinate
+    /// </param>
+    /// <param name="withCompression">
+    /// if true encode with point compression
+    /// </param>
+    constructor Create(const curve: IECCurve; const x, y: IECFieldElement;
+      withCompression: Boolean); overload;
+      deprecated
+      'Per-point compression property will be removed, see GetEncoded(boolean)';
+
+    constructor Create(const curve: IECCurve; const x, y: IECFieldElement;
+      zs: TCryptoLibGenericArray<IECFieldElement>;
+      withCompression: Boolean); overload;
+
+    function Add(const b: IECPoint): IECPoint; override;
+    function Negate(): IECPoint; override;
+
+    function Twice(): IECPoint; override;
+    function TwicePlus(const b: IECPoint): IECPoint; override;
+
+    function ThreeTimes(): IECPoint; override;
+
+  end;
+
+implementation
+
+uses
+  // included here to avoid circular dependency :)
+  ClpSecP256K1FieldElement;
+
+{ TSecP256K1Point }
+
+constructor TSecP256K1Point.Create(const curve: IECCurve;
+  const x, y: IECFieldElement);
+begin
+  Create(curve, x, y, false);
+end;
+
+constructor TSecP256K1Point.Create(const curve: IECCurve;
+  const x, y: IECFieldElement; withCompression: Boolean);
+begin
+  Inherited Create(curve, x, y, withCompression);
+  if ((x = Nil) <> (y = Nil)) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SOneOfECFieldElementIsNil);
+  end;
+end;
+
+constructor TSecP256K1Point.Create(const curve: IECCurve;
+  const x, y: IECFieldElement; zs: TCryptoLibGenericArray<IECFieldElement>;
+  withCompression: Boolean);
+begin
+  Inherited Create(curve, x, y, zs, withCompression);
+end;
+
+function TSecP256K1Point.Add(const b: IECPoint): IECPoint;
+var
+  Lcurve: IECCurve;
+  X1, Y1, X2, Y2, Z1, Z2, X3, Y3, Z3: ISecP256K1FieldElement;
+  c: UInt32;
+  tt1, t2, t3, t4, U2, S2, U1, S1, H, R, HSquared, G, V: TCryptoLibUInt32Array;
+  Z1IsOne, Z2IsOne: Boolean;
+  zs: TCryptoLibGenericArray<IECFieldElement>;
+begin
+  if (IsInfinity) then
+  begin
+    result := b;
+    Exit;
+  end;
+  if (b.IsInfinity) then
+  begin
+    result := Self as IECPoint;
+    Exit;
+  end;
+  if ((Self as IECPoint) = b) then
+  begin
+    result := Twice();
+    Exit;
+  end;
+
+  Lcurve := curve;
+
+  X1 := RawXCoord as ISecP256K1FieldElement;
+  Y1 := RawYCoord as ISecP256K1FieldElement;
+  X2 := b.RawXCoord as ISecP256K1FieldElement;
+  Y2 := b.RawYCoord as ISecP256K1FieldElement;
+
+  Z1 := RawZCoords[0] as ISecP256K1FieldElement;
+  Z2 := b.RawZCoords[0] as ISecP256K1FieldElement;
+
+  tt1 := TNat256.CreateExt();
+  t2 := TNat256.Create();
+  t3 := TNat256.Create();
+  t4 := TNat256.Create();
+
+  Z1IsOne := Z1.IsOne;
+
+  if (Z1IsOne) then
+  begin
+    U2 := X2.x;
+    S2 := Y2.x;
+  end
+  else
+  begin
+    S2 := t3;
+    TSecP256K1Field.Square(Z1.x, S2);
+
+    U2 := t2;
+    TSecP256K1Field.Multiply(S2, X2.x, U2);
+
+    TSecP256K1Field.Multiply(S2, Z1.x, S2);
+    TSecP256K1Field.Multiply(S2, Y2.x, S2);
+  end;
+
+  Z2IsOne := Z2.IsOne;
+  if (Z2IsOne) then
+  begin
+    U1 := X1.x;
+    S1 := Y1.x;
+  end
+  else
+  begin
+    S1 := t4;
+    TSecP256K1Field.Square(Z2.x, S1);
+
+    U1 := tt1;
+    TSecP256K1Field.Multiply(S1, X1.x, U1);
+
+    TSecP256K1Field.Multiply(S1, Z2.x, S1);
+    TSecP256K1Field.Multiply(S1, Y1.x, S1);
+  end;
+
+  H := TNat256.Create();
+  TSecP256K1Field.Subtract(U1, U2, H);
+
+  R := t2;
+  TSecP256K1Field.Subtract(S1, S2, R);
+
+  // Check if b = Self or b = -Self
+  if (TNat256.IsZero(H)) then
+  begin
+    if (TNat256.IsZero(R)) then
+    begin
+      // Self = b, i.e. Self must be doubled
+      result := Twice();
+      Exit;
+    end;
+
+    // Self = -b, i.e. the result is the point at infinity
+    result := Lcurve.Infinity;
+    Exit;
+  end;
+
+  HSquared := t3;
+  TSecP256K1Field.Square(H, HSquared);
+
+  G := TNat256.Create();
+  TSecP256K1Field.Multiply(HSquared, H, G);
+
+  V := t3;
+  TSecP256K1Field.Multiply(HSquared, U1, V);
+
+  TSecP256K1Field.Negate(G, G);
+  TNat256.Mul(S1, G, tt1);
+
+  c := TNat256.AddBothTo(V, V, G);
+  TSecP256K1Field.Reduce32(c, G);
+
+  X3 := TSecP256K1FieldElement.Create(t4);
+  TSecP256K1Field.Square(R, X3.x);
+  TSecP256K1Field.Subtract(X3.x, G, X3.x);
+
+  Y3 := TSecP256K1FieldElement.Create(G);
+  TSecP256K1Field.Subtract(V, X3.x, Y3.x);
+  TSecP256K1Field.MultiplyAddToExt(Y3.x, R, tt1);
+  TSecP256K1Field.Reduce(tt1, Y3.x);
+
+  Z3 := TSecP256K1FieldElement.Create(H);
+  if (not(Z1IsOne)) then
+  begin
+    TSecP256K1Field.Multiply(Z3.x, Z1.x, Z3.x);
+  end;
+  if (not(Z2IsOne)) then
+  begin
+    TSecP256K1Field.Multiply(Z3.x, Z2.x, Z3.x);
+  end;
+
+  zs := TCryptoLibGenericArray<IECFieldElement>.Create(Z3);
+
+  result := TSecP256K1Point.Create(Lcurve, X3, Y3, zs, IsCompressed)
+    as IECPoint;
+end;
+
+function TSecP256K1Point.Detach: IECPoint;
+begin
+  result := TSecP256K1Point.Create(Nil, AffineXCoord, AffineYCoord) as IECPoint;
+end;
+
+function TSecP256K1Point.Negate: IECPoint;
+begin
+  if (IsInfinity) then
+  begin
+    result := Self as IECPoint;
+    Exit;
+  end;
+
+  result := TSecP256K1Point.Create(curve, RawXCoord, RawYCoord.Negate(),
+    RawZCoords, IsCompressed) as IECPoint;
+end;
+
+function TSecP256K1Point.ThreeTimes: IECPoint;
+begin
+  if ((IsInfinity) or (RawYCoord.IsZero)) then
+  begin
+    result := Self as IECPoint;
+    Exit;
+  end;
+
+  // NOTE: Be careful about recursions between TwicePlus and ThreeTimes
+  result := Twice().Add(Self as IECPoint);
+end;
+
+function TSecP256K1Point.Twice: IECPoint;
+var
+  Lcurve: IECCurve;
+  Y1, X1, Z1, X3, Y3, Z3: ISecP256K1FieldElement;
+  c: UInt32;
+  Y1Squared, T, M, S, t1: TCryptoLibUInt32Array;
+begin
+
+  if (IsInfinity) then
+  begin
+    result := Self as IECPoint;
+    Exit;
+  end;
+
+  Lcurve := curve;
+
+  Y1 := RawYCoord as ISecP256K1FieldElement;
+  if (Y1.IsZero) then
+  begin
+    result := Lcurve.Infinity;
+    Exit;
+  end;
+
+  X1 := RawXCoord as ISecP256K1FieldElement;
+  Z1 := RawZCoords[0] as ISecP256K1FieldElement;
+
+  Y1Squared := TNat256.Create();
+  TSecP256K1Field.Square(Y1.x, Y1Squared);
+
+  T := TNat256.Create();
+  TSecP256K1Field.Square(Y1Squared, T);
+
+  M := TNat256.Create();
+  TSecP256K1Field.Square(X1.x, M);
+  c := TNat256.AddBothTo(M, M, M);
+  TSecP256K1Field.Reduce32(c, M);
+
+  S := Y1Squared;
+  TSecP256K1Field.Multiply(Y1Squared, X1.x, S);
+  c := TNat.ShiftUpBits(8, S, 2, 0);
+  TSecP256K1Field.Reduce32(c, S);
+
+  t1 := TNat256.Create();
+  c := TNat.ShiftUpBits(8, T, 3, 0, t1);
+  TSecP256K1Field.Reduce32(c, t1);
+
+  X3 := TSecP256K1FieldElement.Create(T);
+  TSecP256K1Field.Square(M, X3.x);
+  TSecP256K1Field.Subtract(X3.x, S, X3.x);
+  TSecP256K1Field.Subtract(X3.x, S, X3.x);
+
+  Y3 := TSecP256K1FieldElement.Create(S);
+  TSecP256K1Field.Subtract(S, X3.x, Y3.x);
+  TSecP256K1Field.Multiply(Y3.x, M, Y3.x);
+  TSecP256K1Field.Subtract(Y3.x, t1, Y3.x);
+
+  Z3 := TSecP256K1FieldElement.Create(M);
+  TSecP256K1Field.Twice(Y1.x, Z3.x);
+  if (not(Z1.IsOne)) then
+  begin
+    TSecP256K1Field.Multiply(Z3.x, Z1.x, Z3.x);
+  end;
+
+  result := TSecP256K1Point.Create(Lcurve, X3, Y3,
+    TCryptoLibGenericArray<IECFieldElement>.Create(Z3), IsCompressed)
+    as IECPoint;
+end;
+
+function TSecP256K1Point.TwicePlus(const b: IECPoint): IECPoint;
+var
+  Y1: IECFieldElement;
+begin
+  if ((Self as IECPoint) = b) then
+  begin
+    result := ThreeTimes();
+    Exit;
+  end;
+  if (IsInfinity) then
+  begin
+    result := b;
+    Exit;
+  end;
+  if (b.IsInfinity) then
+  begin
+    result := Twice();
+    Exit;
+  end;
+
+  Y1 := RawYCoord;
+  if (Y1.IsZero) then
+  begin
+    result := b;
+    Exit;
+  end;
+
+  result := Twice().Add(b);
+end;
+
+end.

+ 269 - 0
CryptoLib/src/Math/EC/Custom/Sec/ClpSecP384R1Curve.pas

@@ -0,0 +1,269 @@
+{ *********************************************************************************** }
+{ *                              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 ClpSecP384R1Curve;
+
+{$I ..\..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpHex,
+  ClpBits,
+  ClpNat,
+  ClpECCurve,
+  ClpIECInterface,
+  ClpISecP384R1FieldElement,
+  ClpSecP384R1Point,
+  ClpISecP384R1Curve,
+  ClpISecP384R1Point,
+  ClpIECFieldElement,
+  ClpBigInteger,
+  ClpCryptoLibTypes;
+
+type
+  TSecP384R1Curve = class sealed(TAbstractFpCurve, ISecP384R1Curve)
+
+  strict private
+
+  type
+    TSecP384R1LookupTable = class sealed(TInterfacedObject,
+      ISecP384R1LookupTable, IECLookupTable)
+
+    strict private
+    var
+      Fm_outer: ISecP384R1Curve;
+      Fm_table: TCryptoLibUInt32Array;
+      Fm_size: Int32;
+
+      function GetSize: Int32; virtual;
+
+    public
+
+      constructor Create(const outer: ISecP384R1Curve;
+        table: TCryptoLibUInt32Array; size: Int32);
+
+      function Lookup(index: Int32): IECPoint; virtual;
+
+      property size: Int32 read GetSize;
+
+    end;
+
+  const
+    SECP384R1_DEFAULT_COORDS = Int32(TECCurve.COORD_JACOBIAN);
+    SECP384R1_FE_INTS = Int32(12);
+
+    class var
+
+      Fq: TBigInteger;
+
+    class function GetSecP384R1Curve_Q: TBigInteger; static; inline;
+    class constructor SecP384R1Curve();
+
+  strict protected
+  var
+    Fm_infinity: ISecP384R1Point;
+
+    function GetQ: TBigInteger; virtual;
+    function GetFieldSize: Int32; override;
+    function GetInfinity: IECPoint; override;
+
+    function CloneCurve(): IECCurve; override;
+
+    function CreateRawPoint(const x, y: IECFieldElement;
+      withCompression: Boolean): IECPoint; overload; override;
+
+    function CreateRawPoint(const x, y: IECFieldElement;
+      zs: TCryptoLibGenericArray<IECFieldElement>; withCompression: Boolean)
+      : IECPoint; overload; override;
+
+  public
+    constructor Create();
+    function FromBigInteger(const x: TBigInteger): IECFieldElement; override;
+
+    function SupportsCoordinateSystem(coord: Int32): Boolean; override;
+
+    function CreateCacheSafeLookupTable
+      (points: TCryptoLibGenericArray<IECPoint>; off, len: Int32)
+      : IECLookupTable; override;
+
+    property Q: TBigInteger read GetQ;
+    property Infinity: IECPoint read GetInfinity;
+    property FieldSize: Int32 read GetFieldSize;
+
+    class property SecP384R1Curve_Q: TBigInteger read GetSecP384R1Curve_Q;
+
+  end;
+
+implementation
+
+uses
+  // included here to avoid circular dependency :)
+  ClpSecP384R1FieldElement;
+
+{ TSecP384R1Curve }
+
+class function TSecP384R1Curve.GetSecP384R1Curve_Q: TBigInteger;
+begin
+  result := Fq;
+end;
+
+class constructor TSecP384R1Curve.SecP384R1Curve;
+begin
+  Fq := TBigInteger.Create(1,
+    THex.Decode
+    ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF')
+    );
+end;
+
+constructor TSecP384R1Curve.Create;
+begin
+  Inherited Create(Fq);
+  Fm_infinity := TSecP384R1Point.Create(Self as IECCurve, Nil, Nil);
+  Fm_a := FromBigInteger(TBigInteger.Create(1,
+    THex.Decode
+    ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC'))
+    );
+  Fm_b := FromBigInteger(TBigInteger.Create(1,
+    THex.Decode
+    ('B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF'))
+    );
+  Fm_order := TBigInteger.Create(1,
+    THex.Decode
+    ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973')
+    );
+  Fm_cofactor := TBigInteger.One;
+  Fm_coord := SECP384R1_DEFAULT_COORDS;
+end;
+
+function TSecP384R1Curve.CloneCurve: IECCurve;
+begin
+  result := TSecP384R1Curve.Create();
+end;
+
+function TSecP384R1Curve.CreateCacheSafeLookupTable
+  (points: TCryptoLibGenericArray<IECPoint>; off, len: Int32): IECLookupTable;
+var
+  table: TCryptoLibUInt32Array;
+  pos, i: Int32;
+  p: IECPoint;
+begin
+  System.SetLength(table, len * SECP384R1_FE_INTS * 2);
+
+  pos := 0;
+  for i := 0 to System.Pred(len) do
+  begin
+    p := points[off + i];
+    TNat.Copy(SECP384R1_FE_INTS, (p.RawXCoord as ISecP384R1FieldElement).x, 0,
+      table, pos);
+    pos := pos + SECP384R1_FE_INTS;
+    TNat.Copy(SECP384R1_FE_INTS, (p.RawYCoord as ISecP384R1FieldElement).x, 0,
+      table, pos);
+    pos := pos + SECP384R1_FE_INTS;
+  end;
+
+  result := TSecP384R1LookupTable.Create(Self as ISecP384R1Curve, table, len);
+end;
+
+function TSecP384R1Curve.CreateRawPoint(const x, y: IECFieldElement;
+  withCompression: Boolean): IECPoint;
+begin
+  result := TSecP384R1Point.Create(Self as IECCurve, x, y, withCompression);
+end;
+
+function TSecP384R1Curve.CreateRawPoint(const x, y: IECFieldElement;
+  zs: TCryptoLibGenericArray<IECFieldElement>; withCompression: Boolean)
+  : IECPoint;
+begin
+  result := TSecP384R1Point.Create(Self as IECCurve, x, y, zs, withCompression);
+end;
+
+function TSecP384R1Curve.FromBigInteger(const x: TBigInteger): IECFieldElement;
+begin
+  result := TSecP384R1FieldElement.Create(x);
+end;
+
+function TSecP384R1Curve.GetFieldSize: Int32;
+begin
+  result := Fq.BitLength;
+end;
+
+function TSecP384R1Curve.GetInfinity: IECPoint;
+begin
+  result := Fm_infinity;
+end;
+
+function TSecP384R1Curve.GetQ: TBigInteger;
+begin
+  result := Fq;
+end;
+
+function TSecP384R1Curve.SupportsCoordinateSystem(coord: Int32): Boolean;
+begin
+  case coord of
+    COORD_JACOBIAN:
+      result := True
+  else
+    result := False;
+  end;
+end;
+
+{ TSecP384R1Curve.TSecP384R1LookupTable }
+
+constructor TSecP384R1Curve.TSecP384R1LookupTable.Create
+  (const outer: ISecP384R1Curve; table: TCryptoLibUInt32Array; size: Int32);
+begin
+  Inherited Create();
+  Fm_outer := outer;
+  Fm_table := table;
+  Fm_size := size;
+end;
+
+function TSecP384R1Curve.TSecP384R1LookupTable.GetSize: Int32;
+begin
+  result := Fm_size;
+end;
+
+function TSecP384R1Curve.TSecP384R1LookupTable.Lookup(index: Int32): IECPoint;
+var
+  x, y: TCryptoLibUInt32Array;
+  pos, i, J: Int32;
+  MASK: UInt32;
+begin
+  x := TNat.Create(SECP384R1_FE_INTS);
+  y := TNat.Create(SECP384R1_FE_INTS);
+  pos := 0;
+
+  for i := 0 to System.Pred(Fm_size) do
+  begin
+    MASK := UInt32(TBits.Asr32((i xor index) - 1, 31));
+
+    for J := 0 to System.Pred(SECP384R1_FE_INTS) do
+    begin
+      x[J] := x[J] xor (Fm_table[pos + J] and MASK);
+      y[J] := y[J] xor (Fm_table[pos + SECP384R1_FE_INTS + J] and MASK);
+    end;
+
+    pos := pos + (SECP384R1_FE_INTS * 2);
+  end;
+
+  result := Fm_outer.CreateRawPoint(TSecP384R1FieldElement.Create(x)
+    as ISecP384R1FieldElement, TSecP384R1FieldElement.Create(y)
+    as ISecP384R1FieldElement, False);
+end;
+
+end.

+ 417 - 0
CryptoLib/src/Math/EC/Custom/Sec/ClpSecP384R1Field.pas

@@ -0,0 +1,417 @@
+{ *********************************************************************************** }
+{ *                              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 ClpSecP384R1Field;
+
+{$I ..\..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpNat,
+  ClpNat384,
+  ClpBits,
+  ClpBigInteger,
+  ClpCryptoLibTypes;
+
+type
+  // 2^384 - 2^128 - 2^96 + 2^32 - 1
+  TSecP384R1Field = class sealed(TObject)
+
+  strict private
+  const
+    P11 = UInt32($FFFFFFFF);
+    PExt23 = UInt32($FFFFFFFF);
+
+    class var
+
+      FP, FPExt, FPExtInv: TCryptoLibUInt32Array;
+
+    class function GetP: TCryptoLibUInt32Array; static; inline;
+
+    class procedure AddPInvTo(z: TCryptoLibUInt32Array); static;
+    class procedure SubPInvFrom(z: TCryptoLibUInt32Array); static;
+
+    class constructor SecP384R1Field();
+
+  public
+    class procedure Add(x, y, z: TCryptoLibUInt32Array); static; inline;
+    class procedure AddExt(xx, yy, zz: TCryptoLibUInt32Array); static; inline;
+    class procedure AddOne(x, z: TCryptoLibUInt32Array); static; inline;
+    class function FromBigInteger(const x: TBigInteger): TCryptoLibUInt32Array;
+      static; inline;
+    class procedure Half(x, z: TCryptoLibUInt32Array); static; inline;
+    class procedure Multiply(x, y, z: TCryptoLibUInt32Array); static; inline;
+    class procedure Negate(x, z: TCryptoLibUInt32Array); static; inline;
+    class procedure Reduce(xx, z: TCryptoLibUInt32Array); static;
+    class procedure Reduce32(x: UInt32; z: TCryptoLibUInt32Array); static;
+    class procedure Square(x, z: TCryptoLibUInt32Array); static; inline;
+    class procedure SquareN(x: TCryptoLibUInt32Array; n: Int32;
+      z: TCryptoLibUInt32Array); static; inline;
+    class procedure Subtract(x, y, z: TCryptoLibUInt32Array); static; inline;
+    class procedure SubtractExt(xx, yy, zz: TCryptoLibUInt32Array);
+      static; inline;
+    class procedure Twice(x, z: TCryptoLibUInt32Array); static; inline;
+
+    class property P: TCryptoLibUInt32Array read GetP;
+  end;
+
+implementation
+
+{ TSecP384R1Field }
+
+class constructor TSecP384R1Field.SecP384R1Field;
+begin
+  FP := TCryptoLibUInt32Array.Create($FFFFFFFF, $00000000, $00000000, $FFFFFFFF,
+    $FFFFFFFE, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
+    $FFFFFFFF);
+  FPExt := TCryptoLibUInt32Array.Create($00000001, $FFFFFFFE, $00000000,
+    $00000002, $00000000, $FFFFFFFE, $00000000, $00000002, $00000001, $00000000,
+    $00000000, $00000000, $FFFFFFFE, $00000001, $00000000, $FFFFFFFE, $FFFFFFFD,
+    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
+    $FFFFFFFF);
+  FPExtInv := TCryptoLibUInt32Array.Create($FFFFFFFF, $00000001, $FFFFFFFF,
+    $FFFFFFFD, $FFFFFFFF, $00000001, $FFFFFFFF, $FFFFFFFD, $FFFFFFFE, $FFFFFFFF,
+    $FFFFFFFF, $FFFFFFFF, $00000001, $FFFFFFFE, $FFFFFFFF, $00000001,
+    $00000002);
+end;
+
+class function TSecP384R1Field.GetP: TCryptoLibUInt32Array;
+begin
+  result := FP;
+end;
+
+class procedure TSecP384R1Field.AddPInvTo(z: TCryptoLibUInt32Array);
+var
+  c: Int64;
+begin
+  c := Int64(z[0]) + 1;
+  z[0] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[1]) - 1);
+  z[1] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  if (c <> 0) then
+  begin
+    c := c + Int64(z[2]);
+    z[2] := UInt32(c);
+    c := TBits.Asr64(c, 32);
+  end;
+  c := c + (Int64(z[3]) + 1);
+  z[3] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[4]) + 1);
+  z[4] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  if (c <> 0) then
+  begin
+    TNat.IncAt(12, z, 5);
+  end;
+end;
+
+class procedure TSecP384R1Field.SubPInvFrom(z: TCryptoLibUInt32Array);
+var
+  c: Int64;
+begin
+  c := Int64(z[0]) - 1;
+  z[0] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[1]) + 1);
+  z[1] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  if (c <> 0) then
+  begin
+    c := c + Int64(z[2]);
+    z[2] := UInt32(c);
+    c := TBits.Asr64(c, 32);
+  end;
+  c := c + (Int64(z[3]) - 1);
+  z[3] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[4]) - 1);
+  z[4] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  if (c <> 0) then
+  begin
+    TNat.DecAt(12, z, 5);
+  end;
+end;
+
+class procedure TSecP384R1Field.Add(x, y, z: TCryptoLibUInt32Array);
+var
+  c: UInt32;
+begin
+  c := TNat.Add(12, x, y, z);
+  if ((c <> 0) or ((z[11] = P11) and (TNat.Gte(12, z, FP)))) then
+  begin
+    AddPInvTo(z);
+  end;
+end;
+
+class procedure TSecP384R1Field.AddExt(xx, yy, zz: TCryptoLibUInt32Array);
+var
+  c: UInt32;
+begin
+  c := TNat.Add(24, xx, yy, zz);
+  if ((c <> 0) or ((zz[23] = PExt23) and (TNat.Gte(24, zz, FPExt)))) then
+  begin
+    if (TNat.AddTo(System.Length(FPExtInv), FPExtInv, zz) <> 0) then
+    begin
+      TNat.IncAt(24, zz, System.Length(FPExtInv));
+    end;
+  end;
+end;
+
+class procedure TSecP384R1Field.AddOne(x, z: TCryptoLibUInt32Array);
+var
+  c: UInt32;
+begin
+  c := TNat.Inc(12, x, z);
+  if ((c <> 0) or ((z[11] = P11) and (TNat.Gte(12, z, FP)))) then
+  begin
+    AddPInvTo(z);
+  end;
+end;
+
+class function TSecP384R1Field.FromBigInteger(const x: TBigInteger)
+  : TCryptoLibUInt32Array;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.FromBigInteger(384, x);
+  if ((z[11] = P11) and (TNat.Gte(12, z, FP))) then
+  begin
+    TNat.SubFrom(12, FP, z);
+  end;
+  result := z;
+end;
+
+class procedure TSecP384R1Field.Half(x, z: TCryptoLibUInt32Array);
+var
+  c: UInt32;
+begin
+  if ((x[0] and 1) = 0) then
+  begin
+    TNat.ShiftDownBit(12, x, 0, z);
+  end
+  else
+  begin
+    c := TNat.Add(12, x, FP, z);
+    TNat.ShiftDownBit(12, z, c);
+  end;
+end;
+
+class procedure TSecP384R1Field.Reduce32(x: UInt32; z: TCryptoLibUInt32Array);
+var
+  cc, xx12: Int64;
+begin
+  cc := 0;
+
+  if (x <> 0) then
+  begin
+    xx12 := x;
+
+    cc := cc + (Int64(z[0]) + xx12);
+    z[0] := UInt32(cc);
+    cc := TBits.Asr64(cc, 32);
+    cc := cc + (Int64(z[1]) - xx12);
+    z[1] := UInt32(cc);
+    cc := TBits.Asr64(cc, 32);
+    if (cc <> 0) then
+    begin
+      cc := cc + Int64(z[2]);
+      z[2] := UInt32(cc);
+      cc := TBits.Asr64(cc, 32);
+    end;
+    cc := cc + (Int64(z[3]) + xx12);
+    z[3] := UInt32(cc);
+    cc := TBits.Asr64(cc, 32);
+    cc := cc + (Int64(z[4]) + xx12);
+    z[4] := UInt32(cc);
+    cc := TBits.Asr64(cc, 32);
+
+{$IFDEF DEBUG}
+    System.Assert((cc = 0) or (cc = 1));
+{$ENDIF DEBUG}
+  end;
+
+  if (((cc <> 0) and (TNat.IncAt(12, z, 5) <> 0)) or
+    ((z[11] = P11) and (TNat.Gte(12, z, FP)))) then
+  begin
+    AddPInvTo(z);
+  end;
+end;
+
+class procedure TSecP384R1Field.Reduce(xx, z: TCryptoLibUInt32Array);
+const
+  n: Int64 = 1;
+var
+  cc, xx16, xx17, xx18, xx19, xx20, xx21, xx22, xx23, t0, t1, t2, t3, t4, t5,
+    t6, t7: Int64;
+
+begin
+  xx16 := xx[16];
+  xx17 := xx[17];
+  xx18 := xx[18];
+  xx19 := xx[19];
+  xx20 := xx[20];
+  xx21 := xx[21];
+  xx22 := xx[22];
+  xx23 := xx[23];
+
+  t0 := Int64(xx[12]) + xx20 - n;
+  t1 := Int64(xx[13]) + xx22;
+  t2 := Int64(xx[14]) + xx22 + xx23;
+  t3 := Int64(xx[15]) + xx23;
+  t4 := xx17 + xx21;
+  t5 := xx21 - xx23;
+  t6 := xx22 - xx23;
+  t7 := t0 + t5;
+
+  cc := 0;
+  cc := cc + (Int64(xx[0]) + t7);
+  z[0] := UInt32(cc);
+  cc := TBits.Asr64(cc, 32);
+  cc := cc + (Int64(xx[1]) + xx23 - t0 + t1);
+  z[1] := UInt32(cc);
+  cc := TBits.Asr64(cc, 32);
+  cc := cc + (Int64(xx[2]) - xx21 - t1 + t2);
+  z[2] := UInt32(cc);
+  cc := TBits.Asr64(cc, 32);
+  cc := cc + (Int64(xx[3]) - t2 + t3 + t7);
+  z[3] := UInt32(cc);
+  cc := TBits.Asr64(cc, 32);
+  cc := cc + (Int64(xx[4]) + xx16 + xx21 + t1 - t3 + t7);
+  z[4] := UInt32(cc);
+  cc := TBits.Asr64(cc, 32);
+  cc := cc + (Int64(xx[5]) - xx16 + t1 + t2 + t4);
+  z[5] := UInt32(cc);
+  cc := TBits.Asr64(cc, 32);
+  cc := cc + (Int64(xx[6]) + xx18 - xx17 + t2 + t3);
+  z[6] := UInt32(cc);
+  cc := TBits.Asr64(cc, 32);
+  cc := cc + (Int64(xx[7]) + xx16 + xx19 - xx18 + t3);
+  z[7] := UInt32(cc);
+  cc := TBits.Asr64(cc, 32);
+  cc := cc + (Int64(xx[8]) + xx16 + xx17 + xx20 - xx19);
+  z[8] := UInt32(cc);
+  cc := TBits.Asr64(cc, 32);
+  cc := cc + (Int64(xx[9]) + xx18 - xx20 + t4);
+  z[9] := UInt32(cc);
+  cc := TBits.Asr64(cc, 32);
+  cc := cc + (Int64(xx[10]) + xx18 + xx19 - t5 + t6);
+  z[10] := UInt32(cc);
+  cc := TBits.Asr64(cc, 32);
+  cc := cc + (Int64(xx[11]) + xx19 + xx20 - t6);
+  z[11] := UInt32(cc);
+  cc := TBits.Asr64(cc, 32);
+  cc := cc + (n);
+
+{$IFDEF DEBUG}
+  System.Assert(cc >= 0);
+{$ENDIF DEBUG}
+  Reduce32(UInt32(cc), z);
+end;
+
+class procedure TSecP384R1Field.Multiply(x, y, z: TCryptoLibUInt32Array);
+var
+  tt: TCryptoLibUInt32Array;
+begin
+  tt := TNat.Create(24);
+  TNat384.Mul(x, y, tt);
+  Reduce(tt, z);
+end;
+
+class procedure TSecP384R1Field.Negate(x, z: TCryptoLibUInt32Array);
+begin
+  if (TNat.IsZero(12, x)) then
+  begin
+    TNat.Zero(12, z);
+  end
+  else
+  begin
+    TNat.Sub(12, FP, x, z);
+  end;
+end;
+
+class procedure TSecP384R1Field.Square(x, z: TCryptoLibUInt32Array);
+var
+  tt: TCryptoLibUInt32Array;
+begin
+  tt := TNat.Create(24);
+  TNat384.Square(x, tt);
+  Reduce(tt, z);
+end;
+
+class procedure TSecP384R1Field.SquareN(x: TCryptoLibUInt32Array; n: Int32;
+  z: TCryptoLibUInt32Array);
+var
+  tt: TCryptoLibUInt32Array;
+begin
+{$IFDEF DEBUG}
+  System.Assert(n > 0);
+{$ENDIF DEBUG}
+  tt := TNat.Create(24);
+  TNat384.Square(x, tt);
+  Reduce(tt, z);
+
+  System.Dec(n);
+  while (n > 0) do
+  begin
+    TNat384.Square(z, tt);
+    Reduce(tt, z);
+    System.Dec(n);
+  end;
+end;
+
+class procedure TSecP384R1Field.Subtract(x, y, z: TCryptoLibUInt32Array);
+var
+  c: Int32;
+begin
+  c := TNat.Sub(12, x, y, z);
+  if (c <> 0) then
+  begin
+    SubPInvFrom(z);
+  end;
+end;
+
+class procedure TSecP384R1Field.SubtractExt(xx, yy, zz: TCryptoLibUInt32Array);
+var
+  c: Int32;
+begin
+  c := TNat.Sub(24, xx, yy, zz);
+  if (c <> 0) then
+  begin
+    if (TNat.SubFrom(System.Length(FPExtInv), FPExtInv, zz) <> 0) then
+    begin
+      TNat.DecAt(24, zz, System.Length(FPExtInv));
+    end;
+  end;
+end;
+
+class procedure TSecP384R1Field.Twice(x, z: TCryptoLibUInt32Array);
+var
+  c: UInt32;
+begin
+  c := TNat.ShiftUpBit(12, x, 0, z);
+  if ((c <> 0) or ((z[11] = P11) and (TNat.Gte(12, z, FP)))) then
+  begin
+    AddPInvTo(z);
+  end;
+end;
+
+end.

+ 342 - 0
CryptoLib/src/Math/EC/Custom/Sec/ClpSecP384R1FieldElement.pas

@@ -0,0 +1,342 @@
+{ *********************************************************************************** }
+{ *                              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 ClpSecP384R1FieldElement;
+
+{$I ..\..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpNat,
+  ClpMod,
+  ClpSecP384R1Curve,
+  ClpECFieldElement,
+  ClpIECFieldElement,
+  ClpSecP384R1Field,
+  ClpISecP384R1FieldElement,
+  ClpBigInteger,
+  ClpArrayUtils,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SInvalidValueForSecP384R1FieldElement =
+    'Value Invalid for SecP384R1FieldElement "%s"';
+
+type
+  TSecP384R1FieldElement = class(TAbstractFpFieldElement,
+    ISecP384R1FieldElement)
+
+  strict private
+
+    function Equals(const other: ISecP384R1FieldElement): Boolean;
+      reintroduce; overload;
+
+    class function GetQ: TBigInteger; static; inline;
+
+  strict protected
+  var
+    Fx: TCryptoLibUInt32Array;
+
+    function GetFieldName: string; override;
+    function GetFieldSize: Int32; override;
+    function GetIsOne: Boolean; override;
+    function GetIsZero: Boolean; override;
+
+    function GetX: TCryptoLibUInt32Array; inline;
+    property X: TCryptoLibUInt32Array read GetX;
+
+  public
+    constructor Create(); overload;
+    constructor Create(const X: TBigInteger); overload;
+    constructor Create(X: TCryptoLibUInt32Array); overload;
+
+    function TestBitZero: Boolean; override;
+    function ToBigInteger(): TBigInteger; override;
+
+    function Add(const b: IECFieldElement): IECFieldElement; override;
+    function AddOne(): IECFieldElement; override;
+    function Subtract(const b: IECFieldElement): IECFieldElement; override;
+
+    function Multiply(const b: IECFieldElement): IECFieldElement; override;
+    function Divide(const b: IECFieldElement): IECFieldElement; override;
+    function Negate(): IECFieldElement; override;
+    function Square(): IECFieldElement; override;
+
+    function Invert(): IECFieldElement; override;
+
+    /// <summary>
+    /// return a sqrt root - the routine verifies that the calculation
+    /// returns the right value - if <br />none exists it returns null.
+    /// </summary>
+    function Sqrt(): IECFieldElement; override;
+
+    function Equals(const other: IECFieldElement): Boolean; overload; override;
+
+    function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}override;
+
+    property IsZero: Boolean read GetIsZero;
+    property IsOne: Boolean read GetIsOne;
+    property FieldName: string read GetFieldName;
+    property FieldSize: Int32 read GetFieldSize;
+
+    class property Q: TBigInteger read GetQ;
+  end;
+
+implementation
+
+{ TSecP384R1FieldElement }
+
+class function TSecP384R1FieldElement.GetQ: TBigInteger;
+begin
+  result := TSecP384R1Curve.SecP384R1Curve_Q;
+end;
+
+function TSecP384R1FieldElement.GetX: TCryptoLibUInt32Array;
+begin
+  result := Fx;
+end;
+
+constructor TSecP384R1FieldElement.Create;
+begin
+  Inherited Create();
+  Fx := TNat.Create(12);
+end;
+
+constructor TSecP384R1FieldElement.Create(const X: TBigInteger);
+begin
+  if ((not(X.IsInitialized)) or (X.SignValue < 0) or (X.CompareTo(Q) >= 0)) then
+  begin
+    raise EArgumentCryptoLibException.CreateResFmt
+      (@SInvalidValueForSecP384R1FieldElement, ['x']);
+  end;
+  Inherited Create();
+  Fx := TSecP384R1Field.FromBigInteger(X);
+end;
+
+constructor TSecP384R1FieldElement.Create(X: TCryptoLibUInt32Array);
+begin
+  Inherited Create();
+  Fx := X;
+end;
+
+function TSecP384R1FieldElement.GetFieldName: string;
+begin
+  result := 'SecP384R1Field';
+end;
+
+function TSecP384R1FieldElement.GetFieldSize: Int32;
+begin
+  result := Q.BitLength;
+end;
+
+function TSecP384R1FieldElement.GetHashCode: {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}
+begin
+  result := Q.GetHashCode() xor TArrayUtils.GetArrayHashCode(Fx, 0, 12);
+end;
+
+function TSecP384R1FieldElement.GetIsOne: Boolean;
+begin
+  result := TNat.IsOne(12, Fx);
+end;
+
+function TSecP384R1FieldElement.GetIsZero: Boolean;
+begin
+  result := TNat.IsZero(12, Fx);
+end;
+
+function TSecP384R1FieldElement.Sqrt: IECFieldElement;
+var
+  x1, t1, t2, t3, t4, r: TCryptoLibUInt32Array;
+begin
+  // Raise this element to the exponent 2^382 - 2^126 - 2^94 + 2^30
+  x1 := Fx;
+  if ((TNat.IsZero(12, x1)) or (TNat.IsOne(12, x1))) then
+  begin
+    result := Self as IECFieldElement;
+    Exit;
+  end;
+
+  t1 := TNat.Create(12);
+  t2 := TNat.Create(12);
+  t3 := TNat.Create(12);
+  t4 := TNat.Create(12);
+
+  TSecP384R1Field.Square(x1, t1);
+  TSecP384R1Field.Multiply(t1, x1, t1);
+
+  TSecP384R1Field.SquareN(t1, 2, t2);
+  TSecP384R1Field.Multiply(t2, t1, t2);
+
+  TSecP384R1Field.Square(t2, t2);
+  TSecP384R1Field.Multiply(t2, x1, t2);
+
+  TSecP384R1Field.SquareN(t2, 5, t3);
+  TSecP384R1Field.Multiply(t3, t2, t3);
+
+  TSecP384R1Field.SquareN(t3, 5, t4);
+  TSecP384R1Field.Multiply(t4, t2, t4);
+
+  TSecP384R1Field.SquareN(t4, 15, t2);
+  TSecP384R1Field.Multiply(t2, t4, t2);
+
+  TSecP384R1Field.SquareN(t2, 2, t3);
+  TSecP384R1Field.Multiply(t1, t3, t1);
+
+  TSecP384R1Field.SquareN(t3, 28, t3);
+  TSecP384R1Field.Multiply(t2, t3, t2);
+
+  TSecP384R1Field.SquareN(t2, 60, t3);
+  TSecP384R1Field.Multiply(t3, t2, t3);
+
+  r := t2;
+
+  TSecP384R1Field.SquareN(t3, 120, r);
+  TSecP384R1Field.Multiply(r, t3, r);
+
+  TSecP384R1Field.SquareN(r, 15, r);
+  TSecP384R1Field.Multiply(r, t4, r);
+
+  TSecP384R1Field.SquareN(r, 33, r);
+  TSecP384R1Field.Multiply(r, t1, r);
+
+  TSecP384R1Field.SquareN(r, 64, r);
+  TSecP384R1Field.Multiply(r, x1, r);
+
+  TSecP384R1Field.SquareN(r, 30, t1);
+  TSecP384R1Field.Square(t1, t2);
+
+  if TNat.Eq(12, x1, t2) then
+  begin
+    result := TSecP384R1FieldElement.Create(t1);
+  end
+  else
+  begin
+    result := Nil;
+  end;
+end;
+
+function TSecP384R1FieldElement.TestBitZero: Boolean;
+begin
+  result := TNat.GetBit(Fx, 0) = 1;
+end;
+
+function TSecP384R1FieldElement.ToBigInteger: TBigInteger;
+begin
+  result := TNat.ToBigInteger(12, Fx);
+end;
+
+function TSecP384R1FieldElement.Add(const b: IECFieldElement): IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.Create(12);
+  TSecP384R1Field.Add(Fx, (b as ISecP384R1FieldElement).X, z);
+  result := TSecP384R1FieldElement.Create(z);
+end;
+
+function TSecP384R1FieldElement.AddOne: IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.Create(12);
+  TSecP384R1Field.AddOne(Fx, z);
+  result := TSecP384R1FieldElement.Create(z);
+end;
+
+function TSecP384R1FieldElement.Subtract(const b: IECFieldElement)
+  : IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.Create(12);
+  TSecP384R1Field.Subtract(Fx, (b as ISecP384R1FieldElement).X, z);
+  result := TSecP384R1FieldElement.Create(z);
+end;
+
+function TSecP384R1FieldElement.Multiply(const b: IECFieldElement)
+  : IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.Create(12);
+  TSecP384R1Field.Multiply(Fx, (b as ISecP384R1FieldElement).X, z);
+  result := TSecP384R1FieldElement.Create(z);
+end;
+
+function TSecP384R1FieldElement.Divide(const b: IECFieldElement)
+  : IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.Create(12);
+  TMod.Invert(TSecP384R1Field.P, (b as ISecP384R1FieldElement).X, z);
+  TSecP384R1Field.Multiply(z, Fx, z);
+  result := TSecP384R1FieldElement.Create(z);
+end;
+
+function TSecP384R1FieldElement.Negate: IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.Create(12);
+  TSecP384R1Field.Negate(Fx, z);
+  result := TSecP384R1FieldElement.Create(z);
+end;
+
+function TSecP384R1FieldElement.Square: IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.Create(12);
+  TSecP384R1Field.Square(Fx, z);
+  result := TSecP384R1FieldElement.Create(z);
+end;
+
+function TSecP384R1FieldElement.Invert: IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.Create(12);
+  TMod.Invert(TSecP384R1Field.P, Fx, z);
+  result := TSecP384R1FieldElement.Create(z);
+end;
+
+function TSecP384R1FieldElement.Equals(const other
+  : ISecP384R1FieldElement): Boolean;
+begin
+  if ((Self as ISecP384R1FieldElement) = other) then
+  begin
+    result := true;
+    Exit;
+  end;
+  if (other = Nil) then
+  begin
+    result := false;
+    Exit;
+  end;
+  result := TNat.Eq(12, Fx, other.X);
+end;
+
+function TSecP384R1FieldElement.Equals(const other: IECFieldElement): Boolean;
+begin
+  result := Equals(other as ISecP384R1FieldElement);
+end;
+
+end.

+ 406 - 0
CryptoLib/src/Math/EC/Custom/Sec/ClpSecP384R1Point.pas

@@ -0,0 +1,406 @@
+{ *********************************************************************************** }
+{ *                              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 ClpSecP384R1Point;
+
+{$I ..\..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpNat,
+  ClpNat384,
+  ClpECPoint,
+  ClpSecP384R1Field,
+  ClpISecP384R1Point,
+  ClpISecP384R1FieldElement,
+  ClpIECFieldElement,
+  ClpIECInterface,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SOneOfECFieldElementIsNil = 'Exactly One of the Field Elements is Nil';
+
+type
+  TSecP384R1Point = class sealed(TAbstractFpPoint, ISecP384R1Point)
+
+  strict protected
+    function Detach(): IECPoint; override;
+
+  public
+
+    /// <summary>
+    /// Create a point which encodes without point compression.
+    /// </summary>
+    /// <param name="curve">
+    /// the curve to use
+    /// </param>
+    /// <param name="x">
+    /// affine x co-ordinate
+    /// </param>
+    /// <param name="y">
+    /// affine y co-ordinate
+    /// </param>
+    constructor Create(const curve: IECCurve; const x, y: IECFieldElement);
+      overload; deprecated 'Use ECCurve.createPoint to construct points';
+
+    /// <summary>
+    /// Create a point that encodes with or without point compresion.
+    /// </summary>
+    /// <param name="curve">
+    /// the curve to use
+    /// </param>
+    /// <param name="x">
+    /// affine x co-ordinate
+    /// </param>
+    /// <param name="y">
+    /// affine y co-ordinate
+    /// </param>
+    /// <param name="withCompression">
+    /// if true encode with point compression
+    /// </param>
+    constructor Create(const curve: IECCurve; const x, y: IECFieldElement;
+      withCompression: Boolean); overload;
+      deprecated
+      'Per-point compression property will be removed, see GetEncoded(boolean)';
+
+    constructor Create(const curve: IECCurve; const x, y: IECFieldElement;
+      zs: TCryptoLibGenericArray<IECFieldElement>;
+      withCompression: Boolean); overload;
+
+    function Add(const b: IECPoint): IECPoint; override;
+    function Negate(): IECPoint; override;
+
+    function Twice(): IECPoint; override;
+    function TwicePlus(const b: IECPoint): IECPoint; override;
+
+    function ThreeTimes(): IECPoint; override;
+
+  end;
+
+implementation
+
+uses
+  // included here to avoid circular dependency :)
+  ClpSecP384R1FieldElement;
+
+{ TSecP384R1Point }
+
+constructor TSecP384R1Point.Create(const curve: IECCurve;
+  const x, y: IECFieldElement);
+begin
+  Create(curve, x, y, false);
+end;
+
+constructor TSecP384R1Point.Create(const curve: IECCurve;
+  const x, y: IECFieldElement; withCompression: Boolean);
+begin
+  Inherited Create(curve, x, y, withCompression);
+  if ((x = Nil) <> (y = Nil)) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SOneOfECFieldElementIsNil);
+  end;
+end;
+
+constructor TSecP384R1Point.Create(const curve: IECCurve;
+  const x, y: IECFieldElement; zs: TCryptoLibGenericArray<IECFieldElement>;
+  withCompression: Boolean);
+begin
+  Inherited Create(curve, x, y, zs, withCompression);
+end;
+
+function TSecP384R1Point.Add(const b: IECPoint): IECPoint;
+var
+  Lcurve: IECCurve;
+  X1, Y1, X2, Y2, Z1, Z2, X3, Y3, Z3: ISecP384R1FieldElement;
+  c: UInt32;
+  tt1, tt2, t3, t4, U2, S2, U1, S1, H, R, HSquared, G, V: TCryptoLibUInt32Array;
+  Z1IsOne, Z2IsOne: Boolean;
+  zs: TCryptoLibGenericArray<IECFieldElement>;
+begin
+  if (IsInfinity) then
+  begin
+    result := b;
+    Exit;
+  end;
+  if (b.IsInfinity) then
+  begin
+    result := Self as IECPoint;
+    Exit;
+  end;
+  if ((Self as IECPoint) = b) then
+  begin
+    result := Twice();
+    Exit;
+  end;
+
+  Lcurve := curve;
+
+  X1 := RawXCoord as ISecP384R1FieldElement;
+  Y1 := RawYCoord as ISecP384R1FieldElement;
+  X2 := b.RawXCoord as ISecP384R1FieldElement;
+  Y2 := b.RawYCoord as ISecP384R1FieldElement;
+
+  Z1 := RawZCoords[0] as ISecP384R1FieldElement;
+  Z2 := b.RawZCoords[0] as ISecP384R1FieldElement;
+
+  tt1 := TNat.Create(24);
+  tt2 := TNat.Create(24);
+  t3 := TNat.Create(12);
+  t4 := TNat.Create(12);
+
+  Z1IsOne := Z1.IsOne;
+
+  if (Z1IsOne) then
+  begin
+    U2 := X2.x;
+    S2 := Y2.x;
+  end
+  else
+  begin
+    S2 := t3;
+    TSecP384R1Field.Square(Z1.x, S2);
+
+    U2 := tt2;
+    TSecP384R1Field.Multiply(S2, X2.x, U2);
+
+    TSecP384R1Field.Multiply(S2, Z1.x, S2);
+    TSecP384R1Field.Multiply(S2, Y2.x, S2);
+  end;
+
+  Z2IsOne := Z2.IsOne;
+  if (Z2IsOne) then
+  begin
+    U1 := X1.x;
+    S1 := Y1.x;
+  end
+  else
+  begin
+    S1 := t4;
+    TSecP384R1Field.Square(Z2.x, S1);
+
+    U1 := tt1;
+    TSecP384R1Field.Multiply(S1, X1.x, U1);
+
+    TSecP384R1Field.Multiply(S1, Z2.x, S1);
+    TSecP384R1Field.Multiply(S1, Y1.x, S1);
+  end;
+
+  H := TNat.Create(12);
+  TSecP384R1Field.Subtract(U1, U2, H);
+
+  R := TNat.Create(12);
+  TSecP384R1Field.Subtract(S1, S2, R);
+
+  // Check if b = Self or b = -Self
+  if (TNat.IsZero(12, H)) then
+  begin
+    if (TNat.IsZero(12, R)) then
+    begin
+      // Self = b, i.e. Self must be doubled
+      result := Twice();
+      Exit;
+    end;
+
+    // Self = -b, i.e. the result is the point at infinity
+    result := Lcurve.Infinity;
+    Exit;
+  end;
+
+  HSquared := t3;
+  TSecP384R1Field.Square(H, HSquared);
+
+  G := TNat.Create(12);
+  TSecP384R1Field.Multiply(HSquared, H, G);
+
+  V := t3;
+  TSecP384R1Field.Multiply(HSquared, U1, V);
+
+  TSecP384R1Field.Negate(G, G);
+  TNat384.Mul(S1, G, tt1);
+
+  c := TNat.AddBothTo(12, V, V, G);
+  TSecP384R1Field.Reduce32(c, G);
+
+  X3 := TSecP384R1FieldElement.Create(t4);
+  TSecP384R1Field.Square(R, X3.x);
+  TSecP384R1Field.Subtract(X3.x, G, X3.x);
+
+  Y3 := TSecP384R1FieldElement.Create(G);
+  TSecP384R1Field.Subtract(V, X3.x, Y3.x);
+  TNat384.Mul(Y3.x, R, tt2);
+  TSecP384R1Field.AddExt(tt1, tt2, tt1);
+  TSecP384R1Field.Reduce(tt1, Y3.x);
+
+  Z3 := TSecP384R1FieldElement.Create(H);
+  if (not(Z1IsOne)) then
+  begin
+    TSecP384R1Field.Multiply(Z3.x, Z1.x, Z3.x);
+  end;
+  if (not(Z2IsOne)) then
+  begin
+    TSecP384R1Field.Multiply(Z3.x, Z2.x, Z3.x);
+  end;
+
+  zs := TCryptoLibGenericArray<IECFieldElement>.Create(Z3);
+
+  result := TSecP384R1Point.Create(Lcurve, X3, Y3, zs, IsCompressed)
+    as IECPoint;
+end;
+
+function TSecP384R1Point.Detach: IECPoint;
+begin
+  result := TSecP384R1Point.Create(Nil, AffineXCoord, AffineYCoord) as IECPoint;
+end;
+
+function TSecP384R1Point.Negate: IECPoint;
+begin
+  if (IsInfinity) then
+  begin
+    result := Self as IECPoint;
+    Exit;
+  end;
+
+  result := TSecP384R1Point.Create(curve, RawXCoord, RawYCoord.Negate(),
+    RawZCoords, IsCompressed) as IECPoint;
+end;
+
+function TSecP384R1Point.ThreeTimes: IECPoint;
+begin
+  if ((IsInfinity) or (RawYCoord.IsZero)) then
+  begin
+    result := Self as IECPoint;
+    Exit;
+  end;
+
+  // NOTE: Be careful about recursions between TwicePlus and ThreeTimes
+  result := Twice().Add(Self as IECPoint);
+end;
+
+function TSecP384R1Point.Twice: IECPoint;
+var
+  Lcurve: IECCurve;
+  Y1, X1, Z1, X3, Y3, Z3: ISecP384R1FieldElement;
+  c: UInt32;
+  Y1Squared, Z1Squared, T, M, S, t1, t2: TCryptoLibUInt32Array;
+  Z1IsOne: Boolean;
+begin
+
+  if (IsInfinity) then
+  begin
+    result := Self as IECPoint;
+    Exit;
+  end;
+
+  Lcurve := curve;
+
+  Y1 := RawYCoord as ISecP384R1FieldElement;
+  if (Y1.IsZero) then
+  begin
+    result := Lcurve.Infinity;
+    Exit;
+  end;
+
+  X1 := RawXCoord as ISecP384R1FieldElement;
+  Z1 := RawZCoords[0] as ISecP384R1FieldElement;
+
+  t1 := TNat.Create(12);
+  t2 := TNat.Create(12);
+  Y1Squared := TNat.Create(12);
+  TSecP384R1Field.Square(Y1.x, Y1Squared);
+
+  T := TNat.Create(12);
+  TSecP384R1Field.Square(Y1Squared, T);
+
+  Z1IsOne := Z1.IsOne;
+
+  Z1Squared := Z1.x;
+  if (not(Z1IsOne)) then
+  begin
+    Z1Squared := t2;
+    TSecP384R1Field.Square(Z1.x, Z1Squared);
+  end;
+
+  TSecP384R1Field.Subtract(X1.x, Z1Squared, t1);
+
+  M := t2;
+  TSecP384R1Field.Add(X1.x, Z1Squared, M);
+  TSecP384R1Field.Multiply(M, t1, M);
+  c := TNat.AddBothTo(12, M, M, M);
+  TSecP384R1Field.Reduce32(c, M);
+
+  S := Y1Squared;
+  TSecP384R1Field.Multiply(Y1Squared, X1.x, S);
+  c := TNat.ShiftUpBits(12, S, 2, 0);
+  TSecP384R1Field.Reduce32(c, S);
+
+  c := TNat.ShiftUpBits(12, T, 3, 0, t1);
+  TSecP384R1Field.Reduce32(c, t1);
+
+  X3 := TSecP384R1FieldElement.Create(T);
+  TSecP384R1Field.Square(M, X3.x);
+  TSecP384R1Field.Subtract(X3.x, S, X3.x);
+  TSecP384R1Field.Subtract(X3.x, S, X3.x);
+
+  Y3 := TSecP384R1FieldElement.Create(S);
+  TSecP384R1Field.Subtract(S, X3.x, Y3.x);
+  TSecP384R1Field.Multiply(Y3.x, M, Y3.x);
+  TSecP384R1Field.Subtract(Y3.x, t1, Y3.x);
+
+  Z3 := TSecP384R1FieldElement.Create(M);
+  TSecP384R1Field.Twice(Y1.x, Z3.x);
+  if (not(Z1IsOne)) then
+  begin
+    TSecP384R1Field.Multiply(Z3.x, Z1.x, Z3.x);
+  end;
+
+  result := TSecP384R1Point.Create(Lcurve, X3, Y3,
+    TCryptoLibGenericArray<IECFieldElement>.Create(Z3), IsCompressed)
+    as IECPoint;
+end;
+
+function TSecP384R1Point.TwicePlus(const b: IECPoint): IECPoint;
+var
+  Y1: IECFieldElement;
+begin
+  if ((Self as IECPoint) = b) then
+  begin
+    result := ThreeTimes();
+    Exit;
+  end;
+  if (IsInfinity) then
+  begin
+    result := b;
+    Exit;
+  end;
+  if (b.IsInfinity) then
+  begin
+    result := Twice();
+    Exit;
+  end;
+
+  Y1 := RawYCoord;
+  if (Y1.IsZero) then
+  begin
+    result := b;
+    Exit;
+  end;
+
+  result := Twice().Add(b);
+end;
+
+end.

+ 269 - 0
CryptoLib/src/Math/EC/Custom/Sec/ClpSecP521R1Curve.pas

@@ -0,0 +1,269 @@
+{ *********************************************************************************** }
+{ *                              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 ClpSecP521R1Curve;
+
+{$I ..\..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpHex,
+  ClpBits,
+  ClpNat,
+  ClpECCurve,
+  ClpIECInterface,
+  ClpISecP521R1FieldElement,
+  ClpSecP521R1Point,
+  ClpISecP521R1Curve,
+  ClpISecP521R1Point,
+  ClpIECFieldElement,
+  ClpBigInteger,
+  ClpCryptoLibTypes;
+
+type
+  TSecP521R1Curve = class sealed(TAbstractFpCurve, ISecP521R1Curve)
+
+  strict private
+
+  type
+    TSecP521R1LookupTable = class sealed(TInterfacedObject,
+      ISecP521R1LookupTable, IECLookupTable)
+
+    strict private
+    var
+      Fm_outer: ISecP521R1Curve;
+      Fm_table: TCryptoLibUInt32Array;
+      Fm_size: Int32;
+
+      function GetSize: Int32; virtual;
+
+    public
+
+      constructor Create(const outer: ISecP521R1Curve;
+        table: TCryptoLibUInt32Array; size: Int32);
+
+      function Lookup(index: Int32): IECPoint; virtual;
+
+      property size: Int32 read GetSize;
+
+    end;
+
+  const
+    SECP521R1_DEFAULT_COORDS = Int32(TECCurve.COORD_JACOBIAN);
+    SECP521R1_FE_INTS = Int32(17);
+
+    class var
+
+      Fq: TBigInteger;
+
+    class function GetSecP521R1Curve_Q: TBigInteger; static; inline;
+    class constructor SecP521R1Curve();
+
+  strict protected
+  var
+    Fm_infinity: ISecP521R1Point;
+
+    function GetQ: TBigInteger; virtual;
+    function GetFieldSize: Int32; override;
+    function GetInfinity: IECPoint; override;
+
+    function CloneCurve(): IECCurve; override;
+
+    function CreateRawPoint(const x, y: IECFieldElement;
+      withCompression: Boolean): IECPoint; overload; override;
+
+    function CreateRawPoint(const x, y: IECFieldElement;
+      zs: TCryptoLibGenericArray<IECFieldElement>; withCompression: Boolean)
+      : IECPoint; overload; override;
+
+  public
+    constructor Create();
+    function FromBigInteger(const x: TBigInteger): IECFieldElement; override;
+
+    function SupportsCoordinateSystem(coord: Int32): Boolean; override;
+
+    function CreateCacheSafeLookupTable
+      (points: TCryptoLibGenericArray<IECPoint>; off, len: Int32)
+      : IECLookupTable; override;
+
+    property Q: TBigInteger read GetQ;
+    property Infinity: IECPoint read GetInfinity;
+    property FieldSize: Int32 read GetFieldSize;
+
+    class property SecP521R1Curve_Q: TBigInteger read GetSecP521R1Curve_Q;
+
+  end;
+
+implementation
+
+uses
+  // included here to avoid circular dependency :)
+  ClpSecP521R1FieldElement;
+
+{ TSecP521R1Curve }
+
+class function TSecP521R1Curve.GetSecP521R1Curve_Q: TBigInteger;
+begin
+  result := Fq;
+end;
+
+class constructor TSecP521R1Curve.SecP521R1Curve;
+begin
+  Fq := TBigInteger.Create(1,
+    THex.Decode
+    ('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF')
+    );
+end;
+
+constructor TSecP521R1Curve.Create;
+begin
+  Inherited Create(Fq);
+  Fm_infinity := TSecP521R1Point.Create(Self as IECCurve, Nil, Nil);
+  Fm_a := FromBigInteger(TBigInteger.Create(1,
+    THex.Decode
+    ('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC'))
+    );
+  Fm_b := FromBigInteger(TBigInteger.Create(1,
+    THex.Decode
+    ('0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00'))
+    );
+  Fm_order := TBigInteger.Create(1,
+    THex.Decode
+    ('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409')
+    );
+  Fm_cofactor := TBigInteger.One;
+  Fm_coord := SECP521R1_DEFAULT_COORDS;
+end;
+
+function TSecP521R1Curve.CloneCurve: IECCurve;
+begin
+  result := TSecP521R1Curve.Create();
+end;
+
+function TSecP521R1Curve.CreateCacheSafeLookupTable
+  (points: TCryptoLibGenericArray<IECPoint>; off, len: Int32): IECLookupTable;
+var
+  table: TCryptoLibUInt32Array;
+  pos, i: Int32;
+  p: IECPoint;
+begin
+  System.SetLength(table, len * SECP521R1_FE_INTS * 2);
+
+  pos := 0;
+  for i := 0 to System.Pred(len) do
+  begin
+    p := points[off + i];
+    TNat.Copy(SECP521R1_FE_INTS, (p.RawXCoord as ISecP521R1FieldElement).x, 0,
+      table, pos);
+    pos := pos + SECP521R1_FE_INTS;
+    TNat.Copy(SECP521R1_FE_INTS, (p.RawYCoord as ISecP521R1FieldElement).x, 0,
+      table, pos);
+    pos := pos + SECP521R1_FE_INTS;
+  end;
+
+  result := TSecP521R1LookupTable.Create(Self as ISecP521R1Curve, table, len);
+end;
+
+function TSecP521R1Curve.CreateRawPoint(const x, y: IECFieldElement;
+  withCompression: Boolean): IECPoint;
+begin
+  result := TSecP521R1Point.Create(Self as IECCurve, x, y, withCompression);
+end;
+
+function TSecP521R1Curve.CreateRawPoint(const x, y: IECFieldElement;
+  zs: TCryptoLibGenericArray<IECFieldElement>; withCompression: Boolean)
+  : IECPoint;
+begin
+  result := TSecP521R1Point.Create(Self as IECCurve, x, y, zs, withCompression);
+end;
+
+function TSecP521R1Curve.FromBigInteger(const x: TBigInteger): IECFieldElement;
+begin
+  result := TSecP521R1FieldElement.Create(x);
+end;
+
+function TSecP521R1Curve.GetFieldSize: Int32;
+begin
+  result := Fq.BitLength;
+end;
+
+function TSecP521R1Curve.GetInfinity: IECPoint;
+begin
+  result := Fm_infinity;
+end;
+
+function TSecP521R1Curve.GetQ: TBigInteger;
+begin
+  result := Fq;
+end;
+
+function TSecP521R1Curve.SupportsCoordinateSystem(coord: Int32): Boolean;
+begin
+  case coord of
+    COORD_JACOBIAN:
+      result := True
+  else
+    result := False;
+  end;
+end;
+
+{ TSecP521R1Curve.TSecP521R1LookupTable }
+
+constructor TSecP521R1Curve.TSecP521R1LookupTable.Create
+  (const outer: ISecP521R1Curve; table: TCryptoLibUInt32Array; size: Int32);
+begin
+  Inherited Create();
+  Fm_outer := outer;
+  Fm_table := table;
+  Fm_size := size;
+end;
+
+function TSecP521R1Curve.TSecP521R1LookupTable.GetSize: Int32;
+begin
+  result := Fm_size;
+end;
+
+function TSecP521R1Curve.TSecP521R1LookupTable.Lookup(index: Int32): IECPoint;
+var
+  x, y: TCryptoLibUInt32Array;
+  pos, i, J: Int32;
+  MASK: UInt32;
+begin
+  x := TNat.Create(SECP521R1_FE_INTS);
+  y := TNat.Create(SECP521R1_FE_INTS);
+  pos := 0;
+
+  for i := 0 to System.Pred(Fm_size) do
+  begin
+    MASK := UInt32(TBits.Asr32((i xor index) - 1, 31));
+
+    for J := 0 to System.Pred(SECP521R1_FE_INTS) do
+    begin
+      x[J] := x[J] xor (Fm_table[pos + J] and MASK);
+      y[J] := y[J] xor (Fm_table[pos + SECP521R1_FE_INTS + J] and MASK);
+    end;
+
+    pos := pos + (SECP521R1_FE_INTS * 2);
+  end;
+
+  result := Fm_outer.CreateRawPoint(TSecP521R1FieldElement.Create(x)
+    as ISecP521R1FieldElement, TSecP521R1FieldElement.Create(y)
+    as ISecP521R1FieldElement, False);
+end;
+
+end.

+ 258 - 0
CryptoLib/src/Math/EC/Custom/Sec/ClpSecP521R1Field.pas

@@ -0,0 +1,258 @@
+{ *********************************************************************************** }
+{ *                              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 ClpSecP521R1Field;
+
+{$I ..\..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpNat,
+  ClpNat512,
+  ClpBigInteger,
+  ClpCryptoLibTypes;
+
+type
+  // 2^521 - 1
+  TSecP521R1Field = class sealed(TObject)
+
+  strict private
+  const
+    P16 = UInt32($1FF);
+
+    class var
+
+      FP: TCryptoLibUInt32Array;
+
+    class function GetP: TCryptoLibUInt32Array; static; inline;
+
+    class procedure ImplMultiply(x, y, zz: TCryptoLibUInt32Array);
+      static; inline;
+    class procedure ImplSquare(x, zz: TCryptoLibUInt32Array); static; inline;
+
+    class constructor SecP521R1Field();
+
+  public
+    class procedure Add(x, y, z: TCryptoLibUInt32Array); static; inline;
+    class procedure AddOne(x, z: TCryptoLibUInt32Array); static; inline;
+    class function FromBigInteger(const x: TBigInteger): TCryptoLibUInt32Array;
+      static; inline;
+    class procedure Half(x, z: TCryptoLibUInt32Array); static; inline;
+    class procedure Multiply(x, y, z: TCryptoLibUInt32Array); static; inline;
+    class procedure Negate(x, z: TCryptoLibUInt32Array); static; inline;
+    class procedure Reduce(xx, z: TCryptoLibUInt32Array); static; inline;
+    class procedure Reduce23(z: TCryptoLibUInt32Array); static; inline;
+    class procedure Square(x, z: TCryptoLibUInt32Array); static; inline;
+    class procedure SquareN(x: TCryptoLibUInt32Array; n: Int32;
+      z: TCryptoLibUInt32Array); static; inline;
+    class procedure Subtract(x, y, z: TCryptoLibUInt32Array); static; inline;
+    class procedure Twice(x, z: TCryptoLibUInt32Array); static; inline;
+
+    class property P: TCryptoLibUInt32Array read GetP;
+  end;
+
+implementation
+
+{ TSecP521R1Field }
+
+class constructor TSecP521R1Field.SecP521R1Field;
+begin
+  FP := TCryptoLibUInt32Array.Create($FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
+    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
+    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $1FF);
+end;
+
+class function TSecP521R1Field.GetP: TCryptoLibUInt32Array;
+begin
+  result := FP;
+end;
+
+class procedure TSecP521R1Field.Add(x, y, z: TCryptoLibUInt32Array);
+var
+  c: UInt32;
+begin
+  c := TNat.Add(16, x, y, z) + x[16] + y[16];
+  if ((c > P16) or ((c = P16) and (TNat.Eq(16, z, FP)))) then
+  begin
+    c := c + (TNat.Inc(16, z));
+    c := c and P16;
+  end;
+  z[16] := c;
+end;
+
+class procedure TSecP521R1Field.AddOne(x, z: TCryptoLibUInt32Array);
+var
+  c: UInt32;
+begin
+  c := TNat.Inc(16, x, z) + x[16];
+  if ((c > P16) or ((c = P16) and (TNat.Eq(16, z, FP)))) then
+  begin
+    c := c + TNat.Inc(16, z);
+    c := c and P16;
+  end;
+  z[16] := c;
+end;
+
+class function TSecP521R1Field.FromBigInteger(const x: TBigInteger)
+  : TCryptoLibUInt32Array;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.FromBigInteger(521, x);
+  if (TNat.Eq(17, z, FP)) then
+  begin
+    TNat.Zero(17, z);
+  end;
+  result := z;
+end;
+
+class procedure TSecP521R1Field.Half(x, z: TCryptoLibUInt32Array);
+var
+  x16, c: UInt32;
+begin
+  x16 := x[16];
+  c := TNat.ShiftDownBit(16, x, x16, z);
+  z[16] := (x16 shr 1) or (c shr 23);
+end;
+
+class procedure TSecP521R1Field.ImplMultiply(x, y, zz: TCryptoLibUInt32Array);
+var
+  x16, y16: UInt32;
+begin
+  TNat512.Mul(x, y, zz);
+  x16 := x[16];
+  y16 := y[16];
+  zz[32] := TNat.Mul31BothAdd(16, x16, y, y16, x, zz, 16) + (x16 * y16);
+end;
+
+class procedure TSecP521R1Field.ImplSquare(x, zz: TCryptoLibUInt32Array);
+var
+  x16: UInt32;
+begin
+  TNat512.Square(x, zz);
+  x16 := x[16];
+  zz[32] := TNat.MulWordAddTo(16, (x16 shl 1), x, 0, zz, 16) + (x16 * x16);
+end;
+
+class procedure TSecP521R1Field.Reduce23(z: TCryptoLibUInt32Array);
+var
+  z16, c: UInt32;
+begin
+  z16 := z[16];
+  c := TNat.AddWordTo(16, (z16 shr 9), z) + (z16 and P16);
+  if ((c > P16) or ((c = P16) and (TNat.Eq(16, z, FP)))) then
+  begin
+    c := c + (TNat.Inc(16, z));
+    c := c and P16;
+  end;
+  z[16] := c;
+end;
+
+class procedure TSecP521R1Field.Reduce(xx, z: TCryptoLibUInt32Array);
+var
+  xx32, c: UInt32;
+begin
+{$IFDEF DEBUG}
+  System.Assert((xx[32] shr 18) = 0);
+{$ENDIF DEBUG}
+  xx32 := xx[32];
+  c := TNat.ShiftDownBits(16, xx, 16, 9, xx32, z, 0) shr 23;
+  c := c + (xx32 shr 9);
+  c := c + (TNat.AddTo(16, xx, z));
+  if ((c > P16) or ((c = P16) and (TNat.Eq(16, z, FP)))) then
+  begin
+    c := c + (TNat.Inc(16, z));
+    c := c and P16;
+  end;
+  z[16] := c;
+end;
+
+class procedure TSecP521R1Field.Multiply(x, y, z: TCryptoLibUInt32Array);
+var
+  tt: TCryptoLibUInt32Array;
+begin
+  tt := TNat.Create(33);
+  ImplMultiply(x, y, tt);
+  Reduce(tt, z);
+end;
+
+class procedure TSecP521R1Field.Negate(x, z: TCryptoLibUInt32Array);
+begin
+  if (TNat.IsZero(17, x)) then
+  begin
+    TNat.Zero(17, z);
+  end
+  else
+  begin
+    TNat.Sub(17, FP, x, z);
+  end;
+end;
+
+class procedure TSecP521R1Field.Square(x, z: TCryptoLibUInt32Array);
+var
+  tt: TCryptoLibUInt32Array;
+begin
+  tt := TNat.Create(33);
+  ImplSquare(x, tt);
+  Reduce(tt, z);
+end;
+
+class procedure TSecP521R1Field.SquareN(x: TCryptoLibUInt32Array; n: Int32;
+  z: TCryptoLibUInt32Array);
+var
+  tt: TCryptoLibUInt32Array;
+begin
+{$IFDEF DEBUG}
+  System.Assert(n > 0);
+{$ENDIF DEBUG}
+  tt := TNat.Create(33);
+  ImplSquare(x, tt);
+  Reduce(tt, z);
+
+  System.Dec(n);
+  while (n > 0) do
+  begin
+    ImplSquare(z, tt);
+    Reduce(tt, z);
+    System.Dec(n);
+  end;
+end;
+
+class procedure TSecP521R1Field.Subtract(x, y, z: TCryptoLibUInt32Array);
+var
+  c: Int32;
+begin
+  c := TNat.Sub(16, x, y, z) + Int32(x[16] - y[16]);
+  if (c < 0) then
+  begin
+    c := c + TNat.Dec(16, z);
+    c := c and P16;
+  end;
+  z[16] := UInt32(c);
+end;
+
+class procedure TSecP521R1Field.Twice(x, z: TCryptoLibUInt32Array);
+var
+  x16, c: UInt32;
+begin
+  x16 := x[16];
+  c := TNat.ShiftUpBit(16, x, x16 shl 23, z) or (x16 shl 1);
+  z[16] := c and P16;
+end;
+
+end.

+ 299 - 0
CryptoLib/src/Math/EC/Custom/Sec/ClpSecP521R1FieldElement.pas

@@ -0,0 +1,299 @@
+{ *********************************************************************************** }
+{ *                              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 ClpSecP521R1FieldElement;
+
+{$I ..\..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpNat,
+  ClpMod,
+  ClpSecP521R1Curve,
+  ClpECFieldElement,
+  ClpIECFieldElement,
+  ClpSecP521R1Field,
+  ClpISecP521R1FieldElement,
+  ClpBigInteger,
+  ClpArrayUtils,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SInvalidValueForSecP521R1FieldElement =
+    'Value Invalid for SecP521R1FieldElement "%s"';
+
+type
+  TSecP521R1FieldElement = class(TAbstractFpFieldElement,
+    ISecP521R1FieldElement)
+
+  strict private
+
+    function Equals(const other: ISecP521R1FieldElement): Boolean;
+      reintroduce; overload;
+
+    class function GetQ: TBigInteger; static; inline;
+
+  strict protected
+  var
+    Fx: TCryptoLibUInt32Array;
+
+    function GetFieldName: string; override;
+    function GetFieldSize: Int32; override;
+    function GetIsOne: Boolean; override;
+    function GetIsZero: Boolean; override;
+
+    function GetX: TCryptoLibUInt32Array; inline;
+    property X: TCryptoLibUInt32Array read GetX;
+
+  public
+    constructor Create(); overload;
+    constructor Create(const X: TBigInteger); overload;
+    constructor Create(X: TCryptoLibUInt32Array); overload;
+
+    function TestBitZero: Boolean; override;
+    function ToBigInteger(): TBigInteger; override;
+
+    function Add(const b: IECFieldElement): IECFieldElement; override;
+    function AddOne(): IECFieldElement; override;
+    function Subtract(const b: IECFieldElement): IECFieldElement; override;
+
+    function Multiply(const b: IECFieldElement): IECFieldElement; override;
+    function Divide(const b: IECFieldElement): IECFieldElement; override;
+    function Negate(): IECFieldElement; override;
+    function Square(): IECFieldElement; override;
+
+    function Invert(): IECFieldElement; override;
+
+    /// <summary>
+    /// return a sqrt root - the routine verifies that the calculation
+    /// returns the right value - if <br />none exists it returns null.
+    /// </summary>
+    function Sqrt(): IECFieldElement; override;
+
+    function Equals(const other: IECFieldElement): Boolean; overload; override;
+
+    function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}override;
+
+    property IsZero: Boolean read GetIsZero;
+    property IsOne: Boolean read GetIsOne;
+    property FieldName: string read GetFieldName;
+    property FieldSize: Int32 read GetFieldSize;
+
+    class property Q: TBigInteger read GetQ;
+  end;
+
+implementation
+
+{ TSecP521R1FieldElement }
+
+class function TSecP521R1FieldElement.GetQ: TBigInteger;
+begin
+  result := TSecP521R1Curve.SecP521R1Curve_Q;
+end;
+
+function TSecP521R1FieldElement.GetX: TCryptoLibUInt32Array;
+begin
+  result := Fx;
+end;
+
+constructor TSecP521R1FieldElement.Create;
+begin
+  Inherited Create();
+  Fx := TNat.Create(17);
+end;
+
+constructor TSecP521R1FieldElement.Create(const X: TBigInteger);
+begin
+  if ((not(X.IsInitialized)) or (X.SignValue < 0) or (X.CompareTo(Q) >= 0)) then
+  begin
+    raise EArgumentCryptoLibException.CreateResFmt
+      (@SInvalidValueForSecP521R1FieldElement, ['x']);
+  end;
+  Inherited Create();
+  Fx := TSecP521R1Field.FromBigInteger(X);
+end;
+
+constructor TSecP521R1FieldElement.Create(X: TCryptoLibUInt32Array);
+begin
+  Inherited Create();
+  Fx := X;
+end;
+
+function TSecP521R1FieldElement.GetFieldName: string;
+begin
+  result := 'SecP521R1Field';
+end;
+
+function TSecP521R1FieldElement.GetFieldSize: Int32;
+begin
+  result := Q.BitLength;
+end;
+
+function TSecP521R1FieldElement.GetHashCode: {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}
+begin
+  result := Q.GetHashCode() xor TArrayUtils.GetArrayHashCode(Fx, 0, 17);
+end;
+
+function TSecP521R1FieldElement.GetIsOne: Boolean;
+begin
+  result := TNat.IsOne(17, Fx);
+end;
+
+function TSecP521R1FieldElement.GetIsZero: Boolean;
+begin
+  result := TNat.IsZero(17, Fx);
+end;
+
+function TSecP521R1FieldElement.Sqrt: IECFieldElement;
+var
+  x1, t1, t2: TCryptoLibUInt32Array;
+begin
+  // Raise this element to the exponent 2^519
+  x1 := Fx;
+  if ((TNat.IsZero(17, x1)) or (TNat.IsOne(17, x1))) then
+  begin
+    result := Self as IECFieldElement;
+    Exit;
+  end;
+
+  t1 := TNat.Create(17);
+  t2 := TNat.Create(17);
+
+  TSecP521R1Field.SquareN(x1, 519, t1);
+  TSecP521R1Field.Square(t1, t2);
+
+  if TNat.Eq(17, x1, t2) then
+  begin
+    result := TSecP521R1FieldElement.Create(t1);
+  end
+  else
+  begin
+    result := Nil;
+  end;
+end;
+
+function TSecP521R1FieldElement.TestBitZero: Boolean;
+begin
+  result := TNat.GetBit(Fx, 0) = 1;
+end;
+
+function TSecP521R1FieldElement.ToBigInteger: TBigInteger;
+begin
+  result := TNat.ToBigInteger(17, Fx);
+end;
+
+function TSecP521R1FieldElement.Add(const b: IECFieldElement): IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.Create(17);
+  TSecP521R1Field.Add(Fx, (b as ISecP521R1FieldElement).X, z);
+  result := TSecP521R1FieldElement.Create(z);
+end;
+
+function TSecP521R1FieldElement.AddOne: IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.Create(17);
+  TSecP521R1Field.AddOne(Fx, z);
+  result := TSecP521R1FieldElement.Create(z);
+end;
+
+function TSecP521R1FieldElement.Subtract(const b: IECFieldElement)
+  : IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.Create(17);
+  TSecP521R1Field.Subtract(Fx, (b as ISecP521R1FieldElement).X, z);
+  result := TSecP521R1FieldElement.Create(z);
+end;
+
+function TSecP521R1FieldElement.Multiply(const b: IECFieldElement)
+  : IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.Create(17);
+  TSecP521R1Field.Multiply(Fx, (b as ISecP521R1FieldElement).X, z);
+  result := TSecP521R1FieldElement.Create(z);
+end;
+
+function TSecP521R1FieldElement.Divide(const b: IECFieldElement)
+  : IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.Create(17);
+  TMod.Invert(TSecP521R1Field.P, (b as ISecP521R1FieldElement).X, z);
+  TSecP521R1Field.Multiply(z, Fx, z);
+  result := TSecP521R1FieldElement.Create(z);
+end;
+
+function TSecP521R1FieldElement.Negate: IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.Create(17);
+  TSecP521R1Field.Negate(Fx, z);
+  result := TSecP521R1FieldElement.Create(z);
+end;
+
+function TSecP521R1FieldElement.Square: IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.Create(17);
+  TSecP521R1Field.Square(Fx, z);
+  result := TSecP521R1FieldElement.Create(z);
+end;
+
+function TSecP521R1FieldElement.Invert: IECFieldElement;
+var
+  z: TCryptoLibUInt32Array;
+begin
+  z := TNat.Create(17);
+  TMod.Invert(TSecP521R1Field.P, Fx, z);
+  result := TSecP521R1FieldElement.Create(z);
+end;
+
+function TSecP521R1FieldElement.Equals(const other
+  : ISecP521R1FieldElement): Boolean;
+begin
+  if ((Self as ISecP521R1FieldElement) = other) then
+  begin
+    result := true;
+    Exit;
+  end;
+  if (other = Nil) then
+  begin
+    result := false;
+    Exit;
+  end;
+  result := TNat.Eq(17, Fx, other.X);
+end;
+
+function TSecP521R1FieldElement.Equals(const other: IECFieldElement): Boolean;
+begin
+  result := Equals(other as ISecP521R1FieldElement);
+end;
+
+end.

+ 400 - 0
CryptoLib/src/Math/EC/Custom/Sec/ClpSecP521R1Point.pas

@@ -0,0 +1,400 @@
+{ *********************************************************************************** }
+{ *                              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 ClpSecP521R1Point;
+
+{$I ..\..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpNat,
+  ClpECPoint,
+  ClpSecP521R1Field,
+  ClpISecP521R1Point,
+  ClpISecP521R1FieldElement,
+  ClpIECFieldElement,
+  ClpIECInterface,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SOneOfECFieldElementIsNil = 'Exactly One of the Field Elements is Nil';
+
+type
+  TSecP521R1Point = class sealed(TAbstractFpPoint, ISecP521R1Point)
+
+  strict protected
+    function Detach(): IECPoint; override;
+
+  public
+
+    /// <summary>
+    /// Create a point which encodes without point compression.
+    /// </summary>
+    /// <param name="curve">
+    /// the curve to use
+    /// </param>
+    /// <param name="x">
+    /// affine x co-ordinate
+    /// </param>
+    /// <param name="y">
+    /// affine y co-ordinate
+    /// </param>
+    constructor Create(const curve: IECCurve; const x, y: IECFieldElement);
+      overload; deprecated 'Use ECCurve.createPoint to construct points';
+
+    /// <summary>
+    /// Create a point that encodes with or without point compresion.
+    /// </summary>
+    /// <param name="curve">
+    /// the curve to use
+    /// </param>
+    /// <param name="x">
+    /// affine x co-ordinate
+    /// </param>
+    /// <param name="y">
+    /// affine y co-ordinate
+    /// </param>
+    /// <param name="withCompression">
+    /// if true encode with point compression
+    /// </param>
+    constructor Create(const curve: IECCurve; const x, y: IECFieldElement;
+      withCompression: Boolean); overload;
+      deprecated
+      'Per-point compression property will be removed, see GetEncoded(boolean)';
+
+    constructor Create(const curve: IECCurve; const x, y: IECFieldElement;
+      zs: TCryptoLibGenericArray<IECFieldElement>;
+      withCompression: Boolean); overload;
+
+    function Add(const b: IECPoint): IECPoint; override;
+    function Negate(): IECPoint; override;
+
+    function Twice(): IECPoint; override;
+    function TwicePlus(const b: IECPoint): IECPoint; override;
+
+    function ThreeTimes(): IECPoint; override;
+
+  end;
+
+implementation
+
+uses
+  // included here to avoid circular dependency :)
+  ClpSecP521R1FieldElement;
+
+{ TSecP521R1Point }
+
+constructor TSecP521R1Point.Create(const curve: IECCurve;
+  const x, y: IECFieldElement);
+begin
+  Create(curve, x, y, false);
+end;
+
+constructor TSecP521R1Point.Create(const curve: IECCurve;
+  const x, y: IECFieldElement; withCompression: Boolean);
+begin
+  Inherited Create(curve, x, y, withCompression);
+  if ((x = Nil) <> (y = Nil)) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SOneOfECFieldElementIsNil);
+  end;
+end;
+
+constructor TSecP521R1Point.Create(const curve: IECCurve;
+  const x, y: IECFieldElement; zs: TCryptoLibGenericArray<IECFieldElement>;
+  withCompression: Boolean);
+begin
+  Inherited Create(curve, x, y, zs, withCompression);
+end;
+
+function TSecP521R1Point.Add(const b: IECPoint): IECPoint;
+var
+  Lcurve: IECCurve;
+  X1, Y1, X2, Y2, Z1, Z2, X3, Y3, Z3: ISecP521R1FieldElement;
+  t1, t2, t3, t4, U2, S2, U1, S1, H, R, HSquared, G, V: TCryptoLibUInt32Array;
+  Z1IsOne, Z2IsOne: Boolean;
+  zs: TCryptoLibGenericArray<IECFieldElement>;
+begin
+  if (IsInfinity) then
+  begin
+    result := b;
+    Exit;
+  end;
+  if (b.IsInfinity) then
+  begin
+    result := Self as IECPoint;
+    Exit;
+  end;
+  if ((Self as IECPoint) = b) then
+  begin
+    result := Twice();
+    Exit;
+  end;
+
+  Lcurve := curve;
+
+  X1 := RawXCoord as ISecP521R1FieldElement;
+  Y1 := RawYCoord as ISecP521R1FieldElement;
+  X2 := b.RawXCoord as ISecP521R1FieldElement;
+  Y2 := b.RawYCoord as ISecP521R1FieldElement;
+
+  Z1 := RawZCoords[0] as ISecP521R1FieldElement;
+  Z2 := b.RawZCoords[0] as ISecP521R1FieldElement;
+
+  t1 := TNat.Create(17);
+  t2 := TNat.Create(17);
+  t3 := TNat.Create(17);
+  t4 := TNat.Create(17);
+
+  Z1IsOne := Z1.IsOne;
+
+  if (Z1IsOne) then
+  begin
+    U2 := X2.x;
+    S2 := Y2.x;
+  end
+  else
+  begin
+    S2 := t3;
+    TSecP521R1Field.Square(Z1.x, S2);
+
+    U2 := t2;
+    TSecP521R1Field.Multiply(S2, X2.x, U2);
+
+    TSecP521R1Field.Multiply(S2, Z1.x, S2);
+    TSecP521R1Field.Multiply(S2, Y2.x, S2);
+  end;
+
+  Z2IsOne := Z2.IsOne;
+  if (Z2IsOne) then
+  begin
+    U1 := X1.x;
+    S1 := Y1.x;
+  end
+  else
+  begin
+    S1 := t4;
+    TSecP521R1Field.Square(Z2.x, S1);
+
+    U1 := t1;
+    TSecP521R1Field.Multiply(S1, X1.x, U1);
+
+    TSecP521R1Field.Multiply(S1, Z2.x, S1);
+    TSecP521R1Field.Multiply(S1, Y1.x, S1);
+  end;
+
+  H := TNat.Create(17);
+  TSecP521R1Field.Subtract(U1, U2, H);
+
+  R := t2;
+  TSecP521R1Field.Subtract(S1, S2, R);
+
+  // Check if b = Self or b = -Self
+  if (TNat.IsZero(17, H)) then
+  begin
+    if (TNat.IsZero(17, R)) then
+    begin
+      // Self = b, i.e. Self must be doubled
+      result := Twice();
+      Exit;
+    end;
+
+    // Self = -b, i.e. the result is the point at infinity
+    result := Lcurve.Infinity;
+    Exit;
+  end;
+
+  HSquared := t3;
+  TSecP521R1Field.Square(H, HSquared);
+
+  G := TNat.Create(17);
+  TSecP521R1Field.Multiply(HSquared, H, G);
+
+  V := t3;
+  TSecP521R1Field.Multiply(HSquared, U1, V);
+
+  TSecP521R1Field.Multiply(S1, G, t1);
+
+  X3 := TSecP521R1FieldElement.Create(t4);
+  TSecP521R1Field.Square(R, X3.x);
+  TSecP521R1Field.Add(X3.x, G, X3.x);
+  TSecP521R1Field.Subtract(X3.x, V, X3.x);
+  TSecP521R1Field.Subtract(X3.x, V, X3.x);
+
+  Y3 := TSecP521R1FieldElement.Create(G);
+  TSecP521R1Field.Subtract(V, X3.x, Y3.x);
+  TSecP521R1Field.Multiply(Y3.x, R, t2);
+  TSecP521R1Field.Subtract(t2, t1, Y3.x);
+
+  Z3 := TSecP521R1FieldElement.Create(H);
+  if (not(Z1IsOne)) then
+  begin
+    TSecP521R1Field.Multiply(Z3.x, Z1.x, Z3.x);
+  end;
+  if (not(Z2IsOne)) then
+  begin
+    TSecP521R1Field.Multiply(Z3.x, Z2.x, Z3.x);
+  end;
+
+  zs := TCryptoLibGenericArray<IECFieldElement>.Create(Z3);
+
+  result := TSecP521R1Point.Create(Lcurve, X3, Y3, zs, IsCompressed)
+    as IECPoint;
+end;
+
+function TSecP521R1Point.Detach: IECPoint;
+begin
+  result := TSecP521R1Point.Create(Nil, AffineXCoord, AffineYCoord) as IECPoint;
+end;
+
+function TSecP521R1Point.Negate: IECPoint;
+begin
+  if (IsInfinity) then
+  begin
+    result := Self as IECPoint;
+    Exit;
+  end;
+
+  result := TSecP521R1Point.Create(curve, RawXCoord, RawYCoord.Negate(),
+    RawZCoords, IsCompressed) as IECPoint;
+end;
+
+function TSecP521R1Point.ThreeTimes: IECPoint;
+begin
+  if ((IsInfinity) or (RawYCoord.IsZero)) then
+  begin
+    result := Self as IECPoint;
+    Exit;
+  end;
+
+  // NOTE: Be careful about recursions between TwicePlus and ThreeTimes
+  result := Twice().Add(Self as IECPoint);
+end;
+
+function TSecP521R1Point.Twice: IECPoint;
+var
+  Lcurve: IECCurve;
+  Y1, X1, Z1, X3, Y3, Z3: ISecP521R1FieldElement;
+  Y1Squared, Z1Squared, T, M, S, t1, t2: TCryptoLibUInt32Array;
+  Z1IsOne: Boolean;
+begin
+
+  if (IsInfinity) then
+  begin
+    result := Self as IECPoint;
+    Exit;
+  end;
+
+  Lcurve := curve;
+
+  Y1 := RawYCoord as ISecP521R1FieldElement;
+  if (Y1.IsZero) then
+  begin
+    result := Lcurve.Infinity;
+    Exit;
+  end;
+
+  X1 := RawXCoord as ISecP521R1FieldElement;
+  Z1 := RawZCoords[0] as ISecP521R1FieldElement;
+
+  t1 := TNat.Create(17);
+  t2 := TNat.Create(17);
+  Y1Squared := TNat.Create(17);
+  TSecP521R1Field.Square(Y1.x, Y1Squared);
+
+  T := TNat.Create(17);
+  TSecP521R1Field.Square(Y1Squared, T);
+
+  Z1IsOne := Z1.IsOne;
+
+  Z1Squared := Z1.x;
+  if (not(Z1IsOne)) then
+  begin
+    Z1Squared := t2;
+    TSecP521R1Field.Square(Z1.x, Z1Squared);
+  end;
+
+  TSecP521R1Field.Subtract(X1.x, Z1Squared, t1);
+
+  M := t2;
+  TSecP521R1Field.Add(X1.x, Z1Squared, M);
+  TSecP521R1Field.Multiply(M, t1, M);
+  TNat.AddBothTo(17, M, M, M);
+  TSecP521R1Field.Reduce23(M);
+
+  S := Y1Squared;
+  TSecP521R1Field.Multiply(Y1Squared, X1.x, S);
+  TNat.ShiftUpBits(17, S, 2, 0);
+  TSecP521R1Field.Reduce23(S);
+
+  TNat.ShiftUpBits(17, T, 3, 0, t1);
+  TSecP521R1Field.Reduce23(t1);
+
+  X3 := TSecP521R1FieldElement.Create(T);
+  TSecP521R1Field.Square(M, X3.x);
+  TSecP521R1Field.Subtract(X3.x, S, X3.x);
+  TSecP521R1Field.Subtract(X3.x, S, X3.x);
+
+  Y3 := TSecP521R1FieldElement.Create(S);
+  TSecP521R1Field.Subtract(S, X3.x, Y3.x);
+  TSecP521R1Field.Multiply(Y3.x, M, Y3.x);
+  TSecP521R1Field.Subtract(Y3.x, t1, Y3.x);
+
+  Z3 := TSecP521R1FieldElement.Create(M);
+  TSecP521R1Field.Twice(Y1.x, Z3.x);
+  if (not(Z1IsOne)) then
+  begin
+    TSecP521R1Field.Multiply(Z3.x, Z1.x, Z3.x);
+  end;
+
+  result := TSecP521R1Point.Create(Lcurve, X3, Y3,
+    TCryptoLibGenericArray<IECFieldElement>.Create(Z3), IsCompressed)
+    as IECPoint;
+end;
+
+function TSecP521R1Point.TwicePlus(const b: IECPoint): IECPoint;
+var
+  Y1: IECFieldElement;
+begin
+  if ((Self as IECPoint) = b) then
+  begin
+    result := ThreeTimes();
+    Exit;
+  end;
+  if (IsInfinity) then
+  begin
+    result := b;
+    Exit;
+  end;
+  if (b.IsInfinity) then
+  begin
+    result := Twice();
+    Exit;
+  end;
+
+  Y1 := RawYCoord;
+  if (Y1.IsZero) then
+  begin
+    result := b;
+    Exit;
+  end;
+
+  result := Twice().Add(b);
+end;
+
+end.

+ 533 - 0
CryptoLib/src/Math/EC/Custom/Sec/ClpSecT283Field.pas

@@ -0,0 +1,533 @@
+{ *********************************************************************************** }
+{ *                              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 ClpSecT283Field;
+
+{$I ..\..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpBits,
+  ClpNat,
+  ClpNat320,
+  ClpInterleave,
+  ClpBigInteger,
+  ClpCryptoLibTypes;
+
+type
+  TSecT283Field = class sealed(TObject)
+
+  strict private
+  const
+    M27 = UInt64(System.High(UInt64) shr 37);
+    M57 = UInt64(System.High(UInt64) shr 7);
+
+    class var
+
+      FROOT_Z: TCryptoLibUInt64Array;
+
+    class procedure ImplCompactExt(zz: TCryptoLibUInt64Array); static;
+    class procedure ImplExpand(x, z: TCryptoLibUInt64Array); static; inline;
+    class procedure ImplMultiply(x, y, zz: TCryptoLibUInt64Array); static;
+    class procedure ImplMulw(x, y: UInt64; z: TCryptoLibUInt64Array;
+      zOff: Int32); static;
+
+    class procedure ImplSquare(x, zz: TCryptoLibUInt64Array); static; inline;
+
+    class constructor SecT283Field();
+
+  public
+    class procedure Add(x, y, z: TCryptoLibUInt64Array); static; inline;
+    class procedure AddExt(xx, yy, zz: TCryptoLibUInt64Array); static; inline;
+    class procedure AddOne(x, z: TCryptoLibUInt64Array); static; inline;
+    class function FromBigInteger(const x: TBigInteger): TCryptoLibUInt64Array;
+      static; inline;
+
+    class procedure Invert(x, z: TCryptoLibUInt64Array); static;
+    class procedure Multiply(x, y, z: TCryptoLibUInt64Array); static; inline;
+    class procedure MultiplyAddToExt(x, y, zz: TCryptoLibUInt64Array);
+      static; inline;
+    class procedure Reduce(xx, z: TCryptoLibUInt64Array); static;
+    class procedure Reduce37(z: TCryptoLibUInt64Array; zOff: Int32);
+      static; inline;
+    class procedure Sqrt(x, z: TCryptoLibUInt64Array); static;
+
+    class procedure Square(x, z: TCryptoLibUInt64Array); static; inline;
+    class procedure SquareAddToExt(x, zz: TCryptoLibUInt64Array);
+      static; inline;
+    class procedure SquareN(x: TCryptoLibUInt64Array; n: Int32;
+      z: TCryptoLibUInt64Array); static; inline;
+
+    class function Trace(x: TCryptoLibUInt64Array): UInt32; static; inline;
+
+  end;
+
+implementation
+
+{ TSecT283Field }
+
+class constructor TSecT283Field.SecT283Field;
+begin
+  FROOT_Z := TCryptoLibUInt64Array.Create(UInt64($0C30C30C30C30808),
+    UInt64($30C30C30C30C30C3), UInt64($820820820820830C),
+    UInt64($0820820820820820), UInt64($2082082));
+end;
+
+class procedure TSecT283Field.Reduce37(z: TCryptoLibUInt64Array; zOff: Int32);
+var
+  z4, t: UInt64;
+begin
+  z4 := z[zOff + 4];
+  t := z4 shr 27;
+  z[zOff] := z[zOff] xor (t xor (t shl 5) xor (t shl 7) xor (t shl 12));
+  z[zOff + 4] := z4 and M27;
+end;
+
+class procedure TSecT283Field.Add(x, y, z: TCryptoLibUInt64Array);
+begin
+  z[0] := x[0] xor y[0];
+  z[1] := x[1] xor y[1];
+  z[2] := x[2] xor y[2];
+  z[3] := x[3] xor y[3];
+  z[4] := x[4] xor y[4];
+end;
+
+class procedure TSecT283Field.AddExt(xx, yy, zz: TCryptoLibUInt64Array);
+begin
+  zz[0] := xx[0] xor yy[0];
+  zz[1] := xx[1] xor yy[1];
+  zz[2] := xx[2] xor yy[2];
+  zz[3] := xx[3] xor yy[3];
+  zz[4] := xx[4] xor yy[4];
+  zz[5] := xx[5] xor yy[5];
+  zz[6] := xx[6] xor yy[6];
+  zz[7] := xx[7] xor yy[7];
+  zz[8] := xx[8] xor yy[8];
+end;
+
+class procedure TSecT283Field.AddOne(x, z: TCryptoLibUInt64Array);
+begin
+  z[0] := x[0] xor UInt64(1);
+  z[1] := x[1];
+  z[2] := x[2];
+  z[3] := x[3];
+  z[4] := x[4];
+end;
+
+class function TSecT283Field.FromBigInteger(const x: TBigInteger)
+  : TCryptoLibUInt64Array;
+var
+  z: TCryptoLibUInt64Array;
+begin
+  z := TNat320.FromBigInteger64(x);
+  Reduce37(z, 0);
+  result := z;
+end;
+
+class procedure TSecT283Field.Multiply(x, y, z: TCryptoLibUInt64Array);
+var
+  tt: TCryptoLibUInt64Array;
+begin
+  tt := TNat320.CreateExt64();
+  ImplMultiply(x, y, tt);
+  Reduce(tt, z);
+end;
+
+class procedure TSecT283Field.ImplSquare(x, zz: TCryptoLibUInt64Array);
+var
+  i: Int32;
+begin
+  for i := 0 to System.Pred(4) do
+  begin
+    TInterleave.Expand64To128(x[i], zz, i shl 1);
+  end;
+
+  zz[8] := TInterleave.Expand32to64(UInt32(x[4]));
+end;
+
+class procedure TSecT283Field.Square(x, z: TCryptoLibUInt64Array);
+var
+  tt: TCryptoLibUInt64Array;
+begin
+  tt := TNat.Create64(9);
+  ImplSquare(x, tt);
+  Reduce(tt, z);
+end;
+
+class procedure TSecT283Field.SquareN(x: TCryptoLibUInt64Array; n: Int32;
+  z: TCryptoLibUInt64Array);
+var
+  tt: TCryptoLibUInt64Array;
+begin
+{$IFDEF DEBUG}
+  System.Assert(n > 0);
+{$ENDIF DEBUG}
+  tt := TNat.Create64(9);
+  ImplSquare(x, tt);
+  Reduce(tt, z);
+
+  System.Dec(n);
+  while (n > 0) do
+  begin
+    ImplSquare(z, tt);
+    Reduce(tt, z);
+    System.Dec(n);
+  end;
+end;
+
+class procedure TSecT283Field.Invert(x, z: TCryptoLibUInt64Array);
+var
+  t0, t1: TCryptoLibUInt64Array;
+begin
+  if TNat320.IsZero64(x) then
+  begin
+    raise EInvalidOperationCryptoLibException.Create('');
+  end;
+
+  // Itoh-Tsujii inversion
+
+  t0 := TNat320.Create64();
+  t1 := TNat320.Create64();
+
+  Square(x, t0);
+  Multiply(t0, x, t0);
+  SquareN(t0, 2, t1);
+  Multiply(t1, t0, t1);
+  SquareN(t1, 4, t0);
+  Multiply(t0, t1, t0);
+  SquareN(t0, 8, t1);
+  Multiply(t1, t0, t1);
+  Square(t1, t1);
+  Multiply(t1, x, t1);
+  SquareN(t1, 17, t0);
+  Multiply(t0, t1, t0);
+  Square(t0, t0);
+  Multiply(t0, x, t0);
+  SquareN(t0, 35, t1);
+  Multiply(t1, t0, t1);
+  SquareN(t1, 70, t0);
+  Multiply(t0, t1, t0);
+  Square(t0, t0);
+  Multiply(t0, x, t0);
+  SquareN(t0, 141, t1);
+  Multiply(t1, t0, t1);
+  Square(t1, z);
+end;
+
+class procedure TSecT283Field.ImplCompactExt(zz: TCryptoLibUInt64Array);
+var
+  z0, z1, z2, z3, z4, z5, z6, z7, z8, z9: UInt64;
+begin
+  z0 := zz[0];
+  z1 := zz[1];
+  z2 := zz[2];
+  z3 := zz[3];
+  z4 := zz[4];
+  z5 := zz[5];
+  z6 := zz[6];
+  z7 := zz[7];
+  z8 := zz[8];
+  z9 := zz[9];
+  zz[0] := z0 xor (z1 shl 57);
+  zz[1] := (z1 shr 7) xor (z2 shl 50);
+  zz[2] := (z2 shr 14) xor (z3 shl 43);
+  zz[3] := (z3 shr 21) xor (z4 shl 36);
+  zz[4] := (z4 shr 28) xor (z5 shl 29);
+  zz[5] := (z5 shr 35) xor (z6 shl 22);
+  zz[6] := (z6 shr 42) xor (z7 shl 15);
+  zz[7] := (z7 shr 49) xor (z8 shl 8);
+  zz[8] := (z8 shr 56) xor (z9 shl 1);
+  zz[9] := (z9 shr 63); // Zero!
+end;
+
+class procedure TSecT283Field.ImplExpand(x, z: TCryptoLibUInt64Array);
+var
+  x0, x1, x2, x3, x4: UInt64;
+begin
+  x0 := x[0];
+  x1 := x[1];
+  x2 := x[2];
+  x3 := x[3];
+  x4 := x[4];
+  z[0] := x0 and M57;
+  z[1] := ((x0 shr 57) xor (x1 shl 7)) and M57;
+  z[2] := ((x1 shr 50) xor (x2 shl 14)) and M57;
+  z[3] := ((x2 shr 43) xor (x3 shl 21)) and M57;
+  z[4] := ((x3 shr 36) xor (x4 shl 28));
+end;
+
+class procedure TSecT283Field.ImplMultiply(x, y, zz: TCryptoLibUInt64Array);
+var
+  a, b, p: TCryptoLibUInt64Array;
+  u0, u1, u2, u3, v0, v1, v2, v3, A4, A5, B4, B5, t1, t2, t3, t4, t5, t6, t7,
+    t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t20, t21, t22,
+    t23, t24, t25, t26, t27, t28, t29, t30, t31, t32, t33, t34, t35, t36, t37,
+    t38, t39: UInt64;
+begin
+  // /*
+  // * Formula (17) from "Some New Results on Binary Polynomial Multiplication",
+  // * Murat Cenk and M. Anwar Hasan.
+  // *
+  // * The formula as given contained an error in the term t25, as noted below
+  // */
+  System.SetLength(a, 5);
+  System.SetLength(b, 5);
+  ImplExpand(x, a);
+  ImplExpand(y, b);
+
+  System.SetLength(p, 26);
+
+  ImplMulw(a[0], b[0], p, 0); // m1
+  ImplMulw(a[1], b[1], p, 2); // m2
+  ImplMulw(a[2], b[2], p, 4); // m3
+  ImplMulw(a[3], b[3], p, 6); // m4
+  ImplMulw(a[4], b[4], p, 8); // m5
+
+  u0 := a[0] xor a[1];
+  v0 := b[0] xor b[1];
+  u1 := a[0] xor a[2];
+  v1 := b[0] xor b[2];
+  u2 := a[2] xor a[4];
+  v2 := b[2] xor b[4];
+  u3 := a[3] xor a[4];
+  v3 := b[3] xor b[4];
+
+  ImplMulw(u1 xor a[3], v1 xor b[3], p, 18); // m10
+  ImplMulw(u2 xor a[1], v2 xor b[1], p, 20); // m11
+
+  A4 := u0 xor u3;
+  B4 := v0 xor v3;
+  A5 := A4 xor a[2];
+  B5 := B4 xor b[2];
+
+  ImplMulw(A4, B4, p, 22); // m12
+  ImplMulw(A5, B5, p, 24); // m13
+
+  ImplMulw(u0, v0, p, 10); // m6
+  ImplMulw(u1, v1, p, 12); // m7
+  ImplMulw(u2, v2, p, 14); // m8
+  ImplMulw(u3, v3, p, 16); // m9
+
+
+  // Improved method factors out common single-word terms
+  // NOTE: p1,...,p26 in the paper maps to p[0],...,p[25] here
+
+  zz[0] := p[0];
+  zz[9] := p[9];
+
+  t1 := p[0] xor p[1];
+  t2 := t1 xor p[2];
+  t3 := t2 xor p[10];
+
+  zz[1] := t3;
+
+  t4 := p[3] xor p[4];
+  t5 := p[11] xor p[12];
+  t6 := t4 xor t5;
+  t7 := t2 xor t6;
+
+  zz[2] := t7;
+
+  t8 := t1 xor t4;
+  t9 := p[5] xor p[6];
+  t10 := t8 xor t9;
+  t11 := t10 xor p[8];
+  t12 := p[13] xor p[14];
+  t13 := t11 xor t12;
+  t14 := p[18] xor p[22];
+  t15 := t14 xor p[24];
+  t16 := t13 xor t15;
+
+  zz[3] := t16;
+
+  t17 := p[7] xor p[8];
+  t18 := t17 xor p[9];
+  t19 := t18 xor p[17];
+
+  zz[8] := t19;
+
+  t20 := t18 xor t9;
+  t21 := p[15] xor p[16];
+  t22 := t20 xor t21;
+
+  zz[7] := t22;
+
+  t23 := t22 xor t3;
+  t24 := p[19] xor p[20];
+  // t25 := p[23] xor  p[24];
+  t25 := p[25] xor p[24]; // Fixes an error in the paper: p[23] -> p{25]
+  t26 := p[18] xor p[23];
+  t27 := t24 xor t25;
+  t28 := t27 xor t26;
+  t29 := t28 xor t23;
+
+  zz[4] := t29;
+
+  t30 := t7 xor t19;
+  t31 := t27 xor t30;
+  t32 := p[21] xor p[22];
+  t33 := t31 xor t32;
+
+  zz[5] := t33;
+
+  t34 := t11 xor p[0];
+  t35 := t34 xor p[9];
+  t36 := t35 xor t12;
+  t37 := t36 xor p[21];
+  t38 := t37 xor p[23];
+  t39 := t38 xor p[25];
+
+  zz[6] := t39;
+
+  ImplCompactExt(zz);
+end;
+
+class procedure TSecT283Field.ImplMulw(x, y: UInt64; z: TCryptoLibUInt64Array;
+  zOff: Int32);
+var
+  u: TCryptoLibUInt64Array;
+  j: UInt32;
+  g, h, l: UInt64;
+  k: Int32;
+begin
+{$IFDEF DEBUG}
+  System.Assert((x shr 57) = 0);
+  System.Assert((y shr 57) = 0);
+{$ENDIF DEBUG}
+  System.SetLength(u, 8);
+  // u[0] := 0;
+  u[1] := y;
+  u[2] := u[1] shl 1;
+  u[3] := u[2] xor y;
+  u[4] := u[2] shl 1;
+  u[5] := u[4] xor y;
+  u[6] := u[3] shl 1;
+  u[7] := u[6] xor y;
+
+  j := UInt32(x);
+  h := 0;
+  l := u[j and 7];
+  k := 48;
+
+  repeat
+
+    j := UInt32(x shr k);
+    g := u[j and 7] xor u[(j shr 3) and 7] shl 3 xor u[(j shr 6) and 7] shl 6;
+    l := l xor ((g shl k));
+    h := h xor TBits.NegativeRightShift64(g, -k);
+
+    System.Dec(k, 9);
+  until not(k > 0);
+
+  h := h xor (((x and Int64($0100804020100800)) and
+    UInt64(TBits.Asr64(Int64(y) shl 7, 63))) shr 8);
+
+{$IFDEF DEBUG}
+  System.Assert((h shr 49) = 0);
+{$ENDIF DEBUG}
+  z[zOff] := l and M57;
+  z[zOff + 1] := (l shr 57) xor (h shl 7);
+end;
+
+class procedure TSecT283Field.MultiplyAddToExt(x, y, zz: TCryptoLibUInt64Array);
+var
+  tt: TCryptoLibUInt64Array;
+begin
+  tt := TNat320.CreateExt64();
+  ImplMultiply(x, y, tt);
+  AddExt(zz, tt, zz);
+end;
+
+class procedure TSecT283Field.Reduce(xx, z: TCryptoLibUInt64Array);
+var
+  x0, x1, x2, x3, x4, x5, x6, x7, x8, t: UInt64;
+begin
+  x0 := xx[0];
+  x1 := xx[1];
+  x2 := xx[2];
+  x3 := xx[3];
+  x4 := xx[4];
+  x5 := xx[5];
+  x6 := xx[6];
+  x7 := xx[7];
+  x8 := xx[8];
+
+  x3 := x3 xor ((x8 shl 37) xor (x8 shl 42) xor (x8 shl 44) xor (x8 shl 49));
+  x4 := x4 xor ((x8 shr 27) xor (x8 shr 22) xor (x8 shr 20) xor (x8 shr 15));
+
+  x2 := x2 xor ((x7 shl 37) xor (x7 shl 42) xor (x7 shl 44) xor (x7 shl 49));
+  x3 := x3 xor ((x7 shr 27) xor (x7 shr 22) xor (x7 shr 20) xor (x7 shr 15));
+
+  x1 := x1 xor ((x6 shl 37) xor (x6 shl 42) xor (x6 shl 44) xor (x6 shl 49));
+  x2 := x2 xor ((x6 shr 27) xor (x6 shr 22) xor (x6 shr 20) xor (x6 shr 15));
+
+  x0 := x0 xor ((x5 shl 37) xor (x5 shl 42) xor (x5 shl 44) xor (x5 shl 49));
+  x1 := x1 xor ((x5 shr 27) xor (x5 shr 22) xor (x5 shr 20) xor (x5 shr 15));
+
+  t := x4 shr 27;
+  z[0] := x0 xor t xor (t shl 5) xor (t shl 7) xor (t shl 12);
+  z[1] := x1;
+  z[2] := x2;
+  z[3] := x3;
+  z[4] := x4 and M27;
+end;
+
+class procedure TSecT283Field.Sqrt(x, z: TCryptoLibUInt64Array);
+var
+  u0, u1, e0, e1, e2: UInt64;
+  odd: TCryptoLibUInt64Array;
+begin
+  odd := TNat320.Create64();
+
+  u0 := TInterleave.Unshuffle(x[0]);
+  u1 := TInterleave.Unshuffle(x[1]);
+  e0 := (u0 and UInt64($00000000FFFFFFFF)) or (u1 shl 32);
+  odd[0] := (u0 shr 32) or (u1 and UInt64($FFFFFFFF00000000));
+
+  u0 := TInterleave.Unshuffle(x[2]);
+  u1 := TInterleave.Unshuffle(x[3]);
+  e1 := (u0 and UInt64($00000000FFFFFFFF)) or (u1 shl 32);
+  odd[1] := (u0 shr 32) or (u1 and UInt64($FFFFFFFF00000000));
+
+  u0 := TInterleave.Unshuffle(x[4]);
+  e2 := (u0 and UInt64($00000000FFFFFFFF));
+  odd[2] := (u0 shr 32);
+
+  Multiply(odd, FROOT_Z, z);
+
+  z[0] := z[0] xor e0;
+  z[1] := z[1] xor e1;
+  z[2] := z[2] xor e2;
+end;
+
+class procedure TSecT283Field.SquareAddToExt(x, zz: TCryptoLibUInt64Array);
+var
+  tt: TCryptoLibUInt64Array;
+begin
+  tt := TNat.Create64(9);
+  ImplSquare(x, tt);
+  AddExt(zz, tt, zz);
+end;
+
+class function TSecT283Field.Trace(x: TCryptoLibUInt64Array): UInt32;
+begin
+  // Non-zero-trace bits: 0, 271
+  result := UInt32(x[0] xor (x[4] shr 15)) and UInt32(1);
+end;
+
+end.

+ 381 - 0
CryptoLib/src/Math/EC/Custom/Sec/ClpSecT283FieldElement.pas

@@ -0,0 +1,381 @@
+{ *********************************************************************************** }
+{ *                              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 ClpSecT283FieldElement;
+
+{$I ..\..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpNat,
+  ClpNat320,
+  ClpECFieldElement,
+  ClpIECFieldElement,
+  ClpSecT283Field,
+  ClpISecT283FieldElement,
+  ClpBigInteger,
+  ClpArrayUtils,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SInvalidValueForSecT283FieldElement =
+    'Value Invalid for SecT283FieldElement "%s"';
+
+type
+  TSecT283FieldElement = class(TAbstractF2mFieldElement, ISecT283FieldElement)
+
+  strict private
+
+    function GetM: Int32; inline;
+
+    function GetRepresentation: Int32; inline;
+
+    function GetK1: Int32; inline;
+    function GetK2: Int32; inline;
+    function GetK3: Int32; inline;
+
+    function Equals(const other: ISecT283FieldElement): Boolean;
+      reintroduce; overload;
+
+  strict protected
+  var
+    Fx: TCryptoLibUInt64Array;
+
+    function GetFieldName: string; override;
+    function GetFieldSize: Int32; override;
+    function GetIsOne: Boolean; override;
+    function GetIsZero: Boolean; override;
+
+    function GetX: TCryptoLibUInt64Array; inline;
+    property X: TCryptoLibUInt64Array read GetX;
+
+  public
+    constructor Create(); overload;
+    constructor Create(const X: TBigInteger); overload;
+    constructor Create(X: TCryptoLibUInt64Array); overload;
+
+    function TestBitZero: Boolean; override;
+    function ToBigInteger(): TBigInteger; override;
+
+    function Add(const b: IECFieldElement): IECFieldElement; override;
+    function AddOne(): IECFieldElement; override;
+    function Subtract(const b: IECFieldElement): IECFieldElement; override;
+
+    function Multiply(const b: IECFieldElement): IECFieldElement; override;
+    function MultiplyMinusProduct(const b, X, y: IECFieldElement)
+      : IECFieldElement; override;
+    function MultiplyPlusProduct(const b, X, y: IECFieldElement)
+      : IECFieldElement; override;
+    function Divide(const b: IECFieldElement): IECFieldElement; override;
+    function Negate(): IECFieldElement; override;
+    function Square(): IECFieldElement; override;
+    function SquareMinusProduct(const X, y: IECFieldElement)
+      : IECFieldElement; override;
+    function SquarePlusProduct(const X, y: IECFieldElement)
+      : IECFieldElement; override;
+
+    function SquarePow(pow: Int32): IECFieldElement; override;
+
+    function Trace(): Int32; override;
+
+    function Invert(): IECFieldElement; override;
+
+    /// <summary>
+    /// return a sqrt root - the routine verifies that the calculation
+    /// returns the right value - if <br />none exists it returns null.
+    /// </summary>
+    function Sqrt(): IECFieldElement; override;
+
+    function Equals(const other: IECFieldElement): Boolean; overload; override;
+
+    function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}override;
+
+    property IsZero: Boolean read GetIsZero;
+    property IsOne: Boolean read GetIsOne;
+    property FieldName: string read GetFieldName;
+    property FieldSize: Int32 read GetFieldSize;
+
+    property Representation: Int32 read GetRepresentation;
+
+    property M: Int32 read GetM;
+
+    property k1: Int32 read GetK1;
+
+    property k2: Int32 read GetK2;
+
+    property k3: Int32 read GetK3;
+
+  end;
+
+implementation
+
+{ TSecT283FieldElement }
+
+function TSecT283FieldElement.Add(const b: IECFieldElement): IECFieldElement;
+var
+  z: TCryptoLibUInt64Array;
+begin
+  z := TNat320.Create64();
+  TSecT283Field.Add(Fx, (b as ISecT283FieldElement).X, z);
+  result := TSecT283FieldElement.Create(z);
+end;
+
+function TSecT283FieldElement.AddOne: IECFieldElement;
+var
+  z: TCryptoLibUInt64Array;
+begin
+  z := TNat320.Create64();
+  TSecT283Field.AddOne(Fx, z);
+  result := TSecT283FieldElement.Create(z);
+end;
+
+constructor TSecT283FieldElement.Create(const X: TBigInteger);
+begin
+  if ((not(X.IsInitialized)) or (X.SignValue < 0) or (X.BitLength > 283)) then
+  begin
+    raise EArgumentCryptoLibException.CreateResFmt
+      (@SInvalidValueForSecT283FieldElement, ['x']);
+  end;
+  Inherited Create();
+  Fx := TSecT283Field.FromBigInteger(X);
+end;
+
+constructor TSecT283FieldElement.Create;
+begin
+  Inherited Create();
+  Fx := TNat320.Create64();
+end;
+
+constructor TSecT283FieldElement.Create(X: TCryptoLibUInt64Array);
+begin
+  Inherited Create();
+  Fx := X;
+end;
+
+function TSecT283FieldElement.Divide(const b: IECFieldElement): IECFieldElement;
+begin
+  result := Multiply(b.Invert());
+end;
+
+function TSecT283FieldElement.Equals(const other: ISecT283FieldElement)
+  : Boolean;
+begin
+  if ((Self as ISecT283FieldElement) = other) then
+  begin
+    result := true;
+    Exit;
+  end;
+  if (other = Nil) then
+  begin
+    result := false;
+    Exit;
+  end;
+  result := TNat320.Eq64(Fx, other.X);
+end;
+
+function TSecT283FieldElement.Equals(const other: IECFieldElement): Boolean;
+begin
+  result := Equals(other as ISecT283FieldElement);
+end;
+
+function TSecT283FieldElement.GetFieldName: string;
+begin
+  result := 'SecT283Field';
+end;
+
+function TSecT283FieldElement.GetFieldSize: Int32;
+begin
+  result := 283;
+end;
+
+function TSecT283FieldElement.GetHashCode: {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}
+begin
+  result := 2831275 xor TArrayUtils.GetArrayHashCode(Fx, 0, 5);
+end;
+
+function TSecT283FieldElement.GetIsOne: Boolean;
+begin
+  result := TNat320.IsOne64(Fx);
+end;
+
+function TSecT283FieldElement.GetIsZero: Boolean;
+begin
+  result := TNat320.IsZero64(Fx);
+end;
+
+function TSecT283FieldElement.GetK1: Int32;
+begin
+  result := 5;
+end;
+
+function TSecT283FieldElement.GetK2: Int32;
+begin
+  result := 7;
+end;
+
+function TSecT283FieldElement.GetK3: Int32;
+begin
+  result := 12;
+end;
+
+function TSecT283FieldElement.GetM: Int32;
+begin
+  result := 283;
+end;
+
+function TSecT283FieldElement.GetRepresentation: Int32;
+begin
+  result := TF2mFieldElement.Ppb;
+end;
+
+function TSecT283FieldElement.GetX: TCryptoLibUInt64Array;
+begin
+  result := Fx;
+end;
+
+function TSecT283FieldElement.Invert: IECFieldElement;
+var
+  z: TCryptoLibUInt64Array;
+begin
+  z := TNat320.Create64();
+  TSecT283Field.Invert(Fx, z);
+  result := TSecT283FieldElement.Create(z);
+end;
+
+function TSecT283FieldElement.Multiply(const b: IECFieldElement)
+  : IECFieldElement;
+var
+  z: TCryptoLibUInt64Array;
+begin
+  z := TNat320.Create64();
+  TSecT283Field.Multiply(Fx, (b as ISecT283FieldElement).X, z);
+  result := TSecT283FieldElement.Create(z);
+end;
+
+function TSecT283FieldElement.MultiplyMinusProduct(const b, X,
+  y: IECFieldElement): IECFieldElement;
+begin
+  result := MultiplyPlusProduct(b, X, y);
+end;
+
+function TSecT283FieldElement.MultiplyPlusProduct(const b, X,
+  y: IECFieldElement): IECFieldElement;
+var
+  ax, bx, xx, yx, tt, z: TCryptoLibUInt64Array;
+begin
+  ax := Fx;
+  bx := (b as ISecT283FieldElement).X;
+  xx := (X as ISecT283FieldElement).X;
+  yx := (y as ISecT283FieldElement).X;
+
+  tt := TNat.Create64(9);
+  TSecT283Field.MultiplyAddToExt(ax, bx, tt);
+  TSecT283Field.MultiplyAddToExt(xx, yx, tt);
+
+  z := TNat320.Create64();
+  TSecT283Field.Reduce(tt, z);
+  result := TSecT283FieldElement.Create(z);
+end;
+
+function TSecT283FieldElement.Negate: IECFieldElement;
+begin
+  result := Self as IECFieldElement;
+end;
+
+function TSecT283FieldElement.Sqrt: IECFieldElement;
+var
+  z: TCryptoLibUInt64Array;
+begin
+  z := TNat320.Create64();
+  TSecT283Field.Sqrt(Fx, z);
+  result := TSecT283FieldElement.Create(z);
+end;
+
+function TSecT283FieldElement.Square: IECFieldElement;
+var
+  z: TCryptoLibUInt64Array;
+begin
+  z := TNat320.Create64();
+  TSecT283Field.Square(Fx, z);
+  result := TSecT283FieldElement.Create(z);
+end;
+
+function TSecT283FieldElement.SquareMinusProduct(const X, y: IECFieldElement)
+  : IECFieldElement;
+begin
+  result := SquarePlusProduct(X, y);
+end;
+
+function TSecT283FieldElement.SquarePlusProduct(const X, y: IECFieldElement)
+  : IECFieldElement;
+var
+  ax, xx, yx, tt, z: TCryptoLibUInt64Array;
+begin
+  ax := Fx;
+  xx := (X as ISecT283FieldElement).X;
+  yx := (y as ISecT283FieldElement).X;
+
+  tt := TNat.Create64(9);
+  TSecT283Field.SquareAddToExt(ax, tt);
+  TSecT283Field.MultiplyAddToExt(xx, yx, tt);
+
+  z := TNat320.Create64();
+  TSecT283Field.Reduce(tt, z);
+  result := TSecT283FieldElement.Create(z);
+end;
+
+function TSecT283FieldElement.SquarePow(pow: Int32): IECFieldElement;
+var
+  z: TCryptoLibUInt64Array;
+begin
+  if (pow < 1) then
+  begin
+    result := Self as IECFieldElement;
+    Exit;
+  end;
+
+  z := TNat320.Create64();
+  TSecT283Field.SquareN(Fx, pow, z);
+  result := TSecT283FieldElement.Create(z);
+end;
+
+function TSecT283FieldElement.Subtract(const b: IECFieldElement)
+  : IECFieldElement;
+begin
+  // Addition and subtraction are the same in F2m
+  result := Add(b);
+end;
+
+function TSecT283FieldElement.TestBitZero: Boolean;
+begin
+  result := (Fx[0] and UInt64(1)) <> UInt64(0);
+end;
+
+function TSecT283FieldElement.ToBigInteger: TBigInteger;
+begin
+  result := TNat320.ToBigInteger64(Fx);
+end;
+
+function TSecT283FieldElement.Trace: Int32;
+begin
+  result := Int32(TSecT283Field.Trace(Fx));
+end;
+
+end.

+ 283 - 0
CryptoLib/src/Math/EC/Custom/Sec/ClpSecT283K1Curve.pas

@@ -0,0 +1,283 @@
+{ *********************************************************************************** }
+{ *                              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 ClpSecT283K1Curve;
+
+{$I ..\..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpHex,
+  ClpBits,
+  ClpNat320,
+  ClpECCurve,
+  ClpIECInterface,
+  ClpSecT283FieldElement,
+  ClpISecT283FieldElement,
+  ClpSecT283K1Point,
+  ClpISecT283K1Curve,
+  ClpISecT283K1Point,
+  ClpIECFieldElement,
+  ClpWTauNafMultiplier,
+  ClpBigInteger,
+  ClpCryptoLibTypes;
+
+type
+  TSecT283K1Curve = class sealed(TAbstractF2mCurve, ISecT283K1Curve)
+
+  strict private
+
+  type
+    TSecT283K1LookupTable = class sealed(TInterfacedObject,
+      ISecT283K1LookupTable, IECLookupTable)
+
+    strict private
+    var
+      Fm_outer: ISecT283K1Curve;
+      Fm_table: TCryptoLibUInt64Array;
+      Fm_size: Int32;
+
+      function GetSize: Int32; virtual;
+
+    public
+
+      constructor Create(const outer: ISecT283K1Curve;
+        table: TCryptoLibUInt64Array; size: Int32);
+
+      function Lookup(index: Int32): IECPoint; virtual;
+
+      property size: Int32 read GetSize;
+
+    end;
+
+  const
+    SECT283K1_DEFAULT_COORDS = Int32(TECCurve.COORD_LAMBDA_PROJECTIVE);
+    SECT283K1_FE_LONGS = Int32(5);
+
+    function GetM: Int32; inline;
+    function GetK1: Int32; inline;
+    function GetK2: Int32; inline;
+    function GetK3: Int32; inline;
+    function GetIsTrinomial: Boolean; inline;
+
+  strict protected
+  var
+    Fm_infinity: ISecT283K1Point;
+
+    function GetFieldSize: Int32; override;
+    function GetInfinity: IECPoint; override;
+    function GetIsKoblitz: Boolean; override;
+
+    function CloneCurve(): IECCurve; override;
+
+    function CreateDefaultMultiplier(): IECMultiplier; override;
+
+    function CreateRawPoint(const x, y: IECFieldElement;
+      withCompression: Boolean): IECPoint; overload; override;
+
+    function CreateRawPoint(const x, y: IECFieldElement;
+      zs: TCryptoLibGenericArray<IECFieldElement>; withCompression: Boolean)
+      : IECPoint; overload; override;
+
+  public
+    constructor Create();
+    function FromBigInteger(const x: TBigInteger): IECFieldElement; override;
+
+    function SupportsCoordinateSystem(coord: Int32): Boolean; override;
+
+    function CreateCacheSafeLookupTable
+      (points: TCryptoLibGenericArray<IECPoint>; off, len: Int32)
+      : IECLookupTable; override;
+
+    property Infinity: IECPoint read GetInfinity;
+    property FieldSize: Int32 read GetFieldSize;
+    property IsKoblitz: Boolean read GetIsKoblitz;
+
+    property M: Int32 read GetM;
+    property K1: Int32 read GetK1;
+    property K2: Int32 read GetK2;
+    property K3: Int32 read GetK3;
+    property IsTrinomial: Boolean read GetIsTrinomial;
+
+  end;
+
+implementation
+
+{ TSecT283K1Curve }
+
+constructor TSecT283K1Curve.Create;
+begin
+  Inherited Create(283, 5, 7, 12);
+  Fm_infinity := TSecT283K1Point.Create(Self as IECCurve, Nil, Nil);
+
+  Fm_a := FromBigInteger(TBigInteger.Zero);
+  Fm_b := FromBigInteger(TBigInteger.One);
+  Fm_order := TBigInteger.Create(1,
+    THex.Decode
+    ('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61')
+    );
+  Fm_cofactor := TBigInteger.ValueOf(4);
+
+  Fm_coord := SECT283K1_DEFAULT_COORDS;
+end;
+
+function TSecT283K1Curve.CloneCurve: IECCurve;
+begin
+  result := TSecT283K1Curve.Create() as ISecT283K1Curve;
+end;
+
+function TSecT283K1Curve.CreateCacheSafeLookupTable
+  (points: TCryptoLibGenericArray<IECPoint>; off, len: Int32): IECLookupTable;
+var
+  table: TCryptoLibUInt64Array;
+  pos, i: Int32;
+  p: IECPoint;
+begin
+  System.SetLength(table, len * SECT283K1_FE_LONGS * 2);
+
+  pos := 0;
+  for i := 0 to System.Pred(len) do
+  begin
+    p := points[off + i];
+    TNat320.Copy64((p.RawXCoord as ISecT283FieldElement).x, 0, table, pos);
+    pos := pos + SECT283K1_FE_LONGS;
+    TNat320.Copy64((p.RawYCoord as ISecT283FieldElement).x, 0, table, pos);
+    pos := pos + SECT283K1_FE_LONGS;
+  end;
+
+  result := TSecT283K1LookupTable.Create(Self as ISecT283K1Curve, table, len);
+end;
+
+function TSecT283K1Curve.CreateRawPoint(const x, y: IECFieldElement;
+  withCompression: Boolean): IECPoint;
+begin
+  result := TSecT283K1Point.Create(Self as IECCurve, x, y, withCompression);
+end;
+
+function TSecT283K1Curve.CreateRawPoint(const x, y: IECFieldElement;
+  zs: TCryptoLibGenericArray<IECFieldElement>; withCompression: Boolean)
+  : IECPoint;
+begin
+  result := TSecT283K1Point.Create(Self as IECCurve, x, y, zs, withCompression);
+end;
+
+function TSecT283K1Curve.FromBigInteger(const x: TBigInteger): IECFieldElement;
+begin
+  result := TSecT283FieldElement.Create(x);
+end;
+
+function TSecT283K1Curve.GetFieldSize: Int32;
+begin
+  result := 283;
+end;
+
+function TSecT283K1Curve.GetInfinity: IECPoint;
+begin
+  result := Fm_infinity;
+end;
+
+function TSecT283K1Curve.GetIsKoblitz: Boolean;
+begin
+  result := True;
+end;
+
+function TSecT283K1Curve.GetIsTrinomial: Boolean;
+begin
+  result := False;
+end;
+
+function TSecT283K1Curve.GetK1: Int32;
+begin
+  result := 5;
+end;
+
+function TSecT283K1Curve.GetK2: Int32;
+begin
+  result := 7;
+end;
+
+function TSecT283K1Curve.GetK3: Int32;
+begin
+  result := 12;
+end;
+
+function TSecT283K1Curve.GetM: Int32;
+begin
+  result := 283;
+end;
+
+function TSecT283K1Curve.SupportsCoordinateSystem(coord: Int32): Boolean;
+begin
+  case coord of
+    COORD_LAMBDA_PROJECTIVE:
+      result := True
+  else
+    result := False;
+  end;
+end;
+
+function TSecT283K1Curve.CreateDefaultMultiplier(): IECMultiplier;
+begin
+  result := TWTauNafMultiplier.Create() as IECMultiplier;
+end;
+
+{ TSecT283K1Curve.TSecT283K1LookupTable }
+
+constructor TSecT283K1Curve.TSecT283K1LookupTable.Create
+  (const outer: ISecT283K1Curve; table: TCryptoLibUInt64Array; size: Int32);
+begin
+  Inherited Create();
+  Fm_outer := outer;
+  Fm_table := table;
+  Fm_size := size;
+end;
+
+function TSecT283K1Curve.TSecT283K1LookupTable.GetSize: Int32;
+begin
+  result := Fm_size;
+end;
+
+function TSecT283K1Curve.TSecT283K1LookupTable.Lookup(index: Int32): IECPoint;
+var
+  x, y: TCryptoLibUInt64Array;
+  pos, i, J: Int32;
+  MASK: UInt64;
+begin
+  x := TNat320.Create64();
+  y := TNat320.Create64();
+  pos := 0;
+
+  for i := 0 to System.Pred(Fm_size) do
+  begin
+    MASK := UInt64(Int64(TBits.Asr32((i xor index) - 1, 31)));
+
+    for J := 0 to System.Pred(SECT283K1_FE_LONGS) do
+    begin
+      x[J] := x[J] xor (Fm_table[pos + J] and MASK);
+      y[J] := y[J] xor (Fm_table[pos + SECT283K1_FE_LONGS + J] and MASK);
+    end;
+
+    pos := pos + (SECT283K1_FE_LONGS * 2);
+  end;
+
+  result := Fm_outer.CreateRawPoint(TSecT283FieldElement.Create(x)
+    as ISecT283FieldElement, TSecT283FieldElement.Create(y)
+    as ISecT283FieldElement, False);
+end;
+
+end.

+ 476 - 0
CryptoLib/src/Math/EC/Custom/Sec/ClpSecT283K1Point.pas

@@ -0,0 +1,476 @@
+{ *********************************************************************************** }
+{ *                              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 ClpSecT283K1Point;
+
+{$I ..\..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpECPoint,
+  ClpISecT283K1Point,
+  ClpIECFieldElement,
+  ClpIECInterface,
+  ClpBigInteger,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SOneOfECFieldElementIsNil = 'Exactly One of the Field Elements is Nil';
+
+type
+  TSecT283K1Point = class sealed(TAbstractF2mPoint, ISecT283K1Point)
+
+  strict protected
+    function Detach(): IECPoint; override;
+
+    function GetCompressionYTilde: Boolean; override;
+    property CompressionYTilde: Boolean read GetCompressionYTilde;
+
+  public
+
+    /// <summary>
+    /// Create a point which encodes without point compression.
+    /// </summary>
+    /// <param name="curve">
+    /// the curve to use
+    /// </param>
+    /// <param name="x">
+    /// affine x co-ordinate
+    /// </param>
+    /// <param name="y">
+    /// affine y co-ordinate
+    /// </param>
+    constructor Create(const curve: IECCurve; const x, y: IECFieldElement);
+      overload; deprecated 'Use ECCurve.createPoint to construct points';
+
+    /// <summary>
+    /// Create a point that encodes with or without point compresion.
+    /// </summary>
+    /// <param name="curve">
+    /// the curve to use
+    /// </param>
+    /// <param name="x">
+    /// affine x co-ordinate
+    /// </param>
+    /// <param name="y">
+    /// affine y co-ordinate
+    /// </param>
+    /// <param name="withCompression">
+    /// if true encode with point compression
+    /// </param>
+    constructor Create(const curve: IECCurve; const x, y: IECFieldElement;
+      withCompression: Boolean); overload;
+      deprecated
+      'Per-point compression property will be removed, see GetEncoded(boolean)';
+
+    constructor Create(const curve: IECCurve; const x, y: IECFieldElement;
+      zs: TCryptoLibGenericArray<IECFieldElement>;
+      withCompression: Boolean); overload;
+
+    function Add(const b: IECPoint): IECPoint; override;
+    function Negate(): IECPoint; override;
+
+    function Twice(): IECPoint; override;
+    function TwicePlus(const b: IECPoint): IECPoint; override;
+
+    function GetYCoord: IECFieldElement; override;
+    property YCoord: IECFieldElement read GetYCoord;
+
+  end;
+
+implementation
+
+{ TSecT283K1Point }
+
+function TSecT283K1Point.Add(const b: IECPoint): IECPoint;
+var
+  LCurve: IECCurve;
+  X1, X2, L1, L2, Z1, Z2, U2, S2, U1, S1, A, LB, X3, L3, Z3, Y1, Y2, L, Y3, AU1,
+    AU2, ABZ2: IECFieldElement;
+  Z1IsOne, Z2IsOne: Boolean;
+  p: IECPoint;
+begin
+  if ((IsInfinity)) then
+  begin
+    result := b;
+    Exit;
+  end;
+  if ((b.IsInfinity)) then
+  begin
+    result := Self as IECPoint;
+    Exit;
+  end;
+
+  LCurve := curve;
+
+  X1 := RawXCoord;
+  X2 := b.RawXCoord;
+
+  if (X1.IsZero) then
+  begin
+    if (X2.IsZero) then
+    begin
+      result := LCurve.Infinity;
+      Exit;
+    end;
+
+    result := b.Add(Self as IECPoint);
+    Exit;
+  end;
+
+  L1 := RawYCoord;
+  Z1 := RawZCoords[0];
+  L2 := b.RawYCoord;
+  Z2 := b.RawZCoords[0];
+
+  Z1IsOne := Z1.IsOne;
+  U2 := X2;
+  S2 := L2;
+  if (not(Z1IsOne)) then
+  begin
+    U2 := U2.Multiply(Z1);
+    S2 := S2.Multiply(Z1);
+  end;
+
+  Z2IsOne := Z2.IsOne;
+  U1 := X1;
+  S1 := L1;
+  if (not(Z2IsOne)) then
+  begin
+    U1 := U1.Multiply(Z2);
+    S1 := S1.Multiply(Z2);
+  end;
+
+  A := S1.Add(S2);
+  LB := U1.Add(U2);
+
+  if (LB.IsZero) then
+  begin
+    if (A.IsZero) then
+    begin
+      result := Twice();
+      Exit;
+    end;
+
+    result := LCurve.Infinity;
+    Exit;
+  end;
+
+  if (X2.IsZero) then
+  begin
+    // TODO This can probably be optimized quite a bit
+    p := Self.Normalize();
+    X1 := p.XCoord;
+    Y1 := p.YCoord;
+
+    Y2 := L2;
+    L := Y1.Add(Y2).Divide(X1);
+
+    X3 := L.Square().Add(L).Add(X1);
+    if (X3.IsZero) then
+    begin
+      result := TSecT283K1Point.Create(LCurve, X3, LCurve.b, IsCompressed);
+      Exit;
+    end;
+
+    Y3 := L.Multiply(X1.Add(X3)).Add(X3).Add(Y1);
+    L3 := Y3.Divide(X3).Add(X3);
+    Z3 := LCurve.FromBigInteger(TBigInteger.One);
+  end
+  else
+  begin
+    LB := LB.Square();
+
+    AU1 := A.Multiply(U1);
+    AU2 := A.Multiply(U2);
+
+    X3 := AU1.Multiply(AU2);
+    if (X3.IsZero) then
+    begin
+      result := TSecT283K1Point.Create(curve, X3, curve.b, IsCompressed);
+      Exit;
+    end;
+
+    ABZ2 := A.Multiply(LB);
+    if (not(Z2IsOne)) then
+    begin
+      ABZ2 := ABZ2.Multiply(Z2);
+    end;
+
+    L3 := AU2.Add(LB).SquarePlusProduct(ABZ2, L1.Add(Z1));
+
+    Z3 := ABZ2;
+    if (not(Z1IsOne)) then
+    begin
+      Z3 := Z3.Multiply(Z1);
+    end;
+  end;
+
+  result := TSecT283K1Point.Create(LCurve, X3, L3,
+    TCryptoLibGenericArray<IECFieldElement>.Create(Z3), IsCompressed);
+end;
+
+constructor TSecT283K1Point.Create(const curve: IECCurve;
+  const x, y: IECFieldElement);
+begin
+  Create(curve, x, y, false);
+end;
+
+constructor TSecT283K1Point.Create(const curve: IECCurve;
+  const x, y: IECFieldElement; zs: TCryptoLibGenericArray<IECFieldElement>;
+  withCompression: Boolean);
+begin
+  Inherited Create(curve, x, y, zs, withCompression);
+end;
+
+constructor TSecT283K1Point.Create(const curve: IECCurve;
+  const x, y: IECFieldElement; withCompression: Boolean);
+begin
+  Inherited Create(curve, x, y, withCompression);
+  if ((x = Nil) <> (y = Nil)) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SOneOfECFieldElementIsNil);
+  end;
+end;
+
+function TSecT283K1Point.Detach: IECPoint;
+begin
+  result := TSecT283K1Point.Create(Nil, AffineXCoord, AffineYCoord);
+end;
+
+function TSecT283K1Point.GetCompressionYTilde: Boolean;
+var
+  x, y: IECFieldElement;
+begin
+  x := RawXCoord;
+  if (x.IsZero) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  y := RawYCoord;
+
+  // Y is actually Lambda (X + Y/X) here
+  result := y.TestBitZero() <> x.TestBitZero();
+end;
+
+function TSecT283K1Point.GetYCoord: IECFieldElement;
+var
+  x, L, y, Z: IECFieldElement;
+begin
+  x := RawXCoord;
+  L := RawYCoord;
+
+  if ((IsInfinity) or (x.IsZero)) then
+  begin
+    result := L;
+    Exit;
+  end;
+
+  // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
+  y := L.Add(x).Multiply(x);
+
+  Z := RawZCoords[0];
+  if (not(Z.IsOne)) then
+  begin
+    y := y.Divide(Z);
+  end;
+
+  result := y;
+end;
+
+function TSecT283K1Point.Negate: IECPoint;
+var
+  x, L, Z: IECFieldElement;
+begin
+  if (IsInfinity) then
+  begin
+    result := Self as IECPoint;
+    Exit;
+  end;
+
+  x := RawXCoord;
+  if (x.IsZero) then
+  begin
+    result := Self as IECPoint;
+    Exit;
+  end;
+
+  // L is actually Lambda (X + Y/X) here
+  L := RawYCoord;
+  Z := RawZCoords[0];
+  result := TSecT283K1Point.Create(curve, x, L.Add(Z),
+    TCryptoLibGenericArray<IECFieldElement>.Create(Z), IsCompressed);
+end;
+
+function TSecT283K1Point.Twice: IECPoint;
+var
+  LCurve: IECCurve;
+  X1, L1, Z1, Z1Sq, T, X3, Z3, t1, t2, L3: IECFieldElement;
+  Z1IsOne: Boolean;
+begin
+  if ((IsInfinity)) then
+  begin
+    result := Self as IECPoint;
+    Exit;
+  end;
+
+  LCurve := Self.curve;
+
+  X1 := RawXCoord;
+  if (X1.IsZero) then
+  begin
+    // A point with X == 0 is it's own Additive inverse
+    result := LCurve.Infinity;
+    Exit;
+  end;
+
+  L1 := RawYCoord;
+  Z1 := RawZCoords[0];
+
+  Z1IsOne := Z1.IsOne;
+  if Z1IsOne then
+  begin
+    Z1Sq := Z1;
+  end
+  else
+  begin
+    Z1Sq := Z1.Square();
+  end;
+
+  if (Z1IsOne) then
+  begin
+    T := L1.Square().Add(L1);
+  end
+  else
+  begin
+    T := L1.Add(Z1).Multiply(L1);
+  end;
+
+  if (T.IsZero) then
+  begin
+    result := TSecT283K1Point.Create(LCurve, T, LCurve.b, IsCompressed);
+    Exit;
+  end;
+
+  X3 := T.Square();
+  if Z1IsOne then
+  begin
+    Z3 := T;
+  end
+  else
+  begin
+    Z3 := T.Multiply(Z1Sq);
+  end;
+
+  t1 := L1.Add(X1).Square();
+
+  if Z1IsOne then
+  begin
+    t2 := Z1;
+  end
+  else
+  begin
+    t2 := Z1Sq.Square();
+  end;
+
+  L3 := t1.Add(T).Add(Z1Sq).Multiply(t1).Add(t2).Add(X3).Add(Z3);
+
+  result := TSecT283K1Point.Create(LCurve, X3, L3,
+    TCryptoLibGenericArray<IECFieldElement>.Create(Z3), IsCompressed);
+end;
+
+function TSecT283K1Point.TwicePlus(const b: IECPoint): IECPoint;
+var
+  LCurve: IECCurve;
+  X1, X2, Z2, L1, Z1, L2, X1Sq, L1Sq, Z1Sq, L1Z1, T, L2plus1, A, X2Z1Sq, LB, X3,
+    Z3, L3: IECFieldElement;
+begin
+  if ((IsInfinity)) then
+  begin
+    result := b;
+    Exit;
+  end;
+  if (b.IsInfinity) then
+  begin
+    result := Twice();
+    Exit;
+  end;
+
+  LCurve := Self.curve;
+
+  X1 := RawXCoord;
+  if (X1.IsZero) then
+  begin
+    // A point with X == 0 is it's own Additive inverse
+    result := b;
+    Exit;
+  end;
+
+  // NOTE: TwicePlus() only optimized for lambda-affine argument
+  X2 := b.RawXCoord;
+  Z2 := b.RawZCoords[0];
+  if ((X2.IsZero) or (not(Z2.IsOne))) then
+  begin
+    result := Twice().Add(b);
+    Exit;
+  end;
+
+  L1 := RawYCoord;
+  Z1 := RawZCoords[0];
+  L2 := b.RawYCoord;
+
+  X1Sq := X1.Square();
+  L1Sq := L1.Square();
+  Z1Sq := Z1.Square();
+  L1Z1 := L1.Multiply(Z1);
+
+  T := L1Sq.Add(L1Z1);
+  L2plus1 := L2.AddOne();
+  A := L2plus1.Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+  X2Z1Sq := X2.Multiply(Z1Sq);
+  LB := X2Z1Sq.Add(T).Square();
+
+  if (LB.IsZero) then
+  begin
+    if (A.IsZero) then
+    begin
+      result := b.Twice();
+      Exit;
+    end;
+
+    result := LCurve.Infinity;
+    Exit;
+  end;
+
+  if (A.IsZero) then
+  begin
+    result := TSecT283K1Point.Create(LCurve, A, LCurve.b, IsCompressed);
+    Exit;
+  end;
+
+  X3 := A.Square().Multiply(X2Z1Sq);
+  Z3 := A.Multiply(LB).Multiply(Z1Sq);
+  L3 := A.Add(LB).Square().MultiplyPlusProduct(T, L2plus1, Z3);
+
+  result := TSecT283K1Point.Create(LCurve, X3, L3,
+    TCryptoLibGenericArray<IECFieldElement>.Create(Z3), IsCompressed);
+end;
+
+end.

+ 7 - 0
CryptoLib/src/Math/Field/ClpGF2Polynomial.pas

@@ -42,7 +42,9 @@ type
 
     function GetExponentsPresent(): TCryptoLibInt32Array; virtual;
 
+    function Equals(other: TObject): Boolean; overload; override;
     function Equals(const other: IGF2Polynomial): Boolean; reintroduce;
+      overload;
     function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
 {$ENDIF DELPHI}override;
 
@@ -78,6 +80,11 @@ begin
   Result := TArrayUtils.AreEqual(Fexponents, other.exponents);
 end;
 
+function TGF2Polynomial.Equals(other: TObject): Boolean;
+begin
+  Result := Self.Equals((other as TGF2Polynomial) as IGF2Polynomial);
+end;
+
 function TGF2Polynomial.GetDegree: Int32;
 begin
   Result := Fexponents[System.Length(Fexponents) - 1];

+ 235 - 0
CryptoLib/src/Math/Raw/ClpInterleave.pas

@@ -0,0 +1,235 @@
+{ *********************************************************************************** }
+{ *                              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 ClpInterleave;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpCryptoLibTypes;
+
+type
+  TInterleave = class sealed(TObject)
+
+  strict private
+  const
+    M32 = UInt64($55555555);
+    M64 = UInt64($5555555555555555);
+    M64R = UInt64($AAAAAAAAAAAAAAAA);
+
+  public
+    class function Expand8to16(x: UInt32): UInt32; static; inline;
+    class function Expand16to32(x: UInt32): UInt32; static; inline;
+    class function Expand32to64(x: UInt32): UInt64; static;
+    class procedure Expand64To128(x: UInt64; z: TCryptoLibUInt64Array;
+      zOff: Int32); static;
+    class procedure Expand64To128Rev(x: UInt64; z: TCryptoLibUInt64Array;
+      zOff: Int32); static;
+    class function Shuffle(x: UInt32): UInt32; overload; static;
+    class function Shuffle(x: UInt64): UInt64; overload; static;
+    class function Shuffle2(x: UInt32): UInt32; static;
+    class function Unshuffle(x: UInt32): UInt32; overload; static;
+    class function Unshuffle(x: UInt64): UInt64; overload; static;
+    class function Unshuffle2(x: UInt32): UInt32; static;
+
+  end;
+
+implementation
+
+{ TInterleave }
+
+class function TInterleave.Expand8to16(x: UInt32): UInt32;
+begin
+  x := x and UInt32($FF);
+  x := (x or (x shl 4)) and UInt32($0F0F);
+  x := (x or (x shl 2)) and UInt32($3333);
+  x := (x or (x shl 1)) and UInt32($5555);
+  result := x;
+end;
+
+class function TInterleave.Expand16to32(x: UInt32): UInt32;
+begin
+  x := x and UInt32($FFFF);
+  x := (x or (x shl 8)) and UInt32($00FF00FF);
+  x := (x or (x shl 4)) and UInt32($0F0F0F0F);
+  x := (x or (x shl 2)) and UInt32($33333333);
+  x := (x or (x shl 1)) and UInt32($55555555);
+  result := x;
+end;
+
+class function TInterleave.Expand32to64(x: UInt32): UInt64;
+var
+  t: UInt32;
+begin
+  // "shuffle" low half to even bits and high half to odd bits
+  t := (x xor (x shr 8)) and UInt32($0000FF00);
+  x := x xor (t xor (t shl 8));
+  t := (x xor (x shr 4)) and UInt32($00F000F0);
+  x := x xor (t xor (t shl 4));
+  t := (x xor (x shr 2)) and UInt32($0C0C0C0C);
+  x := x xor (t xor (t shl 2));
+  t := (x xor (x shr 1)) and UInt32($22222222);
+  x := x xor (t xor (t shl 1));
+
+  result := ((x shr 1) and M32) shl 32 or (x and M32);
+end;
+
+class procedure TInterleave.Expand64To128(x: UInt64; z: TCryptoLibUInt64Array;
+  zOff: Int32);
+var
+  t: UInt64;
+begin
+  // "shuffle" low half to even bits and high half to odd bits
+  t := (x xor (x shr 16)) and UInt64($00000000FFFF0000);
+  x := x xor (t xor (t shl 16));
+  t := (x xor (x shr 8)) and UInt64($0000FF000000FF00);
+  x := x xor (t xor (t shl 8));
+  t := (x xor (x shr 4)) and UInt64($00F000F000F000F0);
+  x := x xor (t xor (t shl 4));
+  t := (x xor (x shr 2)) and UInt64($0C0C0C0C0C0C0C0C);
+  x := x xor (t xor (t shl 2));
+  t := (x xor (x shr 1)) and UInt64($2222222222222222);
+  x := x xor (t xor (t shl 1));
+
+  z[zOff] := (x) and M64;
+  z[zOff + 1] := (x shr 1) and M64;
+end;
+
+class procedure TInterleave.Expand64To128Rev(x: UInt64;
+  z: TCryptoLibUInt64Array; zOff: Int32);
+var
+  t: UInt64;
+begin
+  // "shuffle" low half to even bits and high half to odd bits
+  t := (x xor (x shr 16)) and UInt64($00000000FFFF0000);
+  x := x xor (t xor (t shl 16));
+  t := (x xor (x shr 8)) and UInt64($0000FF000000FF00);
+  x := x xor (t xor (t shl 8));
+  t := (x xor (x shr 4)) and UInt64($00F000F000F000F0);
+  x := x xor (t xor (t shl 4));
+  t := (x xor (x shr 2)) and UInt64($0C0C0C0C0C0C0C0C);
+  x := x xor (t xor (t shl 2));
+  t := (x xor (x shr 1)) and UInt64($2222222222222222);
+  x := x xor (t xor (t shl 1));
+
+  z[zOff] := (x) and M64R;
+  z[zOff + 1] := (x shl 1) and M64R;
+end;
+
+class function TInterleave.Shuffle(x: UInt32): UInt32;
+var
+  t: UInt32;
+begin
+  // "shuffle" low half to even bits and high half to odd bits
+  t := (x xor (x shr 8)) and UInt32($0000FF00);
+  x := x xor (t xor (t shl 8));
+  t := (x xor (x shr 4)) and UInt32($00F000F0);
+  x := x xor (t xor (t shl 4));
+  t := (x xor (x shr 2)) and UInt32($0C0C0C0C);
+  x := x xor (t xor (t shl 2));
+  t := (x xor (x shr 1)) and UInt32($22222222);
+  x := x xor (t xor (t shl 1));
+  result := x;
+end;
+
+class function TInterleave.Shuffle(x: UInt64): UInt64;
+var
+  t: UInt64;
+begin
+  // "shuffle" low half to even bits and high half to odd bits
+  t := (x xor (x shr 16)) and UInt64($00000000FFFF0000);
+  x := x xor (t xor (t shl 16));
+  t := (x xor (x shr 8)) and UInt64($0000FF000000FF00);
+  x := x xor (t xor (t shl 8));
+  t := (x xor (x shr 4)) and UInt64($00F000F000F000F0);
+  x := x xor (t xor (t shl 4));
+  t := (x xor (x shr 2)) and UInt64($0C0C0C0C0C0C0C0C);
+  x := x xor (t xor (t shl 2));
+  t := (x xor (x shr 1)) and UInt64($2222222222222222);
+  x := x xor (t xor (t shl 1));
+  result := x;
+end;
+
+class function TInterleave.Shuffle2(x: UInt32): UInt32;
+var
+  t: UInt32;
+begin
+  // "shuffle" (twice) low half to even bits and high half to odd bits
+  t := (x xor (x shr 7)) and UInt32($00AA00AA);
+  x := x xor (t xor (t shl 7));
+  t := (x xor (x shr 14)) and UInt32($0000CCCC);
+  x := x xor (t xor (t shl 14));
+  t := (x xor (x shr 4)) and UInt32($00F000F0);
+  x := x xor (t xor (t shl 4));
+  t := (x xor (x shr 8)) and UInt32($0000FF00);
+  x := x xor (t xor (t shl 8));
+  result := x;
+end;
+
+class function TInterleave.Unshuffle(x: UInt32): UInt32;
+var
+  t: UInt32;
+begin
+  // "unshuffle" even bits to low half and odd bits to high half
+  t := (x xor (x shr 1)) and UInt32($22222222);
+  x := x xor (t xor (t shl 1));
+  t := (x xor (x shr 2)) and UInt32($0C0C0C0C);
+  x := x xor (t xor (t shl 2));
+  t := (x xor (x shr 4)) and UInt32($00F000F0);
+  x := x xor (t xor (t shl 4));
+  t := (x xor (x shr 8)) and UInt32($0000FF00);
+  x := x xor (t xor (t shl 8));
+  result := x;
+end;
+
+class function TInterleave.Unshuffle(x: UInt64): UInt64;
+var
+  t: UInt64;
+begin
+  // "unshuffle" even bits to low half and odd bits to high half
+  t := (x xor (x shr 1)) and UInt64($2222222222222222);
+  x := x xor (t xor (t shl 1));
+  t := (x xor (x shr 2)) and UInt64($0C0C0C0C0C0C0C0C);
+  x := x xor (t xor (t shl 2));
+  t := (x xor (x shr 4)) and UInt64($00F000F000F000F0);
+  x := x xor (t xor (t shl 4));
+  t := (x xor (x shr 8)) and UInt64($0000FF000000FF00);
+  x := x xor (t xor (t shl 8));
+  t := (x xor (x shr 16)) and UInt64($00000000FFFF0000);
+  x := x xor (t xor (t shl 16));
+  result := x;
+end;
+
+class function TInterleave.Unshuffle2(x: UInt32): UInt32;
+var
+  t: UInt32;
+begin
+  // "unshuffle" (twice) even bits to low half and odd bits to high half
+  t := (x xor (x shr 8)) and UInt32($0000FF00);
+  x := x xor (t xor (t shl 8));
+  t := (x xor (x shr 4)) and UInt32($00F000F0);
+  x := x xor (t xor (t shl 4));
+  t := (x xor (x shr 14)) and UInt32($0000CCCC);
+  x := x xor (t xor (t shl 14));
+  t := (x xor (x shr 7)) and UInt32($00AA00AA);
+  x := x xor (t xor (t shl 7));
+  result := x;
+end;
+
+end.

+ 103 - 107
CryptoLib/src/Math/Raw/ClpNat.pas

@@ -36,57 +36,57 @@ type
 
   public
 
-    class function Add(len: Int32; x, y, z: TCryptoLibUInt32Array): UInt32;
-      static; inline;
+    class function Add(len: Int32; x, y, z: TCryptoLibUInt32Array)
+      : UInt32; static;
 
     class function Add33At(len: Int32; x: UInt32; z: TCryptoLibUInt32Array;
-      zPos: Int32): UInt32; overload; static; inline;
+      zPos: Int32): UInt32; overload; static;
 
     class function Add33At(len: Int32; x: UInt32; z: TCryptoLibUInt32Array;
-      zOff, zPos: Int32): UInt32; overload; static; inline;
+      zOff, zPos: Int32): UInt32; overload; static;
 
     class function Add33To(len: Int32; x: UInt32; z: TCryptoLibUInt32Array)
-      : UInt32; overload; static; inline;
+      : UInt32; overload; static;
 
     class function Add33To(len: Int32; x: UInt32; z: TCryptoLibUInt32Array;
-      zOff: Int32): UInt32; overload; static; inline;
+      zOff: Int32): UInt32; overload; static;
 
     class function AddBothTo(len: Int32; x, y, z: TCryptoLibUInt32Array)
-      : UInt32; overload; static; inline;
+      : UInt32; overload; static;
 
     class function AddBothTo(len: Int32; x: TCryptoLibUInt32Array; xOff: Int32;
       y: TCryptoLibUInt32Array; yOff: Int32; z: TCryptoLibUInt32Array;
-      zOff: Int32): UInt32; overload; static; inline;
+      zOff: Int32): UInt32; overload; static;
 
     class function AddDWordAt(len: Int32; x: UInt64; z: TCryptoLibUInt32Array;
-      zPos: Int32): UInt32; overload; static; inline;
+      zPos: Int32): UInt32; overload; static;
 
     class function AddDWordAt(len: Int32; x: UInt64; z: TCryptoLibUInt32Array;
-      zOff, zPos: Int32): UInt32; overload; static; inline;
+      zOff, zPos: Int32): UInt32; overload; static;
 
     class function AddDWordTo(len: Int32; x: UInt64; z: TCryptoLibUInt32Array)
-      : UInt32; overload; static; inline;
+      : UInt32; overload; static;
 
     class function AddDWordTo(len: Int32; x: UInt64; z: TCryptoLibUInt32Array;
-      zOff: Int32): UInt32; overload; static; inline;
+      zOff: Int32): UInt32; overload; static;
 
     class function AddTo(len: Int32; x, z: TCryptoLibUInt32Array): UInt32;
-      overload; static; inline;
+      overload; static;
 
     class function AddTo(len: Int32; x: TCryptoLibUInt32Array; xOff: Int32;
-      z: TCryptoLibUInt32Array; zOff: Int32): UInt32; overload; static; inline;
+      z: TCryptoLibUInt32Array; zOff: Int32): UInt32; overload; static;
 
     class function AddWordAt(len: Int32; x: UInt32; z: TCryptoLibUInt32Array;
-      zPos: Int32): UInt32; overload; static; inline;
+      zPos: Int32): UInt32; overload; static;
 
     class function AddWordAt(len: Int32; x: UInt32; z: TCryptoLibUInt32Array;
-      zOff, zPos: Int32): UInt32; overload; static; inline;
+      zOff, zPos: Int32): UInt32; overload; static;
 
     class function AddWordTo(len: Int32; x: UInt32; z: TCryptoLibUInt32Array)
-      : UInt32; overload; static; inline;
+      : UInt32; overload; static;
 
     class function AddWordTo(len: Int32; x: UInt32; z: TCryptoLibUInt32Array;
-      zOff: Int32): UInt32; overload; static; inline;
+      zOff: Int32): UInt32; overload; static;
 
     class procedure Copy(len: Int32; x, z: TCryptoLibUInt32Array); overload;
       static; inline;
@@ -95,146 +95,141 @@ type
       : TCryptoLibUInt32Array; overload; static; inline;
 
     class procedure Copy(len: Int32; x: TCryptoLibUInt32Array; xOff: Int32;
-      z: TCryptoLibUInt32Array; zOff: Int32); overload; static;
+      z: TCryptoLibUInt32Array; zOff: Int32); overload; static; inline;
 
     class function Create(len: Int32): TCryptoLibUInt32Array; static; inline;
 
     class function Create64(len: Int32): TCryptoLibUInt64Array; static; inline;
 
-    class function Dec(len: Int32; z: TCryptoLibUInt32Array): Int32; overload;
-      static; inline;
+    class function Dec(len: Int32; z: TCryptoLibUInt32Array): Int32;
+      overload; static;
 
     class function Dec(len: Int32; x, z: TCryptoLibUInt32Array): Int32;
-      overload; static; inline;
+      overload; static;
 
     class function DecAt(len: Int32; z: TCryptoLibUInt32Array; zPos: Int32)
-      : Int32; overload; static; inline;
+      : Int32; overload; static;
 
     class function DecAt(len: Int32; z: TCryptoLibUInt32Array;
-      zOff, zPos: Int32): Int32; overload; static; inline;
+      zOff, zPos: Int32): Int32; overload; static;
 
-    class function Eq(len: Int32; x, y: TCryptoLibUInt32Array): Boolean;
-      static; inline;
+    class function Eq(len: Int32; x, y: TCryptoLibUInt32Array): Boolean; static;
 
     class function FromBigInteger(bits: Int32; x: TBigInteger)
       : TCryptoLibUInt32Array; static;
 
-    class function GetBit(x: TCryptoLibUInt32Array; bit: Int32): UInt32;
-      static; inline;
+    class function GetBit(x: TCryptoLibUInt32Array; bit: Int32): UInt32; static;
 
-    class function Gte(len: Int32; x, y: TCryptoLibUInt32Array): Boolean;
-      static; inline;
+    class function Gte(len: Int32; x, y: TCryptoLibUInt32Array)
+      : Boolean; static;
 
-    class function Inc(len: Int32; z: TCryptoLibUInt32Array): UInt32; overload;
-      static; inline;
+    class function Inc(len: Int32; z: TCryptoLibUInt32Array): UInt32;
+      overload; static;
 
     class function Inc(len: Int32; x, z: TCryptoLibUInt32Array): UInt32;
-      overload; static; inline;
+      overload; static;
 
     class function IncAt(len: Int32; z: TCryptoLibUInt32Array; zPos: Int32)
-      : UInt32; overload; static; inline;
+      : UInt32; overload; static;
 
     class function IncAt(len: Int32; z: TCryptoLibUInt32Array;
-      zOff, zPos: Int32): UInt32; overload; static; inline;
+      zOff, zPos: Int32): UInt32; overload; static;
 
-    class function IsOne(len: Int32; x: TCryptoLibUInt32Array): Boolean;
-      static; inline;
+    class function IsOne(len: Int32; x: TCryptoLibUInt32Array): Boolean; static;
 
-    class function IsZero(len: Int32; x: TCryptoLibUInt32Array): Boolean;
-      static; inline;
+    class function IsZero(len: Int32; x: TCryptoLibUInt32Array)
+      : Boolean; static;
 
-    class procedure Mul(len: Int32; x, y, zz: TCryptoLibUInt32Array); overload;
-      static; inline;
+    class procedure Mul(len: Int32; x, y, zz: TCryptoLibUInt32Array);
+      overload; static;
 
     class procedure Mul(len: Int32; x: TCryptoLibUInt32Array; xOff: Int32;
       y: TCryptoLibUInt32Array; yOff: Int32; zz: TCryptoLibUInt32Array;
-      zzOff: Int32); overload; static; inline;
+      zzOff: Int32); overload; static;
 
     class function Mul31BothAdd(len: Int32; a: UInt32; x: TCryptoLibUInt32Array;
-      b: UInt32; y, z: TCryptoLibUInt32Array; zOff: Int32): UInt32;
-      static; inline;
+      b: UInt32; y, z: TCryptoLibUInt32Array; zOff: Int32): UInt32; static;
 
     class function MulWord(len: Int32; x: UInt32; y, z: TCryptoLibUInt32Array)
-      : UInt32; overload; static; inline;
+      : UInt32; overload; static;
 
     class function MulWord(len: Int32; x: UInt32; y: TCryptoLibUInt32Array;
-      yOff: Int32; z: TCryptoLibUInt32Array; zOff: Int32): UInt32; overload;
-      static; inline;
+      yOff: Int32; z: TCryptoLibUInt32Array; zOff: Int32): UInt32;
+      overload; static;
 
     class function MulWordAddTo(len: Int32; x: UInt32; y: TCryptoLibUInt32Array;
-      yOff: Int32; z: TCryptoLibUInt32Array; zOff: Int32): UInt32;
-      static; inline;
+      yOff: Int32; z: TCryptoLibUInt32Array; zOff: Int32): UInt32; static;
 
     class function MulWordDwordAddAt(len: Int32; x: UInt32; y: UInt64;
-      z: TCryptoLibUInt32Array; zPos: Int32): UInt32; static; inline;
+      z: TCryptoLibUInt32Array; zPos: Int32): UInt32; static;
 
     class function ShiftDownBit(len: Int32; z: TCryptoLibUInt32Array; c: UInt32)
-      : UInt32; overload; static; inline;
+      : UInt32; overload; static;
 
     class function ShiftDownBit(len: Int32; z: TCryptoLibUInt32Array;
-      zOff: Int32; c: UInt32): UInt32; overload; static; inline;
+      zOff: Int32; c: UInt32): UInt32; overload; static;
 
     class function ShiftDownBit(len: Int32; x: TCryptoLibUInt32Array; c: UInt32;
-      z: TCryptoLibUInt32Array): UInt32; overload; static; inline;
+      z: TCryptoLibUInt32Array): UInt32; overload; static;
 
     class function ShiftDownBit(len: Int32; x: TCryptoLibUInt32Array;
       xOff: UInt32; c: UInt32; z: TCryptoLibUInt32Array; zOff: Int32): UInt32;
-      overload; static; inline;
+      overload; static;
 
     class function ShiftDownBits(len: Int32; z: TCryptoLibUInt32Array;
-      bits: Int32; c: UInt32): UInt32; overload; static; inline;
+      bits: Int32; c: UInt32): UInt32; overload; static;
 
     class function ShiftDownBits(len: Int32; z: TCryptoLibUInt32Array;
-      zOff: Int32; bits: Int32; c: UInt32): UInt32; overload; static; inline;
+      zOff: Int32; bits: Int32; c: UInt32): UInt32; overload; static;
 
     class function ShiftDownBits(len: Int32; x: TCryptoLibUInt32Array;
-      bits: Int32; c: UInt32; z: TCryptoLibUInt32Array): UInt32; overload;
-      static; inline;
+      bits: Int32; c: UInt32; z: TCryptoLibUInt32Array): UInt32;
+      overload; static;
 
     class function ShiftDownBits(len: Int32; x: TCryptoLibUInt32Array;
       xOff, bits: Int32; c: UInt32; z: TCryptoLibUInt32Array; zOff: Int32)
-      : UInt32; overload; static; inline;
+      : UInt32; overload; static;
 
     class function ShiftDownWord(len: Int32; z: TCryptoLibUInt32Array;
-      c: UInt32): UInt32; static; inline;
+      c: UInt32): UInt32; static;
 
     class function ShiftUpBit(len: Int32; z: TCryptoLibUInt32Array; c: UInt32)
-      : UInt32; overload; static; inline;
+      : UInt32; overload; static;
 
     class function ShiftUpBit(len: Int32; z: TCryptoLibUInt32Array; zOff: Int32;
-      c: UInt32): UInt32; overload; static; inline;
+      c: UInt32): UInt32; overload; static;
 
     class function ShiftUpBit(len: Int32; x: TCryptoLibUInt32Array; c: UInt32;
-      z: TCryptoLibUInt32Array): UInt32; overload; static; inline;
+      z: TCryptoLibUInt32Array): UInt32; overload; static;
 
     class function ShiftUpBit(len: Int32; x: TCryptoLibUInt32Array; xOff: Int32;
-      c: UInt32; z: TCryptoLibUInt32Array; zOff: Int32): UInt32; overload;
-      static; inline;
+      c: UInt32; z: TCryptoLibUInt32Array; zOff: Int32): UInt32;
+      overload; static;
 
     class function ShiftUpBit64(len: Int32; x: TCryptoLibUInt64Array;
-      xOff: Int32; c: UInt64; z: TCryptoLibUInt64Array; zOff: Int32): UInt64;
-      static; inline;
+      xOff: Int32; c: UInt64; z: TCryptoLibUInt64Array; zOff: Int32)
+      : UInt64; static;
 
     class function ShiftUpBits(len: Int32; z: TCryptoLibUInt32Array;
-      bits: Int32; c: UInt32): UInt32; overload; static; inline;
+      bits: Int32; c: UInt32): UInt32; overload; static;
 
     class function ShiftUpBits(len: Int32; z: TCryptoLibUInt32Array;
-      zOff: Int32; bits: Int32; c: UInt32): UInt32; overload; static; inline;
+      zOff: Int32; bits: Int32; c: UInt32): UInt32; overload; static;
 
     class function ShiftUpBits64(len: Int32; z: TCryptoLibUInt64Array;
-      zOff: Int32; bits: Int32; c: UInt64): UInt64; overload; static; inline;
+      zOff: Int32; bits: Int32; c: UInt64): UInt64; overload; static;
 
     class function ShiftUpBits(len: Int32; x: TCryptoLibUInt32Array;
-      bits: Int32; c: UInt32; z: TCryptoLibUInt32Array): UInt32; overload;
-      static; inline;
+      bits: Int32; c: UInt32; z: TCryptoLibUInt32Array): UInt32;
+      overload; static;
 
     class function ShiftUpBits(len: Int32; x: TCryptoLibUInt32Array;
       xOff: Int32; bits: Int32; c: UInt32; z: TCryptoLibUInt32Array;
-      zOff: Int32): UInt32; overload; static; inline;
+      zOff: Int32): UInt32; overload; static;
 
     class function ShiftUpBits64(len: Int32; x: TCryptoLibUInt64Array;
       xOff, bits: Int32; c: UInt64; z: TCryptoLibUInt64Array; zOff: Int32)
-      : UInt64; overload; static; inline;
+      : UInt64; overload; static;
 
     class procedure Square(len: Int32; x, zz: TCryptoLibUInt32Array);
       overload; static;
@@ -243,69 +238,69 @@ type
       zz: TCryptoLibUInt32Array; zzOff: Int32); overload; static;
 
     class function SquareWordAdd(x: TCryptoLibUInt32Array; xPos: Int32;
-      z: TCryptoLibUInt32Array): UInt32; overload; static; inline;
+      z: TCryptoLibUInt32Array): UInt32; overload; static;
 
     class function SquareWordAdd(x: TCryptoLibUInt32Array; xOff, xPos: Int32;
-      z: TCryptoLibUInt32Array; zOff: Int32): UInt32; overload; static; inline;
+      z: TCryptoLibUInt32Array; zOff: Int32): UInt32; overload; static;
 
     class function Sub(len: Int32; x, y, z: TCryptoLibUInt32Array): Int32;
-      overload; static; inline;
+      overload; static;
 
     class function Sub(len: Int32; x: TCryptoLibUInt32Array; xOff: Int32;
       y: TCryptoLibUInt32Array; yOff: Int32; z: TCryptoLibUInt32Array;
-      zOff: Int32): Int32; overload; static; inline;
+      zOff: Int32): Int32; overload; static;
 
     class function Sub33At(len: Int32; x: UInt32; z: TCryptoLibUInt32Array;
-      zPos: Int32): Int32; overload; static; inline;
+      zPos: Int32): Int32; overload; static;
 
     class function Sub33At(len: Int32; x: UInt32; z: TCryptoLibUInt32Array;
-      zOff, zPos: Int32): Int32; overload; static; inline;
+      zOff, zPos: Int32): Int32; overload; static;
 
     class function Sub33From(len: Int32; x: UInt32; z: TCryptoLibUInt32Array)
-      : Int32; overload; static; inline;
+      : Int32; overload; static;
 
     class function Sub33From(len: Int32; x: UInt32; z: TCryptoLibUInt32Array;
-      zOff: Int32): Int32; overload; static; inline;
+      zOff: Int32): Int32; overload; static;
 
     class function SubBothFrom(len: Int32; x, y, z: TCryptoLibUInt32Array)
-      : Int32; overload; static; inline;
+      : Int32; overload; static;
 
     class function SubBothFrom(len: Int32; x: TCryptoLibUInt32Array;
       xOff: Int32; y: TCryptoLibUInt32Array; yOff: Int32;
-      z: TCryptoLibUInt32Array; zOff: Int32): Int32; overload; static; inline;
+      z: TCryptoLibUInt32Array; zOff: Int32): Int32; overload; static;
 
     class function SubDWordAt(len: Int32; x: UInt64; z: TCryptoLibUInt32Array;
-      zPos: Int32): Int32; overload; static; inline;
+      zPos: Int32): Int32; overload; static;
 
     class function SubDWordAt(len: Int32; x: UInt64; z: TCryptoLibUInt32Array;
-      zOff, zPos: Int32): Int32; overload; static; inline;
+      zOff, zPos: Int32): Int32; overload; static;
 
     class function SubDWordFrom(len: Int32; x: UInt64; z: TCryptoLibUInt32Array)
-      : Int32; overload; static; inline;
+      : Int32; overload; static;
 
     class function SubDWordFrom(len: Int32; x: UInt64; z: TCryptoLibUInt32Array;
-      zOff: Int32): Int32; overload; static; inline;
+      zOff: Int32): Int32; overload; static;
 
     class function SubFrom(len: Int32; x, z: TCryptoLibUInt32Array): Int32;
-      overload; static; inline;
+      overload; static;
 
     class function SubFrom(len: Int32; x: TCryptoLibUInt32Array; xOff: Int32;
-      z: TCryptoLibUInt32Array; zOff: Int32): Int32; overload; static; inline;
+      z: TCryptoLibUInt32Array; zOff: Int32): Int32; overload; static;
 
     class function SubWordAt(len: Int32; x: UInt32; z: TCryptoLibUInt32Array;
-      zPos: Int32): Int32; overload; static; inline;
+      zPos: Int32): Int32; overload; static;
 
     class function SubWordAt(len: Int32; x: UInt32; z: TCryptoLibUInt32Array;
-      zOff, zPos: Int32): Int32; overload; static; inline;
+      zOff, zPos: Int32): Int32; overload; static;
 
     class function SubWordFrom(len: Int32; x: UInt32; z: TCryptoLibUInt32Array)
-      : Int32; overload; static; inline;
+      : Int32; overload; static;
 
     class function SubWordFrom(len: Int32; x: UInt32; z: TCryptoLibUInt32Array;
-      zOff: Int32): Int32; overload; static; inline;
+      zOff: Int32): Int32; overload; static;
 
     class function ToBigInteger(len: Int32; x: TCryptoLibUInt32Array)
-      : TBigInteger; static; inline;
+      : TBigInteger; static;
 
     class procedure Zero(len: Int32; z: TCryptoLibUInt32Array); static; inline;
 
@@ -1270,6 +1265,7 @@ begin
     next := x[xOff + I];
     z[zOff + I] := (next shr (bits)) or (TBits.NegativeLeftShift32(c, -bits));
     c := next;
+    System.Dec(I);
   end;
   Result := TBits.NegativeLeftShift32(c, -bits);
 end;
@@ -1447,10 +1443,10 @@ begin
   for I := 0 to System.Pred(len) do
   begin
     next := x[xOff + I];
-    z[zOff + I] := (next shl bits) or (c shr (-bits));
+    z[zOff + I] := (next shl bits) or (TBits.NegativeRightShift32(c, -bits));
     c := next;
   end;
-  Result := c shr (-bits);
+  Result := TBits.NegativeRightShift32(c, -bits);
 end;
 
 class function TNat.ShiftUpBits(len: Int32; x: TCryptoLibUInt32Array;
@@ -1465,10 +1461,10 @@ begin
   for I := 0 to System.Pred(len) do
   begin
     next := x[I];
-    z[I] := (next shl bits) or (c shr (-bits));
+    z[I] := (next shl bits) or (TBits.NegativeRightShift32(c, -bits));
     c := next;
   end;
-  Result := c shr (-bits);
+  Result := TBits.NegativeRightShift32(c, -bits);
 end;
 
 class function TNat.ShiftUpBits(len: Int32; z: TCryptoLibUInt32Array;
@@ -1483,10 +1479,10 @@ begin
   for I := 0 to System.Pred(len) do
   begin
     next := z[I];
-    z[I] := (next shl bits) or (c shr (-bits));
+    z[I] := (next shl bits) or (TBits.NegativeRightShift32(c, -bits));
     c := next;
   end;
-  Result := c shr (-bits);
+  Result := TBits.NegativeRightShift32(c, -bits);
 end;
 
 class function TNat.ShiftUpBits(len: Int32; z: TCryptoLibUInt32Array;
@@ -1501,10 +1497,10 @@ begin
   for I := 0 to System.Pred(len) do
   begin
     next := z[zOff + I];
-    z[zOff + I] := (next shl bits) or (c shr (-bits));
+    z[zOff + I] := (next shl bits) or (TBits.NegativeRightShift32(c, -bits));
     c := next;
   end;
-  Result := c shr (-bits);
+  Result := TBits.NegativeRightShift32(c, -bits);
 end;
 
 class function TNat.ShiftUpBits64(len: Int32; x: TCryptoLibUInt64Array;
@@ -1519,10 +1515,10 @@ begin
   for I := 0 to System.Pred(len) do
   begin
     next := x[xOff + I];
-    z[zOff + I] := (next shl bits) or (c shr (-bits));
+    z[zOff + I] := (next shl bits) or (TBits.NegativeRightShift32(c, -bits));
     c := next;
   end;
-  Result := c shr (-bits);
+  Result := TBits.NegativeRightShift32(c, -bits);
 end;
 
 class function TNat.ShiftUpBits64(len: Int32; z: TCryptoLibUInt64Array;
@@ -1537,10 +1533,10 @@ begin
   for I := 0 to System.Pred(len) do
   begin
     next := z[zOff + I];
-    z[zOff + I] := (next shl bits) or (c shr (-bits));
+    z[zOff + I] := (next shl bits) or (TBits.NegativeRightShift32(c, -bits));
     c := next;
   end;
-  Result := c shr (-bits);
+  Result := TBits.NegativeRightShift32(c, -bits);
 end;
 
 class procedure TNat.Square(len: Int32; x, zz: TCryptoLibUInt32Array);

+ 1414 - 0
CryptoLib/src/Math/Raw/ClpNat192.pas

@@ -0,0 +1,1414 @@
+{ *********************************************************************************** }
+{ *                              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 ClpNat192;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpBits,
+  ClpNat,
+  ClpBigInteger,
+  ClpConverters,
+  ClpCryptoLibTypes;
+
+type
+  TNat192 = class sealed(TObject)
+
+  strict private
+  const
+    M = UInt64($FFFFFFFF);
+
+  public
+    class function Add(x, y, z: TCryptoLibUInt32Array): UInt32;
+      overload; static;
+
+    class function AddBothTo(x, y, z: TCryptoLibUInt32Array): UInt32;
+      overload; static;
+
+    class function AddTo(x, z: TCryptoLibUInt32Array): UInt32; overload; static;
+    class function AddTo(x: TCryptoLibUInt32Array; xOff: Int32;
+      z: TCryptoLibUInt32Array; zOff: Int32; cIn: UInt32): UInt32;
+      overload; static;
+    class function AddToEachOther(u: TCryptoLibUInt32Array; uOff: Int32;
+      v: TCryptoLibUInt32Array; vOff: Int32): UInt32; static;
+
+    class procedure Copy(x, z: TCryptoLibUInt32Array); overload; static; inline;
+    class procedure Copy(x: TCryptoLibUInt32Array; xOff: Int32;
+      z: TCryptoLibUInt32Array; zOff: Int32); overload; static; inline;
+
+    class procedure Copy64(x, z: TCryptoLibUInt64Array); overload;
+      static; inline;
+
+    class procedure Copy64(x: TCryptoLibUInt64Array; xOff: Int32;
+      z: TCryptoLibUInt64Array; zOff: Int32); overload; static; inline;
+
+    class function Create(): TCryptoLibUInt32Array; static; inline;
+
+    class function Create64(): TCryptoLibUInt64Array; static; inline;
+
+    class function CreateExt(): TCryptoLibUInt32Array; static; inline;
+
+    class function CreateExt64(): TCryptoLibUInt64Array; static; inline;
+
+    class function Diff(x: TCryptoLibUInt32Array; xOff: Int32;
+      y: TCryptoLibUInt32Array; yOff: Int32; z: TCryptoLibUInt32Array;
+      zOff: Int32): Boolean; static; inline;
+
+    class function Eq(x, y: TCryptoLibUInt32Array): Boolean; static;
+
+    class function Eq64(x, y: TCryptoLibUInt64Array): Boolean; static;
+
+    class function FromBigInteger(const x: TBigInteger)
+      : TCryptoLibUInt32Array; static;
+
+    class function FromBigInteger64(const x: TBigInteger)
+      : TCryptoLibUInt64Array; static;
+
+    class function GetBit(x: TCryptoLibUInt32Array; bit: Int32): UInt32;
+      static; inline;
+
+    class function Gte(x, y: TCryptoLibUInt32Array): Boolean; overload; static;
+
+    class function Gte(x: TCryptoLibUInt32Array; xOff: Int32;
+      y: TCryptoLibUInt32Array; yOff: Int32): Boolean; overload; static;
+
+    class function IsOne(x: TCryptoLibUInt32Array): Boolean; static;
+
+    class function IsOne64(x: TCryptoLibUInt64Array): Boolean; static;
+
+    class function IsZero(x: TCryptoLibUInt32Array): Boolean; static;
+
+    class function IsZero64(x: TCryptoLibUInt64Array): Boolean; static;
+
+    class procedure Mul(x, y, zz: TCryptoLibUInt32Array); overload; static;
+
+    class procedure Mul(x: TCryptoLibUInt32Array; xOff: Int32;
+      y: TCryptoLibUInt32Array; yOff: Int32; zz: TCryptoLibUInt32Array;
+      zzOff: Int32); overload; static;
+
+    class function MulAddTo(x, y, zz: TCryptoLibUInt32Array): UInt32;
+      overload; static;
+
+    class function MulAddTo(x: TCryptoLibUInt32Array; xOff: Int32;
+      y: TCryptoLibUInt32Array; yOff: Int32; zz: TCryptoLibUInt32Array;
+      zzOff: Int32): UInt32; overload; static;
+
+    class function Mul33Add(w: UInt32; x: TCryptoLibUInt32Array; xOff: Int32;
+      y: TCryptoLibUInt32Array; yOff: Int32; z: TCryptoLibUInt32Array;
+      zOff: Int32): UInt64; static;
+
+    class function MulWordAddExt(x: UInt32; yy: TCryptoLibUInt32Array;
+      yyOff: Int32; zz: TCryptoLibUInt32Array; zzOff: Int32): UInt32; static;
+
+    class function Mul33DWordAdd(x: UInt32; y: UInt64; z: TCryptoLibUInt32Array;
+      zOff: Int32): UInt32; static;
+
+    class function Mul33WordAdd(x, y: UInt32; z: TCryptoLibUInt32Array;
+      zOff: Int32): UInt32; static;
+
+    class function MulWordDwordAdd(x: UInt32; y: UInt64;
+      z: TCryptoLibUInt32Array; zOff: Int32): UInt32; static;
+
+    class function MulWord(x: UInt32; y, z: TCryptoLibUInt32Array; zOff: Int32)
+      : UInt32; static;
+
+    class procedure Square(x, zz: TCryptoLibUInt32Array); overload; static;
+
+    class procedure Square(x: TCryptoLibUInt32Array; xOff: Int32;
+      zz: TCryptoLibUInt32Array; zzOff: Int32); overload; static;
+
+    class function Sub(x, y, z: TCryptoLibUInt32Array): Int32; overload; static;
+
+    class function Sub(x: TCryptoLibUInt32Array; xOff: Int32;
+      y: TCryptoLibUInt32Array; yOff: Int32; z: TCryptoLibUInt32Array;
+      zOff: Int32): Int32; overload; static;
+
+    class function SubBothFrom(x, y, z: TCryptoLibUInt32Array): Int32; static;
+
+    class function SubFrom(x, z: TCryptoLibUInt32Array): Int32;
+      overload; static;
+
+    class function SubFrom(x: TCryptoLibUInt32Array; xOff: Int32;
+      z: TCryptoLibUInt32Array; zOff: Int32): Int32; overload; static;
+
+    class function ToBigInteger(x: TCryptoLibUInt32Array): TBigInteger; static;
+
+    class function ToBigInteger64(x: TCryptoLibUInt64Array)
+      : TBigInteger; static;
+
+    class procedure Zero(z: TCryptoLibUInt32Array); static; inline;
+
+  end;
+
+implementation
+
+{ TNat192 }
+
+class function TNat192.Add(x, y, z: TCryptoLibUInt32Array): UInt32;
+var
+  c: UInt64;
+begin
+  c := 0;
+  c := c + (UInt64(x[0]) + y[0]);
+  z[0] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[1]) + y[1]);
+  z[1] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[2]) + y[2]);
+  z[2] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[3]) + y[3]);
+  z[3] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[4]) + y[4]);
+  z[4] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[5]) + y[5]);
+  z[5] := UInt32(c);
+  c := c shr 32;
+  result := UInt32(c);
+end;
+
+class function TNat192.AddBothTo(x, y, z: TCryptoLibUInt32Array): UInt32;
+var
+  c: UInt64;
+begin
+  c := 0;
+  c := c + (UInt64(x[0]) + y[0] + z[0]);
+  z[0] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[1]) + y[1] + z[1]);
+  z[1] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[2]) + y[2] + z[2]);
+  z[2] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[3]) + y[3] + z[3]);
+  z[3] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[4]) + y[4] + z[4]);
+  z[4] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[5]) + y[5] + z[5]);
+  z[5] := UInt32(c);
+  c := c shr 32;
+  result := UInt32(c);
+end;
+
+class function TNat192.AddTo(x, z: TCryptoLibUInt32Array): UInt32;
+var
+  c: UInt64;
+begin
+  c := 0;
+  c := c + (UInt64(x[0]) + z[0]);
+  z[0] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[1]) + z[1]);
+  z[1] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[2]) + z[2]);
+  z[2] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[3]) + z[3]);
+  z[3] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[4]) + z[4]);
+  z[4] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[5]) + z[5]);
+  z[5] := UInt32(c);
+  c := c shr 32;
+  result := UInt32(c);
+end;
+
+class function TNat192.AddTo(x: TCryptoLibUInt32Array; xOff: Int32;
+  z: TCryptoLibUInt32Array; zOff: Int32; cIn: UInt32): UInt32;
+var
+  c: UInt64;
+begin
+  c := cIn;
+  c := c + (UInt64(x[xOff + 0]) + z[zOff + 0]);
+  z[zOff + 0] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 1]) + z[zOff + 1]);
+  z[zOff + 1] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 2]) + z[zOff + 2]);
+  z[zOff + 2] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 3]) + z[zOff + 3]);
+  z[zOff + 3] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 4]) + z[zOff + 4]);
+  z[zOff + 4] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 5]) + z[zOff + 5]);
+  z[zOff + 5] := UInt32(c);
+  c := c shr 32;
+  result := UInt32(c);
+end;
+
+class function TNat192.AddToEachOther(u: TCryptoLibUInt32Array; uOff: Int32;
+  v: TCryptoLibUInt32Array; vOff: Int32): UInt32;
+var
+  c: UInt64;
+begin
+  c := 0;
+  c := c + (UInt64(u[uOff + 0]) + v[vOff + 0]);
+  u[uOff + 0] := UInt32(c);
+  v[vOff + 0] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(u[uOff + 1]) + v[vOff + 1]);
+  u[uOff + 1] := UInt32(c);
+  v[vOff + 1] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(u[uOff + 2]) + v[vOff + 2]);
+  u[uOff + 2] := UInt32(c);
+  v[vOff + 2] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(u[uOff + 3]) + v[vOff + 3]);
+  u[uOff + 3] := UInt32(c);
+  v[vOff + 3] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(u[uOff + 4]) + v[vOff + 4]);
+  u[uOff + 4] := UInt32(c);
+  v[vOff + 4] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(u[uOff + 5]) + v[vOff + 5]);
+  u[uOff + 5] := UInt32(c);
+  v[vOff + 5] := UInt32(c);
+  c := c shr 32;
+  result := UInt32(c);
+end;
+
+class procedure TNat192.Copy(x, z: TCryptoLibUInt32Array);
+begin
+  System.Move(x[0], z[0], 6 * System.SizeOf(UInt32));
+end;
+
+class procedure TNat192.Copy(x: TCryptoLibUInt32Array; xOff: Int32;
+  z: TCryptoLibUInt32Array; zOff: Int32);
+begin
+  System.Move(x[xOff], z[zOff], 6 * System.SizeOf(UInt32));
+end;
+
+class procedure TNat192.Copy64(x, z: TCryptoLibUInt64Array);
+begin
+  System.Move(x[0], z[0], 3 * System.SizeOf(UInt64));
+end;
+
+class procedure TNat192.Copy64(x: TCryptoLibUInt64Array; xOff: Int32;
+  z: TCryptoLibUInt64Array; zOff: Int32);
+begin
+  System.Move(x[xOff], z[zOff], 3 * System.SizeOf(UInt64));
+end;
+
+class function TNat192.Create: TCryptoLibUInt32Array;
+begin
+  System.SetLength(result, 6);
+end;
+
+class function TNat192.Create64: TCryptoLibUInt64Array;
+begin
+  System.SetLength(result, 3);
+end;
+
+class function TNat192.CreateExt: TCryptoLibUInt32Array;
+begin
+  System.SetLength(result, 12);
+end;
+
+class function TNat192.CreateExt64: TCryptoLibUInt64Array;
+begin
+  System.SetLength(result, 6);
+end;
+
+class function TNat192.Diff(x: TCryptoLibUInt32Array; xOff: Int32;
+  y: TCryptoLibUInt32Array; yOff: Int32; z: TCryptoLibUInt32Array;
+  zOff: Int32): Boolean;
+var
+  pos: Boolean;
+begin
+  pos := Gte(x, xOff, y, yOff);
+  if (pos) then
+  begin
+    Sub(x, xOff, y, yOff, z, zOff);
+  end
+  else
+  begin
+    Sub(y, yOff, x, xOff, z, zOff);
+  end;
+  result := pos;
+end;
+
+class function TNat192.Eq(x, y: TCryptoLibUInt32Array): Boolean;
+var
+  i: Int32;
+begin
+  i := 5;
+  while i >= 0 do
+  begin
+    if (x[i] <> y[i]) then
+    begin
+      result := false;
+      Exit;
+    end;
+    System.Dec(i);
+  end;
+  result := true;
+end;
+
+class function TNat192.Eq64(x, y: TCryptoLibUInt64Array): Boolean;
+var
+  i: Int32;
+begin
+  i := 2;
+  while i >= 0 do
+  begin
+    if (x[i] <> y[i]) then
+    begin
+      result := false;
+      Exit;
+    end;
+    System.Dec(i);
+  end;
+  result := true;
+end;
+
+class function TNat192.FromBigInteger(const x: TBigInteger)
+  : TCryptoLibUInt32Array;
+var
+  i: Int32;
+  Lx: TBigInteger;
+begin
+  Lx := x;
+  if ((Lx.SignValue < 0) or (Lx.BitLength > 192)) then
+  begin
+    raise EArgumentCryptoLibException.Create('');
+  end;
+
+  result := Create();
+  i := 0;
+  while (Lx.SignValue <> 0) do
+  begin
+    result[i] := UInt32(Lx.Int32Value);
+    System.Inc(i);
+    Lx := Lx.ShiftRight(32);
+  end;
+end;
+
+class function TNat192.FromBigInteger64(const x: TBigInteger)
+  : TCryptoLibUInt64Array;
+var
+  i: Int32;
+  Lx: TBigInteger;
+begin
+  Lx := x;
+  if ((Lx.SignValue < 0) or (Lx.BitLength > 192)) then
+  begin
+    raise EArgumentCryptoLibException.Create('');
+  end;
+
+  result := Create64();
+  i := 0;
+  while (Lx.SignValue <> 0) do
+  begin
+    result[i] := UInt64(Lx.Int64Value);
+    System.Inc(i);
+    Lx := Lx.ShiftRight(64);
+  end;
+end;
+
+class function TNat192.GetBit(x: TCryptoLibUInt32Array; bit: Int32): UInt32;
+var
+  w, b: Int32;
+begin
+  if (bit = 0) then
+  begin
+    result := x[0] and 1;
+    Exit;
+  end;
+  w := TBits.Asr32(bit, 5);
+  if ((w < 0) or (w >= 6)) then
+  begin
+    result := 0;
+    Exit;
+  end;
+  b := bit and 31;
+  result := (x[w] shr b) and 1;
+end;
+
+class function TNat192.Gte(x, y: TCryptoLibUInt32Array): Boolean;
+var
+  i: Int32;
+  x_i, y_i: UInt32;
+begin
+  i := 5;
+  while i >= 0 do
+  begin
+    x_i := x[i];
+    y_i := y[i];
+
+    if (x_i < y_i) then
+    begin
+      result := false;
+      Exit;
+    end;
+
+    if (x_i > y_i) then
+    begin
+      result := true;
+      Exit;
+    end;
+    System.Dec(i);
+  end;
+  result := true;
+end;
+
+class function TNat192.Gte(x: TCryptoLibUInt32Array; xOff: Int32;
+  y: TCryptoLibUInt32Array; yOff: Int32): Boolean;
+var
+  i: Int32;
+  x_i, y_i: UInt32;
+begin
+  i := 5;
+  while i >= 0 do
+  begin
+    x_i := x[xOff + i];
+    y_i := y[yOff + i];
+
+    if (x_i < y_i) then
+    begin
+      result := false;
+      Exit;
+    end;
+
+    if (x_i > y_i) then
+    begin
+      result := true;
+      Exit;
+    end;
+    System.Dec(i);
+  end;
+  result := true;
+end;
+
+class function TNat192.IsOne(x: TCryptoLibUInt32Array): Boolean;
+var
+  i: Int32;
+begin
+  if (x[0] <> 1) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  i := 1;
+  while i < 6 do
+  begin
+    if (x[i] <> 0) then
+    begin
+      result := false;
+      Exit;
+    end;
+    System.Inc(i);
+  end;
+  result := true;
+end;
+
+class function TNat192.IsOne64(x: TCryptoLibUInt64Array): Boolean;
+var
+  i: Int32;
+begin
+  if (x[0] <> UInt64(1)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  i := 1;
+  while i < 3 do
+  begin
+    if (x[i] <> UInt64(0)) then
+    begin
+      result := false;
+      Exit;
+    end;
+    System.Inc(i);
+  end;
+  result := true;
+end;
+
+class function TNat192.IsZero(x: TCryptoLibUInt32Array): Boolean;
+var
+  i: Int32;
+begin
+  i := 0;
+  while i < 6 do
+  begin
+    if (x[i] <> 0) then
+    begin
+      result := false;
+      Exit;
+    end;
+    System.Inc(i);
+  end;
+  result := true;
+end;
+
+class function TNat192.IsZero64(x: TCryptoLibUInt64Array): Boolean;
+var
+  i: Int32;
+begin
+  i := 0;
+  while i < 3 do
+  begin
+    if (x[i] <> UInt64(0)) then
+    begin
+      result := false;
+      Exit;
+    end;
+    System.Inc(i);
+  end;
+  result := true;
+end;
+
+class procedure TNat192.Mul(x, y, zz: TCryptoLibUInt32Array);
+var
+  c, x_0, x_i, y_0, y_1, y_2, y_3, y_4, y_5: UInt64;
+  i: Int32;
+begin
+  y_0 := y[0];
+  y_1 := y[1];
+  y_2 := y[2];
+  y_3 := y[3];
+  y_4 := y[4];
+  y_5 := y[5];
+
+  c := 0;
+  x_0 := x[0];
+  c := c + (x_0 * y_0);
+  zz[0] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_1);
+  zz[1] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_2);
+  zz[2] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_3);
+  zz[3] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_4);
+  zz[4] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_5);
+  zz[5] := UInt32(c);
+  c := c shr 32;
+  zz[6] := UInt32(c);
+
+  for i := 1 to System.Pred(6) do
+  begin
+    c := 0;
+    x_i := x[i];
+    c := c + (x_i * y_0 + zz[i + 0]);
+    zz[i + 0] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_1 + zz[i + 1]);
+    zz[i + 1] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_2 + zz[i + 2]);
+    zz[i + 2] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_3 + zz[i + 3]);
+    zz[i + 3] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_4 + zz[i + 4]);
+    zz[i + 4] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_5 + zz[i + 5]);
+    zz[i + 5] := UInt32(c);
+    c := c shr 32;
+    zz[i + 6] := UInt32(c);
+  end;
+end;
+
+class procedure TNat192.Mul(x: TCryptoLibUInt32Array; xOff: Int32;
+  y: TCryptoLibUInt32Array; yOff: Int32; zz: TCryptoLibUInt32Array;
+  zzOff: Int32);
+var
+  c, x_0, x_i, y_0, y_1, y_2, y_3, y_4, y_5: UInt64;
+  i: Int32;
+begin
+  y_0 := y[yOff + 0];
+  y_1 := y[yOff + 1];
+  y_2 := y[yOff + 2];
+  y_3 := y[yOff + 3];
+  y_4 := y[yOff + 4];
+  y_5 := y[yOff + 5];
+
+  c := 0;
+  x_0 := x[xOff + 0];
+  c := c + (x_0 * y_0);
+  zz[zzOff + 0] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_1);
+  zz[zzOff + 1] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_2);
+  zz[zzOff + 2] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_3);
+  zz[zzOff + 3] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_4);
+  zz[zzOff + 4] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_5);
+  zz[zzOff + 5] := UInt32(c);
+  c := c shr 32;
+  zz[zzOff + 6] := UInt32(c);
+
+  for i := 1 to System.Pred(6) do
+  begin
+    System.Inc(zzOff);
+    c := 0;
+    x_i := x[xOff + i];
+    c := c + (x_i * y_0 + zz[zzOff + 0]);
+    zz[zzOff + 0] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_1 + zz[zzOff + 1]);
+    zz[zzOff + 1] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_2 + zz[zzOff + 2]);
+    zz[zzOff + 2] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_3 + zz[zzOff + 3]);
+    zz[zzOff + 3] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_4 + zz[zzOff + 4]);
+    zz[zzOff + 4] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_5 + zz[zzOff + 5]);
+    zz[zzOff + 5] := UInt32(c);
+    c := c shr 32;
+    zz[zzOff + 6] := UInt32(c);
+  end;
+end;
+
+class function TNat192.MulAddTo(x, y, zz: TCryptoLibUInt32Array): UInt32;
+var
+  c, x_i, y_0, y_1, y_2, y_3, y_4, y_5, zc: UInt64;
+  i: Int32;
+begin
+  y_0 := y[0];
+  y_1 := y[1];
+  y_2 := y[2];
+  y_3 := y[3];
+  y_4 := y[4];
+  y_5 := y[5];
+
+  zc := 0;
+  for i := 0 to System.Pred(6) do
+  begin
+    c := 0;
+    x_i := x[i];
+    c := c + (x_i * y_0 + zz[i + 0]);
+    zz[i + 0] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_1 + zz[i + 1]);
+    zz[i + 1] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_2 + zz[i + 2]);
+    zz[i + 2] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_3 + zz[i + 3]);
+    zz[i + 3] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_4 + zz[i + 4]);
+    zz[i + 4] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_5 + zz[i + 5]);
+    zz[i + 5] := UInt32(c);
+    c := c shr 32;
+    c := c + (zc + zz[i + 6]);
+    zz[i + 6] := UInt32(c);
+    zc := c shr 32;
+  end;
+  result := UInt32(zc);
+end;
+
+class function TNat192.MulAddTo(x: TCryptoLibUInt32Array; xOff: Int32;
+  y: TCryptoLibUInt32Array; yOff: Int32; zz: TCryptoLibUInt32Array;
+  zzOff: Int32): UInt32;
+var
+  c, x_i, y_0, y_1, y_2, y_3, y_4, y_5, zc: UInt64;
+  i: Int32;
+begin
+  y_0 := y[yOff + 0];
+  y_1 := y[yOff + 1];
+  y_2 := y[yOff + 2];
+  y_3 := y[yOff + 3];
+  y_4 := y[yOff + 4];
+  y_5 := y[yOff + 5];
+
+  zc := 0;
+  for i := 0 to System.Pred(6) do
+  begin
+    c := 0;
+    x_i := x[xOff + i];
+    c := c + (x_i * y_0 + zz[zzOff + 0]);
+    zz[zzOff + 0] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_1 + zz[zzOff + 1]);
+    zz[zzOff + 1] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_2 + zz[zzOff + 2]);
+    zz[zzOff + 2] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_3 + zz[zzOff + 3]);
+    zz[zzOff + 3] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_4 + zz[zzOff + 4]);
+    zz[zzOff + 4] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_5 + zz[zzOff + 5]);
+    zz[zzOff + 5] := UInt32(c);
+    c := c shr 32;
+    c := c + (zc + zz[zzOff + 6]);
+    zz[zzOff + 6] := UInt32(c);
+    zc := c shr 32;
+    System.Inc(zzOff);
+  end;
+  result := UInt32(zc);
+end;
+
+class function TNat192.Mul33Add(w: UInt32; x: TCryptoLibUInt32Array;
+  xOff: Int32; y: TCryptoLibUInt32Array; yOff: Int32; z: TCryptoLibUInt32Array;
+  zOff: Int32): UInt64;
+var
+  c, wVal, x0, x1, x2, x3, x4, x5: UInt64;
+begin
+{$IFDEF DEBUG}
+  System.Assert(w shr 31 = 0);
+{$ENDIF DEBUG}
+  c := 0;
+  wVal := w;
+  x0 := x[xOff + 0];
+  c := c + (wVal * x0 + y[yOff + 0]);
+  z[zOff + 0] := UInt32(c);
+  c := c shr 32;
+  x1 := x[xOff + 1];
+  c := c + (wVal * x1 + x0 + y[yOff + 1]);
+  z[zOff + 1] := UInt32(c);
+  c := c shr 32;
+  x2 := x[xOff + 2];
+  c := c + (wVal * x2 + x1 + y[yOff + 2]);
+  z[zOff + 2] := UInt32(c);
+  c := c shr 32;
+  x3 := x[xOff + 3];
+  c := c + (wVal * x3 + x2 + y[yOff + 3]);
+  z[zOff + 3] := UInt32(c);
+  c := c shr 32;
+  x4 := x[xOff + 4];
+  c := c + (wVal * x4 + x3 + y[yOff + 4]);
+  z[zOff + 4] := UInt32(c);
+  c := c shr 32;
+  x5 := x[xOff + 5];
+  c := c + (wVal * x5 + x4 + y[yOff + 5]);
+  z[zOff + 5] := UInt32(c);
+  c := c shr 32;
+  c := c + x5;
+  result := c;
+end;
+
+class function TNat192.MulWordAddExt(x: UInt32; yy: TCryptoLibUInt32Array;
+  yyOff: Int32; zz: TCryptoLibUInt32Array; zzOff: Int32): UInt32;
+var
+  c, xVal: UInt64;
+begin
+{$IFDEF DEBUG}
+  System.Assert(yyOff <= 6);
+  System.Assert(zzOff <= 6);
+{$ENDIF DEBUG}
+  c := 0;
+  xVal := x;
+  c := c + (xVal * yy[yyOff + 0] + zz[zzOff + 0]);
+  zz[zzOff + 0] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * yy[yyOff + 1] + zz[zzOff + 1]);
+  zz[zzOff + 1] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * yy[yyOff + 2] + zz[zzOff + 2]);
+  zz[zzOff + 2] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * yy[yyOff + 3] + zz[zzOff + 3]);
+  zz[zzOff + 3] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * yy[yyOff + 4] + zz[zzOff + 4]);
+  zz[zzOff + 4] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * yy[yyOff + 5] + zz[zzOff + 5]);
+  zz[zzOff + 5] := UInt32(c);
+  c := c shr 32;
+  result := UInt32(c);
+end;
+
+class function TNat192.Mul33DWordAdd(x: UInt32; y: UInt64;
+  z: TCryptoLibUInt32Array; zOff: Int32): UInt32;
+var
+  c, xVal, y00, y01: UInt64;
+begin
+{$IFDEF DEBUG}
+  System.Assert(x shr 31 = 0);
+  System.Assert(zOff <= 2);
+{$ENDIF DEBUG}
+  c := 0;
+  xVal := x;
+  y00 := y and M;
+  c := c + (xVal * y00 + z[zOff + 0]);
+  z[zOff + 0] := UInt32(c);
+  c := c shr 32;
+  y01 := y shr 32;
+  c := c + (xVal * y01 + y00 + z[zOff + 1]);
+  z[zOff + 1] := UInt32(c);
+  c := c shr 32;
+  c := c + (y01 + z[zOff + 2]);
+  z[zOff + 2] := UInt32(c);
+  c := c shr 32;
+  c := c + (z[zOff + 3]);
+  z[zOff + 3] := UInt32(c);
+  c := c shr 32;
+  if c = 0 then
+  begin
+    result := 0;
+  end
+  else
+  begin
+    result := TNat.IncAt(6, z, zOff, 4);
+  end;
+end;
+
+class function TNat192.Mul33WordAdd(x, y: UInt32; z: TCryptoLibUInt32Array;
+  zOff: Int32): UInt32;
+var
+  c, yVal: UInt64;
+begin
+{$IFDEF DEBUG}
+  System.Assert(x shr 31 = 0);
+  System.Assert(zOff <= 3);
+{$ENDIF DEBUG}
+  c := 0;
+  yVal := y;
+  c := c + (yVal * x + z[zOff + 0]);
+  z[zOff + 0] := UInt32(c);
+  c := c shr 32;
+  c := c + (yVal + z[zOff + 1]);
+  z[zOff + 1] := UInt32(c);
+  c := c shr 32;
+  c := c + (z[zOff + 2]);
+  z[zOff + 2] := UInt32(c);
+  c := c shr 32;
+  if c = 0 then
+  begin
+    result := 0;
+  end
+  else
+  begin
+    result := TNat.IncAt(6, z, zOff, 3);
+  end;
+end;
+
+class function TNat192.MulWordDwordAdd(x: UInt32; y: UInt64;
+  z: TCryptoLibUInt32Array; zOff: Int32): UInt32;
+var
+  c, xVal: UInt64;
+begin
+{$IFDEF DEBUG}
+  System.Assert(zOff <= 3);
+{$ENDIF DEBUG}
+  c := 0;
+  xVal := x;
+  c := c + (xVal * y + z[zOff + 0]);
+  z[zOff + 0] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * (y shr 32) + z[zOff + 1]);
+  z[zOff + 1] := UInt32(c);
+  c := c shr 32;
+  c := c + (z[zOff + 2]);
+  z[zOff + 2] := UInt32(c);
+  c := c shr 32;
+  if c = 0 then
+  begin
+    result := 0;
+  end
+  else
+  begin
+    result := TNat.IncAt(6, z, zOff, 3);
+  end;
+end;
+
+class function TNat192.MulWord(x: UInt32; y, z: TCryptoLibUInt32Array;
+  zOff: Int32): UInt32;
+var
+  c, xVal: UInt64;
+  i: Int32;
+begin
+  c := 0;
+  xVal := x;
+  i := 0;
+  repeat
+    c := c + (xVal * y[i]);
+    z[zOff + i] := UInt32(c);
+    c := c shr 32;
+    System.Inc(i);
+  until not(i < 6);
+  result := UInt32(c);
+end;
+
+class procedure TNat192.Square(x, zz: TCryptoLibUInt32Array);
+var
+  x_0, zz_1, xVal, p, x_1, zz_2, x_2, zz_3, zz_4, x_3, zz_5, zz_6, x_4, zz_7,
+    zz_8, x_5, zz_9, zz_10: UInt64;
+  c, w: UInt32;
+  i, j: Int32;
+begin
+  x_0 := x[0];
+  c := 0;
+  i := 5;
+  j := 12;
+
+  repeat
+    xVal := x[i];
+    System.Dec(i);
+    p := xVal * xVal;
+    System.Dec(j);
+    zz[j] := (c shl 31) or UInt32(p shr 33);
+    System.Dec(j);
+    zz[j] := UInt32(p shr 1);
+    c := UInt32(p);
+  until not(i > 0);
+
+  p := x_0 * x_0;
+  zz_1 := UInt64(c shl 31) or (p shr 33);
+  zz[0] := UInt32(p);
+  c := UInt32(p shr 32) and 1;
+
+  x_1 := x[1];
+  zz_2 := zz[2];
+
+  zz_1 := zz_1 + (x_1 * x_0);
+  w := UInt32(zz_1);
+  zz[1] := (w shl 1) or c;
+  c := w shr 31;
+  zz_2 := zz_2 + (zz_1 shr 32);
+
+  x_2 := x[2];
+  zz_3 := zz[3];
+  zz_4 := zz[4];
+
+  zz_2 := zz_2 + (x_2 * x_0);
+  w := UInt32(zz_2);
+  zz[2] := (w shl 1) or c;
+  c := w shr 31;
+  zz_3 := zz_3 + ((zz_2 shr 32) + x_2 * x_1);
+  zz_4 := zz_4 + (zz_3 shr 32);
+  zz_3 := zz_3 and M;
+
+  x_3 := x[3];
+  zz_5 := zz[5] + (zz_4 shr 32);
+  zz_4 := zz_4 and M;
+  zz_6 := zz[6] + (zz_5 shr 32);
+  zz_5 := zz_5 and M;
+
+  zz_3 := zz_3 + (x_3 * x_0);
+  w := UInt32(zz_3);
+  zz[3] := (w shl 1) or c;
+  c := w shr 31;
+  zz_4 := zz_4 + ((zz_3 shr 32) + x_3 * x_1);
+  zz_5 := zz_5 + ((zz_4 shr 32) + x_3 * x_2);
+  zz_4 := zz_4 and M;
+  zz_6 := zz_6 + (zz_5 shr 32);
+  zz_5 := zz_5 and M;
+
+  x_4 := x[4];
+  zz_7 := zz[7] + (zz_6 shr 32);
+  zz_6 := zz_6 and M;
+  zz_8 := zz[8] + (zz_7 shr 32);
+  zz_7 := zz_7 and M;
+
+  zz_4 := zz_4 + (x_4 * x_0);
+  w := UInt32(zz_4);
+  zz[4] := (w shl 1) or c;
+  c := w shr 31;
+  zz_5 := zz_5 + ((zz_4 shr 32) + x_4 * x_1);
+  zz_6 := zz_6 + ((zz_5 shr 32) + x_4 * x_2);
+  zz_5 := zz_5 and M;
+  zz_7 := zz_7 + ((zz_6 shr 32) + x_4 * x_3);
+  zz_6 := zz_6 and M;
+  zz_8 := zz_8 + (zz_7 shr 32);
+  zz_7 := zz_7 and M;
+
+  x_5 := x[5];
+  zz_9 := zz[9] + (zz_8 shr 32);
+  zz_8 := zz_8 and M;
+  zz_10 := zz[10] + (zz_9 shr 32);
+  zz_9 := zz_9 and M;
+
+  zz_5 := zz_5 + (x_5 * x_0);
+  w := UInt32(zz_5);
+  zz[5] := (w shl 1) or c;
+  c := w shr 31;
+  zz_6 := zz_6 + ((zz_5 shr 32) + x_5 * x_1);
+  zz_7 := zz_7 + ((zz_6 shr 32) + x_5 * x_2);
+  zz_8 := zz_8 + ((zz_7 shr 32) + x_5 * x_3);
+  zz_9 := zz_9 + ((zz_8 shr 32) + x_5 * x_4);
+  zz_10 := zz_10 + (zz_9 shr 32);
+
+  w := UInt32(zz_6);
+  zz[6] := (w shl 1) or c;
+  c := w shr 31;
+
+  w := UInt32(zz_7);
+  zz[7] := (w shl 1) or c;
+  c := w shr 31;
+
+  w := UInt32(zz_8);
+  zz[8] := (w shl 1) or c;
+  c := w shr 31;
+
+  w := UInt32(zz_9);
+  zz[9] := (w shl 1) or c;
+  c := w shr 31;
+
+  w := UInt32(zz_10);
+  zz[10] := (w shl 1) or c;
+  c := w shr 31;
+
+  w := zz[11] + UInt32(zz_10 shr 32);
+  zz[11] := (w shl 1) or c;
+end;
+
+class procedure TNat192.Square(x: TCryptoLibUInt32Array; xOff: Int32;
+  zz: TCryptoLibUInt32Array; zzOff: Int32);
+var
+  x_0, zz_1, xVal, p, x_1, zz_2, x_2, zz_3, zz_4, x_3, zz_5, zz_6, x_4, zz_7,
+    zz_8, x_5, zz_9, zz_10: UInt64;
+  c, w: UInt32;
+  i, j: Int32;
+begin
+  x_0 := x[xOff + 0];
+  c := 0;
+  i := 5;
+  j := 12;
+
+  repeat
+    xVal := x[xOff + i];
+    System.Dec(i);
+    p := xVal * xVal;
+    System.Dec(j);
+    zz[zzOff + j] := (c shl 31) or UInt32(p shr 33);
+    System.Dec(j);
+    zz[zzOff + j] := UInt32(p shr 1);
+    c := UInt32(p);
+  until not(i > 0);
+
+  p := x_0 * x_0;
+  zz_1 := UInt64(c shl 31) or (p shr 33);
+  zz[zzOff + 0] := UInt32(p);
+  c := UInt32(p shr 32) and 1;
+
+  x_1 := x[xOff + 1];
+  zz_2 := zz[zzOff + 2];
+
+  zz_1 := zz_1 + (x_1 * x_0);
+  w := UInt32(zz_1);
+  zz[zzOff + 1] := (w shl 1) or c;
+  c := w shr 31;
+  zz_2 := zz_2 + (zz_1 shr 32);
+
+  x_2 := x[xOff + 2];
+  zz_3 := zz[zzOff + 3];
+  zz_4 := zz[zzOff + 4];
+
+  zz_2 := zz_2 + (x_2 * x_0);
+  w := UInt32(zz_2);
+  zz[zzOff + 2] := (w shl 1) or c;
+  c := w shr 31;
+  zz_3 := zz_3 + ((zz_2 shr 32) + x_2 * x_1);
+  zz_4 := zz_4 + (zz_3 shr 32);
+  zz_3 := zz_3 and M;
+
+  x_3 := x[xOff + 3];
+  zz_5 := zz[zzOff + 5] + (zz_4 shr 32);
+  zz_4 := zz_4 and M;
+  zz_6 := zz[zzOff + 6] + (zz_5 shr 32);
+  zz_5 := zz_5 and M;
+
+  zz_3 := zz_3 + (x_3 * x_0);
+  w := UInt32(zz_3);
+  zz[zzOff + 3] := (w shl 1) or c;
+  c := w shr 31;
+  zz_4 := zz_4 + ((zz_3 shr 32) + x_3 * x_1);
+  zz_5 := zz_5 + ((zz_4 shr 32) + x_3 * x_2);
+  zz_4 := zz_4 and M;
+  zz_6 := zz_6 + (zz_5 shr 32);
+  zz_5 := zz_5 and M;
+
+  x_4 := x[xOff + 4];
+  zz_7 := zz[zzOff + 7] + (zz_6 shr 32);
+  zz_6 := zz_6 and M;
+  zz_8 := zz[zzOff + 8] + (zz_7 shr 32);
+  zz_7 := zz_7 and M;
+
+  zz_4 := zz_4 + (x_4 * x_0);
+  w := UInt32(zz_4);
+  zz[zzOff + 4] := (w shl 1) or c;
+  c := w shr 31;
+  zz_5 := zz_5 + ((zz_4 shr 32) + x_4 * x_1);
+  zz_6 := zz_6 + ((zz_5 shr 32) + x_4 * x_2);
+  zz_5 := zz_5 and M;
+  zz_7 := zz_7 + ((zz_6 shr 32) + x_4 * x_3);
+  zz_6 := zz_6 and M;
+  zz_8 := zz_8 + (zz_7 shr 32);
+  zz_7 := zz_7 and M;
+
+  x_5 := x[xOff + 5];
+  zz_9 := zz[zzOff + 9] + (zz_8 shr 32);
+  zz_8 := zz_8 and M;
+  zz_10 := zz[zzOff + 10] + (zz_9 shr 32);
+  zz_9 := zz_9 and M;
+
+  zz_5 := zz_5 + (x_5 * x_0);
+  w := UInt32(zz_5);
+  zz[zzOff + 5] := (w shl 1) or c;
+  c := w shr 31;
+  zz_6 := zz_6 + ((zz_5 shr 32) + x_5 * x_1);
+  zz_7 := zz_7 + ((zz_6 shr 32) + x_5 * x_2);
+  zz_8 := zz_8 + ((zz_7 shr 32) + x_5 * x_3);
+  zz_9 := zz_9 + ((zz_8 shr 32) + x_5 * x_4);
+  zz_10 := zz_10 + (zz_9 shr 32);
+
+  w := UInt32(zz_6);
+  zz[zzOff + 6] := (w shl 1) or c;
+  c := w shr 31;
+
+  w := UInt32(zz_7);
+  zz[zzOff + 7] := (w shl 1) or c;
+  c := w shr 31;
+
+  w := UInt32(zz_8);
+  zz[zzOff + 8] := (w shl 1) or c;
+  c := w shr 31;
+
+  w := UInt32(zz_9);
+  zz[zzOff + 9] := (w shl 1) or c;
+  c := w shr 31;
+
+  w := UInt32(zz_10);
+  zz[zzOff + 10] := (w shl 1) or c;
+  c := w shr 31;
+
+  w := zz[zzOff + 11] + UInt32(zz_10 shr 32);
+  zz[zzOff + 11] := (w shl 1) or c;
+end;
+
+class function TNat192.Sub(x, y, z: TCryptoLibUInt32Array): Int32;
+var
+  c: Int64;
+begin
+  c := 0;
+  c := c + (Int64(x[0]) - y[0]);
+  z[0] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[1]) - y[1]);
+  z[1] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[2]) - y[2]);
+  z[2] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[3]) - y[3]);
+  z[3] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[4]) - y[4]);
+  z[4] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[5]) - y[5]);
+  z[5] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  result := Int32(c);
+end;
+
+class function TNat192.Sub(x: TCryptoLibUInt32Array; xOff: Int32;
+  y: TCryptoLibUInt32Array; yOff: Int32; z: TCryptoLibUInt32Array;
+  zOff: Int32): Int32;
+var
+  c: Int64;
+begin
+  c := 0;
+  c := c + (Int64(x[xOff + 0]) - y[yOff + 0]);
+  z[zOff + 0] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[xOff + 1]) - y[yOff + 1]);
+  z[zOff + 1] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[xOff + 2]) - y[yOff + 2]);
+  z[zOff + 2] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[xOff + 3]) - y[yOff + 3]);
+  z[zOff + 3] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[xOff + 4]) - y[yOff + 4]);
+  z[zOff + 4] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[xOff + 5]) - y[yOff + 5]);
+  z[zOff + 5] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  result := Int32(c);
+end;
+
+class function TNat192.SubBothFrom(x, y, z: TCryptoLibUInt32Array): Int32;
+var
+  c: Int64;
+begin
+  c := 0;
+  c := c + (Int64(z[0]) - x[0] - y[0]);
+  z[0] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[1]) - x[1] - y[1]);
+  z[1] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[2]) - x[2] - y[2]);
+  z[2] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[3]) - x[3] - y[3]);
+  z[3] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[4]) - x[4] - y[4]);
+  z[4] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[5]) - x[5] - y[5]);
+  z[5] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  result := Int32(c);
+end;
+
+class function TNat192.SubFrom(x, z: TCryptoLibUInt32Array): Int32;
+var
+  c: Int64;
+begin
+  c := 0;
+  c := c + (Int64(z[0]) - x[0]);
+  z[0] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[1]) - x[1]);
+  z[1] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[2]) - x[2]);
+  z[2] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[3]) - x[3]);
+  z[3] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[4]) - x[4]);
+  z[4] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[5]) - x[5]);
+  z[5] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  result := Int32(c);
+end;
+
+class function TNat192.SubFrom(x: TCryptoLibUInt32Array; xOff: Int32;
+  z: TCryptoLibUInt32Array; zOff: Int32): Int32;
+var
+  c: Int64;
+begin
+  c := 0;
+  c := c + (Int64(z[zOff + 0]) - x[xOff + 0]);
+  z[zOff + 0] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[zOff + 1]) - x[xOff + 1]);
+  z[zOff + 1] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[zOff + 2]) - x[xOff + 2]);
+  z[zOff + 2] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[zOff + 3]) - x[xOff + 3]);
+  z[zOff + 3] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[zOff + 4]) - x[xOff + 4]);
+  z[zOff + 4] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[zOff + 5]) - x[xOff + 5]);
+  z[zOff + 5] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  result := Int32(c);
+end;
+
+class function TNat192.ToBigInteger(x: TCryptoLibUInt32Array): TBigInteger;
+var
+  bs, temp: TCryptoLibByteArray;
+  i: Int32;
+  x_i: UInt32;
+begin
+  System.SetLength(bs, 24);
+  for i := 0 to System.Pred(6) do
+
+  begin
+    x_i := x[i];
+    if (x_i <> 0) then
+    begin
+      temp := TConverters.ReadUInt32AsBytesBE(x_i);
+      System.Move(temp[0], bs[(5 - i) shl 2], System.Length(temp) *
+        System.SizeOf(Byte))
+    end;
+  end;
+  result := TBigInteger.Create(1, bs);
+end;
+
+class function TNat192.ToBigInteger64(x: TCryptoLibUInt64Array): TBigInteger;
+var
+  bs, temp: TCryptoLibByteArray;
+  i: Int32;
+  x_i: UInt64;
+begin
+  System.SetLength(bs, 24);
+  for i := 0 to System.Pred(3) do
+
+  begin
+    x_i := x[i];
+    if (x_i <> Int64(0)) then
+    begin
+      temp := TConverters.ReadUInt64AsBytesBE(x_i);
+      System.Move(temp[0], bs[(2 - i) shl 3], System.Length(temp) *
+        System.SizeOf(Byte))
+    end;
+  end;
+  result := TBigInteger.Create(1, bs);
+end;
+
+class procedure TNat192.Zero(z: TCryptoLibUInt32Array);
+begin
+  System.FillChar(z[0], 6 * System.SizeOf(UInt32), UInt32(0));
+end;
+
+end.

+ 1768 - 0
CryptoLib/src/Math/Raw/ClpNat256.pas

@@ -0,0 +1,1768 @@
+{ *********************************************************************************** }
+{ *                              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 ClpNat256;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpNat,
+  ClpConverters,
+  ClpBits,
+  ClpBigInteger,
+  ClpCryptoLibTypes;
+
+type
+  TNat256 = class abstract(TObject)
+
+  strict private
+  const
+    M = UInt64($FFFFFFFF);
+
+  public
+    class function Add(x, y, z: TCryptoLibUInt32Array): UInt32;
+      overload; static;
+    class function Add(x: TCryptoLibUInt32Array; xOff: Int32;
+      y: TCryptoLibUInt32Array; yOff: Int32; z: TCryptoLibUInt32Array;
+      zOff: Int32): UInt32; overload; static;
+
+    class function AddBothTo(x, y, z: TCryptoLibUInt32Array): UInt32;
+      overload; static;
+    class function AddBothTo(x: TCryptoLibUInt32Array; xOff: Int32;
+      y: TCryptoLibUInt32Array; yOff: Int32; z: TCryptoLibUInt32Array;
+      zOff: Int32): UInt32; overload; static;
+
+    class function AddTo(x, z: TCryptoLibUInt32Array): UInt32; overload; static;
+    class function AddTo(x: TCryptoLibUInt32Array; xOff: Int32;
+      z: TCryptoLibUInt32Array; zOff: Int32; cIn: UInt32): UInt32;
+      overload; static;
+
+    class function AddToEachOther(u: TCryptoLibUInt32Array; uOff: Int32;
+      v: TCryptoLibUInt32Array; vOff: Int32): UInt32; static;
+
+    class procedure Copy(x, z: TCryptoLibUInt32Array); overload; static; inline;
+    class procedure Copy(x: TCryptoLibUInt32Array; xOff: Int32;
+      z: TCryptoLibUInt32Array; zOff: Int32); overload; static; inline;
+
+    class procedure Copy64(x, z: TCryptoLibUInt64Array); overload;
+      static; inline;
+
+    class procedure Copy64(x: TCryptoLibUInt64Array; xOff: Int32;
+      z: TCryptoLibUInt64Array; zOff: Int32); overload; static; inline;
+
+    class function Create(): TCryptoLibUInt32Array; static; inline;
+
+    class function Create64(): TCryptoLibUInt64Array; static; inline;
+
+    class function CreateExt(): TCryptoLibUInt32Array; static; inline;
+
+    class function CreateExt64(): TCryptoLibUInt64Array; static; inline;
+
+    class function Diff(x: TCryptoLibUInt32Array; xOff: Int32;
+      y: TCryptoLibUInt32Array; yOff: Int32; z: TCryptoLibUInt32Array;
+      zOff: Int32): Boolean; static; inline;
+
+    class function Eq(x, y: TCryptoLibUInt32Array): Boolean; static;
+
+    class function Eq64(x, y: TCryptoLibUInt64Array): Boolean; static;
+
+    class function FromBigInteger(const x: TBigInteger)
+      : TCryptoLibUInt32Array; static;
+
+    class function FromBigInteger64(const x: TBigInteger)
+      : TCryptoLibUInt64Array; static;
+
+    class function GetBit(x: TCryptoLibUInt32Array; bit: Int32): UInt32;
+      static; inline;
+
+    class function Gte(x, y: TCryptoLibUInt32Array): Boolean; overload; static;
+
+    class function Gte(x: TCryptoLibUInt32Array; xOff: Int32;
+      y: TCryptoLibUInt32Array; yOff: Int32): Boolean; overload; static;
+
+    class function IsOne(x: TCryptoLibUInt32Array): Boolean; static;
+
+    class function IsOne64(x: TCryptoLibUInt64Array): Boolean; static;
+
+    class function IsZero(x: TCryptoLibUInt32Array): Boolean; static;
+
+    class function IsZero64(x: TCryptoLibUInt64Array): Boolean; static;
+
+    class procedure Mul(x, y, zz: TCryptoLibUInt32Array); overload; static;
+
+    class procedure Mul(x: TCryptoLibUInt32Array; xOff: Int32;
+      y: TCryptoLibUInt32Array; yOff: Int32; zz: TCryptoLibUInt32Array;
+      zzOff: Int32); overload; static;
+
+    class function MulAddTo(x, y, zz: TCryptoLibUInt32Array): UInt32;
+      overload; static;
+
+    class function MulAddTo(x: TCryptoLibUInt32Array; xOff: Int32;
+      y: TCryptoLibUInt32Array; yOff: Int32; zz: TCryptoLibUInt32Array;
+      zzOff: Int32): UInt32; overload; static;
+
+    class function Mul33Add(w: UInt32; x: TCryptoLibUInt32Array; xOff: Int32;
+      y: TCryptoLibUInt32Array; yOff: Int32; z: TCryptoLibUInt32Array;
+      zOff: Int32): UInt64; static;
+
+    class function MulByWord(x: UInt32; z: TCryptoLibUInt32Array)
+      : UInt32; static;
+
+    class function MulByWordAddTo(x: UInt32; y, z: TCryptoLibUInt32Array)
+      : UInt32; static;
+
+    class function MulWordAddTo(x: UInt32; y: TCryptoLibUInt32Array;
+      yOff: Int32; z: TCryptoLibUInt32Array; zOff: Int32): UInt32; static;
+
+    class function Mul33DWordAdd(x: UInt32; y: UInt64; z: TCryptoLibUInt32Array;
+      zOff: Int32): UInt32; static;
+
+    class function Mul33WordAdd(x, y: UInt32; z: TCryptoLibUInt32Array;
+      zOff: Int32): UInt32; static;
+
+    class function MulWordDwordAdd(x: UInt32; y: UInt64;
+      z: TCryptoLibUInt32Array; zOff: Int32): UInt32; static;
+
+    class function MulWord(x: UInt32; y, z: TCryptoLibUInt32Array; zOff: Int32)
+      : UInt32; static;
+
+    class procedure Square(x, zz: TCryptoLibUInt32Array); overload; static;
+
+    class procedure Square(x: TCryptoLibUInt32Array; xOff: Int32;
+      zz: TCryptoLibUInt32Array; zzOff: Int32); overload; static;
+
+    class function Sub(x, y, z: TCryptoLibUInt32Array): Int32; overload; static;
+
+    class function Sub(x: TCryptoLibUInt32Array; xOff: Int32;
+      y: TCryptoLibUInt32Array; yOff: Int32; z: TCryptoLibUInt32Array;
+      zOff: Int32): Int32; overload; static;
+
+    class function SubBothFrom(x, y, z: TCryptoLibUInt32Array): Int32; static;
+
+    class function SubFrom(x, z: TCryptoLibUInt32Array): Int32;
+      overload; static;
+
+    class function SubFrom(x: TCryptoLibUInt32Array; xOff: Int32;
+      z: TCryptoLibUInt32Array; zOff: Int32): Int32; overload; static;
+
+    class function ToBigInteger(x: TCryptoLibUInt32Array): TBigInteger; static;
+
+    class function ToBigInteger64(x: TCryptoLibUInt64Array)
+      : TBigInteger; static;
+
+    class procedure Zero(z: TCryptoLibUInt32Array); static; inline;
+
+  end;
+
+implementation
+
+{ TNat256 }
+
+class function TNat256.Add(x, y, z: TCryptoLibUInt32Array): UInt32;
+var
+  c: UInt64;
+begin
+  c := 0;
+  c := c + (UInt64(x[0]) + y[0]);
+  z[0] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[1]) + y[1]);
+  z[1] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[2]) + y[2]);
+  z[2] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[3]) + y[3]);
+  z[3] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[4]) + y[4]);
+  z[4] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[5]) + y[5]);
+  z[5] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[6]) + y[6]);
+  z[6] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[7]) + y[7]);
+  z[7] := UInt32(c);
+  c := c shr 32;
+  result := UInt32(c);
+end;
+
+class function TNat256.Add(x: TCryptoLibUInt32Array; xOff: Int32;
+  y: TCryptoLibUInt32Array; yOff: Int32; z: TCryptoLibUInt32Array;
+  zOff: Int32): UInt32;
+var
+  c: UInt64;
+begin
+  c := 0;
+  c := c + (UInt64(x[xOff + 0]) + y[yOff + 0]);
+  z[zOff + 0] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 1]) + y[yOff + 1]);
+  z[zOff + 1] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 2]) + y[yOff + 2]);
+  z[zOff + 2] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 3]) + y[yOff + 3]);
+  z[zOff + 3] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 4]) + y[yOff + 4]);
+  z[zOff + 4] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 5]) + y[yOff + 5]);
+  z[zOff + 5] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 6]) + y[yOff + 6]);
+  z[zOff + 6] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 7]) + y[yOff + 7]);
+  z[zOff + 7] := UInt32(c);
+  c := c shr 32;
+  result := UInt32(c);
+end;
+
+class function TNat256.AddBothTo(x, y, z: TCryptoLibUInt32Array): UInt32;
+var
+  c: UInt64;
+begin
+  c := 0;
+  c := c + (UInt64(x[0]) + y[0] + z[0]);
+  z[0] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[1]) + y[1] + z[1]);
+  z[1] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[2]) + y[2] + z[2]);
+  z[2] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[3]) + y[3] + z[3]);
+  z[3] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[4]) + y[4] + z[4]);
+  z[4] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[5]) + y[5] + z[5]);
+  z[5] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[6]) + y[6] + z[6]);
+  z[6] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[7]) + y[7] + z[7]);
+  z[7] := UInt32(c);
+  c := c shr 32;
+  result := UInt32(c);
+end;
+
+class function TNat256.AddBothTo(x: TCryptoLibUInt32Array; xOff: Int32;
+  y: TCryptoLibUInt32Array; yOff: Int32; z: TCryptoLibUInt32Array;
+  zOff: Int32): UInt32;
+var
+  c: UInt64;
+begin
+  c := 0;
+  c := c + (UInt64(x[xOff + 0]) + y[yOff + 0] + z[zOff + 0]);
+  z[zOff + 0] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 1]) + y[yOff + 1] + z[zOff + 1]);
+  z[zOff + 1] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 2]) + y[yOff + 2] + z[zOff + 2]);
+  z[zOff + 2] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 3]) + y[yOff + 3] + z[zOff + 3]);
+  z[zOff + 3] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 4]) + y[yOff + 4] + z[zOff + 4]);
+  z[zOff + 4] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 5]) + y[yOff + 5] + z[zOff + 5]);
+  z[zOff + 5] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 6]) + y[yOff + 6] + z[zOff + 6]);
+  z[zOff + 6] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 7]) + y[yOff + 7] + z[zOff + 7]);
+  z[zOff + 7] := UInt32(c);
+  c := c shr 32;
+  result := UInt32(c);
+end;
+
+class function TNat256.AddTo(x, z: TCryptoLibUInt32Array): UInt32;
+var
+  c: UInt64;
+begin
+  c := 0;
+  c := c + (UInt64(x[0]) + z[0]);
+  z[0] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[1]) + z[1]);
+  z[1] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[2]) + z[2]);
+  z[2] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[3]) + z[3]);
+  z[3] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[4]) + z[4]);
+  z[4] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[5]) + z[5]);
+  z[5] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[6]) + z[6]);
+  z[6] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[7]) + z[7]);
+  z[7] := UInt32(c);
+  c := c shr 32;
+  result := UInt32(c);
+end;
+
+class function TNat256.AddTo(x: TCryptoLibUInt32Array; xOff: Int32;
+  z: TCryptoLibUInt32Array; zOff: Int32; cIn: UInt32): UInt32;
+var
+  c: UInt64;
+begin
+  c := cIn;
+  c := c + (UInt64(x[xOff + 0]) + z[zOff + 0]);
+  z[zOff + 0] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 1]) + z[zOff + 1]);
+  z[zOff + 1] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 2]) + z[zOff + 2]);
+  z[zOff + 2] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 3]) + z[zOff + 3]);
+  z[zOff + 3] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 4]) + z[zOff + 4]);
+  z[zOff + 4] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 5]) + z[zOff + 5]);
+  z[zOff + 5] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 6]) + z[zOff + 6]);
+  z[zOff + 6] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(x[xOff + 7]) + z[zOff + 7]);
+  z[zOff + 7] := UInt32(c);
+  c := c shr 32;
+  result := UInt32(c);
+end;
+
+class function TNat256.AddToEachOther(u: TCryptoLibUInt32Array; uOff: Int32;
+  v: TCryptoLibUInt32Array; vOff: Int32): UInt32;
+var
+  c: UInt64;
+begin
+  c := 0;
+  c := c + (UInt64(u[uOff + 0]) + v[vOff + 0]);
+  u[uOff + 0] := UInt32(c);
+  v[vOff + 0] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(u[uOff + 1]) + v[vOff + 1]);
+  u[uOff + 1] := UInt32(c);
+  v[vOff + 1] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(u[uOff + 2]) + v[vOff + 2]);
+  u[uOff + 2] := UInt32(c);
+  v[vOff + 2] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(u[uOff + 3]) + v[vOff + 3]);
+  u[uOff + 3] := UInt32(c);
+  v[vOff + 3] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(u[uOff + 4]) + v[vOff + 4]);
+  u[uOff + 4] := UInt32(c);
+  v[vOff + 4] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(u[uOff + 5]) + v[vOff + 5]);
+  u[uOff + 5] := UInt32(c);
+  v[vOff + 5] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(u[uOff + 6]) + v[vOff + 6]);
+  u[uOff + 6] := UInt32(c);
+  v[vOff + 6] := UInt32(c);
+  c := c shr 32;
+  c := c + (UInt64(u[uOff + 7]) + v[vOff + 7]);
+  u[uOff + 7] := UInt32(c);
+  v[vOff + 7] := UInt32(c);
+  c := c shr 32;
+  result := UInt32(c);
+end;
+
+class procedure TNat256.Copy(x, z: TCryptoLibUInt32Array);
+begin
+  System.Move(x[0], z[0], 8 * System.SizeOf(UInt32));
+end;
+
+class procedure TNat256.Copy(x: TCryptoLibUInt32Array; xOff: Int32;
+  z: TCryptoLibUInt32Array; zOff: Int32);
+begin
+  System.Move(x[xOff], z[zOff], 8 * System.SizeOf(UInt32));
+end;
+
+class procedure TNat256.Copy64(x, z: TCryptoLibUInt64Array);
+begin
+  System.Move(x[0], z[0], 4 * System.SizeOf(UInt64));
+end;
+
+class procedure TNat256.Copy64(x: TCryptoLibUInt64Array; xOff: Int32;
+  z: TCryptoLibUInt64Array; zOff: Int32);
+begin
+  System.Move(x[xOff], z[zOff], 4 * System.SizeOf(UInt64));
+end;
+
+class function TNat256.Create: TCryptoLibUInt32Array;
+begin
+  System.SetLength(result, 8);
+end;
+
+class function TNat256.Create64: TCryptoLibUInt64Array;
+begin
+  System.SetLength(result, 4);
+end;
+
+class function TNat256.CreateExt: TCryptoLibUInt32Array;
+begin
+  System.SetLength(result, 16);
+end;
+
+class function TNat256.CreateExt64: TCryptoLibUInt64Array;
+begin
+  System.SetLength(result, 8);
+end;
+
+class function TNat256.Diff(x: TCryptoLibUInt32Array; xOff: Int32;
+  y: TCryptoLibUInt32Array; yOff: Int32; z: TCryptoLibUInt32Array;
+  zOff: Int32): Boolean;
+var
+  pos: Boolean;
+begin
+  pos := Gte(x, xOff, y, yOff);
+  if (pos) then
+  begin
+    Sub(x, xOff, y, yOff, z, zOff);
+  end
+  else
+  begin
+    Sub(y, yOff, x, xOff, z, zOff);
+  end;
+  result := pos;
+end;
+
+class function TNat256.Eq(x, y: TCryptoLibUInt32Array): Boolean;
+var
+  i: Int32;
+begin
+  i := 7;
+  while i >= 0 do
+  begin
+    if (x[i] <> y[i]) then
+    begin
+      result := false;
+      Exit;
+    end;
+    System.Dec(i);
+  end;
+  result := true;
+end;
+
+class function TNat256.Eq64(x, y: TCryptoLibUInt64Array): Boolean;
+var
+  i: Int32;
+begin
+  i := 3;
+  while i >= 0 do
+  begin
+    if (x[i] <> y[i]) then
+    begin
+      result := false;
+      Exit;
+    end;
+    System.Dec(i);
+  end;
+  result := true;
+end;
+
+class function TNat256.FromBigInteger(const x: TBigInteger)
+  : TCryptoLibUInt32Array;
+var
+  i: Int32;
+  Lx: TBigInteger;
+begin
+  Lx := x;
+  if ((Lx.SignValue < 0) or (Lx.BitLength > 256)) then
+  begin
+    raise EArgumentCryptoLibException.Create('');
+  end;
+
+  result := Create();
+  i := 0;
+  while (Lx.SignValue <> 0) do
+  begin
+    result[i] := UInt32(Lx.Int32Value);
+    System.Inc(i);
+    Lx := Lx.ShiftRight(32);
+  end;
+end;
+
+class function TNat256.FromBigInteger64(const x: TBigInteger)
+  : TCryptoLibUInt64Array;
+var
+  i: Int32;
+  Lx: TBigInteger;
+begin
+  Lx := x;
+  if ((Lx.SignValue < 0) or (Lx.BitLength > 256)) then
+  begin
+    raise EArgumentCryptoLibException.Create('');
+  end;
+
+  result := Create64();
+  i := 0;
+  while (Lx.SignValue <> 0) do
+  begin
+    result[i] := UInt64(Lx.Int64Value);
+    System.Inc(i);
+    Lx := Lx.ShiftRight(64);
+  end;
+end;
+
+class function TNat256.GetBit(x: TCryptoLibUInt32Array; bit: Int32): UInt32;
+var
+  w, b: Int32;
+begin
+  if (bit = 0) then
+  begin
+    result := x[0] and 1;
+    Exit;
+  end;
+  if ((bit and 255) <> bit) then
+  begin
+    result := 0;
+    Exit;
+  end;
+  w := TBits.Asr32(bit, 5);
+  b := bit and 31;
+  result := (x[w] shr b) and 1;
+end;
+
+class function TNat256.Gte(x, y: TCryptoLibUInt32Array): Boolean;
+var
+  i: Int32;
+  x_i, y_i: UInt32;
+begin
+  i := 7;
+  while i >= 0 do
+  begin
+    x_i := x[i];
+    y_i := y[i];
+
+    if (x_i < y_i) then
+    begin
+      result := false;
+      Exit;
+    end;
+
+    if (x_i > y_i) then
+    begin
+      result := true;
+      Exit;
+    end;
+    System.Dec(i);
+  end;
+  result := true;
+end;
+
+class function TNat256.Gte(x: TCryptoLibUInt32Array; xOff: Int32;
+  y: TCryptoLibUInt32Array; yOff: Int32): Boolean;
+var
+  i: Int32;
+  x_i, y_i: UInt32;
+begin
+  i := 7;
+  while i >= 0 do
+  begin
+    x_i := x[xOff + i];
+    y_i := y[yOff + i];
+
+    if (x_i < y_i) then
+    begin
+      result := false;
+      Exit;
+    end;
+
+    if (x_i > y_i) then
+    begin
+      result := true;
+      Exit;
+    end;
+    System.Dec(i);
+  end;
+  result := true;
+end;
+
+class function TNat256.IsOne(x: TCryptoLibUInt32Array): Boolean;
+var
+  i: Int32;
+begin
+  if (x[0] <> 1) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  i := 1;
+  while i < 8 do
+  begin
+    if (x[i] <> 0) then
+    begin
+      result := false;
+      Exit;
+    end;
+    System.Inc(i);
+  end;
+  result := true;
+end;
+
+class function TNat256.IsOne64(x: TCryptoLibUInt64Array): Boolean;
+var
+  i: Int32;
+begin
+  if (x[0] <> UInt64(1)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  i := 1;
+  while i < 4 do
+  begin
+    if (x[i] <> UInt64(0)) then
+    begin
+      result := false;
+      Exit;
+    end;
+    System.Inc(i);
+  end;
+  result := true;
+end;
+
+class function TNat256.IsZero(x: TCryptoLibUInt32Array): Boolean;
+var
+  i: Int32;
+begin
+  i := 0;
+  while i < 8 do
+  begin
+    if (x[i] <> 0) then
+    begin
+      result := false;
+      Exit;
+    end;
+    System.Inc(i);
+  end;
+  result := true;
+end;
+
+class function TNat256.IsZero64(x: TCryptoLibUInt64Array): Boolean;
+var
+  i: Int32;
+begin
+  i := 0;
+  while i < 4 do
+  begin
+    if (x[i] <> UInt64(0)) then
+    begin
+      result := false;
+      Exit;
+    end;
+    System.Inc(i);
+  end;
+  result := true;
+end;
+
+class procedure TNat256.Mul(x, y, zz: TCryptoLibUInt32Array);
+var
+  c, x_0, x_i, y_0, y_1, y_2, y_3, y_4, y_5, y_6, y_7: UInt64;
+  i: Int32;
+begin
+  y_0 := y[0];
+  y_1 := y[1];
+  y_2 := y[2];
+  y_3 := y[3];
+  y_4 := y[4];
+  y_5 := y[5];
+  y_6 := y[6];
+  y_7 := y[7];
+
+  c := 0;
+  x_0 := x[0];
+  c := c + (x_0 * y_0);
+  zz[0] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_1);
+  zz[1] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_2);
+  zz[2] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_3);
+  zz[3] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_4);
+  zz[4] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_5);
+  zz[5] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_6);
+  zz[6] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_7);
+  zz[7] := UInt32(c);
+  c := c shr 32;
+  zz[8] := UInt32(c);
+
+  for i := 1 to System.Pred(8) do
+  begin
+    c := 0;
+    x_i := x[i];
+    c := c + (x_i * y_0 + zz[i + 0]);
+    zz[i + 0] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_1 + zz[i + 1]);
+    zz[i + 1] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_2 + zz[i + 2]);
+    zz[i + 2] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_3 + zz[i + 3]);
+    zz[i + 3] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_4 + zz[i + 4]);
+    zz[i + 4] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_5 + zz[i + 5]);
+    zz[i + 5] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_6 + zz[i + 6]);
+    zz[i + 6] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_7 + zz[i + 7]);
+    zz[i + 7] := UInt32(c);
+    c := c shr 32;
+    zz[i + 8] := UInt32(c);
+  end;
+end;
+
+class procedure TNat256.Mul(x: TCryptoLibUInt32Array; xOff: Int32;
+  y: TCryptoLibUInt32Array; yOff: Int32; zz: TCryptoLibUInt32Array;
+  zzOff: Int32);
+var
+  c, x_0, x_i, y_0, y_1, y_2, y_3, y_4, y_5, y_6, y_7: UInt64;
+  i: Int32;
+begin
+  y_0 := y[yOff + 0];
+  y_1 := y[yOff + 1];
+  y_2 := y[yOff + 2];
+  y_3 := y[yOff + 3];
+  y_4 := y[yOff + 4];
+  y_5 := y[yOff + 5];
+  y_6 := y[yOff + 6];
+  y_7 := y[yOff + 7];
+
+  c := 0;
+  x_0 := x[xOff + 0];
+  c := c + (x_0 * y_0);
+  zz[zzOff + 0] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_1);
+  zz[zzOff + 1] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_2);
+  zz[zzOff + 2] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_3);
+  zz[zzOff + 3] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_4);
+  zz[zzOff + 4] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_5);
+  zz[zzOff + 5] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_6);
+  zz[zzOff + 6] := UInt32(c);
+  c := c shr 32;
+  c := c + (x_0 * y_7);
+  zz[zzOff + 7] := UInt32(c);
+  c := c shr 32;
+  zz[zzOff + 8] := UInt32(c);
+
+  for i := 1 to System.Pred(8) do
+  begin
+    System.Inc(zzOff);
+    c := 0;
+    x_i := x[xOff + i];
+    c := c + (x_i * y_0 + zz[zzOff + 0]);
+    zz[zzOff + 0] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_1 + zz[zzOff + 1]);
+    zz[zzOff + 1] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_2 + zz[zzOff + 2]);
+    zz[zzOff + 2] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_3 + zz[zzOff + 3]);
+    zz[zzOff + 3] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_4 + zz[zzOff + 4]);
+    zz[zzOff + 4] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_5 + zz[zzOff + 5]);
+    zz[zzOff + 5] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_6 + zz[zzOff + 6]);
+    zz[zzOff + 6] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_7 + zz[zzOff + 7]);
+    zz[zzOff + 7] := UInt32(c);
+    c := c shr 32;
+    zz[zzOff + 8] := UInt32(c);
+  end;
+end;
+
+class function TNat256.MulAddTo(x, y, zz: TCryptoLibUInt32Array): UInt32;
+var
+  c, x_i, y_0, y_1, y_2, y_3, y_4, y_5, y_6, y_7, zc: UInt64;
+  i: Int32;
+begin
+  y_0 := y[0];
+  y_1 := y[1];
+  y_2 := y[2];
+  y_3 := y[3];
+  y_4 := y[4];
+  y_5 := y[5];
+  y_6 := y[6];
+  y_7 := y[7];
+
+  zc := 0;
+  for i := 0 to System.Pred(8) do
+  begin
+    c := 0;
+    x_i := x[i];
+    c := c + (x_i * y_0 + zz[i + 0]);
+    zz[i + 0] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_1 + zz[i + 1]);
+    zz[i + 1] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_2 + zz[i + 2]);
+    zz[i + 2] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_3 + zz[i + 3]);
+    zz[i + 3] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_4 + zz[i + 4]);
+    zz[i + 4] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_5 + zz[i + 5]);
+    zz[i + 5] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_6 + zz[i + 6]);
+    zz[i + 6] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_7 + zz[i + 7]);
+    zz[i + 7] := UInt32(c);
+    c := c shr 32;
+    c := c + (zc + zz[i + 8]);
+    zz[i + 8] := UInt32(c);
+    zc := c shr 32;
+  end;
+  result := UInt32(zc);
+end;
+
+class function TNat256.MulAddTo(x: TCryptoLibUInt32Array; xOff: Int32;
+  y: TCryptoLibUInt32Array; yOff: Int32; zz: TCryptoLibUInt32Array;
+  zzOff: Int32): UInt32;
+var
+  c, x_i, y_0, y_1, y_2, y_3, y_4, y_5, y_6, y_7, zc: UInt64;
+  i: Int32;
+begin
+  y_0 := y[yOff + 0];
+  y_1 := y[yOff + 1];
+  y_2 := y[yOff + 2];
+  y_3 := y[yOff + 3];
+  y_4 := y[yOff + 4];
+  y_5 := y[yOff + 5];
+  y_6 := y[yOff + 6];
+  y_7 := y[yOff + 7];
+
+  zc := 0;
+  for i := 0 to System.Pred(8) do
+  begin
+    c := 0;
+    x_i := x[xOff + i];
+    c := c + (x_i * y_0 + zz[zzOff + 0]);
+    zz[zzOff + 0] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_1 + zz[zzOff + 1]);
+    zz[zzOff + 1] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_2 + zz[zzOff + 2]);
+    zz[zzOff + 2] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_3 + zz[zzOff + 3]);
+    zz[zzOff + 3] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_4 + zz[zzOff + 4]);
+    zz[zzOff + 4] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_5 + zz[zzOff + 5]);
+    zz[zzOff + 5] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_6 + zz[zzOff + 6]);
+    zz[zzOff + 6] := UInt32(c);
+    c := c shr 32;
+    c := c + (x_i * y_7 + zz[zzOff + 7]);
+    zz[zzOff + 7] := UInt32(c);
+    c := c shr 32;
+    c := c + (zc + zz[zzOff + 8]);
+    zz[zzOff + 8] := UInt32(c);
+    zc := c shr 32;
+    System.Inc(zzOff);
+  end;
+  result := UInt32(zc);
+end;
+
+class function TNat256.Mul33Add(w: UInt32; x: TCryptoLibUInt32Array;
+  xOff: Int32; y: TCryptoLibUInt32Array; yOff: Int32; z: TCryptoLibUInt32Array;
+  zOff: Int32): UInt64;
+var
+  c, wVal, x0, x1, x2, x3, x4, x5, x6, x7: UInt64;
+begin
+{$IFDEF DEBUG}
+  System.Assert(w shr 31 = 0);
+{$ENDIF DEBUG}
+  c := 0;
+  wVal := w;
+  x0 := x[xOff + 0];
+  c := c + (wVal * x0 + y[yOff + 0]);
+  z[zOff + 0] := UInt32(c);
+  c := c shr 32;
+  x1 := x[xOff + 1];
+  c := c + (wVal * x1 + x0 + y[yOff + 1]);
+  z[zOff + 1] := UInt32(c);
+  c := c shr 32;
+  x2 := x[xOff + 2];
+  c := c + (wVal * x2 + x1 + y[yOff + 2]);
+  z[zOff + 2] := UInt32(c);
+  c := c shr 32;
+  x3 := x[xOff + 3];
+  c := c + (wVal * x3 + x2 + y[yOff + 3]);
+  z[zOff + 3] := UInt32(c);
+  c := c shr 32;
+  x4 := x[xOff + 4];
+  c := c + (wVal * x4 + x3 + y[yOff + 4]);
+  z[zOff + 4] := UInt32(c);
+  c := c shr 32;
+  x5 := x[xOff + 5];
+  c := c + (wVal * x5 + x4 + y[yOff + 5]);
+  z[zOff + 5] := UInt32(c);
+  c := c shr 32;
+  x6 := x[xOff + 6];
+  c := c + (wVal * x6 + x5 + y[yOff + 6]);
+  z[zOff + 6] := UInt32(c);
+  c := c shr 32;
+  x7 := x[xOff + 7];
+  c := c + (wVal * x7 + x6 + y[yOff + 7]);
+  z[zOff + 7] := UInt32(c);
+  c := c shr 32;
+  c := c + x7;
+  result := c;
+end;
+
+class function TNat256.MulByWord(x: UInt32; z: TCryptoLibUInt32Array): UInt32;
+var
+  c, xVal: UInt64;
+begin
+  c := 0;
+  xVal := x;
+  c := c + (xVal * UInt64(z[0]));
+  z[0] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * UInt64(z[1]));
+  z[1] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * UInt64(z[2]));
+  z[2] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * UInt64(z[3]));
+  z[3] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * UInt64(z[4]));
+  z[4] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * UInt64(z[5]));
+  z[5] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * UInt64(z[6]));
+  z[6] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * UInt64(z[7]));
+  z[7] := UInt32(c);
+  c := c shr 32;
+  result := UInt32(c);
+end;
+
+class function TNat256.MulByWordAddTo(x: UInt32;
+  y, z: TCryptoLibUInt32Array): UInt32;
+var
+  c, xVal: UInt64;
+begin
+  c := 0;
+  xVal := x;
+  c := c + (xVal * UInt64(z[0]) + y[0]);
+  z[0] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * UInt64(z[1]) + y[1]);
+  z[1] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * UInt64(z[2]) + y[2]);
+  z[2] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * UInt64(z[3]) + y[3]);
+  z[3] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * UInt64(z[4]) + y[4]);
+  z[4] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * UInt64(z[5]) + y[5]);
+  z[5] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * UInt64(z[6]) + y[6]);
+  z[6] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * UInt64(z[7]) + y[7]);
+  z[7] := UInt32(c);
+  c := c shr 32;
+  result := UInt32(c);
+end;
+
+class function TNat256.MulWordAddTo(x: UInt32; y: TCryptoLibUInt32Array;
+  yOff: Int32; z: TCryptoLibUInt32Array; zOff: Int32): UInt32;
+var
+  c, xVal: UInt64;
+begin
+  c := 0;
+  xVal := x;
+  c := c + (xVal * y[yOff + 0] + z[zOff + 0]);
+  z[zOff + 0] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * y[yOff + 1] + z[zOff + 1]);
+  z[zOff + 1] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * y[yOff + 2] + z[zOff + 2]);
+  z[zOff + 2] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * y[yOff + 3] + z[zOff + 3]);
+  z[zOff + 3] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * y[yOff + 4] + z[zOff + 4]);
+  z[zOff + 4] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * y[yOff + 5] + z[zOff + 5]);
+  z[zOff + 5] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * y[yOff + 6] + z[zOff + 6]);
+  z[zOff + 6] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * y[yOff + 7] + z[zOff + 7]);
+  z[zOff + 7] := UInt32(c);
+  c := c shr 32;
+  result := UInt32(c);
+end;
+
+class function TNat256.Mul33DWordAdd(x: UInt32; y: UInt64;
+  z: TCryptoLibUInt32Array; zOff: Int32): UInt32;
+var
+  c, xVal, y00, y01: UInt64;
+begin
+{$IFDEF DEBUG}
+  System.Assert(x shr 31 = 0);
+  System.Assert(zOff <= 4);
+{$ENDIF DEBUG}
+  c := 0;
+  xVal := x;
+  y00 := y and M;
+  c := c + (xVal * y00 + z[zOff + 0]);
+  z[zOff + 0] := UInt32(c);
+  c := c shr 32;
+  y01 := y shr 32;
+  c := c + (xVal * y01 + y00 + z[zOff + 1]);
+  z[zOff + 1] := UInt32(c);
+  c := c shr 32;
+  c := c + (y01 + z[zOff + 2]);
+  z[zOff + 2] := UInt32(c);
+  c := c shr 32;
+  c := c + (z[zOff + 3]);
+  z[zOff + 3] := UInt32(c);
+  c := c shr 32;
+  if c = 0 then
+  begin
+    result := 0;
+  end
+  else
+  begin
+    result := TNat.IncAt(8, z, zOff, 4);
+  end;
+end;
+
+class function TNat256.Mul33WordAdd(x, y: UInt32; z: TCryptoLibUInt32Array;
+  zOff: Int32): UInt32;
+var
+  c, yVal: UInt64;
+begin
+{$IFDEF DEBUG}
+  System.Assert(x shr 31 = 0);
+  System.Assert(zOff <= 5);
+{$ENDIF DEBUG}
+  c := 0;
+  yVal := y;
+  c := c + (yVal * x + z[zOff + 0]);
+  z[zOff + 0] := UInt32(c);
+  c := c shr 32;
+  c := c + (yVal + z[zOff + 1]);
+  z[zOff + 1] := UInt32(c);
+  c := c shr 32;
+  c := c + (z[zOff + 2]);
+  z[zOff + 2] := UInt32(c);
+  c := c shr 32;
+  if c = 0 then
+  begin
+    result := 0;
+  end
+  else
+  begin
+    result := TNat.IncAt(8, z, zOff, 3);
+  end;
+end;
+
+class function TNat256.MulWordDwordAdd(x: UInt32; y: UInt64;
+  z: TCryptoLibUInt32Array; zOff: Int32): UInt32;
+var
+  c, xVal: UInt64;
+begin
+{$IFDEF DEBUG}
+  System.Assert(zOff <= 5);
+{$ENDIF DEBUG}
+  c := 0;
+  xVal := x;
+  c := c + (xVal * y + z[zOff + 0]);
+  z[zOff + 0] := UInt32(c);
+  c := c shr 32;
+  c := c + (xVal * (y shr 32) + z[zOff + 1]);
+  z[zOff + 1] := UInt32(c);
+  c := c shr 32;
+  c := c + (z[zOff + 2]);
+  z[zOff + 2] := UInt32(c);
+  c := c shr 32;
+  if c = 0 then
+  begin
+    result := 0;
+  end
+  else
+  begin
+    result := TNat.IncAt(8, z, zOff, 3);
+  end;
+end;
+
+class function TNat256.MulWord(x: UInt32; y, z: TCryptoLibUInt32Array;
+  zOff: Int32): UInt32;
+var
+  c, xVal: UInt64;
+  i: Int32;
+begin
+  c := 0;
+  xVal := x;
+  i := 0;
+  repeat
+    c := c + (xVal * y[i]);
+    z[zOff + i] := UInt32(c);
+    c := c shr 32;
+    System.Inc(i);
+  until not(i < 8);
+  result := UInt32(c);
+end;
+
+class procedure TNat256.Square(x, zz: TCryptoLibUInt32Array);
+var
+  x_0, zz_1, xVal, p, x_1, zz_2, x_2, zz_3, zz_4, x_3, zz_5, zz_6, x_4, zz_7,
+    zz_8, x_5, zz_9, zz_10, x_6, zz_11, zz_12, x_7, zz_13, zz_14: UInt64;
+  c, w: UInt32;
+  i, j: Int32;
+begin
+  x_0 := x[0];
+  c := 0;
+  i := 7;
+  j := 16;
+
+  repeat
+    xVal := x[i];
+    System.Dec(i);
+    p := xVal * xVal;
+    System.Dec(j);
+    zz[j] := (c shl 31) or UInt32(p shr 33);
+    System.Dec(j);
+    zz[j] := UInt32(p shr 1);
+    c := UInt32(p);
+  until not(i > 0);
+
+  p := x_0 * x_0;
+  zz_1 := UInt64(c shl 31) or (p shr 33);
+  zz[0] := UInt32(p);
+  c := UInt32(p shr 32) and 1;
+
+  x_1 := x[1];
+  zz_2 := zz[2];
+
+  zz_1 := zz_1 + (x_1 * x_0);
+  w := UInt32(zz_1);
+  zz[1] := (w shl 1) or c;
+  c := w shr 31;
+  zz_2 := zz_2 + (zz_1 shr 32);
+
+  x_2 := x[2];
+  zz_3 := zz[3];
+  zz_4 := zz[4];
+
+  zz_2 := zz_2 + (x_2 * x_0);
+  w := UInt32(zz_2);
+  zz[2] := (w shl 1) or c;
+  c := w shr 31;
+  zz_3 := zz_3 + ((zz_2 shr 32) + x_2 * x_1);
+  zz_4 := zz_4 + (zz_3 shr 32);
+  zz_3 := zz_3 and M;
+
+  x_3 := x[3];
+  zz_5 := zz[5] + (zz_4 shr 32);
+  zz_4 := zz_4 and M;
+  zz_6 := zz[6] + (zz_5 shr 32);
+  zz_5 := zz_5 and M;
+
+  zz_3 := zz_3 + (x_3 * x_0);
+  w := UInt32(zz_3);
+  zz[3] := (w shl 1) or c;
+  c := w shr 31;
+  zz_4 := zz_4 + ((zz_3 shr 32) + x_3 * x_1);
+  zz_5 := zz_5 + ((zz_4 shr 32) + x_3 * x_2);
+  zz_4 := zz_4 and M;
+  zz_6 := zz_6 + (zz_5 shr 32);
+  zz_5 := zz_5 and M;
+
+  x_4 := x[4];
+  zz_7 := zz[7] + (zz_6 shr 32);
+  zz_6 := zz_6 and M;
+  zz_8 := zz[8] + (zz_7 shr 32);
+  zz_7 := zz_7 and M;
+
+  zz_4 := zz_4 + (x_4 * x_0);
+  w := UInt32(zz_4);
+  zz[4] := (w shl 1) or c;
+  c := w shr 31;
+  zz_5 := zz_5 + ((zz_4 shr 32) + x_4 * x_1);
+  zz_6 := zz_6 + ((zz_5 shr 32) + x_4 * x_2);
+  zz_5 := zz_5 and M;
+  zz_7 := zz_7 + ((zz_6 shr 32) + x_4 * x_3);
+  zz_6 := zz_6 and M;
+  zz_8 := zz_8 + (zz_7 shr 32);
+  zz_7 := zz_7 and M;
+
+  x_5 := x[5];
+  zz_9 := zz[9] + (zz_8 shr 32);
+  zz_8 := zz_8 and M;
+  zz_10 := zz[10] + (zz_9 shr 32);
+  zz_9 := zz_9 and M;
+
+  zz_5 := zz_5 + (x_5 * x_0);
+  w := UInt32(zz_5);
+  zz[5] := (w shl 1) or c;
+  c := w shr 31;
+  zz_6 := zz_6 + ((zz_5 shr 32) + x_5 * x_1);
+  zz_7 := zz_7 + ((zz_6 shr 32) + x_5 * x_2);
+  zz_6 := zz_6 and M;
+  zz_8 := zz_8 + ((zz_7 shr 32) + x_5 * x_3);
+  zz_7 := zz_7 and M;
+  zz_9 := zz_9 + ((zz_8 shr 32) + x_5 * x_4);
+  zz_8 := zz_8 and M;
+  zz_10 := zz_10 + (zz_9 shr 32);
+  zz_9 := zz_9 and M;
+
+  x_6 := x[6];
+  zz_11 := zz[11] + (zz_10 shr 32);
+  zz_10 := zz_10 and M;
+  zz_12 := zz[12] + (zz_11 shr 32);
+  zz_11 := zz_11 and M;
+
+  zz_6 := zz_6 + (x_6 * x_0);
+  w := UInt32(zz_6);
+  zz[6] := (w shl 1) or c;
+  c := w shr 31;
+  zz_7 := zz_7 + ((zz_6 shr 32) + x_6 * x_1);
+  zz_8 := zz_8 + ((zz_7 shr 32) + x_6 * x_2);
+  zz_7 := zz_7 and M;
+  zz_9 := zz_9 + ((zz_8 shr 32) + x_6 * x_3);
+  zz_8 := zz_8 and M;
+  zz_10 := zz_10 + ((zz_9 shr 32) + x_6 * x_4);
+  zz_9 := zz_9 and M;
+  zz_11 := zz_11 + ((zz_10 shr 32) + x_6 * x_5);
+  zz_10 := zz_10 and M;
+  zz_12 := zz_12 + (zz_11 shr 32);
+  zz_11 := zz_11 and M;
+
+  x_7 := x[7];
+  zz_13 := zz[13] + (zz_12 shr 32);
+  zz_12 := zz_12 and M;
+  zz_14 := zz[14] + (zz_13 shr 32);
+  zz_13 := zz_13 and M;
+
+  zz_7 := zz_7 + (x_7 * x_0);
+  w := UInt32(zz_7);
+  zz[7] := (w shl 1) or c;
+  c := w shr 31;
+  zz_8 := zz_8 + ((zz_7 shr 32) + x_7 * x_1);
+  zz_9 := zz_9 + ((zz_8 shr 32) + x_7 * x_2);
+  zz_10 := zz_10 + ((zz_9 shr 32) + x_7 * x_3);
+  zz_11 := zz_11 + ((zz_10 shr 32) + x_7 * x_4);
+  zz_12 := zz_12 + ((zz_11 shr 32) + x_7 * x_5);
+  zz_13 := zz_13 + ((zz_12 shr 32) + x_7 * x_6);
+  zz_14 := zz_14 + (zz_13 shr 32);
+
+  w := UInt32(zz_8);
+  zz[8] := (w shl 1) or c;
+  c := w shr 31;
+  w := UInt32(zz_9);
+  zz[9] := (w shl 1) or c;
+  c := w shr 31;
+  w := UInt32(zz_10);
+  zz[10] := (w shl 1) or c;
+  c := w shr 31;
+  w := UInt32(zz_11);
+  zz[11] := (w shl 1) or c;
+  c := w shr 31;
+  w := UInt32(zz_12);
+  zz[12] := (w shl 1) or c;
+  c := w shr 31;
+  w := UInt32(zz_13);
+  zz[13] := (w shl 1) or c;
+  c := w shr 31;
+  w := UInt32(zz_14);
+  zz[14] := (w shl 1) or c;
+  c := w shr 31;
+  w := zz[15] + UInt32(zz_14 shr 32);
+  zz[15] := (w shl 1) or c;
+end;
+
+class procedure TNat256.Square(x: TCryptoLibUInt32Array; xOff: Int32;
+  zz: TCryptoLibUInt32Array; zzOff: Int32);
+var
+  x_0, zz_1, xVal, p, x_1, zz_2, x_2, zz_3, zz_4, x_3, zz_5, zz_6, x_4, zz_7,
+    zz_8, x_5, zz_9, zz_10, x_6, zz_11, zz_12, x_7, zz_13, zz_14: UInt64;
+  c, w: UInt32;
+  i, j: Int32;
+begin
+  x_0 := x[xOff + 0];
+  c := 0;
+  i := 7;
+  j := 16;
+
+  repeat
+    xVal := x[xOff + i];
+    System.Dec(i);
+    p := xVal * xVal;
+    System.Dec(j);
+    zz[zzOff + j] := (c shl 31) or UInt32(p shr 33);
+    System.Dec(j);
+    zz[zzOff + j] := UInt32(p shr 1);
+    c := UInt32(p);
+  until not(i > 0);
+
+  p := x_0 * x_0;
+  zz_1 := UInt64(c shl 31) or (p shr 33);
+  zz[zzOff + 0] := UInt32(p);
+  c := UInt32(p shr 32) and 1;
+
+  x_1 := x[xOff + 1];
+  zz_2 := zz[zzOff + 2];
+
+  zz_1 := zz_1 + (x_1 * x_0);
+  w := UInt32(zz_1);
+  zz[zzOff + 1] := (w shl 1) or c;
+  c := w shr 31;
+  zz_2 := zz_2 + (zz_1 shr 32);
+
+  x_2 := x[xOff + 2];
+  zz_3 := zz[zzOff + 3];
+  zz_4 := zz[zzOff + 4];
+
+  zz_2 := zz_2 + (x_2 * x_0);
+  w := UInt32(zz_2);
+  zz[zzOff + 2] := (w shl 1) or c;
+  c := w shr 31;
+  zz_3 := zz_3 + ((zz_2 shr 32) + x_2 * x_1);
+  zz_4 := zz_4 + (zz_3 shr 32);
+  zz_3 := zz_3 and M;
+
+  x_3 := x[xOff + 3];
+  zz_5 := zz[zzOff + 5] + (zz_4 shr 32);
+  zz_4 := zz_4 and M;
+  zz_6 := zz[zzOff + 6] + (zz_5 shr 32);
+  zz_5 := zz_5 and M;
+
+  zz_3 := zz_3 + (x_3 * x_0);
+  w := UInt32(zz_3);
+  zz[zzOff + 3] := (w shl 1) or c;
+  c := w shr 31;
+  zz_4 := zz_4 + ((zz_3 shr 32) + x_3 * x_1);
+  zz_5 := zz_5 + ((zz_4 shr 32) + x_3 * x_2);
+  zz_4 := zz_4 and M;
+  zz_6 := zz_6 + (zz_5 shr 32);
+  zz_5 := zz_5 and M;
+
+  x_4 := x[xOff + 4];
+  zz_7 := zz[zzOff + 7] + (zz_6 shr 32);
+  zz_6 := zz_6 and M;
+  zz_8 := zz[zzOff + 8] + (zz_7 shr 32);
+  zz_7 := zz_7 and M;
+
+  zz_4 := zz_4 + (x_4 * x_0);
+  w := UInt32(zz_4);
+  zz[zzOff + 4] := (w shl 1) or c;
+  c := w shr 31;
+  zz_5 := zz_5 + ((zz_4 shr 32) + x_4 * x_1);
+  zz_6 := zz_6 + ((zz_5 shr 32) + x_4 * x_2);
+  zz_5 := zz_5 and M;
+  zz_7 := zz_7 + ((zz_6 shr 32) + x_4 * x_3);
+  zz_6 := zz_6 and M;
+  zz_8 := zz_8 + (zz_7 shr 32);
+  zz_7 := zz_7 and M;
+
+  x_5 := x[xOff + 5];
+  zz_9 := zz[zzOff + 9] + (zz_8 shr 32);
+  zz_8 := zz_8 and M;
+  zz_10 := zz[zzOff + 10] + (zz_9 shr 32);
+  zz_9 := zz_9 and M;
+
+  zz_5 := zz_5 + (x_5 * x_0);
+  w := UInt32(zz_5);
+  zz[zzOff + 5] := (w shl 1) or c;
+  c := w shr 31;
+  zz_6 := zz_6 + ((zz_5 shr 32) + x_5 * x_1);
+  zz_7 := zz_7 + ((zz_6 shr 32) + x_5 * x_2);
+  zz_6 := zz_6 and M;
+  zz_8 := zz_8 + ((zz_7 shr 32) + x_5 * x_3);
+  zz_7 := zz_7 and M;
+  zz_9 := zz_9 + ((zz_8 shr 32) + x_5 * x_4);
+  zz_8 := zz_8 and M;
+  zz_10 := zz_10 + (zz_9 shr 32);
+  zz_9 := zz_9 and M;
+
+  x_6 := x[xOff + 6];
+  zz_11 := zz[zzOff + 11] + (zz_10 shr 32);
+  zz_10 := zz_10 and M;
+  zz_12 := zz[zzOff + 12] + (zz_11 shr 32);
+  zz_11 := zz_11 and M;
+
+  zz_6 := zz_6 + (x_6 * x_0);
+  w := UInt32(zz_6);
+  zz[zzOff + 6] := (w shl 1) or c;
+  c := w shr 31;
+  zz_7 := zz_7 + ((zz_6 shr 32) + x_6 * x_1);
+  zz_8 := zz_8 + ((zz_7 shr 32) + x_6 * x_2);
+  zz_7 := zz_7 and M;
+  zz_9 := zz_9 + ((zz_8 shr 32) + x_6 * x_3);
+  zz_8 := zz_8 and M;
+  zz_10 := zz_10 + ((zz_9 shr 32) + x_6 * x_4);
+  zz_9 := zz_9 and M;
+  zz_11 := zz_11 + ((zz_10 shr 32) + x_6 * x_5);
+  zz_10 := zz_10 and M;
+  zz_12 := zz_12 + (zz_11 shr 32);
+  zz_11 := zz_11 and M;
+
+  x_7 := x[xOff + 7];
+  zz_13 := zz[zzOff + 13] + (zz_12 shr 32);
+  zz_12 := zz_12 and M;
+  zz_14 := zz[zzOff + 14] + (zz_13 shr 32);
+  zz_13 := zz_13 and M;
+
+  zz_7 := zz_7 + (x_7 * x_0);
+  w := UInt32(zz_7);
+  zz[zzOff + 7] := (w shl 1) or c;
+  c := w shr 31;
+  zz_8 := zz_8 + ((zz_7 shr 32) + x_7 * x_1);
+  zz_9 := zz_9 + ((zz_8 shr 32) + x_7 * x_2);
+  zz_10 := zz_10 + ((zz_9 shr 32) + x_7 * x_3);
+  zz_11 := zz_11 + ((zz_10 shr 32) + x_7 * x_4);
+  zz_12 := zz_12 + ((zz_11 shr 32) + x_7 * x_5);
+  zz_13 := zz_13 + ((zz_12 shr 32) + x_7 * x_6);
+  zz_14 := zz_14 + (zz_13 shr 32);
+
+  w := UInt32(zz_8);
+  zz[zzOff + 8] := (w shl 1) or c;
+  c := w shr 31;
+  w := UInt32(zz_9);
+  zz[zzOff + 9] := (w shl 1) or c;
+  c := w shr 31;
+  w := UInt32(zz_10);
+  zz[zzOff + 10] := (w shl 1) or c;
+  c := w shr 31;
+  w := UInt32(zz_11);
+  zz[zzOff + 11] := (w shl 1) or c;
+  c := w shr 31;
+  w := UInt32(zz_12);
+  zz[zzOff + 12] := (w shl 1) or c;
+  c := w shr 31;
+  w := UInt32(zz_13);
+  zz[zzOff + 13] := (w shl 1) or c;
+  c := w shr 31;
+  w := UInt32(zz_14);
+  zz[zzOff + 14] := (w shl 1) or c;
+  c := w shr 31;
+  w := zz[zzOff + 15] + UInt32(zz_14 shr 32);
+  zz[zzOff + 15] := (w shl 1) or c;
+end;
+
+class function TNat256.Sub(x, y, z: TCryptoLibUInt32Array): Int32;
+var
+  c: Int64;
+begin
+  c := 0;
+  c := c + (Int64(x[0]) - y[0]);
+  z[0] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[1]) - y[1]);
+  z[1] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[2]) - y[2]);
+  z[2] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[3]) - y[3]);
+  z[3] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[4]) - y[4]);
+  z[4] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[5]) - y[5]);
+  z[5] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[6]) - y[6]);
+  z[6] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[7]) - y[7]);
+  z[7] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  result := Int32(c);
+end;
+
+class function TNat256.Sub(x: TCryptoLibUInt32Array; xOff: Int32;
+  y: TCryptoLibUInt32Array; yOff: Int32; z: TCryptoLibUInt32Array;
+  zOff: Int32): Int32;
+var
+  c: Int64;
+begin
+  c := 0;
+  c := c + (Int64(x[xOff + 0]) - y[yOff + 0]);
+  z[zOff + 0] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[xOff + 1]) - y[yOff + 1]);
+  z[zOff + 1] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[xOff + 2]) - y[yOff + 2]);
+  z[zOff + 2] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[xOff + 3]) - y[yOff + 3]);
+  z[zOff + 3] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[xOff + 4]) - y[yOff + 4]);
+  z[zOff + 4] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[xOff + 5]) - y[yOff + 5]);
+  z[zOff + 5] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[xOff + 6]) - y[yOff + 6]);
+  z[zOff + 6] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(x[xOff + 7]) - y[yOff + 7]);
+  z[zOff + 7] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  result := Int32(c);
+end;
+
+class function TNat256.SubBothFrom(x, y, z: TCryptoLibUInt32Array): Int32;
+var
+  c: Int64;
+begin
+  c := 0;
+  c := c + (Int64(z[0]) - x[0] - y[0]);
+  z[0] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[1]) - x[1] - y[1]);
+  z[1] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[2]) - x[2] - y[2]);
+  z[2] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[3]) - x[3] - y[3]);
+  z[3] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[4]) - x[4] - y[4]);
+  z[4] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[5]) - x[5] - y[5]);
+  z[5] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[6]) - x[6] - y[6]);
+  z[6] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[7]) - x[7] - y[7]);
+  z[7] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  result := Int32(c);
+end;
+
+class function TNat256.SubFrom(x, z: TCryptoLibUInt32Array): Int32;
+var
+  c: Int64;
+begin
+  c := 0;
+  c := c + (Int64(z[0]) - x[0]);
+  z[0] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[1]) - x[1]);
+  z[1] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[2]) - x[2]);
+  z[2] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[3]) - x[3]);
+  z[3] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[4]) - x[4]);
+  z[4] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[5]) - x[5]);
+  z[5] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[6]) - x[6]);
+  z[6] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[7]) - x[7]);
+  z[7] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  result := Int32(c);
+end;
+
+class function TNat256.SubFrom(x: TCryptoLibUInt32Array; xOff: Int32;
+  z: TCryptoLibUInt32Array; zOff: Int32): Int32;
+var
+  c: Int64;
+begin
+  c := 0;
+  c := c + (Int64(z[zOff + 0]) - x[xOff + 0]);
+  z[zOff + 0] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[zOff + 1]) - x[xOff + 1]);
+  z[zOff + 1] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[zOff + 2]) - x[xOff + 2]);
+  z[zOff + 2] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[zOff + 3]) - x[xOff + 3]);
+  z[zOff + 3] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[zOff + 4]) - x[xOff + 4]);
+  z[zOff + 4] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[zOff + 5]) - x[xOff + 5]);
+  z[zOff + 5] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[zOff + 6]) - x[xOff + 6]);
+  z[zOff + 6] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  c := c + (Int64(z[zOff + 7]) - x[xOff + 7]);
+  z[zOff + 7] := UInt32(c);
+  c := TBits.Asr64(c, 32);
+  result := Int32(c);
+end;
+
+class function TNat256.ToBigInteger(x: TCryptoLibUInt32Array): TBigInteger;
+var
+  bs, temp: TCryptoLibByteArray;
+  i: Int32;
+  x_i: UInt32;
+begin
+  System.SetLength(bs, 32);
+  for i := 0 to System.Pred(8) do
+
+  begin
+    x_i := x[i];
+    if (x_i <> 0) then
+    begin
+      temp := TConverters.ReadUInt32AsBytesBE(x_i);
+      System.Move(temp[0], bs[(7 - i) shl 2], System.Length(temp) *
+        System.SizeOf(Byte))
+    end;
+  end;
+  result := TBigInteger.Create(1, bs);
+end;
+
+class function TNat256.ToBigInteger64(x: TCryptoLibUInt64Array): TBigInteger;
+var
+  bs, temp: TCryptoLibByteArray;
+  i: Int32;
+  x_i: UInt64;
+begin
+  System.SetLength(bs, 32);
+  for i := 0 to System.Pred(4) do
+
+  begin
+    x_i := x[i];
+    if (x_i <> Int64(0)) then
+    begin
+      temp := TConverters.ReadUInt64AsBytesBE(x_i);
+      System.Move(temp[0], bs[(3 - i) shl 3], System.Length(temp) *
+        System.SizeOf(Byte))
+    end;
+  end;
+  result := TBigInteger.Create(1, bs);
+end;
+
+class procedure TNat256.Zero(z: TCryptoLibUInt32Array);
+begin
+  System.FillChar(z[0], 8 * System.SizeOf(UInt32), UInt32(0));
+end;
+
+end.

+ 181 - 0
CryptoLib/src/Math/Raw/ClpNat320.pas

@@ -0,0 +1,181 @@
+{ *********************************************************************************** }
+{ *                              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 ClpNat320;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpBigInteger,
+  ClpConverters,
+  ClpCryptoLibTypes;
+
+type
+  TNat320 = class abstract(TObject)
+
+  public
+    class procedure Copy64(x, z: TCryptoLibUInt64Array); overload;
+      static; inline;
+
+    class procedure Copy64(x: TCryptoLibUInt64Array; xOff: Int32;
+      z: TCryptoLibUInt64Array; zOff: Int32); overload; static; inline;
+
+    class function Create64(): TCryptoLibUInt64Array; static; inline;
+
+    class function CreateExt64(): TCryptoLibUInt64Array; static; inline;
+
+    class function Eq64(x, y: TCryptoLibUInt64Array): Boolean; static;
+
+    class function FromBigInteger64(const x: TBigInteger)
+      : TCryptoLibUInt64Array; static;
+
+    class function IsOne64(x: TCryptoLibUInt64Array): Boolean; static;
+
+    class function IsZero64(x: TCryptoLibUInt64Array): Boolean; static;
+
+    class function ToBigInteger64(x: TCryptoLibUInt64Array)
+      : TBigInteger; static;
+
+  end;
+
+implementation
+
+{ TNat320 }
+
+class procedure TNat320.Copy64(x, z: TCryptoLibUInt64Array);
+begin
+  System.Move(x[0], z[0], 5 * System.SizeOf(UInt64));
+end;
+
+class procedure TNat320.Copy64(x: TCryptoLibUInt64Array; xOff: Int32;
+  z: TCryptoLibUInt64Array; zOff: Int32);
+begin
+  System.Move(x[xOff], z[zOff], 5 * System.SizeOf(UInt64));
+end;
+
+class function TNat320.Create64: TCryptoLibUInt64Array;
+begin
+  System.SetLength(Result, 5);
+end;
+
+class function TNat320.CreateExt64: TCryptoLibUInt64Array;
+begin
+  System.SetLength(Result, 10);
+end;
+
+class function TNat320.Eq64(x, y: TCryptoLibUInt64Array): Boolean;
+var
+  i: Int32;
+begin
+  i := 4;
+  while i >= 0 do
+  begin
+    if (x[i] <> y[i]) then
+    begin
+      Result := False;
+      Exit;
+    end;
+    System.Dec(i);
+  end;
+  Result := True;
+end;
+
+class function TNat320.FromBigInteger64(const x: TBigInteger)
+  : TCryptoLibUInt64Array;
+var
+  i: Int32;
+  Lx: TBigInteger;
+begin
+  Lx := x;
+  if ((Lx.SignValue < 0) or (Lx.BitLength > 320)) then
+  begin
+    raise EArgumentCryptoLibException.Create('');
+  end;
+
+  Result := Create64();
+  i := 0;
+  while (Lx.SignValue <> 0) do
+  begin
+    Result[i] := UInt64(Lx.Int64Value);
+    System.Inc(i);
+    Lx := Lx.ShiftRight(64);
+  end;
+end;
+
+class function TNat320.IsOne64(x: TCryptoLibUInt64Array): Boolean;
+var
+  i: Int32;
+begin
+  if (x[0] <> UInt64(1)) then
+  begin
+    Result := False;
+    Exit;
+  end;
+  i := 1;
+  while i < 5 do
+  begin
+    if (x[i] <> UInt64(0)) then
+    begin
+      Result := False;
+      Exit;
+    end;
+    System.Inc(i);
+  end;
+  Result := True;
+end;
+
+class function TNat320.IsZero64(x: TCryptoLibUInt64Array): Boolean;
+var
+  i: Int32;
+begin
+  i := 0;
+  while i < 5 do
+  begin
+    if (x[i] <> UInt64(0)) then
+    begin
+      Result := False;
+      Exit;
+    end;
+    System.Inc(i);
+  end;
+  Result := True;
+end;
+
+class function TNat320.ToBigInteger64(x: TCryptoLibUInt64Array): TBigInteger;
+var
+  bs, temp: TCryptoLibByteArray;
+  i: Int32;
+  x_i: UInt64;
+begin
+  System.SetLength(bs, 40);
+  for i := 0 to System.Pred(5) do
+
+  begin
+    x_i := x[i];
+    if (x_i <> Int64(0)) then
+    begin
+      temp := TConverters.ReadUInt64AsBytesBE(x_i);
+      System.Move(temp[0], bs[(4 - i) shl 3], System.Length(temp) *
+        System.SizeOf(Byte))
+    end;
+  end;
+  Result := TBigInteger.Create(1, bs);
+end;
+
+end.

+ 95 - 0
CryptoLib/src/Math/Raw/ClpNat384.pas

@@ -0,0 +1,95 @@
+{ *********************************************************************************** }
+{ *                              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 ClpNat384;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpNat,
+  ClpNat192,
+  ClpCryptoLibTypes;
+
+type
+  TNat384 = class sealed(TObject)
+
+  public
+    class procedure Mul(x, y, zz: TCryptoLibUInt32Array); static;
+    class procedure Square(x, zz: TCryptoLibUInt32Array); static;
+
+  end;
+
+implementation
+
+{ TNat384 }
+
+class procedure TNat384.Mul(x, y, zz: TCryptoLibUInt32Array);
+var
+  c18, c12: UInt32;
+  dx, dy, tt: TCryptoLibUInt32Array;
+  neg: Boolean;
+begin
+  TNat192.Mul(x, y, zz);
+  TNat192.Mul(x, 6, y, 6, zz, 12);
+
+  c18 := TNat192.AddToEachOther(zz, 6, zz, 12);
+  c12 := c18 + TNat192.AddTo(zz, 0, zz, 6, 0);
+  c18 := c18 + (TNat192.AddTo(zz, 18, zz, 12, c12));
+
+  dx := TNat192.Create();
+  dy := TNat192.Create();
+  neg := TNat192.Diff(x, 6, x, 0, dx, 0) <> TNat192.Diff(y, 6, y, 0, dy, 0);
+
+  tt := TNat192.CreateExt();
+  TNat192.Mul(dx, dy, tt);
+
+  if neg then
+  begin
+    c18 := c18 + TNat.AddTo(12, tt, 0, zz, 6);
+  end
+  else
+  begin
+    c18 := c18 + UInt32(TNat.SubFrom(12, tt, 0, zz, 6));
+  end;
+  TNat.AddWordAt(24, c18, zz, 18);
+end;
+
+class procedure TNat384.Square(x, zz: TCryptoLibUInt32Array);
+var
+  c18, c12: UInt32;
+  dx, m: TCryptoLibUInt32Array;
+begin
+  TNat192.Square(x, zz);
+  TNat192.Square(x, 6, zz, 12);
+
+  c18 := TNat192.AddToEachOther(zz, 6, zz, 12);
+  c12 := c18 + TNat192.AddTo(zz, 0, zz, 6, 0);
+  c18 := c18 + TNat192.AddTo(zz, 18, zz, 12, c12);
+
+  dx := TNat192.Create();
+  TNat192.Diff(x, 6, x, 0, dx, 0);
+
+  m := TNat192.CreateExt();
+  TNat192.Square(dx, m);
+
+  c18 := c18 + UInt32(TNat.SubFrom(12, m, 0, zz, 6));
+  TNat.AddWordAt(24, c18, zz, 18);
+end;
+
+end.

+ 96 - 0
CryptoLib/src/Math/Raw/ClpNat512.pas

@@ -0,0 +1,96 @@
+{ *********************************************************************************** }
+{ *                              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 ClpNat512;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpNat,
+  ClpNat256,
+  ClpCryptoLibTypes;
+
+type
+  TNat512 = class sealed(TObject)
+
+  public
+    class procedure Mul(x, y, zz: TCryptoLibUInt32Array); static;
+    class procedure Square(x, zz: TCryptoLibUInt32Array); static;
+
+  end;
+
+implementation
+
+{ TNat512 }
+
+class procedure TNat512.Mul(x, y, zz: TCryptoLibUInt32Array);
+var
+  c24, c16: UInt32;
+  dx, dy, tt: TCryptoLibUInt32Array;
+  neg: Boolean;
+begin
+  TNat256.Mul(x, y, zz);
+  TNat256.Mul(x, 8, y, 8, zz, 16);
+
+  c24 := TNat256.AddToEachOther(zz, 8, zz, 16);
+  c16 := c24 + TNat256.AddTo(zz, 0, zz, 8, 0);
+  c24 := c24 + (TNat256.AddTo(zz, 24, zz, 16, c16));
+
+  dx := TNat256.Create();
+  dy := TNat256.Create();
+  neg := TNat256.Diff(x, 8, x, 0, dx, 0) <> TNat256.Diff(y, 8, y, 0, dy, 0);
+
+  tt := TNat256.CreateExt();
+  TNat256.Mul(dx, dy, tt);
+
+  if neg then
+  begin
+    c24 := c24 + TNat.AddTo(16, tt, 0, zz, 8);
+  end
+  else
+  begin
+    c24 := c24 + UInt32(TNat.SubFrom(16, tt, 0, zz, 8));
+  end;
+
+  TNat.AddWordAt(32, c24, zz, 24);
+end;
+
+class procedure TNat512.Square(x, zz: TCryptoLibUInt32Array);
+var
+  c24, c16: UInt32;
+  dx, m: TCryptoLibUInt32Array;
+begin
+  TNat256.Square(x, zz);
+  TNat256.Square(x, 8, zz, 16);
+
+  c24 := TNat256.AddToEachOther(zz, 8, zz, 16);
+  c16 := c24 + TNat256.AddTo(zz, 0, zz, 8, 0);
+  c24 := c24 + (TNat256.AddTo(zz, 24, zz, 16, c16));
+
+  dx := TNat256.Create();
+  TNat256.Diff(x, 8, x, 0, dx, 0);
+
+  m := TNat256.CreateExt();
+  TNat256.Square(dx, m);
+
+  c24 := c24 + UInt32(TNat.SubFrom(16, m, 0, zz, 8));
+  TNat.AddWordAt(32, c24, zz, 24);
+end;
+
+end.

+ 173 - 19
CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.lpk

@@ -10,7 +10,7 @@
       <PathDelim Value="\"/>
       <SearchPaths>
         <IncludeFiles Value="..\..\Include;..\..\3rdParty\generics.collections\src\inc"/>
-        <OtherUnitFiles Value="..\..\Asn1;..\..\Asn1\CryptoPro;..\..\Asn1\Nist;..\..\Asn1\Oiw;..\..\Asn1\Pkcs;..\..\Asn1\RossStandart;..\..\Asn1\Sec;..\..\Asn1\TeleTrust;..\..\Asn1\X9;..\..\Crypto;..\..\Crypto\Generators;..\..\Crypto\Parameters;..\..\Crypto\Prng;..\..\Crypto\Signers;..\..\Interfaces;..\..\Math;..\..\Math\EC;..\..\Math\EC\Abc;..\..\Math\EC\Endo;..\..\Math\EC\Multiplier;..\..\Math\Field;..\..\Math\Raw;..\..\Security;..\..\Utils;..\..\Utils\Collections;..\..\Utils\Encoders;..\..\Utils\Helpers;..\..\Utils\IO;..\..\Utils\Randoms;..\..\Utils\Rng;..\..\Crypto\Modes;..\..\Crypto\Paddings;..\..\Crypto\Engines;..\..\Crypto\Parsers;..\..\Crypto\Agreement;..\..\Crypto\Macs;..\..\Asn1\Misc;..\..\Asn1\Iana;..\..\Crypto\Digests;..\..\Asn1\X509;..\..\3rdParty\generics.collections\src"/>
+        <OtherUnitFiles Value="..\..\Asn1;..\..\Asn1\CryptoPro;..\..\Asn1\Nist;..\..\Asn1\Oiw;..\..\Asn1\Pkcs;..\..\Asn1\RossStandart;..\..\Asn1\Sec;..\..\Asn1\TeleTrust;..\..\Asn1\X9;..\..\Crypto;..\..\Crypto\Generators;..\..\Crypto\Parameters;..\..\Crypto\Prng;..\..\Crypto\Signers;..\..\Interfaces;..\..\Math;..\..\Math\EC;..\..\Math\EC\Abc;..\..\Math\EC\Endo;..\..\Math\EC\Multiplier;..\..\Math\Field;..\..\Math\Raw;..\..\Security;..\..\Utils;..\..\Utils\Collections;..\..\Utils\Encoders;..\..\Utils\Helpers;..\..\Utils\IO;..\..\Utils\Randoms;..\..\Utils\Rng;..\..\Crypto\Modes;..\..\Crypto\Paddings;..\..\Crypto\Engines;..\..\Crypto\Parsers;..\..\Crypto\Agreement;..\..\Crypto\Macs;..\..\Asn1\Misc;..\..\Asn1\Iana;..\..\Crypto\Digests;..\..\Asn1\X509;..\..\Crypto\EC;..\..\Math\EC\Custom\Sec;..\..\3rdParty\generics.collections\src"/>
         <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
       </SearchPaths>
       <CodeGeneration>
@@ -25,7 +25,7 @@
  Acknowledgements: 
 Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring the development of this library "/>
     <Version Major="2" Minor="3"/>
-    <Files Count="416">
+    <Files Count="454">
       <Item1>
         <Filename Value="..\..\Asn1\ClpAsn1Encodable.pas"/>
         <UnitName Value="ClpAsn1Encodable"/>
@@ -1661,46 +1661,200 @@ Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring the devel
         <UnitName Value="ClpValidityPrecompInfo"/>
       </Item408>
       <Item409>
-        <Filename Value="..\..\3rdParty\generics.collections\src\generics.collections.pas"/>
-        <UnitName Value="Generics.Collections"/>
+        <Filename Value="..\..\Asn1\Nist\ClpNistNamedCurves.pas"/>
+        <UnitName Value="ClpNistNamedCurves"/>
       </Item409>
       <Item410>
-        <Filename Value="..\..\3rdParty\generics.collections\src\generics.defaults.pas"/>
-        <UnitName Value="Generics.Defaults"/>
+        <Filename Value="..\..\Math\Raw\ClpNat256.pas"/>
+        <UnitName Value="ClpNat256"/>
       </Item410>
       <Item411>
-        <Filename Value="..\..\3rdParty\generics.collections\src\generics.hashes.pas"/>
-        <UnitName Value="Generics.Hashes"/>
+        <Filename Value="..\..\Math\Raw\ClpNat320.pas"/>
+        <UnitName Value="ClpNat320"/>
       </Item411>
       <Item412>
-        <Filename Value="..\..\3rdParty\generics.collections\src\generics.helpers.pas"/>
-        <UnitName Value="Generics.Helpers"/>
+        <Filename Value="..\..\Crypto\Engines\ClpAesLightEngine.pas"/>
+        <UnitName Value="ClpAesLightEngine"/>
       </Item412>
       <Item413>
-        <Filename Value="..\..\3rdParty\generics.collections\src\generics.memoryexpanders.pas"/>
-        <UnitName Value="Generics.MemoryExpanders"/>
+        <Filename Value="..\..\Interfaces\ClpIAesLightEngine.pas"/>
+        <UnitName Value="ClpIAesLightEngine"/>
       </Item413>
       <Item414>
-        <Filename Value="..\..\3rdParty\generics.collections\src\generics.strings.pas"/>
-        <UnitName Value="Generics.Strings"/>
+        <Filename Value="..\..\Crypto\EC\ClpCustomNamedCurves.pas"/>
+        <UnitName Value="ClpCustomNamedCurves"/>
       </Item414>
       <Item415>
-        <Filename Value="..\..\3rdParty\generics.collections\src\inc\generics.dictionaries.inc"/>
-        <Type Value="Include"/>
+        <Filename Value="..\..\Math\EC\Custom\Sec\ClpSecP256K1Field.pas"/>
+        <UnitName Value="ClpSecP256K1Field"/>
       </Item415>
       <Item416>
+        <Filename Value="..\..\Math\EC\Custom\Sec\ClpSecP256K1FieldElement.pas"/>
+        <UnitName Value="ClpSecP256K1FieldElement"/>
+      </Item416>
+      <Item417>
+        <Filename Value="..\..\Interfaces\ClpISecP256K1FieldElement.pas"/>
+        <UnitName Value="ClpISecP256K1FieldElement"/>
+      </Item417>
+      <Item418>
+        <Filename Value="..\..\Math\EC\Custom\Sec\ClpSecP256K1Point.pas"/>
+        <UnitName Value="ClpSecP256K1Point"/>
+      </Item418>
+      <Item419>
+        <Filename Value="..\..\Interfaces\ClpISecP256K1Point.pas"/>
+        <UnitName Value="ClpISecP256K1Point"/>
+      </Item419>
+      <Item420>
+        <Filename Value="..\..\Math\EC\Custom\Sec\ClpSecP256K1Curve.pas"/>
+        <UnitName Value="ClpSecP256K1Curve"/>
+      </Item420>
+      <Item421>
+        <Filename Value="..\..\Interfaces\ClpISecP256K1Curve.pas"/>
+        <UnitName Value="ClpISecP256K1Curve"/>
+      </Item421>
+      <Item422>
+        <Filename Value="..\..\Math\EC\Custom\Sec\ClpSecP384R1Field.pas"/>
+        <UnitName Value="ClpSecP384R1Field"/>
+      </Item422>
+      <Item423>
+        <Filename Value="..\..\Math\Raw\ClpNat384.pas"/>
+        <UnitName Value="ClpNat384"/>
+      </Item423>
+      <Item424>
+        <Filename Value="..\..\Math\EC\Custom\Sec\ClpSecP384R1FieldElement.pas"/>
+        <UnitName Value="ClpSecP384R1FieldElement"/>
+      </Item424>
+      <Item425>
+        <Filename Value="..\..\Interfaces\ClpISecP384R1FieldElement.pas"/>
+        <UnitName Value="ClpISecP384R1FieldElement"/>
+      </Item425>
+      <Item426>
+        <Filename Value="..\..\Math\EC\Custom\Sec\ClpSecP384R1Point.pas"/>
+        <UnitName Value="ClpSecP384R1Point"/>
+      </Item426>
+      <Item427>
+        <Filename Value="..\..\Interfaces\ClpISecP384R1Point.pas"/>
+        <UnitName Value="ClpISecP384R1Point"/>
+      </Item427>
+      <Item428>
+        <Filename Value="..\..\Math\EC\Custom\Sec\ClpSecP384R1Curve.pas"/>
+        <UnitName Value="ClpSecP384R1Curve"/>
+      </Item428>
+      <Item429>
+        <Filename Value="..\..\Math\Raw\ClpNat192.pas"/>
+        <UnitName Value="ClpNat192"/>
+      </Item429>
+      <Item430>
+        <Filename Value="..\..\Interfaces\ClpISecP384R1Curve.pas"/>
+        <UnitName Value="ClpISecP384R1Curve"/>
+      </Item430>
+      <Item431>
+        <Filename Value="..\..\Math\EC\Custom\Sec\ClpSecP521R1Field.pas"/>
+        <UnitName Value="ClpSecP521R1Field"/>
+      </Item431>
+      <Item432>
+        <Filename Value="..\..\Math\Raw\ClpNat512.pas"/>
+        <UnitName Value="ClpNat512"/>
+      </Item432>
+      <Item433>
+        <Filename Value="..\..\Math\EC\Custom\Sec\ClpSecP521R1FieldElement.pas"/>
+        <UnitName Value="ClpSecP521R1FieldElement"/>
+      </Item433>
+      <Item434>
+        <Filename Value="..\..\Interfaces\ClpISecP521R1FieldElement.pas"/>
+        <UnitName Value="ClpISecP521R1FieldElement"/>
+      </Item434>
+      <Item435>
+        <Filename Value="..\..\Math\EC\Custom\Sec\ClpSecP521R1Point.pas"/>
+        <UnitName Value="ClpSecP521R1Point"/>
+      </Item435>
+      <Item436>
+        <Filename Value="..\..\Interfaces\ClpISecP521R1Point.pas"/>
+        <UnitName Value="ClpISecP521R1Point"/>
+      </Item436>
+      <Item437>
+        <Filename Value="..\..\Math\EC\Custom\Sec\ClpSecP521R1Curve.pas"/>
+        <UnitName Value="ClpSecP521R1Curve"/>
+      </Item437>
+      <Item438>
+        <Filename Value="..\..\Interfaces\ClpISecP521R1Curve.pas"/>
+        <UnitName Value="ClpISecP521R1Curve"/>
+      </Item438>
+      <Item439>
+        <Filename Value="..\..\Math\Raw\ClpInterleave.pas"/>
+        <UnitName Value="ClpInterleave"/>
+      </Item439>
+      <Item440>
+        <Filename Value="..\..\Math\EC\Custom\Sec\ClpSecT283Field.pas"/>
+        <UnitName Value="ClpSecT283Field"/>
+      </Item440>
+      <Item441>
+        <Filename Value="..\..\Math\EC\Custom\Sec\ClpSecT283FieldElement.pas"/>
+        <UnitName Value="ClpSecT283FieldElement"/>
+      </Item441>
+      <Item442>
+        <Filename Value="..\..\Interfaces\ClpISecT283FieldElement.pas"/>
+        <UnitName Value="ClpISecT283FieldElement"/>
+      </Item442>
+      <Item443>
+        <Filename Value="..\..\Math\EC\Custom\Sec\ClpSecT283K1Point.pas"/>
+        <UnitName Value="ClpSecT283K1Point"/>
+      </Item443>
+      <Item444>
+        <Filename Value="..\..\Interfaces\ClpISecT283K1Point.pas"/>
+        <UnitName Value="ClpISecT283K1Point"/>
+      </Item444>
+      <Item445>
+        <Filename Value="..\..\Interfaces\ClpISecT283K1Curve.pas"/>
+        <UnitName Value="ClpISecT283K1Curve"/>
+      </Item445>
+      <Item446>
+        <Filename Value="..\..\Math\EC\Custom\Sec\ClpSecT283K1Curve.pas"/>
+        <UnitName Value="ClpSecT283K1Curve"/>
+      </Item446>
+      <Item447>
+        <Filename Value="..\..\3rdParty\generics.collections\src\generics.collections.pas"/>
+        <UnitName Value="Generics.Collections"/>
+      </Item447>
+      <Item448>
+        <Filename Value="..\..\3rdParty\generics.collections\src\generics.defaults.pas"/>
+        <UnitName Value="Generics.Defaults"/>
+      </Item448>
+      <Item449>
+        <Filename Value="..\..\3rdParty\generics.collections\src\generics.hashes.pas"/>
+        <UnitName Value="Generics.Hashes"/>
+      </Item449>
+      <Item450>
+        <Filename Value="..\..\3rdParty\generics.collections\src\generics.helpers.pas"/>
+        <UnitName Value="Generics.Helpers"/>
+      </Item450>
+      <Item451>
+        <Filename Value="..\..\3rdParty\generics.collections\src\generics.memoryexpanders.pas"/>
+        <UnitName Value="Generics.MemoryExpanders"/>
+      </Item451>
+      <Item452>
+        <Filename Value="..\..\3rdParty\generics.collections\src\generics.strings.pas"/>
+        <UnitName Value="Generics.Strings"/>
+      </Item452>
+      <Item453>
+        <Filename Value="..\..\3rdParty\generics.collections\src\inc\generics.dictionaries.inc"/>
+        <Type Value="Include"/>
+      </Item453>
+      <Item454>
         <Filename Value="..\..\3rdParty\generics.collections\src\inc\generics.dictionariesh.inc"/>
         <Type Value="Include"/>
-      </Item416>
+      </Item454>
     </Files>
     <RequiredPkgs Count="3">
       <Item1>
         <PackageName Value="HashLib4PascalPackage"/>
-        <MinVersion Major="2" Minor="4" Valid="True"/>
+        <MaxVersion Major="2" Minor="4"/>
+        <MinVersion Major="2" Minor="5" Valid="True"/>
       </Item1>
       <Item2>
         <PackageName Value="SimpleBaseLib4PascalPackage"/>
-        <MinVersion Major="1" Minor="2" Valid="True"/>
+        <MaxVersion Major="1" Minor="2"/>
+        <MinVersion Major="1" Minor="4" Valid="True"/>
       </Item2>
       <Item3>
         <PackageName Value="FCL"/>

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

@@ -135,8 +135,20 @@ uses
   ClpIDsaParameterGenerationParameters, ClpValidityPrecompInfo, 
   ClpIValidityPrecompInfo, ClpDsaParametersGenerator, ClpDsaParameter, 
   ClpIDsaParameter, ClpIKeyEncoder, ClpIDsaParametersGenerator, 
-  ClpIPreCompCallBack, Generics.Collections, Generics.Defaults, 
-  Generics.Hashes, Generics.Helpers, Generics.MemoryExpanders, Generics.Strings;
+  ClpIPreCompCallBack, ClpNistNamedCurves, ClpNat256, ClpNat320, 
+  ClpAesLightEngine, ClpIAesLightEngine, ClpCustomNamedCurves, 
+  ClpSecP256K1Field, ClpSecP256K1FieldElement, ClpISecP256K1FieldElement, 
+  ClpSecP256K1Point, ClpISecP256K1Point, ClpSecP256K1Curve, 
+  ClpISecP256K1Curve, ClpSecP384R1Field, ClpNat384, ClpSecP384R1FieldElement, 
+  ClpISecP384R1FieldElement, ClpSecP384R1Point, ClpISecP384R1Point, 
+  ClpSecP384R1Curve, ClpNat192, ClpISecP384R1Curve, ClpSecP521R1Field, 
+  ClpNat512, ClpSecP521R1FieldElement, ClpISecP521R1FieldElement, 
+  ClpSecP521R1Point, ClpISecP521R1Point, ClpSecP521R1Curve, 
+  ClpISecP521R1Curve, ClpInterleave, ClpSecT283Field, ClpSecT283FieldElement, 
+  ClpISecT283FieldElement, ClpSecT283K1Point, ClpISecT283K1Point, 
+  ClpISecT283K1Curve, ClpSecT283K1Curve, Generics.Collections, 
+  Generics.Defaults, Generics.Hashes, Generics.Helpers, 
+  Generics.MemoryExpanders, Generics.Strings;
 
 implementation
 

+ 12 - 5
CryptoLib/src/Security/ClpSecureRandom.pas

@@ -50,6 +50,7 @@ type
   strict private
   class var
 
+    FIsBooted: Boolean;
     FCounter: Int64;
     Fmaster: ISecureRandom;
     FDoubleScale: Double;
@@ -68,6 +69,7 @@ type
     class destructor DestroySecureRandom();
 
   strict protected
+  var
     Fgenerator: IRandomGenerator;
 
   public
@@ -267,7 +269,6 @@ end;
 class constructor TSecureRandom.CreateSecureRandom;
 begin
   TSecureRandom.Boot;
-  FLock := TCriticalSection.Create;
 end;
 
 class destructor TSecureRandom.DestroySecureRandom;
@@ -309,10 +310,16 @@ end;
 
 class procedure TSecureRandom.Boot;
 begin
-  FCounter := TTimes.NanoTime();
-  Fmaster := TSecureRandom.Create(TCryptoApiRandomGenerator.Create()
-    as ICryptoApiRandomGenerator);
-  FDoubleScale := Power(2.0, 64.0);
+  if not FIsBooted then
+  begin
+    FLock := TCriticalSection.Create;
+    FCounter := TTimes.NanoTime();
+    Fmaster := TSecureRandom.Create(TCryptoApiRandomGenerator.Create()
+      as ICryptoApiRandomGenerator);
+    FDoubleScale := Power(2.0, 64.0);
+
+    FIsBooted := True;
+  end;
 end;
 
 constructor TSecureRandom.Create;

+ 114 - 1
CryptoLib/src/Utils/ClpArrayUtils.pas

@@ -41,7 +41,11 @@ type
       : TCryptoLibStringArray; static;
 
     class function AddByteArray(const A, B: TCryptoLibByteArray)
-      : TCryptoLibByteArray; static; inline;
+      : TCryptoLibByteArray; overload; static; inline;
+
+    class function AddByteArray(const A: TCryptoLibByteArray;
+      const Others: TCryptoLibMatrixByteArray): TCryptoLibByteArray;
+      overload; static;
 
     class function AreEqual(const A, B: TCryptoLibByteArray): Boolean;
       overload; static;
@@ -55,6 +59,15 @@ type
     class function GetArrayHashCode(const data: TCryptoLibInt32Array): Int32;
       overload; static;
 
+    class function GetArrayHashCode(const data: TCryptoLibUInt32Array): Int32;
+      overload; static;
+
+    class function GetArrayHashCode(const data: TCryptoLibUInt32Array;
+      off, len: Int32): Int32; overload; static;
+
+    class function GetArrayHashCode(const data: TCryptoLibUInt64Array;
+      off, len: Int32): Int32; overload; static;
+
     class function Prepend(const A: TCryptoLibByteArray; B: Byte)
       : TCryptoLibByteArray; static;
 
@@ -97,6 +110,30 @@ begin
   System.Move(B[0], Result[l], System.Length(B) * System.SizeOf(Byte));
 end;
 
+class function TArrayUtils.AddByteArray(const A: TCryptoLibByteArray;
+  const Others: TCryptoLibMatrixByteArray): TCryptoLibByteArray;
+var
+  len, Idx, Pos: Int32;
+  temp: TCryptoLibByteArray;
+begin
+  len := 0;
+  for Idx := System.Low(Others) to System.High(Others) do
+  begin
+    len := len + System.Length(Others[Idx]);
+  end;
+  len := len + System.Length(A);
+  System.SetLength(Result, len);
+  System.Move(A[0], Result[0], System.Length(A) * System.SizeOf(Byte));
+  Pos := System.Length(A);
+  for Idx := System.Low(Others) to System.High(Others) do
+  begin
+    temp := Others[Idx];
+    System.Move(temp[0], Result[Pos], System.Length(temp) *
+      System.SizeOf(Byte));
+    Pos := Pos + System.Length(temp);
+  end;
+end;
+
 class function TArrayUtils.AddStringArray(const A, B: TCryptoLibStringArray)
   : TCryptoLibStringArray;
 var
@@ -234,6 +271,82 @@ begin
   Result := hc;
 end;
 
+class function TArrayUtils.GetArrayHashCode(const data
+  : TCryptoLibUInt32Array): Int32;
+var
+  i, hc: Int32;
+begin
+  if data = Nil then
+  begin
+    Result := 0;
+    Exit;
+  end;
+
+  i := System.Length(data);
+  hc := i + 1;
+
+  System.Dec(i);
+  while (i >= 0) do
+  begin
+    hc := hc * 257;
+    hc := hc xor data[i];
+    System.Dec(i);
+  end;
+  Result := hc;
+end;
+
+class function TArrayUtils.GetArrayHashCode(const data: TCryptoLibUInt32Array;
+  off, len: Int32): Int32;
+var
+  i, hc: Int32;
+begin
+  if data = Nil then
+  begin
+    Result := 0;
+    Exit;
+  end;
+
+  i := len;
+  hc := i + 1;
+
+  System.Dec(i);
+  while (i >= 0) do
+  begin
+    hc := hc * 257;
+    hc := hc xor data[off + i];
+    System.Dec(i);
+  end;
+  Result := hc;
+end;
+
+class function TArrayUtils.GetArrayHashCode(const data: TCryptoLibUInt64Array;
+  off, len: Int32): Int32;
+var
+  i, hc: Int32;
+  di: UInt64;
+begin
+  if data = Nil then
+  begin
+    Result := 0;
+    Exit;
+  end;
+
+  i := len;
+  hc := i + 1;
+
+  System.Dec(i);
+  while (i >= 0) do
+  begin
+    di := data[off + i];
+    hc := hc * 257;
+    hc := hc xor Int32(di);
+    hc := hc * 257;
+    hc := hc xor Int32(di shr 32);
+    System.Dec(i);
+  end;
+  Result := hc;
+end;
+
 class function TArrayUtils.Prepend(const A: TCryptoLibByteArray; B: Byte)
   : TCryptoLibByteArray;
 var

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

@@ -22,6 +22,7 @@ unit ClpBigIntegers;
 interface
 
 uses
+  Math,
   ClpBigInteger,
   ClpCryptoLibTypes,
   ClpISecureRandom;
@@ -93,6 +94,25 @@ type
       // TODO Should have been just Random class
       const random: ISecureRandom): TBigInteger; static;
 
+    /// <summary>
+    /// <para>
+    /// The regular <b>BigInteger.toByteArray()</b> includes the sign bit
+    /// of the number and <br />might result in an extra byte addition.
+    /// This method removes this extra byte.
+    /// </para>
+    /// </summary>
+    /// <param name="b">
+    /// the integer to format into a byte array
+    /// </param>
+    /// <param name="numBytes">
+    /// the desired size of the resulting byte array
+    /// </param>
+    /// <returns>
+    /// numBytes byte long array.
+    /// </returns>
+    class function BigIntegerToBytes(const b: TBigInteger; numBytes: Int32)
+      : TCryptoLibByteArray; static; inline;
+
   end;
 
 implementation
@@ -129,6 +149,28 @@ begin
 
 end;
 
+class function TBigIntegers.BigIntegerToBytes(const b: TBigInteger;
+  numBytes: Int32): TCryptoLibByteArray;
+var
+  biBytes: TCryptoLibByteArray;
+  start, length: Int32;
+begin
+  System.SetLength(Result, numBytes);
+  biBytes := b.ToByteArray();
+  if System.length(biBytes) = (numBytes + 1) then
+  begin
+    start := 1
+  end
+  else
+  begin
+    start := 0
+  end;
+
+  length := min(System.length(biBytes), numBytes);
+  System.Move(biBytes[start], Result[numBytes - length],
+    length * System.SizeOf(Byte));
+end;
+
 class function TBigIntegers.CreateRandomInRange(const min, max: TBigInteger;
   // TODO Should have been just Random class
   const random: ISecureRandom): TBigInteger;

+ 107 - 8
CryptoLib/src/Utils/ClpBits.pas

@@ -41,7 +41,7 @@ type
     /// <param name="Size">Size of the Array to Reverse.</param>
 
     class procedure ReverseByteArray(Source, Dest: Pointer;
-      Size: int64); static;
+      Size: Int64); static;
 
     /// <summary>
     /// Calculates Arithmetic shift right.
@@ -60,7 +60,7 @@ type
     /// <returns>Shifted value.</returns>
     /// Implementation was found here <see cref="https://github.com/Spelt/ZXing.Delphi/blob/master/Lib/Classes/Common/MathUtils.pas" />
 
-    class function Asr64(Value: int64; ShiftBits: Int32): int64; static; inline;
+    class function Asr64(Value: Int64; ShiftBits: Int32): Int64; static; inline;
 
     /// <summary>
     /// Calculates Negative Left Shift. This was implemented to circumvent a
@@ -69,6 +69,9 @@ type
     /// should give "3221225472" but in FPC ARM, It gives "0". In some C
     /// Compilers, this is "Undefined"
     /// </summary>
+    /// <param name="Value">
+    /// Value to Perform Shift On
+    /// </param>
     /// <param name="ShiftBits">
     /// Integer, number of bits to shift value to. This Number <b>Must be
     /// Negative</b>
@@ -83,13 +86,60 @@ type
     class function NegativeLeftShift32(Value: UInt32; ShiftBits: Int32): UInt32;
       static; inline;
 
-    class function RotateLeft32(a_value: UInt32; a_n: Int32): UInt32; overload;
+    /// <summary>
+    /// Calculates Negative Right Shift. This was implemented to circumvent a
+    /// compiler issue when performing Shift Right on certain values with a
+    /// Negative Shift Bits. In some C Compilers, this is "Undefined"
+    /// </summary>
+    /// <param name="Value">
+    /// Value to Perform Shift On
+    /// </param>
+    /// <param name="ShiftBits">
+    /// Integer, number of bits to shift value to. This Number <b>Must be
+    /// Negative</b>
+    /// </param>
+    /// <param name="value">
+    /// UInt32 value to compute 'NRS' on.
+    /// </param>
+    /// <returns>
+    /// Shifted value.
+    /// </returns>
+
+    class function NegativeRightShift32(Value: UInt32; ShiftBits: Int32)
+      : UInt32; static; inline;
+
+    /// <summary>
+    /// Calculates Negative Right Shift. This was implemented to circumvent a
+    /// compiler issue when performing Shift Right on certain values with a
+    /// Negative Shift Bits. In some C Compilers, this is "Undefined"
+    /// </summary>
+    /// <param name="Value">
+    /// Value to Perform Shift On
+    /// </param>
+    /// <param name="ShiftBits">
+    /// Integer, number of bits to shift value to. This Number <b>Must be
+    /// Negative</b>
+    /// </param>
+    /// <param name="value">
+    /// UInt64 value to compute 'NRS' on.
+    /// </param>
+    /// <returns>
+    /// Shifted value.
+    /// </returns>
+
+    class function NegativeRightShift64(Value: UInt64; ShiftBits: Int32)
+      : UInt64; static; inline;
+
+    class function RotateLeft8(a_value: Byte; a_n: Int32): Byte; static; inline;
+    class function RotateLeft32(a_value: UInt32; a_n: Int32): UInt32;
+      static; inline;
+    class function RotateLeft64(a_value: UInt64; a_n: Int32): UInt64;
       static; inline;
-    class function RotateLeft64(a_value: UInt64; a_n: Int32): UInt64; overload;
+    class function RotateRight8(a_value: Byte; a_n: Int32): Byte;
       static; inline;
-    class function RotateRight32(a_value: UInt32; a_n: Int32): UInt32; overload;
+    class function RotateRight32(a_value: UInt32; a_n: Int32): UInt32;
       static; inline;
-    class function RotateRight64(a_value: UInt64; a_n: Int32): UInt64; overload;
+    class function RotateRight64(a_value: UInt64; a_n: Int32): UInt64;
       static; inline;
 
   end;
@@ -98,7 +148,7 @@ implementation
 
 { TBits }
 
-class procedure TBits.ReverseByteArray(Source, Dest: Pointer; Size: int64);
+class procedure TBits.ReverseByteArray(Source, Dest: Pointer; Size: Int64);
 var
   ptr_src, ptr_dest: PByte;
 begin
@@ -196,7 +246,7 @@ begin
 {$ENDIF FPC}
 end;
 
-class function TBits.Asr64(Value: int64; ShiftBits: Int32): int64;
+class function TBits.Asr64(Value: Int64; ShiftBits: Int32): Int64;
 begin
 {$IFDEF FPC}
   Result := SarInt64(Value, ShiftBits);
@@ -212,12 +262,47 @@ begin
 {$ENDIF FPC}
 end;
 
+class function TBits.RotateLeft8(a_value: Byte; a_n: Int32): Byte;
+begin
+{$IFDEF DEBUG}
+  System.Assert(a_n >= 0);
+{$ENDIF DEBUG}
+{$IFDEF FPC}
+  Result := RolByte(a_value, a_n);
+{$ELSE}
+  a_n := a_n and 7;
+
+  Result := (a_value shl a_n) or (a_value shr (8 - a_n));
+{$ENDIF FPC}
+end;
+
 class function TBits.NegativeLeftShift32(Value: UInt32;
   ShiftBits: Int32): UInt32;
 begin
+{$IFDEF DEBUG}
+  System.Assert(ShiftBits < 0);
+{$ENDIF DEBUG}
   Result := Value shl (32 + ShiftBits);
 end;
 
+class function TBits.NegativeRightShift32(Value: UInt32;
+  ShiftBits: Int32): UInt32;
+begin
+{$IFDEF DEBUG}
+  System.Assert(ShiftBits < 0);
+{$ENDIF DEBUG}
+  Result := Value shr (32 + ShiftBits);
+end;
+
+class function TBits.NegativeRightShift64(Value: UInt64;
+  ShiftBits: Int32): UInt64;
+begin
+{$IFDEF DEBUG}
+  System.Assert(ShiftBits < 0);
+{$ENDIF DEBUG}
+  Result := Value shr (64 + ShiftBits);
+end;
+
 class function TBits.RotateLeft32(a_value: UInt32; a_n: Int32): UInt32;
 begin
 {$IFDEF DEBUG}
@@ -246,6 +331,20 @@ begin
 {$ENDIF FPC}
 end;
 
+class function TBits.RotateRight8(a_value: Byte; a_n: Int32): Byte;
+begin
+{$IFDEF DEBUG}
+  System.Assert(a_n >= 0);
+{$ENDIF DEBUG}
+{$IFDEF FPC}
+  Result := RorByte(a_value, a_n);
+{$ELSE}
+  a_n := a_n and 7;
+
+  Result := (a_value shr a_n) or (a_value shl (8 - a_n));
+{$ENDIF FPC}
+end;
+
 class function TBits.RotateRight32(a_value: UInt32; a_n: Int32): UInt32;
 begin
 {$IFDEF DEBUG}

+ 0 - 6
CryptoLib/src/Utils/ClpConverters.pas

@@ -22,15 +22,9 @@ unit ClpConverters;
 interface
 
 uses
-{$IFDEF HAS_UNITSCOPE}
-  System.Classes,
-  System.StrUtils,
-  System.SysUtils,
-{$ELSE}
   Classes,
   StrUtils,
   SysUtils,
-{$ENDIF HAS_UNITSCOPE}
   ClpCryptoLibTypes,
   ClpBits,
   ClpBitConverter;

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