瀏覽代碼

add base functionality for X25519, Ed25519, Ed25519Blake2B

Ugochukwu Mmaduekwe 6 年之前
父節點
當前提交
9412a45319
共有 59 個文件被更改,包括 7891 次插入15 次删除
  1. 50 0
      CryptoLib.Samples/Delphi.Samples/UsageSamples.dpr
  2. 53 1
      CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.TestInsight.dpr
  3. 53 1
      CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.dpr
  4. 11 3
      CryptoLib.Tests/FreePascal.Tests/CryptoLib.Tests.lpi
  5. 2 0
      CryptoLib.Tests/FreePascal.Tests/CryptoLib.lpr
  6. 10 2
      CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.Tests.lpi
  7. 2 0
      CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.lpr
  8. 286 0
      CryptoLib.Tests/src/Math/EC/Rfc7748/X25519Tests.pas
  9. 546 0
      CryptoLib.Tests/src/Math/EC/Rfc8032/Ed25519Tests.pas
  10. 112 0
      CryptoLib/src/Asn1/Edec/ClpEdECObjectIdentifiers.pas
  11. 86 0
      CryptoLib/src/Crypto/Agreement/ClpX25519Agreement.pas
  12. 1 0
      CryptoLib/src/Crypto/Engines/ClpSpeckEngine.pas
  13. 71 0
      CryptoLib/src/Crypto/Generators/ClpEd25519Blake2BKeyPairGenerator.pas
  14. 70 0
      CryptoLib/src/Crypto/Generators/ClpEd25519KeyPairGenerator.pas
  15. 70 0
      CryptoLib/src/Crypto/Generators/ClpX25519KeyPairGenerator.pas
  16. 48 0
      CryptoLib/src/Crypto/Parameters/ClpEd25519Blake2BKeyGenerationParameters.pas
  17. 212 0
      CryptoLib/src/Crypto/Parameters/ClpEd25519Blake2BPrivateKeyParameters.pas
  18. 119 0
      CryptoLib/src/Crypto/Parameters/ClpEd25519Blake2BPublicKeyParameters.pas
  19. 47 0
      CryptoLib/src/Crypto/Parameters/ClpEd25519KeyGenerationParameters.pas
  20. 210 0
      CryptoLib/src/Crypto/Parameters/ClpEd25519PrivateKeyParameters.pas
  21. 118 0
      CryptoLib/src/Crypto/Parameters/ClpEd25519PublicKeyParameters.pas
  22. 47 0
      CryptoLib/src/Crypto/Parameters/ClpX25519KeyGenerationParameters.pas
  23. 158 0
      CryptoLib/src/Crypto/Parameters/ClpX25519PrivateKeyParameters.pas
  24. 118 0
      CryptoLib/src/Crypto/Parameters/ClpX25519PublicKeyParameters.pas
  25. 182 0
      CryptoLib/src/Crypto/Signers/ClpEd25519Blake2BSigner.pas
  26. 185 0
      CryptoLib/src/Crypto/Signers/ClpEd25519CtxBlake2BSigner.pas
  27. 184 0
      CryptoLib/src/Crypto/Signers/ClpEd25519CtxSigner.pas
  28. 173 0
      CryptoLib/src/Crypto/Signers/ClpEd25519PhBlake2BSigner.pas
  29. 172 0
      CryptoLib/src/Crypto/Signers/ClpEd25519PhSigner.pas
  30. 181 0
      CryptoLib/src/Crypto/Signers/ClpEd25519Signer.pas
  31. 97 0
      CryptoLib/src/Interfaces/ClpIEd25519.pas
  32. 35 0
      CryptoLib/src/Interfaces/ClpIEd25519Blake2B.pas
  33. 35 0
      CryptoLib/src/Interfaces/ClpIEd25519Blake2BKeyGenerationParameters.pas
  34. 35 0
      CryptoLib/src/Interfaces/ClpIEd25519Blake2BKeyPairGenerator.pas
  35. 49 0
      CryptoLib/src/Interfaces/ClpIEd25519Blake2BPrivateKeyParameters.pas
  36. 41 0
      CryptoLib/src/Interfaces/ClpIEd25519Blake2BPublicKeyParameters.pas
  37. 36 0
      CryptoLib/src/Interfaces/ClpIEd25519Blake2BSigner.pas
  38. 36 0
      CryptoLib/src/Interfaces/ClpIEd25519CtxBlake2BSigner.pas
  39. 36 0
      CryptoLib/src/Interfaces/ClpIEd25519CtxSigner.pas
  40. 35 0
      CryptoLib/src/Interfaces/ClpIEd25519KeyGenerationParameters.pas
  41. 35 0
      CryptoLib/src/Interfaces/ClpIEd25519KeyPairGenerator.pas
  42. 36 0
      CryptoLib/src/Interfaces/ClpIEd25519PhBlake2BSigner.pas
  43. 36 0
      CryptoLib/src/Interfaces/ClpIEd25519PhSigner.pas
  44. 49 0
      CryptoLib/src/Interfaces/ClpIEd25519PrivateKeyParameters.pas
  45. 41 0
      CryptoLib/src/Interfaces/ClpIEd25519PublicKeyParameters.pas
  46. 36 0
      CryptoLib/src/Interfaces/ClpIEd25519Signer.pas
  47. 43 0
      CryptoLib/src/Interfaces/ClpIRawAgreement.pas
  48. 37 0
      CryptoLib/src/Interfaces/ClpIX25519Agreement.pas
  49. 35 0
      CryptoLib/src/Interfaces/ClpIX25519KeyGenerationParameters.pas
  50. 35 0
      CryptoLib/src/Interfaces/ClpIX25519KeyPairGenerator.pas
  51. 45 0
      CryptoLib/src/Interfaces/ClpIX25519PrivateKeyParameters.pas
  52. 40 0
      CryptoLib/src/Interfaces/ClpIX25519PublicKeyParameters.pas
  53. 230 0
      CryptoLib/src/Math/EC/Rfc7748/ClpX25519.pas
  54. 924 0
      CryptoLib/src/Math/EC/Rfc7748/ClpX25519Field.pas
  55. 1946 0
      CryptoLib/src/Math/EC/Rfc8032/ClpEd25519.pas
  56. 48 0
      CryptoLib/src/Math/EC/Rfc8032/ClpEd25519Blake2B.pas
  57. 202 2
      CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.lpk
  58. 22 1
      CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.pas
  59. 39 5
      CryptoLib/src/Security/ClpGeneratorUtilities.pas

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

@@ -287,6 +287,56 @@ uses
   ClpIAlgorithmParameterSpec in '..\..\CryptoLib\src\Interfaces\ClpIAlgorithmParameterSpec.pas',
   ClpIIESParameterSpec in '..\..\CryptoLib\src\Interfaces\ClpIIESParameterSpec.pas',
   ClpIESParameterSpec in '..\..\CryptoLib\src\Crypto\Parameters\ClpIESParameterSpec.pas',
+  ClpCurve25519Custom in '..\..\CryptoLib\src\Math\EC\Custom\Djb\ClpCurve25519Custom.pas',
+  ClpICurve25519Custom in '..\..\CryptoLib\src\Interfaces\ClpICurve25519Custom.pas',
+  ClpX25519Field in '..\..\CryptoLib\src\Math\EC\Rfc7748\ClpX25519Field.pas',
+  ClpEd25519 in '..\..\CryptoLib\src\Math\EC\Rfc8032\ClpEd25519.pas',
+  ClpIEd25519 in '..\..\CryptoLib\src\Interfaces\ClpIEd25519.pas',
+  ClpEd25519Blake2B in '..\..\CryptoLib\src\Math\EC\Rfc8032\ClpEd25519Blake2B.pas',
+  ClpIEd25519Blake2B in '..\..\CryptoLib\src\Interfaces\ClpIEd25519Blake2B.pas',
+  ClpSpeckLegacyEngine in '..\..\CryptoLib\src\Crypto\Engines\ClpSpeckLegacyEngine.pas',
+  ClpISpeckLegacyEngine in '..\..\CryptoLib\src\Interfaces\ClpISpeckLegacyEngine.pas',
+  ClpX25519 in '..\..\CryptoLib\src\Math\EC\Rfc7748\ClpX25519.pas',
+  ClpEdECObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Edec\ClpEdECObjectIdentifiers.pas',
+  ClpIRawAgreement in '..\..\CryptoLib\src\Interfaces\ClpIRawAgreement.pas',
+  ClpX25519Agreement in '..\..\CryptoLib\src\Crypto\Agreement\ClpX25519Agreement.pas',
+  ClpIX25519Agreement in '..\..\CryptoLib\src\Interfaces\ClpIX25519Agreement.pas',
+  ClpX25519PrivateKeyParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpX25519PrivateKeyParameters.pas',
+  ClpIX25519PrivateKeyParameters in '..\..\CryptoLib\src\Interfaces\ClpIX25519PrivateKeyParameters.pas',
+  ClpIX25519PublicKeyParameters in '..\..\CryptoLib\src\Interfaces\ClpIX25519PublicKeyParameters.pas',
+  ClpX25519PublicKeyParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpX25519PublicKeyParameters.pas',
+  ClpIEd25519PrivateKeyParameters in '..\..\CryptoLib\src\Interfaces\ClpIEd25519PrivateKeyParameters.pas',
+  ClpIEd25519PublicKeyParameters in '..\..\CryptoLib\src\Interfaces\ClpIEd25519PublicKeyParameters.pas',
+  ClpIEd25519Blake2BPublicKeyParameters in '..\..\CryptoLib\src\Interfaces\ClpIEd25519Blake2BPublicKeyParameters.pas',
+  ClpIEd25519Blake2BPrivateKeyParameters in '..\..\CryptoLib\src\Interfaces\ClpIEd25519Blake2BPrivateKeyParameters.pas',
+  ClpEd25519PrivateKeyParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpEd25519PrivateKeyParameters.pas',
+  ClpEd25519Blake2BPrivateKeyParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpEd25519Blake2BPrivateKeyParameters.pas',
+  ClpEd25519PublicKeyParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpEd25519PublicKeyParameters.pas',
+  ClpEd25519Blake2BPublicKeyParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpEd25519Blake2BPublicKeyParameters.pas',
+  ClpX25519KeyPairGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpX25519KeyPairGenerator.pas',
+  ClpIX25519KeyPairGenerator in '..\..\CryptoLib\src\Interfaces\ClpIX25519KeyPairGenerator.pas',
+  ClpIEd25519KeyPairGenerator in '..\..\CryptoLib\src\Interfaces\ClpIEd25519KeyPairGenerator.pas',
+  ClpIEd25519Blake2BKeyPairGenerator in '..\..\CryptoLib\src\Interfaces\ClpIEd25519Blake2BKeyPairGenerator.pas',
+  ClpEd25519KeyPairGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpEd25519KeyPairGenerator.pas',
+  ClpEd25519Blake2BKeyPairGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpEd25519Blake2BKeyPairGenerator.pas',
+  ClpX25519KeyGenerationParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpX25519KeyGenerationParameters.pas',
+  ClpIX25519KeyGenerationParameters in '..\..\CryptoLib\src\Interfaces\ClpIX25519KeyGenerationParameters.pas',
+  ClpIEd25519KeyGenerationParameters in '..\..\CryptoLib\src\Interfaces\ClpIEd25519KeyGenerationParameters.pas',
+  ClpIEd25519Blake2BKeyGenerationParameters in '..\..\CryptoLib\src\Interfaces\ClpIEd25519Blake2BKeyGenerationParameters.pas',
+  ClpEd25519KeyGenerationParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpEd25519KeyGenerationParameters.pas',
+  ClpEd25519Blake2BKeyGenerationParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpEd25519Blake2BKeyGenerationParameters.pas',
+  ClpIEd25519Signer in '..\..\CryptoLib\src\Interfaces\ClpIEd25519Signer.pas',
+  ClpEd25519Signer in '..\..\CryptoLib\src\Crypto\Signers\ClpEd25519Signer.pas',
+  ClpIEd25519Blake2BSigner in '..\..\CryptoLib\src\Interfaces\ClpIEd25519Blake2BSigner.pas',
+  ClpEd25519Blake2BSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpEd25519Blake2BSigner.pas',
+  ClpIEd25519CtxBlake2BSigner in '..\..\CryptoLib\src\Interfaces\ClpIEd25519CtxBlake2BSigner.pas',
+  ClpEd25519CtxSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpEd25519CtxSigner.pas',
+  ClpIEd25519CtxSigner in '..\..\CryptoLib\src\Interfaces\ClpIEd25519CtxSigner.pas',
+  ClpEd25519CtxBlake2BSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpEd25519CtxBlake2BSigner.pas',
+  ClpIEd25519PhSigner in '..\..\CryptoLib\src\Interfaces\ClpIEd25519PhSigner.pas',
+  ClpIEd25519PhBlake2BSigner in '..\..\CryptoLib\src\Interfaces\ClpIEd25519PhBlake2BSigner.pas',
+  ClpEd25519PhSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpEd25519PhSigner.pas',
+  ClpEd25519PhBlake2BSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpEd25519PhBlake2BSigner.pas',
   UsageExamples in '..\src\UsageExamples.pas';
 
 begin

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

@@ -297,6 +297,56 @@ uses
   ClpIAlgorithmParameterSpec in '..\..\CryptoLib\src\Interfaces\ClpIAlgorithmParameterSpec.pas',
   ClpIIESParameterSpec in '..\..\CryptoLib\src\Interfaces\ClpIIESParameterSpec.pas',
   ClpIESParameterSpec in '..\..\CryptoLib\src\Crypto\Parameters\ClpIESParameterSpec.pas',
+  ClpCurve25519Custom in '..\..\CryptoLib\src\Math\EC\Custom\Djb\ClpCurve25519Custom.pas',
+  ClpICurve25519Custom in '..\..\CryptoLib\src\Interfaces\ClpICurve25519Custom.pas',
+  ClpX25519Field in '..\..\CryptoLib\src\Math\EC\Rfc7748\ClpX25519Field.pas',
+  ClpEd25519 in '..\..\CryptoLib\src\Math\EC\Rfc8032\ClpEd25519.pas',
+  ClpIEd25519 in '..\..\CryptoLib\src\Interfaces\ClpIEd25519.pas',
+  ClpEd25519Blake2B in '..\..\CryptoLib\src\Math\EC\Rfc8032\ClpEd25519Blake2B.pas',
+  ClpIEd25519Blake2B in '..\..\CryptoLib\src\Interfaces\ClpIEd25519Blake2B.pas',
+  ClpSpeckLegacyEngine in '..\..\CryptoLib\src\Crypto\Engines\ClpSpeckLegacyEngine.pas',
+  ClpISpeckLegacyEngine in '..\..\CryptoLib\src\Interfaces\ClpISpeckLegacyEngine.pas',
+  ClpX25519 in '..\..\CryptoLib\src\Math\EC\Rfc7748\ClpX25519.pas',
+  ClpEdECObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Edec\ClpEdECObjectIdentifiers.pas',
+  ClpIRawAgreement in '..\..\CryptoLib\src\Interfaces\ClpIRawAgreement.pas',
+  ClpX25519Agreement in '..\..\CryptoLib\src\Crypto\Agreement\ClpX25519Agreement.pas',
+  ClpIX25519Agreement in '..\..\CryptoLib\src\Interfaces\ClpIX25519Agreement.pas',
+  ClpX25519PrivateKeyParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpX25519PrivateKeyParameters.pas',
+  ClpIX25519PrivateKeyParameters in '..\..\CryptoLib\src\Interfaces\ClpIX25519PrivateKeyParameters.pas',
+  ClpIX25519PublicKeyParameters in '..\..\CryptoLib\src\Interfaces\ClpIX25519PublicKeyParameters.pas',
+  ClpX25519PublicKeyParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpX25519PublicKeyParameters.pas',
+  ClpIEd25519PrivateKeyParameters in '..\..\CryptoLib\src\Interfaces\ClpIEd25519PrivateKeyParameters.pas',
+  ClpIEd25519PublicKeyParameters in '..\..\CryptoLib\src\Interfaces\ClpIEd25519PublicKeyParameters.pas',
+  ClpIEd25519Blake2BPublicKeyParameters in '..\..\CryptoLib\src\Interfaces\ClpIEd25519Blake2BPublicKeyParameters.pas',
+  ClpIEd25519Blake2BPrivateKeyParameters in '..\..\CryptoLib\src\Interfaces\ClpIEd25519Blake2BPrivateKeyParameters.pas',
+  ClpEd25519PrivateKeyParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpEd25519PrivateKeyParameters.pas',
+  ClpEd25519Blake2BPrivateKeyParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpEd25519Blake2BPrivateKeyParameters.pas',
+  ClpEd25519PublicKeyParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpEd25519PublicKeyParameters.pas',
+  ClpEd25519Blake2BPublicKeyParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpEd25519Blake2BPublicKeyParameters.pas',
+  ClpX25519KeyPairGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpX25519KeyPairGenerator.pas',
+  ClpIX25519KeyPairGenerator in '..\..\CryptoLib\src\Interfaces\ClpIX25519KeyPairGenerator.pas',
+  ClpIEd25519KeyPairGenerator in '..\..\CryptoLib\src\Interfaces\ClpIEd25519KeyPairGenerator.pas',
+  ClpIEd25519Blake2BKeyPairGenerator in '..\..\CryptoLib\src\Interfaces\ClpIEd25519Blake2BKeyPairGenerator.pas',
+  ClpEd25519KeyPairGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpEd25519KeyPairGenerator.pas',
+  ClpEd25519Blake2BKeyPairGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpEd25519Blake2BKeyPairGenerator.pas',
+  ClpX25519KeyGenerationParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpX25519KeyGenerationParameters.pas',
+  ClpIX25519KeyGenerationParameters in '..\..\CryptoLib\src\Interfaces\ClpIX25519KeyGenerationParameters.pas',
+  ClpIEd25519KeyGenerationParameters in '..\..\CryptoLib\src\Interfaces\ClpIEd25519KeyGenerationParameters.pas',
+  ClpIEd25519Blake2BKeyGenerationParameters in '..\..\CryptoLib\src\Interfaces\ClpIEd25519Blake2BKeyGenerationParameters.pas',
+  ClpEd25519KeyGenerationParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpEd25519KeyGenerationParameters.pas',
+  ClpEd25519Blake2BKeyGenerationParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpEd25519Blake2BKeyGenerationParameters.pas',
+  ClpIEd25519Signer in '..\..\CryptoLib\src\Interfaces\ClpIEd25519Signer.pas',
+  ClpEd25519Signer in '..\..\CryptoLib\src\Crypto\Signers\ClpEd25519Signer.pas',
+  ClpIEd25519Blake2BSigner in '..\..\CryptoLib\src\Interfaces\ClpIEd25519Blake2BSigner.pas',
+  ClpEd25519Blake2BSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpEd25519Blake2BSigner.pas',
+  ClpIEd25519CtxBlake2BSigner in '..\..\CryptoLib\src\Interfaces\ClpIEd25519CtxBlake2BSigner.pas',
+  ClpEd25519CtxSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpEd25519CtxSigner.pas',
+  ClpIEd25519CtxSigner in '..\..\CryptoLib\src\Interfaces\ClpIEd25519CtxSigner.pas',
+  ClpEd25519CtxBlake2BSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpEd25519CtxBlake2BSigner.pas',
+  ClpIEd25519PhSigner in '..\..\CryptoLib\src\Interfaces\ClpIEd25519PhSigner.pas',
+  ClpIEd25519PhBlake2BSigner in '..\..\CryptoLib\src\Interfaces\ClpIEd25519PhBlake2BSigner.pas',
+  ClpEd25519PhSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpEd25519PhSigner.pas',
+  ClpEd25519PhBlake2BSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpEd25519PhBlake2BSigner.pas',
   ClpFixedSecureRandom in '..\src\Utils\ClpFixedSecureRandom.pas',
   ClpIFixedSecureRandom in '..\src\Utils\ClpIFixedSecureRandom.pas',
   BlowfishTestVectors in '..\src\Crypto\BlowfishTestVectors.pas',
@@ -352,7 +402,9 @@ uses
   XSalsa20Tests in '..\src\Crypto\XSalsa20Tests.pas',
   StreamCipherResetTests in '..\src\Crypto\StreamCipherResetTests.pas',
   CTSTests in '..\src\Crypto\CTSTests.pas',
-  PascalCoinECIESTests in '..\src\Math\PascalCoinECIESTests.pas';
+  PascalCoinECIESTests in '..\src\Math\PascalCoinECIESTests.pas',
+  X25519Tests in '..\src\Math\EC\Rfc7748\X25519Tests.pas',
+  Ed25519Tests in '..\src\Math\EC\Rfc8032\Ed25519Tests.pas';
 
 begin
 

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

@@ -300,6 +300,56 @@ uses
   ClpIAlgorithmParameterSpec in '..\..\CryptoLib\src\Interfaces\ClpIAlgorithmParameterSpec.pas',
   ClpIIESParameterSpec in '..\..\CryptoLib\src\Interfaces\ClpIIESParameterSpec.pas',
   ClpIESParameterSpec in '..\..\CryptoLib\src\Crypto\Parameters\ClpIESParameterSpec.pas',
+  ClpCurve25519Custom in '..\..\CryptoLib\src\Math\EC\Custom\Djb\ClpCurve25519Custom.pas',
+  ClpICurve25519Custom in '..\..\CryptoLib\src\Interfaces\ClpICurve25519Custom.pas',
+  ClpX25519Field in '..\..\CryptoLib\src\Math\EC\Rfc7748\ClpX25519Field.pas',
+  ClpEd25519 in '..\..\CryptoLib\src\Math\EC\Rfc8032\ClpEd25519.pas',
+  ClpIEd25519 in '..\..\CryptoLib\src\Interfaces\ClpIEd25519.pas',
+  ClpEd25519Blake2B in '..\..\CryptoLib\src\Math\EC\Rfc8032\ClpEd25519Blake2B.pas',
+  ClpIEd25519Blake2B in '..\..\CryptoLib\src\Interfaces\ClpIEd25519Blake2B.pas',
+  ClpSpeckLegacyEngine in '..\..\CryptoLib\src\Crypto\Engines\ClpSpeckLegacyEngine.pas',
+  ClpISpeckLegacyEngine in '..\..\CryptoLib\src\Interfaces\ClpISpeckLegacyEngine.pas',
+  ClpX25519 in '..\..\CryptoLib\src\Math\EC\Rfc7748\ClpX25519.pas',
+  ClpEdECObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Edec\ClpEdECObjectIdentifiers.pas',
+  ClpIRawAgreement in '..\..\CryptoLib\src\Interfaces\ClpIRawAgreement.pas',
+  ClpX25519Agreement in '..\..\CryptoLib\src\Crypto\Agreement\ClpX25519Agreement.pas',
+  ClpIX25519Agreement in '..\..\CryptoLib\src\Interfaces\ClpIX25519Agreement.pas',
+  ClpX25519PrivateKeyParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpX25519PrivateKeyParameters.pas',
+  ClpIX25519PrivateKeyParameters in '..\..\CryptoLib\src\Interfaces\ClpIX25519PrivateKeyParameters.pas',
+  ClpIX25519PublicKeyParameters in '..\..\CryptoLib\src\Interfaces\ClpIX25519PublicKeyParameters.pas',
+  ClpX25519PublicKeyParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpX25519PublicKeyParameters.pas',
+  ClpIEd25519PrivateKeyParameters in '..\..\CryptoLib\src\Interfaces\ClpIEd25519PrivateKeyParameters.pas',
+  ClpIEd25519PublicKeyParameters in '..\..\CryptoLib\src\Interfaces\ClpIEd25519PublicKeyParameters.pas',
+  ClpIEd25519Blake2BPublicKeyParameters in '..\..\CryptoLib\src\Interfaces\ClpIEd25519Blake2BPublicKeyParameters.pas',
+  ClpIEd25519Blake2BPrivateKeyParameters in '..\..\CryptoLib\src\Interfaces\ClpIEd25519Blake2BPrivateKeyParameters.pas',
+  ClpEd25519PrivateKeyParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpEd25519PrivateKeyParameters.pas',
+  ClpEd25519Blake2BPrivateKeyParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpEd25519Blake2BPrivateKeyParameters.pas',
+  ClpEd25519PublicKeyParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpEd25519PublicKeyParameters.pas',
+  ClpEd25519Blake2BPublicKeyParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpEd25519Blake2BPublicKeyParameters.pas',
+  ClpX25519KeyPairGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpX25519KeyPairGenerator.pas',
+  ClpIX25519KeyPairGenerator in '..\..\CryptoLib\src\Interfaces\ClpIX25519KeyPairGenerator.pas',
+  ClpIEd25519KeyPairGenerator in '..\..\CryptoLib\src\Interfaces\ClpIEd25519KeyPairGenerator.pas',
+  ClpIEd25519Blake2BKeyPairGenerator in '..\..\CryptoLib\src\Interfaces\ClpIEd25519Blake2BKeyPairGenerator.pas',
+  ClpEd25519KeyPairGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpEd25519KeyPairGenerator.pas',
+  ClpEd25519Blake2BKeyPairGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpEd25519Blake2BKeyPairGenerator.pas',
+  ClpX25519KeyGenerationParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpX25519KeyGenerationParameters.pas',
+  ClpIX25519KeyGenerationParameters in '..\..\CryptoLib\src\Interfaces\ClpIX25519KeyGenerationParameters.pas',
+  ClpIEd25519KeyGenerationParameters in '..\..\CryptoLib\src\Interfaces\ClpIEd25519KeyGenerationParameters.pas',
+  ClpIEd25519Blake2BKeyGenerationParameters in '..\..\CryptoLib\src\Interfaces\ClpIEd25519Blake2BKeyGenerationParameters.pas',
+  ClpEd25519KeyGenerationParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpEd25519KeyGenerationParameters.pas',
+  ClpEd25519Blake2BKeyGenerationParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpEd25519Blake2BKeyGenerationParameters.pas',
+  ClpIEd25519Signer in '..\..\CryptoLib\src\Interfaces\ClpIEd25519Signer.pas',
+  ClpEd25519Signer in '..\..\CryptoLib\src\Crypto\Signers\ClpEd25519Signer.pas',
+  ClpIEd25519Blake2BSigner in '..\..\CryptoLib\src\Interfaces\ClpIEd25519Blake2BSigner.pas',
+  ClpEd25519Blake2BSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpEd25519Blake2BSigner.pas',
+  ClpIEd25519CtxBlake2BSigner in '..\..\CryptoLib\src\Interfaces\ClpIEd25519CtxBlake2BSigner.pas',
+  ClpEd25519CtxSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpEd25519CtxSigner.pas',
+  ClpIEd25519CtxSigner in '..\..\CryptoLib\src\Interfaces\ClpIEd25519CtxSigner.pas',
+  ClpEd25519CtxBlake2BSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpEd25519CtxBlake2BSigner.pas',
+  ClpIEd25519PhSigner in '..\..\CryptoLib\src\Interfaces\ClpIEd25519PhSigner.pas',
+  ClpIEd25519PhBlake2BSigner in '..\..\CryptoLib\src\Interfaces\ClpIEd25519PhBlake2BSigner.pas',
+  ClpEd25519PhSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpEd25519PhSigner.pas',
+  ClpEd25519PhBlake2BSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpEd25519PhBlake2BSigner.pas',
   ClpFixedSecureRandom in '..\src\Utils\ClpFixedSecureRandom.pas',
   ClpIFixedSecureRandom in '..\src\Utils\ClpIFixedSecureRandom.pas',
   BlowfishTestVectors in '..\src\Crypto\BlowfishTestVectors.pas',
@@ -355,7 +405,9 @@ uses
   XSalsa20Tests in '..\src\Crypto\XSalsa20Tests.pas',
   StreamCipherResetTests in '..\src\Crypto\StreamCipherResetTests.pas',
   CTSTests in '..\src\Crypto\CTSTests.pas',
-  PascalCoinECIESTests in '..\src\Math\PascalCoinECIESTests.pas';
+  PascalCoinECIESTests in '..\src\Math\PascalCoinECIESTests.pas',
+  X25519Tests in '..\src\Math\EC\Rfc7748\X25519Tests.pas',
+  Ed25519Tests in '..\src\Math\EC\Rfc8032\Ed25519Tests.pas';
 
 begin
 

+ 11 - 3
CryptoLib.Tests/FreePascal.Tests/CryptoLib.Tests.lpi

@@ -21,7 +21,7 @@
           </Target>
           <SearchPaths>
             <IncludeFiles Value="$(ProjOutDir)"/>
-            <OtherUnitFiles Value="..\src\Asn1;..\src\Math;..\src\Math\EC\Custom\Sec;..\src\Others;..\src\Security;..\src\Utils;..\src\Crypto;..\src\Math\EC"/>
+            <OtherUnitFiles Value="..\src\Asn1;..\src\Math;..\src\Math\EC\Custom\Sec;..\src\Others;..\src\Security;..\src\Utils;..\src\Crypto;..\src\Math\EC;..\src\Math\EC\Rfc7748;..\src\Math\EC\Rfc8032"/>
             <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
           </SearchPaths>
           <Parsing>
@@ -77,7 +77,7 @@
         <PackageName Value="FCL"/>
       </Item4>
     </RequiredPackages>
-    <Units Count="57">
+    <Units Count="59">
       <Unit0>
         <Filename Value="CryptoLib.lpr"/>
         <IsPartOfProject Value="True"/>
@@ -307,6 +307,14 @@
         <Filename Value="..\src\Math\PascalCoinECIESTests.pas"/>
         <IsPartOfProject Value="True"/>
       </Unit56>
+      <Unit57>
+        <Filename Value="..\src\Math\EC\Rfc7748\X25519Tests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit57>
+      <Unit58>
+        <Filename Value="..\src\Math\EC\Rfc8032\Ed25519Tests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit58>
     </Units>
   </ProjectOptions>
   <CompilerOptions>
@@ -317,7 +325,7 @@
     </Target>
     <SearchPaths>
       <IncludeFiles Value="$(ProjOutDir)"/>
-      <OtherUnitFiles Value="..\src\Asn1;..\src\Math;..\src\Math\EC\Custom\Sec;..\src\Others;..\src\Security;..\src\Utils;..\src\Crypto;..\src\Math\EC"/>
+      <OtherUnitFiles Value="..\src\Asn1;..\src\Math;..\src\Math\EC\Custom\Sec;..\src\Others;..\src\Security;..\src\Utils;..\src\Crypto;..\src\Math\EC;..\src\Math\EC\Rfc7748;..\src\Math\EC\Rfc8032"/>
       <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
     </SearchPaths>
     <CodeGeneration>

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

@@ -60,6 +60,8 @@ uses
   ChaChaTests,
   StreamCipherResetTests,
   CTSTests,
+  X25519Tests,
+  Ed25519Tests,
   ClpFixedSecureRandom,
   ClpIFixedSecureRandom;
 

+ 10 - 2
CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.Tests.lpi

@@ -37,7 +37,7 @@
         <PackageName Value="FCL"/>
       </Item2>
     </RequiredPackages>
-    <Units Count="57">
+    <Units Count="59">
       <Unit0>
         <Filename Value="CryptoLibConsole.lpr"/>
         <IsPartOfProject Value="True"/>
@@ -266,6 +266,14 @@
         <Filename Value="..\src\Math\PascalCoinECIESTests.pas"/>
         <IsPartOfProject Value="True"/>
       </Unit56>
+      <Unit57>
+        <Filename Value="..\src\Math\EC\Rfc7748\X25519Tests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit57>
+      <Unit58>
+        <Filename Value="..\src\Math\EC\Rfc8032\Ed25519Tests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit58>
     </Units>
   </ProjectOptions>
   <CompilerOptions>
@@ -276,7 +284,7 @@
     </Target>
     <SearchPaths>
       <IncludeFiles Value="$(ProjOutDir)"/>
-      <OtherUnitFiles Value="..\src\Others;..\src\Asn1;..\src\Math\EC\Custom\Sec;..\src\Math;..\src\Security;..\src\Utils;..\src\Crypto;..\src\Math\EC"/>
+      <OtherUnitFiles Value="..\src\Others;..\src\Asn1;..\src\Math\EC\Custom\Sec;..\src\Math;..\src\Security;..\src\Utils;..\src\Crypto;..\src\Math\EC;..\src\Math\EC\Rfc7748;..\src\Math\EC\Rfc8032"/>
       <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
     </SearchPaths>
   </CompilerOptions>

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

@@ -58,6 +58,8 @@ uses
   ChaChaTests,
   StreamCipherResetTests,
   CTSTests,
+  X25519Tests,
+  Ed25519Tests,
   ClpFixedSecureRandom,
   ClpIFixedSecureRandom;
 

+ 286 - 0
CryptoLib.Tests/src/Math/EC/Rfc7748/X25519Tests.pas

@@ -0,0 +1,286 @@
+{ *********************************************************************************** }
+{ *                              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 X25519Tests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+uses
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpX25519,
+  ClpSecureRandom,
+  ClpISecureRandom,
+  ClpArrayUtils,
+  ClpEncoders,
+  ClpCryptoLibTypes;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  TTestX25519 = class(TCryptoLibTestCase)
+  private
+  var
+    FRandom: ISecureRandom;
+
+    procedure CheckECDHVector(const sA, sAPub, sB, sBPub, sK, text: String);
+    procedure CheckIterated(count: Int32);
+    procedure CheckValue(const n: TCryptoLibByteArray; const text, se: String);
+    procedure CheckX25519Vector(const sK, su, se, text: String);
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+    procedure TestConsistency();
+    procedure TestECDH();
+    procedure TestECDHVector1();
+    procedure TestX25519Iterated();
+    // disabled because it takes a lot of time
+    // procedure TestX25519IteratedFull();
+    procedure TestX25519Vector1();
+    procedure TestX25519Vector2();
+
+  end;
+
+implementation
+
+{ TTestX25519 }
+
+procedure TTestX25519.CheckECDHVector(const sA, sAPub, sB, sBPub, sK,
+  text: String);
+var
+  a, b, aPub, bPub, aK, bK: TCryptoLibByteArray;
+begin
+  a := THex.Decode(sA);
+  CheckEquals(TX25519.ScalarSize, System.Length(a));
+
+  b := THex.Decode(sB);
+  CheckEquals(TX25519.ScalarSize, System.Length(b));
+
+  System.SetLength(aPub, TX25519.PointSize);
+
+  TX25519.ScalarMultBase(a, 0, aPub, 0);
+  CheckValue(aPub, text, sAPub);
+
+  System.SetLength(bPub, TX25519.PointSize);
+  TX25519.ScalarMultBase(b, 0, bPub, 0);
+  CheckValue(bPub, text, sBPub);
+
+  System.SetLength(aK, TX25519.PointSize);
+
+  TX25519.ScalarMult(a, 0, bPub, 0, aK, 0);
+  CheckValue(aK, text, sK);
+
+  System.SetLength(bK, TX25519.PointSize);
+
+  TX25519.ScalarMult(b, 0, aPub, 0, bK, 0);
+  CheckValue(bK, text, sK);
+end;
+
+procedure TTestX25519.CheckIterated(count: Int32);
+var
+  k, u, r: TCryptoLibByteArray;
+  iterations: Int32;
+begin
+  CheckEquals(TX25519.PointSize, TX25519.ScalarSize);
+
+  System.SetLength(k, TX25519.PointSize);
+  k[0] := 9;
+  System.SetLength(u, TX25519.PointSize);
+  u[0] := 9;
+  System.SetLength(r, TX25519.PointSize);
+
+  iterations := 0;
+
+  while (iterations < count) do
+  begin
+
+    TX25519.ScalarMult(k, 0, u, 0, r, 0);
+
+    System.Move(k[0], u[0], TX25519.PointSize * System.SizeOf(Byte));
+    System.Move(r[0], k[0], TX25519.PointSize * System.SizeOf(Byte));
+
+    System.Inc(iterations);
+    case iterations of
+      1:
+        CheckValue(k, 'Iterated @1',
+          '422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079');
+      1000:
+        CheckValue(k, 'Iterated @1000',
+          '684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51');
+      1000000:
+        CheckValue(k, 'Iterated @1000000',
+          '7c3911e0ab2586fd864497297e575e6f3bc601c0883c30df5f4dd2d24f665424');
+    end;
+
+  end;
+end;
+
+procedure TTestX25519.CheckValue(const n: TCryptoLibByteArray;
+  const text, se: String);
+var
+  e: TCryptoLibByteArray;
+begin
+  e := THex.Decode(se);
+  CheckTrue(TArrayUtils.AreEqual(e, n), text);
+end;
+
+procedure TTestX25519.CheckX25519Vector(const sK, su, se, text: String);
+var
+  k, u, r: TCryptoLibByteArray;
+begin
+  k := THex.Decode(sK);
+  CheckEquals(TX25519.ScalarSize, System.Length(k));
+
+  u := THex.Decode(su);
+  CheckEquals(TX25519.PointSize, System.Length(u));
+
+  System.SetLength(r, TX25519.PointSize);
+  TX25519.ScalarMult(k, 0, u, 0, r, 0);
+  CheckValue(r, text, se);
+end;
+
+procedure TTestX25519.SetUp;
+begin
+  inherited;
+  FRandom := TSecureRandom.Create();
+  TX25519.Precompute();
+end;
+
+procedure TTestX25519.TearDown;
+begin
+  inherited;
+end;
+
+procedure TTestX25519.TestConsistency;
+var
+  u, k, rF, rV: TCryptoLibByteArray;
+  i: Int32;
+begin
+  System.SetLength(u, TX25519.PointSize);
+  u[0] := 9;
+  System.SetLength(k, TX25519.ScalarSize);
+  System.SetLength(rF, TX25519.PointSize);
+  System.SetLength(rV, TX25519.PointSize);
+
+  for i := 1 to 100 do
+  begin
+    FRandom.NextBytes(k);
+    TX25519.ScalarMultBase(k, 0, rF, 0);
+    TX25519.ScalarMult(k, 0, u, 0, rV, 0);
+    CheckTrue(TArrayUtils.AreEqual(rF, rV), Format('Consistency #%d', [i]));
+  end;
+end;
+
+procedure TTestX25519.TestECDH;
+var
+  kA, Kb, qA, qB, sA, sB: TCryptoLibByteArray;
+  i: Int32;
+begin
+  System.SetLength(kA, TX25519.ScalarSize);
+  System.SetLength(Kb, TX25519.ScalarSize);
+  System.SetLength(qA, TX25519.PointSize);
+  System.SetLength(qB, TX25519.PointSize);
+  System.SetLength(sA, TX25519.PointSize);
+  System.SetLength(sB, TX25519.PointSize);
+
+  for i := 1 to 100 do
+  begin
+    // Each party generates an ephemeral private key, ...
+    FRandom.NextBytes(kA);
+    FRandom.NextBytes(Kb);
+
+    // ... publishes their public key, ...
+    TX25519.ScalarMultBase(kA, 0, qA, 0);
+    TX25519.ScalarMultBase(Kb, 0, qB, 0);
+
+    // ... computes the shared secret, ...
+    TX25519.ScalarMult(kA, 0, qB, 0, sA, 0);
+    TX25519.ScalarMult(Kb, 0, qA, 0, sB, 0);
+
+    // ... which is the same for both parties.
+    if (not TArrayUtils.AreEqual(sA, sB)) then
+    begin
+      Fail(Format(' %d', [i]));
+    end;
+  end;
+end;
+
+procedure TTestX25519.TestECDHVector1;
+begin
+  CheckECDHVector
+    ('77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a',
+    '8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a',
+    '5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb',
+    'de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f',
+    '4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742',
+    'ECDH Vector #1');
+end;
+
+procedure TTestX25519.TestX25519Iterated;
+begin
+  CheckIterated(1000);
+end;
+
+// procedure TTestX25519.TestX25519IteratedFull;
+// begin
+// CheckIterated(1000000);
+// end;
+
+procedure TTestX25519.TestX25519Vector1;
+begin
+  CheckX25519Vector
+    ('a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4',
+    'e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c',
+    'c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552',
+    'Vector #1');
+end;
+
+procedure TTestX25519.TestX25519Vector2;
+begin
+  CheckX25519Vector
+    ('4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d',
+    'e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493',
+    '95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957',
+    'Vector #2');
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+// RegisterTest(TTestX25519);
+{$ELSE}
+  RegisterTest(TTestX25519.Suite);
+{$ENDIF FPC}
+
+end.

+ 546 - 0
CryptoLib.Tests/src/Math/EC/Rfc8032/Ed25519Tests.pas

@@ -0,0 +1,546 @@
+{ *********************************************************************************** }
+{ *                              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 Ed25519Tests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+uses
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpEd25519,
+  ClpIEd25519,
+  ClpIDigest,
+  ClpSecureRandom,
+  ClpISecureRandom,
+  ClpArrayUtils,
+  ClpEncoders,
+  ClpCryptoLibTypes;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  TTestEd25519 = class(TCryptoLibTestCase)
+
+  private
+
+  var
+    FRandom: ISecureRandom;
+    procedure CheckEd25519Vector(const sSK, sPK, sM, sSig, text: String);
+    procedure CheckEd25519ctxVector(const sSK, sPK, sM, sCTX, sSig,
+      text: String);
+    procedure CheckEd25519phVector(const sSK, sPK, sM, sCTX, sSig,
+      text: String);
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+    procedure TestEd25519Consistency();
+    procedure TestEd25519ctxConsistency();
+    procedure TestEd25519phConsistency();
+    procedure TestEd25519Vector1();
+    procedure TestEd25519Vector2();
+    procedure TestEd25519Vector3();
+    procedure TestEd25519Vector1023();
+    procedure TestEd25519VectorSHAabc();
+    procedure TestEd25519ctxVector1();
+    procedure TestEd25519ctxVector2();
+    procedure TestEd25519ctxVector3();
+    procedure TestEd25519ctxVector4();
+    procedure TestEd25519phVector1();
+
+  end;
+
+implementation
+
+{ TTestEd25519 }
+
+procedure TTestEd25519.CheckEd25519Vector(const sSK, sPK, sM, sSig,
+  text: String);
+var
+  sk, pk, pkGen, m, sig, badsig, sigGen: TCryptoLibByteArray;
+  Ed25519Instance: IEd25519;
+  shouldVerify, shouldNotVerify: Boolean;
+begin
+  sk := THex.Decode(sSK);
+  pk := THex.Decode(sPK);
+
+  System.SetLength(pkGen, TEd25519.PublicKeySize);
+
+  Ed25519Instance := TEd25519.Create();
+  Ed25519Instance.GeneratePublicKey(sk, 0, pkGen, 0);
+  CheckTrue(TArrayUtils.AreEqual(pk, pkGen), text);
+
+  m := THex.Decode(sM);
+  sig := THex.Decode(sSig);
+
+  badsig := System.Copy(sig);
+
+  badsig[TEd25519.PublicKeySize - 1] :=
+    badsig[TEd25519.SignatureSize - 1] xor $80;
+
+  System.SetLength(sigGen, TEd25519.SignatureSize);
+
+  Ed25519Instance.Sign(sk, 0, m, 0, System.Length(m), sigGen, 0);
+  CheckTrue(TArrayUtils.AreEqual(sig, sigGen), text);
+
+  Ed25519Instance.Sign(sk, 0, pk, 0, m, 0, System.Length(m), sigGen, 0);
+  CheckTrue(TArrayUtils.AreEqual(sig, sigGen), text);
+
+  shouldVerify := Ed25519Instance.Verify(sig, 0, pk, 0, m, 0, System.Length(m));
+  CheckTrue(shouldVerify, text);
+
+  shouldNotVerify := Ed25519Instance.Verify(badsig, 0, pk, 0, m, 0,
+    System.Length(m));
+  CheckFalse(shouldNotVerify, text);
+end;
+
+procedure TTestEd25519.CheckEd25519ctxVector(const sSK, sPK, sM, sCTX, sSig,
+  text: String);
+var
+  sk, pk, pkGen, m, ctx, sig, badsig, sigGen: TCryptoLibByteArray;
+  Ed25519Instance: IEd25519;
+  shouldVerify, shouldNotVerify: Boolean;
+begin
+  sk := THex.Decode(sSK);
+  pk := THex.Decode(sPK);
+
+  System.SetLength(pkGen, TEd25519.PublicKeySize);
+
+  Ed25519Instance := TEd25519.Create();
+  Ed25519Instance.GeneratePublicKey(sk, 0, pkGen, 0);
+  CheckTrue(TArrayUtils.AreEqual(pk, pkGen), text);
+
+  m := THex.Decode(sM);
+  ctx := THex.Decode(sCTX);
+  sig := THex.Decode(sSig);
+
+  badsig := System.Copy(sig);
+
+  badsig[TEd25519.PublicKeySize - 1] :=
+    badsig[TEd25519.SignatureSize - 1] xor $80;
+
+  System.SetLength(sigGen, TEd25519.SignatureSize);
+
+  Ed25519Instance.Sign(sk, 0, ctx, m, 0, System.Length(m), sigGen, 0);
+  CheckTrue(TArrayUtils.AreEqual(sig, sigGen), text);
+
+  Ed25519Instance.Sign(sk, 0, pk, 0, ctx, m, 0, System.Length(m), sigGen, 0);
+  CheckTrue(TArrayUtils.AreEqual(sig, sigGen), text);
+
+  shouldVerify := Ed25519Instance.Verify(sig, 0, pk, 0, ctx, m, 0,
+    System.Length(m));
+  CheckTrue(shouldVerify, text);
+
+  shouldNotVerify := Ed25519Instance.Verify(badsig, 0, pk, 0, ctx, m, 0,
+    System.Length(m));
+  CheckFalse(shouldNotVerify, text);
+end;
+
+procedure TTestEd25519.CheckEd25519phVector(const sSK, sPK, sM, sCTX, sSig,
+  text: String);
+var
+  sk, pk, pkGen, m, ph, ctx, sig, badsig, sigGen: TCryptoLibByteArray;
+  Ed25519Instance: IEd25519;
+  shouldVerify, shouldNotVerify: Boolean;
+  prehash: IDigest;
+begin
+  sk := THex.Decode(sSK);
+  pk := THex.Decode(sPK);
+
+  System.SetLength(pkGen, TEd25519.PublicKeySize);
+
+  Ed25519Instance := TEd25519.Create();
+  Ed25519Instance.GeneratePublicKey(sk, 0, pkGen, 0);
+  CheckTrue(TArrayUtils.AreEqual(pk, pkGen), text);
+
+  m := THex.Decode(sM);
+  ctx := THex.Decode(sCTX);
+  sig := THex.Decode(sSig);
+
+  badsig := System.Copy(sig);
+
+  badsig[TEd25519.PublicKeySize - 1] :=
+    badsig[TEd25519.SignatureSize - 1] xor $80;
+
+  System.SetLength(sigGen, TEd25519.SignatureSize);
+
+  prehash := Ed25519Instance.CreatePreHash();
+  prehash.BlockUpdate(m, 0, System.Length(m));
+
+  System.SetLength(ph, TEd25519.PreHashSize);
+
+  prehash.DoFinal(ph, 0);
+
+  Ed25519Instance.SignPreHash(sk, 0, ctx, ph, 0, sigGen, 0);
+  CheckTrue(TArrayUtils.AreEqual(sig, sigGen), text);
+
+  Ed25519Instance.SignPreHash(sk, 0, pk, 0, ctx, ph, 0, sigGen, 0);
+  CheckTrue(TArrayUtils.AreEqual(sig, sigGen), text);
+
+  shouldVerify := Ed25519Instance.VerifyPreHash(sig, 0, pk, 0, ctx, ph, 0);
+  CheckTrue(shouldVerify, text);
+
+  shouldNotVerify := Ed25519Instance.VerifyPreHash(badsig, 0, pk, 0,
+    ctx, ph, 0);
+  CheckFalse(shouldNotVerify, text);
+
+  prehash := Ed25519Instance.CreatePreHash();
+  prehash.BlockUpdate(m, 0, System.Length(m));
+
+  Ed25519Instance.SignPreHash(sk, 0, ctx, prehash, sigGen, 0);
+  CheckTrue(TArrayUtils.AreEqual(sig, sigGen), text);
+
+  prehash := Ed25519Instance.CreatePreHash();
+  prehash.BlockUpdate(m, 0, System.Length(m));
+
+  Ed25519Instance.SignPreHash(sk, 0, pk, 0, ctx, prehash, sigGen, 0);
+  CheckTrue(TArrayUtils.AreEqual(sig, sigGen), text);
+
+  prehash := Ed25519Instance.CreatePreHash();
+  prehash.BlockUpdate(m, 0, System.Length(m));
+
+  shouldVerify := Ed25519Instance.VerifyPreHash(sig, 0, pk, 0, ctx, prehash);
+  CheckTrue(shouldVerify, text);
+
+  prehash := Ed25519Instance.CreatePreHash();
+  prehash.BlockUpdate(m, 0, System.Length(m));
+
+  shouldNotVerify := Ed25519Instance.VerifyPreHash(badsig, 0, pk, 0,
+    ctx, prehash);
+  CheckFalse(shouldNotVerify, text);
+
+end;
+
+procedure TTestEd25519.SetUp;
+begin
+  inherited;
+  FRandom := TSecureRandom.Create();
+  TEd25519.Precompute();
+end;
+
+procedure TTestEd25519.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestEd25519.TestEd25519Consistency;
+var
+  sk, pk, m, sig1, sig2: TCryptoLibByteArray;
+  i, mLen: Int32;
+  Ed25519Instance: IEd25519;
+  shouldVerify, shouldNotVerify: Boolean;
+begin
+  System.SetLength(sk, TEd25519.SecretKeySize);
+  System.SetLength(pk, TEd25519.PublicKeySize);
+  System.SetLength(m, 255);
+  System.SetLength(sig1, TEd25519.SignatureSize);
+  System.SetLength(sig2, TEd25519.SignatureSize);
+
+  FRandom.NextBytes(m);
+
+  for i := 0 to System.Pred(10) do
+  begin
+    FRandom.NextBytes(sk);
+    Ed25519Instance := TEd25519.Create();
+    Ed25519Instance.GeneratePublicKey(sk, 0, pk, 0);
+
+    mLen := FRandom.NextInt32() and 255;
+
+    Ed25519Instance.Sign(sk, 0, m, 0, mLen, sig1, 0);
+    Ed25519Instance.Sign(sk, 0, pk, 0, m, 0, mLen, sig2, 0);
+
+    CheckTrue(TArrayUtils.AreEqual(sig1, sig2),
+      Format('Ed25519 consistent signatures #%d', [i]));
+
+    shouldVerify := Ed25519Instance.Verify(sig1, 0, pk, 0, m, 0, mLen);
+
+    CheckTrue(shouldVerify, Format('Ed25519 consistent sign/verify #%d', [i]));
+
+    sig1[TEd25519.PublicKeySize - 1] :=
+      sig1[TEd25519.PublicKeySize - 1] xor $80;
+    shouldNotVerify := Ed25519Instance.Verify(sig1, 0, pk, 0, m, 0, mLen);
+
+    CheckFalse(shouldNotVerify,
+      Format('Ed25519 consistent verification failure #%d', [i]));
+  end;
+end;
+
+procedure TTestEd25519.TestEd25519ctxConsistency;
+var
+  sk, pk, ctx, m, sig1, sig2: TCryptoLibByteArray;
+  i, mLen: Int32;
+  Ed25519Instance: IEd25519;
+  shouldVerify, shouldNotVerify: Boolean;
+begin
+  System.SetLength(sk, TEd25519.SecretKeySize);
+  System.SetLength(pk, TEd25519.PublicKeySize);
+  System.SetLength(ctx, FRandom.NextInt32() and 7);
+  System.SetLength(m, 255);
+  System.SetLength(sig1, TEd25519.SignatureSize);
+  System.SetLength(sig2, TEd25519.SignatureSize);
+
+  FRandom.NextBytes(ctx);
+  FRandom.NextBytes(m);
+
+  for i := 0 to System.Pred(10) do
+  begin
+    FRandom.NextBytes(sk);
+    Ed25519Instance := TEd25519.Create();
+    Ed25519Instance.GeneratePublicKey(sk, 0, pk, 0);
+
+    mLen := FRandom.NextInt32() and 255;
+
+    Ed25519Instance.Sign(sk, 0, ctx, m, 0, mLen, sig1, 0);
+    Ed25519Instance.Sign(sk, 0, pk, 0, ctx, m, 0, mLen, sig2, 0);
+
+    CheckTrue(TArrayUtils.AreEqual(sig1, sig2),
+      Format('Ed25519ctx consistent signatures #%d', [i]));
+
+    shouldVerify := Ed25519Instance.Verify(sig1, 0, pk, 0, ctx, m, 0, mLen);
+
+    CheckTrue(shouldVerify,
+      Format('Ed25519ctx consistent sign/verify #%d', [i]));
+
+    sig1[TEd25519.PublicKeySize - 1] :=
+      sig1[TEd25519.PublicKeySize - 1] xor $80;
+    shouldNotVerify := Ed25519Instance.Verify(sig1, 0, pk, 0, ctx, m, 0, mLen);
+
+    CheckFalse(shouldNotVerify,
+      Format('Ed25519ctx consistent verification failure #%d', [i]));
+  end;
+end;
+
+procedure TTestEd25519.TestEd25519Vector1;
+begin
+  CheckEd25519Vector(('9d61b19deffd5a60ba844af492ec2cc4' +
+    '4449c5697b326919703bac031cae7f60'),
+    ('d75a980182b10ab7d54bfed3c964073a' + '0ee172f3daa62325af021a68f707511a'),
+    '', ('e5564300c360ac729086e2cc806e828a' + '84877f1eb8e5d974d873e06522490155'
+    + '5fb8821590a33bacc61e39701cf9b46b' + 'd25bf5f0595bbe24655141438e7a100b'),
+    'Ed25519 Vector #1');
+end;
+
+procedure TTestEd25519.TestEd25519Vector2;
+begin
+  CheckEd25519Vector(('4ccd089b28ff96da9db6c346ec114e0f' +
+    '5b8a319f35aba624da8cf6ed4fb8a6fb'),
+    ('3d4017c3e843895a92b70aa74d1b7ebc' + '9c982ccf2ec4968cc0cd55f12af4660c'),
+    '72', ('92a009a9f0d4cab8720e820b5f642540' +
+    'a2b27b5416503f8fb3762223ebdb69da' + '085ac1e43e15996e458f3613d0f11d8c' +
+    '387b2eaeb4302aeeb00d291612bb0c00'), 'Ed25519 Vector #2');
+end;
+
+procedure TTestEd25519.TestEd25519Vector3;
+begin
+  CheckEd25519Vector(('c5aa8df43f9f837bedb7442f31dcb7b1' +
+    '66d38535076f094b85ce3a2e0b4458f7'),
+    ('fc51cd8e6218a1a38da47ed00230f058' + '0816ed13ba3303ac5deb911548908025'),
+    'af82', ('6291d657deec24024827e69c3abe01a3' +
+    '0ce548a284743a445e3680d7db5ac3ac' + '18ff9b538d16f290ae67f760984dc659' +
+    '4a7c15e9716ed28dc027beceea1ec40a'), 'Ed25519 Vector #3');
+end;
+
+procedure TTestEd25519.TestEd25519Vector1023;
+var
+  m: String;
+begin
+  m := '08b8b2b733424243760fe426a4b54908' + '632110a66c2f6591eabd3345e3e4eb98' +
+    'fa6e264bf09efe12ee50f8f54e9f77b1' + 'e355f6c50544e23fb1433ddf73be84d8' +
+    '79de7c0046dc4996d9e773f4bc9efe57' + '38829adb26c81b37c93a1b270b20329d' +
+    '658675fc6ea534e0810a4432826bf58c' + '941efb65d57a338bbd2e26640f89ffbc' +
+    '1a858efcb8550ee3a5e1998bd177e93a' + '7363c344fe6b199ee5d02e82d522c4fe' +
+    'ba15452f80288a821a579116ec6dad2b' + '3b310da903401aa62100ab5d1a36553e' +
+    '06203b33890cc9b832f79ef80560ccb9' + 'a39ce767967ed628c6ad573cb116dbef' +
+    'efd75499da96bd68a8a97b928a8bbc10' + '3b6621fcde2beca1231d206be6cd9ec7' +
+    'aff6f6c94fcd7204ed3455c68c83f4a4' + '1da4af2b74ef5c53f1d8ac70bdcb7ed1' +
+    '85ce81bd84359d44254d95629e9855a9' + '4a7c1958d1f8ada5d0532ed8a5aa3fb2' +
+    'd17ba70eb6248e594e1a2297acbbb39d' + '502f1a8c6eb6f1ce22b3de1a1f40cc24' +
+    '554119a831a9aad6079cad88425de6bd' + 'e1a9187ebb6092cf67bf2b13fd65f270' +
+    '88d78b7e883c8759d2c4f5c65adb7553' + '878ad575f9fad878e80a0c9ba63bcbcc' +
+    '2732e69485bbc9c90bfbd62481d9089b' + 'eccf80cfe2df16a2cf65bd92dd597b07' +
+    '07e0917af48bbb75fed413d238f5555a' + '7a569d80c3414a8d0859dc65a46128ba' +
+    'b27af87a71314f318c782b23ebfe808b' + '82b0ce26401d2e22f04d83d1255dc51a' +
+    'ddd3b75a2b1ae0784504df543af8969b' + 'e3ea7082ff7fc9888c144da2af58429e' +
+    'c96031dbcad3dad9af0dcbaaaf268cb8' + 'fcffead94f3c7ca495e056a9b47acdb7' +
+    '51fb73e666c6c655ade8297297d07ad1' + 'ba5e43f1bca32301651339e22904cc8c' +
+    '42f58c30c04aafdb038dda0847dd988d' + 'cda6f3bfd15c4b4c4525004aa06eeff8' +
+    'ca61783aacec57fb3d1f92b0fe2fd1a8' + '5f6724517b65e614ad6808d6f6ee34df' +
+    'f7310fdc82aebfd904b01e1dc54b2927' + '094b2db68d6f903b68401adebf5a7e08' +
+    'd78ff4ef5d63653a65040cf9bfd4aca7' + '984a74d37145986780fc0b16ac451649' +
+    'de6188a7dbdf191f64b5fc5e2ab47b57' + 'f7f7276cd419c17a3ca8e1b939ae49e4' +
+    '88acba6b965610b5480109c8b17b80e1' + 'b7b750dfc7598d5d5011fd2dcc5600a3' +
+    '2ef5b52a1ecc820e308aa342721aac09' + '43bf6686b64b2579376504ccc493d97e' +
+    '6aed3fb0f9cd71a43dd497f01f17c0e2' + 'cb3797aa2a2f256656168e6c496afc5f' +
+    'b93246f6b1116398a346f1a641f3b041' + 'e989f7914f90cc2c7fff357876e506b5' +
+    '0d334ba77c225bc307ba537152f3f161' + '0e4eafe595f6d9d90d11faa933a15ef1' +
+    '369546868a7f3a45a96768d40fd9d034' + '12c091c6315cf4fde7cb68606937380d' +
+    'b2eaaa707b4c4185c32eddcdd306705e' + '4dc1ffc872eeee475a64dfac86aba41c' +
+    '0618983f8741c5ef68d3a101e8a3b8ca' + 'c60c905c15fc910840b94c00a0b9d0';
+
+  CheckEd25519Vector(('f5e5767cf153319517630f226876b86c' +
+    '8160cc583bc013744c6bf255f5cc0ee5'),
+    ('278117fc144c72340f67d0f2316e8386' + 'ceffbf2b2428c9c51fef7c597f1d426e'),
+    m, ('0aab4c900501b3e24d7cdf4663326a3a' + '87df5e4843b2cbdb67cbf6e460fec350'
+    + 'aa5371b1508f9f4528ecea23c436d94b' + '5e8fcd4f681e30a6ac00a9704a188a03'),
+    'Ed25519 Vector #1023');
+end;
+
+procedure TTestEd25519.TestEd25519VectorSHAabc;
+begin
+  CheckEd25519Vector(('833fe62409237b9d62ec77587520911e' +
+    '9a759cec1d19755b7da901b96dca3d42'),
+    ('ec172b93ad5e563bf4932c70e1245034' + 'c35467ef2efd4d64ebf819683467e2bf'),
+    ('ddaf35a193617abacc417349ae204131' + '12e6fa4e89a97ea20a9eeee64b55d39a' +
+    '2192992a274fc1a836ba3c23a3feebbd' + '454d4423643ce80e2a9ac94fa54ca49f'),
+    ('dc2a4459e7369633a52b1bf277839a00' + '201009a3efbf3ecb69bea2186c26b589' +
+    '09351fc9ac90b3ecfdfbc7c66431e030' + '3dca179c138ac17ad9bef1177331a704'),
+    'Ed25519 Vector SHA(abc)');
+end;
+
+procedure TTestEd25519.TestEd25519ctxVector1;
+begin
+  CheckEd25519ctxVector(('0305334e381af78f141cb666f6199f57' +
+    'bc3495335a256a95bd2a55bf546663f6'),
+    ('dfc9425e4f968f7f0c29f0259cf5f9ae' + 'd6851c2bb4ad8bfb860cfee0ab248292'),
+    'f726936d19c800494e3fdaff20b276a8', '666f6f',
+    ('55a4cc2f70a54e04288c5f4cd1e45a7b' + 'b520b36292911876cada7323198dd87a' +
+    '8b36950b95130022907a7fb7c4e9b2d5' + 'f6cca685a587b4b21f4b888e4e7edb0d'),
+    'Ed25519ctx Vector #1');
+end;
+
+procedure TTestEd25519.TestEd25519ctxVector2;
+begin
+  CheckEd25519ctxVector(('0305334e381af78f141cb666f6199f57' +
+    'bc3495335a256a95bd2a55bf546663f6'),
+    ('dfc9425e4f968f7f0c29f0259cf5f9ae' + 'd6851c2bb4ad8bfb860cfee0ab248292'),
+    'f726936d19c800494e3fdaff20b276a8', '626172',
+    ('fc60d5872fc46b3aa69f8b5b4351d580' + '8f92bcc044606db097abab6dbcb1aee3' +
+    '216c48e8b3b66431b5b186d1d28f8ee1' + '5a5ca2df6668346291c2043d4eb3e90d'),
+    'Ed25519ctx Vector #2');
+end;
+
+procedure TTestEd25519.TestEd25519ctxVector3;
+begin
+  CheckEd25519ctxVector(('0305334e381af78f141cb666f6199f57' +
+    'bc3495335a256a95bd2a55bf546663f6'),
+    ('dfc9425e4f968f7f0c29f0259cf5f9ae' + 'd6851c2bb4ad8bfb860cfee0ab248292'),
+    '508e9e6882b979fea900f62adceaca35', '666f6f',
+    ('8b70c1cc8310e1de20ac53ce28ae6e72' + '07f33c3295e03bb5c0732a1d20dc6490' +
+    '8922a8b052cf99b7c4fe107a5abb5b2c' + '4085ae75890d02df26269d8945f84b0b'),
+    'Ed25519ctx Vector #3');
+end;
+
+procedure TTestEd25519.TestEd25519ctxVector4;
+begin
+  CheckEd25519ctxVector(('ab9c2853ce297ddab85c993b3ae14bca' +
+    'd39b2c682beabc27d6d4eb20711d6560'),
+    ('0f1d1274943b91415889152e893d80e9' + '3275a1fc0b65fd71b4b0dda10ad7d772'),
+    'f726936d19c800494e3fdaff20b276a8', '666f6f',
+    ('21655b5f1aa965996b3f97b3c849eafb' + 'a922a0a62992f73b3d1b73106a84ad85' +
+    'e9b86a7b6005ea868337ff2d20a7f5fb' + 'd4cd10b0be49a68da2b2e0dc0ad8960f'),
+    'Ed25519ctx Vector #4');
+end;
+
+procedure TTestEd25519.TestEd25519phVector1;
+begin
+  CheckEd25519phVector(('833fe62409237b9d62ec77587520911e' +
+    '9a759cec1d19755b7da901b96dca3d42'),
+    ('ec172b93ad5e563bf4932c70e1245034' + 'c35467ef2efd4d64ebf819683467e2bf'),
+    '616263', '', ('98a70222f0b8121aa9d30f813d683f80' +
+    '9e462b469c7ff87639499bb94e6dae41' + '31f85042463c2a355a2003d062adf5aa' +
+    'a10b8c61e636062aaad11c2a26083406'), 'Ed25519ph Vector #1');
+end;
+
+procedure TTestEd25519.TestEd25519phConsistency;
+var
+  sk, pk, ctx, m, ph, sig1, sig2: TCryptoLibByteArray;
+  i, mLen: Int32;
+  Ed25519Instance: IEd25519;
+  shouldVerify, shouldNotVerify: Boolean;
+  prehash: IDigest;
+begin
+  System.SetLength(sk, TEd25519.SecretKeySize);
+  System.SetLength(pk, TEd25519.PublicKeySize);
+  System.SetLength(ctx, FRandom.NextInt32() and 7);
+  System.SetLength(m, 255);
+  System.SetLength(ph, 255);
+  System.SetLength(sig1, TEd25519.PreHashSize);
+  System.SetLength(sig2, TEd25519.SignatureSize);
+
+  FRandom.NextBytes(ctx);
+  FRandom.NextBytes(m);
+
+  for i := 0 to System.Pred(10) do
+  begin
+    FRandom.NextBytes(sk);
+    Ed25519Instance := TEd25519.Create();
+    Ed25519Instance.GeneratePublicKey(sk, 0, pk, 0);
+
+    mLen := FRandom.NextInt32() and 255;
+
+    prehash := Ed25519Instance.CreatePreHash();
+    prehash.BlockUpdate(m, 0, mLen);
+    prehash.DoFinal(ph, 0);
+
+    Ed25519Instance.SignPreHash(sk, 0, ctx, ph, 0, sig1, 0);
+    Ed25519Instance.SignPreHash(sk, 0, pk, 0, ctx, ph, 0, sig2, 0);
+
+    CheckTrue(TArrayUtils.AreEqual(sig1, sig2),
+      Format('Ed25519ph consistent signatures #%d', [i]));
+
+    shouldVerify := Ed25519Instance.VerifyPreHash(sig1, 0, pk, 0, ctx, ph, 0);
+
+    CheckTrue(shouldVerify,
+      Format('Ed25519ph consistent sign/verify #%d', [i]));
+
+    sig1[TEd25519.PublicKeySize - 1] :=
+      sig1[TEd25519.PublicKeySize - 1] xor $80;
+    shouldNotVerify := Ed25519Instance.VerifyPreHash(sig1, 0, pk, 0,
+      ctx, ph, 0);
+
+    CheckFalse(shouldNotVerify,
+      Format('Ed25519ph consistent verification failure #%d', [i]));
+  end;
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+ // RegisterTest(TTestEd25519);
+{$ELSE}
+  RegisterTest(TTestEd25519.Suite);
+{$ENDIF FPC}
+
+end.

+ 112 - 0
CryptoLib/src/Asn1/Edec/ClpEdECObjectIdentifiers.pas

@@ -0,0 +1,112 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpEdECObjectIdentifiers;
+
+interface
+
+uses
+  ClpAsn1Objects,
+  ClpIAsn1Objects;
+
+type
+
+  /// <summary>
+  /// Edwards Elliptic Curve Object Identifiers (RFC 8410)
+  /// </summary>
+  TEdECObjectIdentifiers = class abstract(TObject)
+
+  strict private
+
+  class var
+
+    FIsBooted: Boolean;
+    Fid_edwards_curve_algs, Fid_X25519, Fid_X448, Fid_Ed25519,
+      Fid_Ed448: IDerObjectIdentifier;
+
+    class constructor EdECObjectIdentifiers();
+  private
+    class function Getid_Ed25519: IDerObjectIdentifier; static; inline;
+    class function Getid_Ed448: IDerObjectIdentifier; static; inline;
+    class function Getid_edwards_curve_algs: IDerObjectIdentifier;
+      static; inline;
+    class function Getid_X25519: IDerObjectIdentifier; static; inline;
+    class function Getid_X448: IDerObjectIdentifier; static; inline;
+
+  public
+
+    class property id_edwards_curve_algs: IDerObjectIdentifier
+      read Getid_edwards_curve_algs;
+    class property id_X25519: IDerObjectIdentifier read Getid_X25519;
+    class property id_X448: IDerObjectIdentifier read Getid_X448;
+    class property id_Ed25519: IDerObjectIdentifier read Getid_Ed25519;
+    class property id_Ed448: IDerObjectIdentifier read Getid_Ed448;
+
+    class procedure Boot(); static;
+  end;
+
+implementation
+
+{ TEdECObjectIdentifiers }
+
+class procedure TEdECObjectIdentifiers.Boot;
+begin
+  if not FIsBooted then
+  begin
+    Fid_edwards_curve_algs := TDerObjectIdentifier.Create('1.3.101');
+
+    Fid_X25519 := id_edwards_curve_algs.Branch('110');
+    Fid_X448 := id_edwards_curve_algs.Branch('111');
+    Fid_Ed25519 := id_edwards_curve_algs.Branch('112');
+    Fid_Ed448 := id_edwards_curve_algs.Branch('113');
+
+    FIsBooted := True;
+  end;
+end;
+
+class constructor TEdECObjectIdentifiers.EdECObjectIdentifiers;
+begin
+  TEdECObjectIdentifiers.Boot();
+end;
+
+class function TEdECObjectIdentifiers.Getid_Ed25519: IDerObjectIdentifier;
+begin
+  result := Fid_Ed25519;
+end;
+
+class function TEdECObjectIdentifiers.Getid_Ed448: IDerObjectIdentifier;
+begin
+  result := Fid_Ed448;
+end;
+
+class function TEdECObjectIdentifiers.Getid_edwards_curve_algs
+  : IDerObjectIdentifier;
+begin
+  result := Fid_edwards_curve_algs;
+end;
+
+class function TEdECObjectIdentifiers.Getid_X25519: IDerObjectIdentifier;
+begin
+  result := Fid_X25519;
+end;
+
+class function TEdECObjectIdentifiers.Getid_X448: IDerObjectIdentifier;
+begin
+  result := Fid_X448;
+end;
+
+end.

+ 86 - 0
CryptoLib/src/Crypto/Agreement/ClpX25519Agreement.pas

@@ -0,0 +1,86 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpX25519Agreement;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpIRawAgreement,
+  ClpIX25519Agreement,
+  ClpICipherParameters,
+  ClpX25519PrivateKeyParameters,
+  ClpIX25519PrivateKeyParameters,
+  ClpIX25519PublicKeyParameters,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SWrongInitCipherParameter =
+    'The Init Parameter does not Contain the Private Key';
+
+type
+  TX25519Agreement = class(TInterfacedObject, IX25519Agreement, IRawAgreement)
+
+  strict protected
+  var
+    FPrivateKey: IX25519PrivateKeyParameters;
+
+    function GetAgreementSize(): Int32; virtual;
+
+  public
+
+    procedure Init(const parameters: ICipherParameters); virtual;
+
+    procedure CalculateAgreement(const publicKey: ICipherParameters;
+      const buf: TCryptoLibByteArray; off: Int32);
+
+    property AgreementSize: Int32 read GetAgreementSize;
+
+  end;
+
+implementation
+
+{ TX25519Agreement }
+
+function TX25519Agreement.GetAgreementSize: Int32;
+begin
+  result := TX25519PrivateKeyParameters.SecretSize;
+end;
+
+procedure TX25519Agreement.Init(const parameters: ICipherParameters);
+begin
+  if Supports(parameters, IX25519PrivateKeyParameters) then
+  begin
+    FPrivateKey := parameters as IX25519PrivateKeyParameters;
+  end
+  else
+  begin
+    raise EInvalidParameterCryptoLibException.CreateRes
+      (@SWrongInitCipherParameter);
+  end;
+end;
+
+procedure TX25519Agreement.CalculateAgreement(const publicKey
+  : ICipherParameters; const buf: TCryptoLibByteArray; off: Int32);
+begin
+  FPrivateKey.GenerateSecret(publicKey as IX25519PublicKeyParameters, buf, off);
+end;
+
+end.

+ 1 - 0
CryptoLib/src/Crypto/Engines/ClpSpeckEngine.pas

@@ -1088,3 +1088,4 @@ begin
 end;
 
 end.
+

+ 71 - 0
CryptoLib/src/Crypto/Generators/ClpEd25519Blake2BKeyPairGenerator.pas

@@ -0,0 +1,71 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpEd25519Blake2BKeyPairGenerator;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpAsymmetricCipherKeyPair,
+  ClpIEd25519Blake2BKeyPairGenerator,
+  ClpIEd25519Blake2BPrivateKeyParameters,
+  ClpEd25519Blake2BPrivateKeyParameters,
+  ClpIEd25519Blake2BPublicKeyParameters,
+  ClpISecureRandom,
+  ClpIKeyGenerationParameters,
+  ClpIAsymmetricCipherKeyPair,
+  ClpIAsymmetricCipherKeyPairGenerator;
+
+type
+  TEd25519Blake2BKeyPairGenerator = class(TInterfacedObject,
+    IEd25519Blake2BKeyPairGenerator, IAsymmetricCipherKeyPairGenerator)
+
+  strict private
+  var
+    FRandom: ISecureRandom;
+
+  public
+    procedure Init(const parameters: IKeyGenerationParameters);
+
+    function GenerateKeyPair(): IAsymmetricCipherKeyPair;
+
+  end;
+
+implementation
+
+{ TEd25519Blake2BKeyPairGenerator }
+
+function TEd25519Blake2BKeyPairGenerator.GenerateKeyPair
+  : IAsymmetricCipherKeyPair;
+var
+  privateKey: IEd25519Blake2BPrivateKeyParameters;
+  publicKey: IEd25519Blake2BPublicKeyParameters;
+begin
+  privateKey := TEd25519Blake2BPrivateKeyParameters.Create(FRandom);
+  publicKey := privateKey.GeneratePublicKey();
+  result := TAsymmetricCipherKeyPair.Create(publicKey, privateKey);
+end;
+
+procedure TEd25519Blake2BKeyPairGenerator.Init(const parameters
+  : IKeyGenerationParameters);
+begin
+  FRandom := parameters.random;
+end;
+
+end.

+ 70 - 0
CryptoLib/src/Crypto/Generators/ClpEd25519KeyPairGenerator.pas

@@ -0,0 +1,70 @@
+{ *********************************************************************************** }
+{ *                              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 ClpEd25519KeyPairGenerator;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpAsymmetricCipherKeyPair,
+  ClpIEd25519KeyPairGenerator,
+  ClpIEd25519PrivateKeyParameters,
+  ClpEd25519PrivateKeyParameters,
+  ClpIEd25519PublicKeyParameters,
+  ClpISecureRandom,
+  ClpIKeyGenerationParameters,
+  ClpIAsymmetricCipherKeyPair,
+  ClpIAsymmetricCipherKeyPairGenerator;
+
+type
+  TEd25519KeyPairGenerator = class(TInterfacedObject, IEd25519KeyPairGenerator,
+    IAsymmetricCipherKeyPairGenerator)
+
+  strict private
+  var
+    FRandom: ISecureRandom;
+
+  public
+    procedure Init(const parameters: IKeyGenerationParameters);
+
+    function GenerateKeyPair(): IAsymmetricCipherKeyPair;
+
+  end;
+
+implementation
+
+{ TEd25519KeyPairGenerator }
+
+function TEd25519KeyPairGenerator.GenerateKeyPair: IAsymmetricCipherKeyPair;
+var
+  privateKey: IEd25519PrivateKeyParameters;
+  publicKey: IEd25519PublicKeyParameters;
+begin
+  privateKey := TEd25519PrivateKeyParameters.Create(FRandom);
+  publicKey := privateKey.GeneratePublicKey();
+  result := TAsymmetricCipherKeyPair.Create(publicKey, privateKey);
+end;
+
+procedure TEd25519KeyPairGenerator.Init(const parameters
+  : IKeyGenerationParameters);
+begin
+  FRandom := parameters.random;
+end;
+
+end.

+ 70 - 0
CryptoLib/src/Crypto/Generators/ClpX25519KeyPairGenerator.pas

@@ -0,0 +1,70 @@
+{ *********************************************************************************** }
+{ *                              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 ClpX25519KeyPairGenerator;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpAsymmetricCipherKeyPair,
+  ClpIX25519KeyPairGenerator,
+  ClpIX25519PrivateKeyParameters,
+  ClpX25519PrivateKeyParameters,
+  ClpIX25519PublicKeyParameters,
+  ClpISecureRandom,
+  ClpIKeyGenerationParameters,
+  ClpIAsymmetricCipherKeyPair,
+  ClpIAsymmetricCipherKeyPairGenerator;
+
+type
+  TX25519KeyPairGenerator = class sealed(TInterfacedObject,
+    IX25519KeyPairGenerator, IAsymmetricCipherKeyPairGenerator)
+
+  strict private
+  var
+    FRandom: ISecureRandom;
+
+  public
+    procedure Init(const parameters: IKeyGenerationParameters);
+
+    function GenerateKeyPair(): IAsymmetricCipherKeyPair;
+
+  end;
+
+implementation
+
+{ TX25519KeyPairGenerator }
+
+function TX25519KeyPairGenerator.GenerateKeyPair: IAsymmetricCipherKeyPair;
+var
+  privateKey: IX25519PrivateKeyParameters;
+  publicKey: IX25519PublicKeyParameters;
+begin
+  privateKey := TX25519PrivateKeyParameters.Create(FRandom);
+  publicKey := privateKey.GeneratePublicKey();
+  result := TAsymmetricCipherKeyPair.Create(publicKey, privateKey);
+end;
+
+procedure TX25519KeyPairGenerator.Init(const parameters
+  : IKeyGenerationParameters);
+begin
+  FRandom := parameters.random;
+end;
+
+end.

+ 48 - 0
CryptoLib/src/Crypto/Parameters/ClpEd25519Blake2BKeyGenerationParameters.pas

@@ -0,0 +1,48 @@
+{ *********************************************************************************** }
+{ *                              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 ClpEd25519Blake2BKeyGenerationParameters;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpISecureRandom,
+  ClpIEd25519Blake2BKeyGenerationParameters,
+  ClpKeyGenerationParameters;
+
+type
+  TEd25519Blake2BKeyGenerationParameters = class sealed
+    (TKeyGenerationParameters, IEd25519Blake2BKeyGenerationParameters)
+
+  public
+    constructor Create(const random: ISecureRandom);
+
+  end;
+
+implementation
+
+{ TEd25519Blake2BKeyGenerationParameters }
+
+constructor TEd25519Blake2BKeyGenerationParameters.Create
+  (const random: ISecureRandom);
+begin
+  Inherited Create(random, 256);
+end;
+
+end.

+ 212 - 0
CryptoLib/src/Crypto/Parameters/ClpEd25519Blake2BPrivateKeyParameters.pas

@@ -0,0 +1,212 @@
+{ *********************************************************************************** }
+{ *                              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 ClpEd25519Blake2BPrivateKeyParameters;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpEd25519Blake2B,
+  ClpIEd25519Blake2B,
+  ClpISecureRandom,
+  ClpAsymmetricKeyParameter,
+  ClpIEd25519Blake2BPrivateKeyParameters,
+  ClpIEd25519Blake2BPublicKeyParameters,
+  ClpEd25519Blake2BPublicKeyParameters,
+  ClpArrayUtils,
+  ClpAsn1Objects,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SEOFInPrivateKey = 'EOF encountered in middle of Ed25519Blake2B private key';
+  SUnsupportedAlgorithm = 'Unsupported Algorithm';
+  SCtxNotNil = 'Ctx must be Nil for Ed25519 Algorithm';
+  SMsgLen = 'MsgLen must be Equal to "PreHashSize" for Ed25519ph Algorithm';
+
+type
+  TEd25519Blake2BPrivateKeyParameters = class sealed(TAsymmetricKeyParameter,
+    IEd25519Blake2BPrivateKeyParameters)
+
+  strict private
+  var
+    FData: TCryptoLibByteArray;
+    FEd25519Blake2BInstance: IEd25519Blake2B;
+
+  public
+
+    const
+    KeySize = Int32(TEd25519Blake2B.SecretKeySize);
+    SignatureSize = Int32(TEd25519Blake2B.SignatureSize);
+
+    constructor Create(const random: ISecureRandom); overload;
+    constructor Create(const buf: TCryptoLibByteArray; off: Int32); overload;
+    constructor Create(input: TStream); overload;
+
+    procedure Encode(const buf: TCryptoLibByteArray; off: Int32); inline;
+    function GetEncoded(): TCryptoLibByteArray; inline;
+    function GeneratePublicKey(): IEd25519Blake2BPublicKeyParameters; inline;
+
+    procedure Sign(algorithm: TEd25519Blake2B.TEd25519Algorithm;
+      const publicKey: IEd25519Blake2BPublicKeyParameters;
+      const ctx, msg: TCryptoLibByteArray; msgOff, msgLen: Int32;
+      const sig: TCryptoLibByteArray; sigOff: Int32);
+
+    function Equals(const other: IEd25519Blake2BPrivateKeyParameters): Boolean;
+      reintroduce; overload;
+    function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}override;
+
+  end;
+
+implementation
+
+{ TEd25519Blake2BPrivateKeyParameters }
+
+function TEd25519Blake2BPrivateKeyParameters.GeneratePublicKey
+  : IEd25519Blake2BPublicKeyParameters;
+var
+  publicKey: TCryptoLibByteArray;
+begin
+  System.SetLength(publicKey, TEd25519Blake2B.PublicKeySize);
+  FEd25519Blake2BInstance.GeneratePublicKey(FData, 0, publicKey, 0);
+  result := TEd25519Blake2BPublicKeyParameters.Create(publicKey, 0);
+end;
+
+function TEd25519Blake2BPrivateKeyParameters.GetEncoded: TCryptoLibByteArray;
+begin
+  result := System.Copy(FData);
+end;
+
+constructor TEd25519Blake2BPrivateKeyParameters.Create
+  (const random: ISecureRandom);
+begin
+  Inherited Create(true);
+  System.SetLength(FData, KeySize);
+  FEd25519Blake2BInstance := TEd25519Blake2B.Create();
+  FEd25519Blake2BInstance.GeneratePrivateKey(random, FData);
+end;
+
+constructor TEd25519Blake2BPrivateKeyParameters.Create
+  (const buf: TCryptoLibByteArray; off: Int32);
+begin
+  Inherited Create(true);
+  System.SetLength(FData, KeySize);
+  FEd25519Blake2BInstance := TEd25519Blake2B.Create();
+  System.Move(buf[off], FData[0], KeySize * System.SizeOf(Byte));
+end;
+
+constructor TEd25519Blake2BPrivateKeyParameters.Create(input: TStream);
+begin
+  Inherited Create(true);
+  System.SetLength(FData, KeySize);
+  FEd25519Blake2BInstance := TEd25519Blake2B.Create();
+  if (KeySize <> TStreamUtils.ReadFully(input, FData)) then
+  begin
+    raise EEndOfStreamCryptoLibException.CreateRes(@SEOFInPrivateKey);
+  end;
+end;
+
+procedure TEd25519Blake2BPrivateKeyParameters.Encode
+  (const buf: TCryptoLibByteArray; off: Int32);
+begin
+  System.Move(FData[0], buf[off], KeySize * System.SizeOf(Byte));
+end;
+
+function TEd25519Blake2BPrivateKeyParameters.Equals
+  (const other: IEd25519Blake2BPrivateKeyParameters): Boolean;
+begin
+  if (other = Self as IEd25519Blake2BPrivateKeyParameters) then
+  begin
+    result := true;
+    Exit;
+  end;
+
+  if (other = Nil) then
+  begin
+    result := false;
+    Exit;
+  end;
+  result := TArrayUtils.ConstantTimeAreEqual(FData, other.GetEncoded())
+end;
+
+function TEd25519Blake2BPrivateKeyParameters.GetHashCode: {$IFDEF DELPHI}Int32;
+{$ELSE}PtrInt;
+{$ENDIF DELPHI}
+begin
+  result := TArrayUtils.GetArrayHashCode(FData);
+end;
+
+procedure TEd25519Blake2BPrivateKeyParameters.Sign
+  (algorithm: TEd25519Blake2B.TEd25519Algorithm;
+  const publicKey: IEd25519Blake2BPublicKeyParameters;
+  const ctx, msg: TCryptoLibByteArray; msgOff, msgLen: Int32;
+  const sig: TCryptoLibByteArray; sigOff: Int32);
+var
+  pk: TCryptoLibByteArray;
+begin
+  System.SetLength(pk, TEd25519Blake2B.PublicKeySize);
+
+  if (publicKey = Nil) then
+  begin
+    FEd25519Blake2BInstance.GeneratePublicKey(FData, 0, pk, 0);
+  end
+  else
+  begin
+    publicKey.Encode(pk, 0);
+  end;
+
+  case algorithm of
+    TEd25519Blake2B.TEd25519Algorithm.Ed25519:
+      begin
+        if (ctx <> Nil) then
+        begin
+          raise EArgumentCryptoLibException.CreateRes(@SCtxNotNil);
+        end;
+
+        FEd25519Blake2BInstance.Sign(FData, 0, pk, 0, msg, msgOff, msgLen,
+          sig, sigOff);
+      end;
+
+    TEd25519Blake2B.TEd25519Algorithm.Ed25519ctx:
+      begin
+        FEd25519Blake2BInstance.Sign(FData, 0, pk, 0, ctx, msg, msgOff, msgLen,
+          sig, sigOff);
+      end;
+
+    TEd25519Blake2B.TEd25519Algorithm.Ed25519ph:
+      begin
+        if (TEd25519Blake2B.PreHashSize <> msgLen) then
+        begin
+          raise EArgumentCryptoLibException.CreateRes(@SMsgLen);
+        end;
+
+        FEd25519Blake2BInstance.SignPrehash(FData, 0, pk, 0, ctx, msg, msgOff,
+          sig, sigOff);
+      end
+  else
+    begin
+      raise EInvalidOperationCryptoLibException.CreateRes
+        (@SUnsupportedAlgorithm);
+    end;
+
+  end;
+end;
+
+end.

+ 119 - 0
CryptoLib/src/Crypto/Parameters/ClpEd25519Blake2BPublicKeyParameters.pas

@@ -0,0 +1,119 @@
+{ *********************************************************************************** }
+{ *                              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 ClpEd25519Blake2BPublicKeyParameters;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpEd25519Blake2B,
+  ClpAsymmetricKeyParameter,
+  ClpIEd25519Blake2BPublicKeyParameters,
+  ClpArrayUtils,
+  ClpAsn1Objects,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SEOFInPublicKey = 'EOF encountered in middle of Ed25519Blake2B public key';
+
+type
+  TEd25519Blake2BPublicKeyParameters = class sealed(TAsymmetricKeyParameter,
+    IEd25519Blake2BPublicKeyParameters)
+
+  strict private
+  var
+    FData: TCryptoLibByteArray;
+
+  public
+
+    const
+    KeySize = Int32(TEd25519Blake2B.PublicKeySize);
+
+    constructor Create(const buf: TCryptoLibByteArray; off: Int32); overload;
+    constructor Create(input: TStream); overload;
+
+    procedure Encode(const buf: TCryptoLibByteArray; off: Int32); inline;
+    function GetEncoded(): TCryptoLibByteArray; inline;
+
+    function Equals(const other: IEd25519Blake2BPublicKeyParameters): Boolean;
+      reintroduce; overload;
+    function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}override;
+
+  end;
+
+implementation
+
+{ TEd25519Blake2BPublicKeyParameters }
+
+function TEd25519Blake2BPublicKeyParameters.GetEncoded: TCryptoLibByteArray;
+begin
+  result := System.Copy(FData);
+end;
+
+constructor TEd25519Blake2BPublicKeyParameters.Create
+  (const buf: TCryptoLibByteArray; off: Int32);
+begin
+  Inherited Create(false);
+  System.SetLength(FData, KeySize);
+  System.Move(buf[off], FData[0], KeySize * System.SizeOf(Byte));
+end;
+
+constructor TEd25519Blake2BPublicKeyParameters.Create(input: TStream);
+begin
+  Inherited Create(false);
+  System.SetLength(FData, KeySize);
+  if (KeySize <> TStreamUtils.ReadFully(input, FData)) then
+  begin
+    raise EEndOfStreamCryptoLibException.CreateRes(@SEOFInPublicKey);
+  end;
+end;
+
+procedure TEd25519Blake2BPublicKeyParameters.Encode
+  (const buf: TCryptoLibByteArray; off: Int32);
+begin
+  System.Move(FData[0], buf[off], KeySize * System.SizeOf(Byte));
+end;
+
+function TEd25519Blake2BPublicKeyParameters.Equals
+  (const other: IEd25519Blake2BPublicKeyParameters): Boolean;
+begin
+  if (other = Self as IEd25519Blake2BPublicKeyParameters) then
+  begin
+    result := true;
+    Exit;
+  end;
+
+  if (other = Nil) then
+  begin
+    result := false;
+    Exit;
+  end;
+  result := TArrayUtils.ConstantTimeAreEqual(FData, other.GetEncoded())
+end;
+
+function TEd25519Blake2BPublicKeyParameters.GetHashCode: {$IFDEF DELPHI}Int32;
+{$ELSE}PtrInt;
+{$ENDIF DELPHI}
+begin
+  result := TArrayUtils.GetArrayHashCode(FData);
+end;
+
+end.

+ 47 - 0
CryptoLib/src/Crypto/Parameters/ClpEd25519KeyGenerationParameters.pas

@@ -0,0 +1,47 @@
+{ *********************************************************************************** }
+{ *                              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 ClpEd25519KeyGenerationParameters;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpISecureRandom,
+  ClpIEd25519KeyGenerationParameters,
+  ClpKeyGenerationParameters;
+
+type
+  TEd25519KeyGenerationParameters = class sealed(TKeyGenerationParameters,
+    IEd25519KeyGenerationParameters)
+
+  public
+    constructor Create(const random: ISecureRandom);
+
+  end;
+
+implementation
+
+{ TEd25519KeyGenerationParameters }
+
+constructor TEd25519KeyGenerationParameters.Create(const random: ISecureRandom);
+begin
+  Inherited Create(random, 256);
+end;
+
+end.

+ 210 - 0
CryptoLib/src/Crypto/Parameters/ClpEd25519PrivateKeyParameters.pas

@@ -0,0 +1,210 @@
+{ *********************************************************************************** }
+{ *                              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 ClpEd25519PrivateKeyParameters;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpEd25519,
+  ClpIEd25519,
+  ClpISecureRandom,
+  ClpAsymmetricKeyParameter,
+  ClpIEd25519PrivateKeyParameters,
+  ClpIEd25519PublicKeyParameters,
+  ClpEd25519PublicKeyParameters,
+  ClpArrayUtils,
+  ClpAsn1Objects,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SEOFInPrivateKey = 'EOF encountered in middle of Ed25519 private key';
+  SUnsupportedAlgorithm = 'Unsupported Algorithm';
+  SCtxNotNil = 'Ctx must be Nil for Ed25519 Algorithm';
+  SMsgLen = 'MsgLen must be Equal to "PreHashSize" for Ed25519ph Algorithm';
+
+type
+  TEd25519PrivateKeyParameters = class sealed(TAsymmetricKeyParameter,
+    IEd25519PrivateKeyParameters)
+
+  strict private
+  var
+    FData: TCryptoLibByteArray;
+    FEd25519Instance: IEd25519;
+
+  public
+
+    const
+    KeySize = Int32(TEd25519.SecretKeySize);
+    SignatureSize = Int32(TEd25519.SignatureSize);
+
+    constructor Create(const random: ISecureRandom); overload;
+    constructor Create(const buf: TCryptoLibByteArray; off: Int32); overload;
+    constructor Create(input: TStream); overload;
+
+    procedure Encode(const buf: TCryptoLibByteArray; off: Int32); inline;
+    function GetEncoded(): TCryptoLibByteArray; inline;
+    function GeneratePublicKey(): IEd25519PublicKeyParameters; inline;
+
+    procedure Sign(algorithm: TEd25519.TEd25519Algorithm;
+      const publicKey: IEd25519PublicKeyParameters;
+      const ctx, msg: TCryptoLibByteArray; msgOff, msgLen: Int32;
+      const sig: TCryptoLibByteArray; sigOff: Int32);
+
+    function Equals(const other: IEd25519PrivateKeyParameters): Boolean;
+      reintroduce; overload;
+    function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}override;
+
+  end;
+
+implementation
+
+{ TEd25519PrivateKeyParameters }
+
+function TEd25519PrivateKeyParameters.GeneratePublicKey
+  : IEd25519PublicKeyParameters;
+var
+  publicKey: TCryptoLibByteArray;
+begin
+  System.SetLength(publicKey, TEd25519.PublicKeySize);
+  FEd25519Instance.GeneratePublicKey(FData, 0, publicKey, 0);
+  result := TEd25519PublicKeyParameters.Create(publicKey, 0);
+end;
+
+function TEd25519PrivateKeyParameters.GetEncoded: TCryptoLibByteArray;
+begin
+  result := System.Copy(FData);
+end;
+
+constructor TEd25519PrivateKeyParameters.Create(const random: ISecureRandom);
+begin
+  Inherited Create(true);
+  System.SetLength(FData, KeySize);
+  FEd25519Instance := TEd25519.Create();
+  FEd25519Instance.GeneratePrivateKey(random, FData);
+end;
+
+constructor TEd25519PrivateKeyParameters.Create(const buf: TCryptoLibByteArray;
+  off: Int32);
+begin
+  Inherited Create(true);
+  System.SetLength(FData, KeySize);
+  FEd25519Instance := TEd25519.Create();
+  System.Move(buf[off], FData[0], KeySize * System.SizeOf(Byte));
+end;
+
+constructor TEd25519PrivateKeyParameters.Create(input: TStream);
+begin
+  Inherited Create(true);
+  System.SetLength(FData, KeySize);
+  FEd25519Instance := TEd25519.Create();
+  if (KeySize <> TStreamUtils.ReadFully(input, FData)) then
+  begin
+    raise EEndOfStreamCryptoLibException.CreateRes(@SEOFInPrivateKey);
+  end;
+end;
+
+procedure TEd25519PrivateKeyParameters.Encode(const buf: TCryptoLibByteArray;
+  off: Int32);
+begin
+  System.Move(FData[0], buf[off], KeySize * System.SizeOf(Byte));
+end;
+
+function TEd25519PrivateKeyParameters.Equals(const other
+  : IEd25519PrivateKeyParameters): Boolean;
+begin
+  if (other = Self as IEd25519PrivateKeyParameters) then
+  begin
+    result := true;
+    Exit;
+  end;
+
+  if (other = Nil) then
+  begin
+    result := false;
+    Exit;
+  end;
+  result := TArrayUtils.ConstantTimeAreEqual(FData, other.GetEncoded())
+end;
+
+function TEd25519PrivateKeyParameters.GetHashCode: {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}
+begin
+  result := TArrayUtils.GetArrayHashCode(FData);
+end;
+
+procedure TEd25519PrivateKeyParameters.Sign
+  (algorithm: TEd25519.TEd25519Algorithm;
+  const publicKey: IEd25519PublicKeyParameters;
+  const ctx, msg: TCryptoLibByteArray; msgOff, msgLen: Int32;
+  const sig: TCryptoLibByteArray; sigOff: Int32);
+var
+  pk: TCryptoLibByteArray;
+begin
+  System.SetLength(pk, TEd25519.PublicKeySize);
+
+  if (publicKey = Nil) then
+  begin
+    FEd25519Instance.GeneratePublicKey(FData, 0, pk, 0);
+  end
+  else
+  begin
+    publicKey.Encode(pk, 0);
+  end;
+
+  case algorithm of
+    TEd25519.TEd25519Algorithm.Ed25519:
+      begin
+        if (ctx <> Nil) then
+        begin
+          raise EArgumentCryptoLibException.CreateRes(@SCtxNotNil);
+        end;
+
+        FEd25519Instance.Sign(FData, 0, pk, 0, msg, msgOff, msgLen,
+          sig, sigOff);
+      end;
+
+    TEd25519.TEd25519Algorithm.Ed25519ctx:
+      begin
+        FEd25519Instance.Sign(FData, 0, pk, 0, ctx, msg, msgOff, msgLen,
+          sig, sigOff);
+      end;
+
+    TEd25519.TEd25519Algorithm.Ed25519ph:
+      begin
+        if (TEd25519.PreHashSize <> msgLen) then
+        begin
+          raise EArgumentCryptoLibException.CreateRes(@SMsgLen);
+        end;
+
+        FEd25519Instance.SignPrehash(FData, 0, pk, 0, ctx, msg, msgOff,
+          sig, sigOff);
+      end
+  else
+    begin
+      raise EInvalidOperationCryptoLibException.CreateRes
+        (@SUnsupportedAlgorithm);
+    end;
+
+  end;
+end;
+
+end.

+ 118 - 0
CryptoLib/src/Crypto/Parameters/ClpEd25519PublicKeyParameters.pas

@@ -0,0 +1,118 @@
+{ *********************************************************************************** }
+{ *                              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 ClpEd25519PublicKeyParameters;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpEd25519,
+  ClpAsymmetricKeyParameter,
+  ClpIEd25519PublicKeyParameters,
+  ClpArrayUtils,
+  ClpAsn1Objects,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SEOFInPublicKey = 'EOF encountered in middle of Ed25519 public key';
+
+type
+  TEd25519PublicKeyParameters = class sealed(TAsymmetricKeyParameter,
+    IEd25519PublicKeyParameters)
+
+  strict private
+  var
+    FData: TCryptoLibByteArray;
+
+  public
+
+    const
+    KeySize = Int32(TEd25519.PublicKeySize);
+
+    constructor Create(const buf: TCryptoLibByteArray; off: Int32); overload;
+    constructor Create(input: TStream); overload;
+
+    procedure Encode(const buf: TCryptoLibByteArray; off: Int32); inline;
+    function GetEncoded(): TCryptoLibByteArray; inline;
+
+    function Equals(const other: IEd25519PublicKeyParameters): Boolean;
+      reintroduce; overload;
+    function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}override;
+
+  end;
+
+implementation
+
+{ TEd25519PublicKeyParameters }
+
+function TEd25519PublicKeyParameters.GetEncoded: TCryptoLibByteArray;
+begin
+  result := System.Copy(FData);
+end;
+
+constructor TEd25519PublicKeyParameters.Create(const buf: TCryptoLibByteArray;
+  off: Int32);
+begin
+  Inherited Create(false);
+  System.SetLength(FData, KeySize);
+  System.Move(buf[off], FData[0], KeySize * System.SizeOf(Byte));
+end;
+
+constructor TEd25519PublicKeyParameters.Create(input: TStream);
+begin
+  Inherited Create(false);
+  System.SetLength(FData, KeySize);
+  if (KeySize <> TStreamUtils.ReadFully(input, FData)) then
+  begin
+    raise EEndOfStreamCryptoLibException.CreateRes(@SEOFInPublicKey);
+  end;
+end;
+
+procedure TEd25519PublicKeyParameters.Encode(const buf: TCryptoLibByteArray;
+  off: Int32);
+begin
+  System.Move(FData[0], buf[off], KeySize * System.SizeOf(Byte));
+end;
+
+function TEd25519PublicKeyParameters.Equals(const other
+  : IEd25519PublicKeyParameters): Boolean;
+begin
+  if (other = Self as IEd25519PublicKeyParameters) then
+  begin
+    result := true;
+    Exit;
+  end;
+
+  if (other = Nil) then
+  begin
+    result := false;
+    Exit;
+  end;
+  result := TArrayUtils.ConstantTimeAreEqual(FData, other.GetEncoded())
+end;
+
+function TEd25519PublicKeyParameters.GetHashCode: {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}
+begin
+  result := TArrayUtils.GetArrayHashCode(FData);
+end;
+
+end.

+ 47 - 0
CryptoLib/src/Crypto/Parameters/ClpX25519KeyGenerationParameters.pas

@@ -0,0 +1,47 @@
+{ *********************************************************************************** }
+{ *                              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 ClpX25519KeyGenerationParameters;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpISecureRandom,
+  ClpIX25519KeyGenerationParameters,
+  ClpKeyGenerationParameters;
+
+type
+  TX25519KeyGenerationParameters = class sealed(TKeyGenerationParameters,
+    IX25519KeyGenerationParameters)
+
+  public
+    constructor Create(const random: ISecureRandom);
+
+  end;
+
+implementation
+
+{ TX25519KeyGenerationParameters }
+
+constructor TX25519KeyGenerationParameters.Create(const random: ISecureRandom);
+begin
+  Inherited Create(random, 255);
+end;
+
+end.

+ 158 - 0
CryptoLib/src/Crypto/Parameters/ClpX25519PrivateKeyParameters.pas

@@ -0,0 +1,158 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpX25519PrivateKeyParameters;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpX25519,
+  ClpISecureRandom,
+  ClpAsymmetricKeyParameter,
+  ClpIX25519PrivateKeyParameters,
+  ClpIX25519PublicKeyParameters,
+  ClpX25519PublicKeyParameters,
+  ClpArrayUtils,
+  ClpAsn1Objects,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SEOFInPrivateKey = 'EOF encountered in middle of X25519 private key';
+  SAgreementCalculationFailed = 'X25519 Agreement Failed';
+
+type
+  TX25519PrivateKeyParameters = class sealed(TAsymmetricKeyParameter,
+    IX25519PrivateKeyParameters)
+
+  strict private
+  var
+    FData: TCryptoLibByteArray;
+
+  public
+
+    const
+    KeySize = Int32(TX25519.ScalarSize);
+    SecretSize = Int32(TX25519.PointSize);
+
+    constructor Create(const random: ISecureRandom); overload;
+    constructor Create(const buf: TCryptoLibByteArray; off: Int32); overload;
+    constructor Create(input: TStream); overload;
+
+    procedure Encode(const buf: TCryptoLibByteArray; off: Int32); inline;
+    function GetEncoded(): TCryptoLibByteArray; inline;
+    function GeneratePublicKey(): IX25519PublicKeyParameters; inline;
+    procedure GenerateSecret(const publicKey: IX25519PublicKeyParameters;
+      const buf: TCryptoLibByteArray; off: Int32);
+
+    function Equals(const other: IX25519PrivateKeyParameters): Boolean;
+      reintroduce; overload;
+    function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}override;
+
+  end;
+
+implementation
+
+{ TX25519PrivateKeyParameters }
+
+function TX25519PrivateKeyParameters.GeneratePublicKey
+  : IX25519PublicKeyParameters;
+var
+  publicKey: TCryptoLibByteArray;
+begin
+  System.SetLength(publicKey, TX25519.PointSize);
+  TX25519.GeneratePublicKey(FData, 0, publicKey, 0);
+  result := TX25519PublicKeyParameters.Create(publicKey, 0);
+end;
+
+procedure TX25519PrivateKeyParameters.GenerateSecret(const publicKey
+  : IX25519PublicKeyParameters; const buf: TCryptoLibByteArray; off: Int32);
+var
+  encoded: TCryptoLibByteArray;
+begin
+  System.SetLength(encoded, TX25519.PointSize);
+  publicKey.Encode(encoded, 0);
+  if (not(TX25519.CalculateAgreement(FData, 0, encoded, 0, buf, off))) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes
+      (@SAgreementCalculationFailed);
+  end;
+end;
+
+function TX25519PrivateKeyParameters.GetEncoded: TCryptoLibByteArray;
+begin
+  result := System.Copy(FData);
+end;
+
+constructor TX25519PrivateKeyParameters.Create(const random: ISecureRandom);
+begin
+  Inherited Create(true);
+  System.SetLength(FData, KeySize);
+  TX25519.GeneratePrivateKey(random, FData);
+end;
+
+constructor TX25519PrivateKeyParameters.Create(const buf: TCryptoLibByteArray;
+  off: Int32);
+begin
+  Inherited Create(true);
+  System.SetLength(FData, KeySize);
+  System.Move(buf[off], FData[0], KeySize * System.SizeOf(Byte));
+end;
+
+constructor TX25519PrivateKeyParameters.Create(input: TStream);
+begin
+  Inherited Create(true);
+  System.SetLength(FData, KeySize);
+  if (KeySize <> TStreamUtils.ReadFully(input, FData)) then
+  begin
+    raise EEndOfStreamCryptoLibException.CreateRes(@SEOFInPrivateKey);
+  end;
+end;
+
+procedure TX25519PrivateKeyParameters.Encode(const buf: TCryptoLibByteArray;
+  off: Int32);
+begin
+  System.Move(FData[0], buf[off], KeySize * System.SizeOf(Byte));
+end;
+
+function TX25519PrivateKeyParameters.Equals(const other
+  : IX25519PrivateKeyParameters): Boolean;
+begin
+  if (other = Self as IX25519PrivateKeyParameters) then
+  begin
+    result := true;
+    Exit;
+  end;
+
+  if (other = Nil) then
+  begin
+    result := false;
+    Exit;
+  end;
+  result := TArrayUtils.ConstantTimeAreEqual(FData, other.GetEncoded())
+end;
+
+function TX25519PrivateKeyParameters.GetHashCode: {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}
+begin
+  result := TArrayUtils.GetArrayHashCode(FData);
+end;
+
+end.

+ 118 - 0
CryptoLib/src/Crypto/Parameters/ClpX25519PublicKeyParameters.pas

@@ -0,0 +1,118 @@
+{ *********************************************************************************** }
+{ *                              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 ClpX25519PublicKeyParameters;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpX25519,
+  ClpAsymmetricKeyParameter,
+  ClpIX25519PublicKeyParameters,
+  ClpArrayUtils,
+  ClpAsn1Objects,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SEOFInPublicKey = 'EOF encountered in middle of X25519 public key';
+
+type
+  TX25519PublicKeyParameters = class sealed(TAsymmetricKeyParameter,
+    IX25519PublicKeyParameters)
+
+  strict private
+  var
+    FData: TCryptoLibByteArray;
+
+  public
+
+    const
+    KeySize = Int32(TX25519.PointSize);
+
+    constructor Create(const buf: TCryptoLibByteArray; off: Int32); overload;
+    constructor Create(input: TStream); overload;
+
+    procedure Encode(const buf: TCryptoLibByteArray; off: Int32); inline;
+    function GetEncoded(): TCryptoLibByteArray; inline;
+
+    function Equals(const other: IX25519PublicKeyParameters): Boolean;
+      reintroduce; overload;
+    function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}override;
+
+  end;
+
+implementation
+
+{ TX25519PublicKeyParameters }
+
+function TX25519PublicKeyParameters.GetEncoded: TCryptoLibByteArray;
+begin
+  result := System.Copy(FData);
+end;
+
+constructor TX25519PublicKeyParameters.Create(const buf: TCryptoLibByteArray;
+  off: Int32);
+begin
+  Inherited Create(false);
+  System.SetLength(FData, KeySize);
+  System.Move(buf[off], FData[0], KeySize * System.SizeOf(Byte));
+end;
+
+constructor TX25519PublicKeyParameters.Create(input: TStream);
+begin
+  Inherited Create(false);
+  System.SetLength(FData, KeySize);
+  if (KeySize <> TStreamUtils.ReadFully(input, FData)) then
+  begin
+    raise EEndOfStreamCryptoLibException.CreateRes(@SEOFInPublicKey);
+  end;
+end;
+
+procedure TX25519PublicKeyParameters.Encode(const buf: TCryptoLibByteArray;
+  off: Int32);
+begin
+  System.Move(FData[0], buf[off], KeySize * System.SizeOf(Byte));
+end;
+
+function TX25519PublicKeyParameters.Equals(const other
+  : IX25519PublicKeyParameters): Boolean;
+begin
+  if (other = Self as IX25519PublicKeyParameters) then
+  begin
+    result := true;
+    Exit;
+  end;
+
+  if (other = Nil) then
+  begin
+    result := false;
+    Exit;
+  end;
+  result := TArrayUtils.ConstantTimeAreEqual(FData, other.GetEncoded())
+end;
+
+function TX25519PublicKeyParameters.GetHashCode: {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}
+begin
+  result := TArrayUtils.GetArrayHashCode(FData);
+end;
+
+end.

+ 182 - 0
CryptoLib/src/Crypto/Signers/ClpEd25519Blake2BSigner.pas

@@ -0,0 +1,182 @@
+{ *********************************************************************************** }
+{ *                              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 ClpEd25519Blake2BSigner;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpIEd25519Blake2B,
+  ClpEd25519Blake2B,
+  ClpICipherParameters,
+  ClpIEd25519Blake2BSigner,
+  ClpIEd25519Blake2BPrivateKeyParameters,
+  ClpIEd25519Blake2BPublicKeyParameters,
+  ClpEd25519Blake2BPrivateKeyParameters,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SNotInitializedForSigning =
+    'Ed25519Blake2BSigner not Initialised for Signature Generation.';
+  SNotInitializedForVerifying =
+    'Ed25519Blake2BSigner not Initialised for Verification';
+
+type
+  TEd25519Blake2BSigner = class(TInterfacedObject, IEd25519Blake2BSigner)
+
+  strict private
+  var
+    FBuffer: TMemoryStream;
+    FforSigning: Boolean;
+    FEd25519Blake2BInstance: IEd25519Blake2B;
+    FPrivateKey: IEd25519Blake2BPrivateKeyParameters;
+    FPublicKey: IEd25519Blake2BPublicKeyParameters;
+
+    function Aggregate: TCryptoLibByteArray; inline;
+
+  strict protected
+    function GetAlgorithmName: String; virtual;
+
+  public
+    constructor Create();
+    destructor Destroy(); override;
+
+    procedure Init(forSigning: Boolean;
+      const parameters: ICipherParameters); virtual;
+    procedure Update(b: Byte); virtual;
+    procedure BlockUpdate(const buf: TCryptoLibByteArray;
+      off, len: Int32); virtual;
+    function GenerateSignature(): TCryptoLibByteArray; virtual;
+    function VerifySignature(const signature: TCryptoLibByteArray)
+      : Boolean; virtual;
+    procedure Reset(); virtual;
+
+    property AlgorithmName: String read GetAlgorithmName;
+
+  end;
+
+implementation
+
+{ TEd25519Blake2BSigner }
+
+function TEd25519Blake2BSigner.Aggregate: TCryptoLibByteArray;
+begin
+  FBuffer.Position := 0;
+  System.SetLength(Result, FBuffer.Size);
+  FBuffer.Read(Result[0], FBuffer.Size);
+end;
+
+procedure TEd25519Blake2BSigner.BlockUpdate(const buf: TCryptoLibByteArray;
+  off, len: Int32);
+begin
+  FBuffer.Write(buf[off], len);
+end;
+
+constructor TEd25519Blake2BSigner.Create;
+begin
+  Inherited Create();
+  FBuffer := TMemoryStream.Create();
+  FEd25519Blake2BInstance := TEd25519Blake2B.Create();
+end;
+
+destructor TEd25519Blake2BSigner.Destroy;
+begin
+  FBuffer.Free;
+  inherited Destroy;
+end;
+
+function TEd25519Blake2BSigner.GetAlgorithmName: String;
+begin
+  Result := 'Ed25519Blake2B';
+end;
+
+procedure TEd25519Blake2BSigner.Init(forSigning: Boolean;
+  const parameters: ICipherParameters);
+begin
+  FforSigning := forSigning;
+
+  if (forSigning) then
+  begin
+    // TODO Allow IAsymmetricCipherKeyPair to be an ICipherParameters?
+
+    FPrivateKey := parameters as IEd25519Blake2BPrivateKeyParameters;
+    FPublicKey := FPrivateKey.GeneratePublicKey();
+  end
+  else
+  begin
+    FPrivateKey := Nil;
+    FPublicKey := parameters as IEd25519Blake2BPublicKeyParameters;
+  end;
+
+  Reset();
+end;
+
+procedure TEd25519Blake2BSigner.Reset;
+begin
+  FBuffer.Clear;
+  FBuffer.SetSize(Int64(0));
+end;
+
+procedure TEd25519Blake2BSigner.Update(b: Byte);
+begin
+  FBuffer.Write(TCryptoLibByteArray.Create(b)[0], 1);
+end;
+
+function TEd25519Blake2BSigner.GenerateSignature: TCryptoLibByteArray;
+var
+  signature, buf: TCryptoLibByteArray;
+  count: Int32;
+begin
+  if ((not FforSigning) or (FPrivateKey = Nil)) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes
+      (@SNotInitializedForSigning);
+  end;
+
+  System.SetLength(signature,
+    TEd25519Blake2BPrivateKeyParameters.SignatureSize);
+  buf := Aggregate();
+  count := System.Length(buf);
+
+  FPrivateKey.Sign(TEd25519Blake2B.TEd25519Algorithm.Ed25519, FPublicKey, Nil,
+    buf, 0, count, signature, 0);
+  Reset();
+  Result := signature;
+end;
+
+function TEd25519Blake2BSigner.VerifySignature(const signature
+  : TCryptoLibByteArray): Boolean;
+var
+  buf, pk: TCryptoLibByteArray;
+  count: Int32;
+begin
+  if ((FforSigning) or (FPublicKey = Nil)) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes
+      (@SNotInitializedForVerifying);
+  end;
+  pk := FPublicKey.GetEncoded();
+  buf := Aggregate();
+  count := System.Length(buf);
+  Result := FEd25519Blake2BInstance.Verify(signature, 0, pk, 0, buf, 0, count);
+  Reset();
+end;
+
+end.

+ 185 - 0
CryptoLib/src/Crypto/Signers/ClpEd25519CtxBlake2BSigner.pas

@@ -0,0 +1,185 @@
+{ *********************************************************************************** }
+{ *                              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 ClpEd25519CtxBlake2BSigner;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpIEd25519Blake2B,
+  ClpEd25519Blake2B,
+  ClpICipherParameters,
+  ClpIEd25519CtxBlake2BSigner,
+  ClpIEd25519Blake2BPrivateKeyParameters,
+  ClpIEd25519Blake2BPublicKeyParameters,
+  ClpEd25519Blake2BPrivateKeyParameters,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SNotInitializedForSigning =
+    'Ed25519CtxBlake2BSigner not Initialised for Signature Generation.';
+  SNotInitializedForVerifying =
+    'Ed25519CtxBlake2BSigner not Initialised for Verification';
+
+type
+  TEd25519CtxBlake2BSigner = class(TInterfacedObject, IEd25519CtxBlake2BSigner)
+
+  strict private
+  var
+    FContext: TCryptoLibByteArray;
+    FBuffer: TMemoryStream;
+    FforSigning: Boolean;
+    FEd25519Blake2BInstance: IEd25519Blake2B;
+    FPrivateKey: IEd25519Blake2BPrivateKeyParameters;
+    FPublicKey: IEd25519Blake2BPublicKeyParameters;
+
+    function Aggregate: TCryptoLibByteArray; inline;
+
+  strict protected
+    function GetAlgorithmName: String; virtual;
+
+  public
+    constructor Create(const context: TCryptoLibByteArray);
+    destructor Destroy(); override;
+
+    procedure Init(forSigning: Boolean;
+      const parameters: ICipherParameters); virtual;
+    procedure Update(b: Byte); virtual;
+    procedure BlockUpdate(const buf: TCryptoLibByteArray;
+      off, len: Int32); virtual;
+    function GenerateSignature(): TCryptoLibByteArray; virtual;
+    function VerifySignature(const signature: TCryptoLibByteArray)
+      : Boolean; virtual;
+    procedure Reset(); virtual;
+
+    property AlgorithmName: String read GetAlgorithmName;
+
+  end;
+
+implementation
+
+{ TEd25519CtxBlake2BSigner }
+
+function TEd25519CtxBlake2BSigner.Aggregate: TCryptoLibByteArray;
+begin
+  FBuffer.Position := 0;
+  System.SetLength(Result, FBuffer.Size);
+  FBuffer.Read(Result[0], FBuffer.Size);
+end;
+
+procedure TEd25519CtxBlake2BSigner.BlockUpdate(const buf: TCryptoLibByteArray;
+  off, len: Int32);
+begin
+  FBuffer.Write(buf[off], len);
+end;
+
+constructor TEd25519CtxBlake2BSigner.Create(const context: TCryptoLibByteArray);
+begin
+  Inherited Create();
+  FBuffer := TMemoryStream.Create();
+  FContext := System.Copy(context);
+  FEd25519Blake2BInstance := TEd25519Blake2B.Create();
+end;
+
+destructor TEd25519CtxBlake2BSigner.Destroy;
+begin
+  FBuffer.Free;
+  inherited Destroy;
+end;
+
+function TEd25519CtxBlake2BSigner.GetAlgorithmName: String;
+begin
+  Result := 'Ed25519CtxBlake2B';
+end;
+
+procedure TEd25519CtxBlake2BSigner.Init(forSigning: Boolean;
+  const parameters: ICipherParameters);
+begin
+  FforSigning := forSigning;
+
+  if (forSigning) then
+  begin
+    // TODO Allow IAsymmetricCipherKeyPair to be an ICipherParameters?
+
+    FPrivateKey := parameters as IEd25519Blake2BPrivateKeyParameters;
+    FPublicKey := FPrivateKey.GeneratePublicKey();
+  end
+  else
+  begin
+    FPrivateKey := Nil;
+    FPublicKey := parameters as IEd25519Blake2BPublicKeyParameters;
+  end;
+
+  Reset();
+end;
+
+procedure TEd25519CtxBlake2BSigner.Reset;
+begin
+  FBuffer.Clear;
+  FBuffer.SetSize(Int64(0));
+end;
+
+procedure TEd25519CtxBlake2BSigner.Update(b: Byte);
+begin
+  FBuffer.Write(TCryptoLibByteArray.Create(b)[0], 1);
+end;
+
+function TEd25519CtxBlake2BSigner.GenerateSignature: TCryptoLibByteArray;
+var
+  signature, buf: TCryptoLibByteArray;
+  count: Int32;
+begin
+  if ((not FforSigning) or (FPrivateKey = Nil)) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes
+      (@SNotInitializedForSigning);
+  end;
+
+  System.SetLength(signature,
+    TEd25519Blake2BPrivateKeyParameters.SignatureSize);
+  buf := Aggregate();
+  count := System.Length(buf);
+
+  FPrivateKey.Sign(TEd25519Blake2B.TEd25519Algorithm.Ed25519Ctx, FPublicKey,
+    FContext, buf, 0, count, signature, 0);
+  Reset();
+  Result := signature;
+end;
+
+function TEd25519CtxBlake2BSigner.VerifySignature(const signature
+  : TCryptoLibByteArray): Boolean;
+var
+  buf, pk: TCryptoLibByteArray;
+  count: Int32;
+begin
+  if ((FforSigning) or (FPublicKey = Nil)) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes
+      (@SNotInitializedForVerifying);
+  end;
+  pk := FPublicKey.GetEncoded();
+  buf := Aggregate();
+  count := System.Length(buf);
+  Result := FEd25519Blake2BInstance.Verify(signature, 0, pk, 0, FContext, buf,
+    0, count);
+  Reset();
+end;
+
+end.

+ 184 - 0
CryptoLib/src/Crypto/Signers/ClpEd25519CtxSigner.pas

@@ -0,0 +1,184 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpEd25519CtxSigner;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpIEd25519,
+  ClpEd25519,
+  ClpICipherParameters,
+  ClpIEd25519CtxSigner,
+  ClpIEd25519PrivateKeyParameters,
+  ClpIEd25519PublicKeyParameters,
+  ClpEd25519PrivateKeyParameters,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SNotInitializedForSigning =
+    'Ed25519CtxSigner not Initialised for Signature Generation.';
+  SNotInitializedForVerifying =
+    'Ed25519CtxSigner not Initialised for Verification';
+
+type
+  TEd25519CtxSigner = class(TInterfacedObject, IEd25519CtxSigner)
+
+  strict private
+  var
+    FContext: TCryptoLibByteArray;
+    FBuffer: TMemoryStream;
+    FforSigning: Boolean;
+    FEd25519Instance: IEd25519;
+    FPrivateKey: IEd25519PrivateKeyParameters;
+    FPublicKey: IEd25519PublicKeyParameters;
+
+    function Aggregate: TCryptoLibByteArray; inline;
+
+  strict protected
+    function GetAlgorithmName: String; virtual;
+
+  public
+    constructor Create(const context: TCryptoLibByteArray);
+    destructor Destroy(); override;
+
+    procedure Init(forSigning: Boolean;
+      const parameters: ICipherParameters); virtual;
+    procedure Update(b: Byte); virtual;
+    procedure BlockUpdate(const buf: TCryptoLibByteArray;
+      off, len: Int32); virtual;
+    function GenerateSignature(): TCryptoLibByteArray; virtual;
+    function VerifySignature(const signature: TCryptoLibByteArray)
+      : Boolean; virtual;
+    procedure Reset(); virtual;
+
+    property AlgorithmName: String read GetAlgorithmName;
+
+  end;
+
+implementation
+
+{ TEd25519CtxSigner }
+
+function TEd25519CtxSigner.Aggregate: TCryptoLibByteArray;
+begin
+  FBuffer.Position := 0;
+  System.SetLength(Result, FBuffer.Size);
+  FBuffer.Read(Result[0], FBuffer.Size);
+end;
+
+procedure TEd25519CtxSigner.BlockUpdate(const buf: TCryptoLibByteArray;
+  off, len: Int32);
+begin
+  FBuffer.Write(buf[off], len);
+end;
+
+constructor TEd25519CtxSigner.Create(const context: TCryptoLibByteArray);
+begin
+  Inherited Create();
+  FBuffer := TMemoryStream.Create();
+  FContext := System.Copy(context);
+  FEd25519Instance := TEd25519.Create();
+end;
+
+destructor TEd25519CtxSigner.Destroy;
+begin
+  FBuffer.Free;
+  inherited Destroy;
+end;
+
+function TEd25519CtxSigner.GetAlgorithmName: String;
+begin
+  Result := 'Ed25519ctx';
+end;
+
+procedure TEd25519CtxSigner.Init(forSigning: Boolean;
+  const parameters: ICipherParameters);
+begin
+  FforSigning := forSigning;
+
+  if (forSigning) then
+  begin
+    // TODO Allow IAsymmetricCipherKeyPair to be an ICipherParameters?
+
+    FPrivateKey := parameters as IEd25519PrivateKeyParameters;
+    FPublicKey := FPrivateKey.GeneratePublicKey();
+  end
+  else
+  begin
+    FPrivateKey := Nil;
+    FPublicKey := parameters as IEd25519PublicKeyParameters;
+  end;
+
+  Reset();
+end;
+
+procedure TEd25519CtxSigner.Reset;
+begin
+  FBuffer.Clear;
+  FBuffer.SetSize(Int64(0));
+end;
+
+procedure TEd25519CtxSigner.Update(b: Byte);
+begin
+  FBuffer.Write(TCryptoLibByteArray.Create(b)[0], 1);
+end;
+
+function TEd25519CtxSigner.GenerateSignature: TCryptoLibByteArray;
+var
+  signature, buf: TCryptoLibByteArray;
+  count: Int32;
+begin
+  if ((not FforSigning) or (FPrivateKey = Nil)) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes
+      (@SNotInitializedForSigning);
+  end;
+
+  System.SetLength(signature, TEd25519PrivateKeyParameters.SignatureSize);
+  buf := Aggregate();
+  count := System.Length(buf);
+
+  FPrivateKey.Sign(TEd25519.TEd25519Algorithm.Ed25519ctx, FPublicKey, FContext,
+    buf, 0, count, signature, 0);
+  Reset();
+  Result := signature;
+end;
+
+function TEd25519CtxSigner.VerifySignature(const signature
+  : TCryptoLibByteArray): Boolean;
+var
+  buf, pk: TCryptoLibByteArray;
+  count: Int32;
+begin
+  if ((FforSigning) or (FPublicKey = Nil)) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes
+      (@SNotInitializedForVerifying);
+  end;
+  pk := FPublicKey.GetEncoded();
+  buf := Aggregate();
+  count := System.Length(buf);
+  Result := FEd25519Instance.Verify(signature, 0, pk, 0, FContext, buf,
+    0, count);
+  Reset();
+end;
+
+end.

+ 173 - 0
CryptoLib/src/Crypto/Signers/ClpEd25519PhBlake2BSigner.pas

@@ -0,0 +1,173 @@
+{ *********************************************************************************** }
+{ *                              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 ClpEd25519PhBlake2BSigner;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIDigest,
+  ClpIEd25519Blake2B,
+  ClpEd25519Blake2B,
+  ClpICipherParameters,
+  ClpIEd25519PhBlake2BSigner,
+  ClpIEd25519Blake2BPrivateKeyParameters,
+  ClpIEd25519Blake2BPublicKeyParameters,
+  ClpEd25519Blake2BPrivateKeyParameters,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SNotInitializedForSigning =
+    'Ed25519PhBlake2BSigner not Initialised for Signature Generation.';
+  SNotInitializedForVerifying =
+    'Ed25519PhBlake2BSigner not Initialised for Verification';
+  SPreHashDigestFailed = 'PreHash Digest Failed';
+
+type
+  TEd25519PhBlake2BSigner = class(TInterfacedObject, IEd25519PhBlake2BSigner)
+
+  strict private
+  var
+    FPreHash: IDigest;
+    FContext: TCryptoLibByteArray;
+    FforSigning: Boolean;
+    FEd25519Blake2BInstance: IEd25519Blake2B;
+    FPrivateKey: IEd25519Blake2BPrivateKeyParameters;
+    FPublicKey: IEd25519Blake2BPublicKeyParameters;
+
+  strict protected
+    function GetAlgorithmName: String; virtual;
+
+  public
+    constructor Create(const context: TCryptoLibByteArray);
+    destructor Destroy(); override;
+
+    procedure Init(forSigning: Boolean;
+      const parameters: ICipherParameters); virtual;
+    procedure Update(b: Byte); virtual;
+    procedure BlockUpdate(const buf: TCryptoLibByteArray;
+      off, len: Int32); virtual;
+    function GenerateSignature(): TCryptoLibByteArray; virtual;
+    function VerifySignature(const signature: TCryptoLibByteArray)
+      : Boolean; virtual;
+    procedure Reset(); virtual;
+
+    property AlgorithmName: String read GetAlgorithmName;
+
+  end;
+
+implementation
+
+{ TEd25519PhBlake2BSigner }
+
+procedure TEd25519PhBlake2BSigner.BlockUpdate(const buf: TCryptoLibByteArray;
+  off, len: Int32);
+begin
+  FPreHash.BlockUpdate(buf, off, len);
+end;
+
+constructor TEd25519PhBlake2BSigner.Create(const context: TCryptoLibByteArray);
+begin
+  Inherited Create();
+  FContext := System.Copy(context);
+  FEd25519Blake2BInstance := TEd25519Blake2B.Create();
+  FPreHash := FEd25519Blake2BInstance.CreatePreHash();
+end;
+
+destructor TEd25519PhBlake2BSigner.Destroy;
+begin
+  inherited Destroy;
+end;
+
+function TEd25519PhBlake2BSigner.GetAlgorithmName: String;
+begin
+  Result := 'Ed25519PhBlake2B';
+end;
+
+procedure TEd25519PhBlake2BSigner.Init(forSigning: Boolean;
+  const parameters: ICipherParameters);
+begin
+  FforSigning := forSigning;
+
+  if (forSigning) then
+  begin
+    // TODO Allow IAsymmetricCipherKeyPair to be an ICipherParameters?
+
+    FPrivateKey := parameters as IEd25519Blake2BPrivateKeyParameters;
+    FPublicKey := FPrivateKey.GeneratePublicKey();
+  end
+  else
+  begin
+    FPrivateKey := Nil;
+    FPublicKey := parameters as IEd25519Blake2BPublicKeyParameters;
+  end;
+
+  Reset();
+end;
+
+procedure TEd25519PhBlake2BSigner.Reset;
+begin
+  FPreHash.Reset();
+end;
+
+procedure TEd25519PhBlake2BSigner.Update(b: Byte);
+begin
+  FPreHash.Update(b);
+end;
+
+function TEd25519PhBlake2BSigner.GenerateSignature: TCryptoLibByteArray;
+var
+  signature, msg: TCryptoLibByteArray;
+begin
+  if ((not FforSigning) or (FPrivateKey = Nil)) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes
+      (@SNotInitializedForSigning);
+  end;
+  System.SetLength(msg, TEd25519Blake2B.PreHashSize);
+
+  if ((TEd25519Blake2B.PreHashSize) <> (FPreHash.DoFinal(msg, 0))) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes(@SPreHashDigestFailed);
+  end;
+
+  System.SetLength(signature,
+    TEd25519Blake2BPrivateKeyParameters.SignatureSize);
+
+  FPrivateKey.Sign(TEd25519Blake2B.TEd25519Algorithm.Ed25519Ph, FPublicKey,
+    FContext, msg, 0, TEd25519Blake2B.PreHashSize, signature, 0);
+  Result := signature;
+end;
+
+function TEd25519PhBlake2BSigner.VerifySignature(const signature
+  : TCryptoLibByteArray): Boolean;
+var
+  pk: TCryptoLibByteArray;
+begin
+  if ((FforSigning) or (FPublicKey = Nil)) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes
+      (@SNotInitializedForVerifying);
+  end;
+  pk := FPublicKey.GetEncoded();
+  Result := FEd25519Blake2BInstance.VerifyPrehash(signature, 0, pk, 0, FContext,
+    FPreHash);
+end;
+
+end.

+ 172 - 0
CryptoLib/src/Crypto/Signers/ClpEd25519PhSigner.pas

@@ -0,0 +1,172 @@
+{ *********************************************************************************** }
+{ *                              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 ClpEd25519PhSigner;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIDigest,
+  ClpIEd25519,
+  ClpEd25519,
+  ClpICipherParameters,
+  ClpIEd25519PhSigner,
+  ClpIEd25519PrivateKeyParameters,
+  ClpIEd25519PublicKeyParameters,
+  ClpEd25519PrivateKeyParameters,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SNotInitializedForSigning =
+    'Ed25519PhSigner not Initialised for Signature Generation.';
+  SNotInitializedForVerifying =
+    'Ed25519PhSigner not Initialised for Verification';
+  SPreHashDigestFailed = 'PreHash Digest Failed';
+
+type
+  TEd25519PhSigner = class(TInterfacedObject, IEd25519PhSigner)
+
+  strict private
+  var
+    FPreHash: IDigest;
+    FContext: TCryptoLibByteArray;
+    FforSigning: Boolean;
+    FEd25519Instance: IEd25519;
+    FPrivateKey: IEd25519PrivateKeyParameters;
+    FPublicKey: IEd25519PublicKeyParameters;
+
+  strict protected
+    function GetAlgorithmName: String; virtual;
+
+  public
+    constructor Create(const context: TCryptoLibByteArray);
+    destructor Destroy(); override;
+
+    procedure Init(forSigning: Boolean;
+      const parameters: ICipherParameters); virtual;
+    procedure Update(b: Byte); virtual;
+    procedure BlockUpdate(const buf: TCryptoLibByteArray;
+      off, len: Int32); virtual;
+    function GenerateSignature(): TCryptoLibByteArray; virtual;
+    function VerifySignature(const signature: TCryptoLibByteArray)
+      : Boolean; virtual;
+    procedure Reset(); virtual;
+
+    property AlgorithmName: String read GetAlgorithmName;
+
+  end;
+
+implementation
+
+{ TEd25519PhSigner }
+
+procedure TEd25519PhSigner.BlockUpdate(const buf: TCryptoLibByteArray;
+  off, len: Int32);
+begin
+  FPreHash.BlockUpdate(buf, off, len);
+end;
+
+constructor TEd25519PhSigner.Create(const context: TCryptoLibByteArray);
+begin
+  Inherited Create();
+  FContext := System.Copy(context);
+  FEd25519Instance := TEd25519.Create();
+  FPreHash := FEd25519Instance.CreatePreHash();
+end;
+
+destructor TEd25519PhSigner.Destroy;
+begin
+  inherited Destroy;
+end;
+
+function TEd25519PhSigner.GetAlgorithmName: String;
+begin
+  Result := 'Ed25519Ph';
+end;
+
+procedure TEd25519PhSigner.Init(forSigning: Boolean;
+  const parameters: ICipherParameters);
+begin
+  FforSigning := forSigning;
+
+  if (forSigning) then
+  begin
+    // TODO Allow IAsymmetricCipherKeyPair to be an ICipherParameters?
+
+    FPrivateKey := parameters as IEd25519PrivateKeyParameters;
+    FPublicKey := FPrivateKey.GeneratePublicKey();
+  end
+  else
+  begin
+    FPrivateKey := Nil;
+    FPublicKey := parameters as IEd25519PublicKeyParameters;
+  end;
+
+  Reset();
+end;
+
+procedure TEd25519PhSigner.Reset;
+begin
+  FPreHash.Reset();
+end;
+
+procedure TEd25519PhSigner.Update(b: Byte);
+begin
+  FPreHash.Update(b);
+end;
+
+function TEd25519PhSigner.GenerateSignature: TCryptoLibByteArray;
+var
+  signature, msg: TCryptoLibByteArray;
+begin
+  if ((not FforSigning) or (FPrivateKey = Nil)) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes
+      (@SNotInitializedForSigning);
+  end;
+  System.SetLength(msg, TEd25519.PreHashSize);
+
+  if ((TEd25519.PreHashSize) <> (FPreHash.DoFinal(msg, 0))) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes(@SPreHashDigestFailed);
+  end;
+
+  System.SetLength(signature, TEd25519PrivateKeyParameters.SignatureSize);
+
+  FPrivateKey.Sign(TEd25519.TEd25519Algorithm.Ed25519Ph, FPublicKey, FContext,
+    msg, 0, TEd25519.PreHashSize, signature, 0);
+  Result := signature;
+end;
+
+function TEd25519PhSigner.VerifySignature(const signature
+  : TCryptoLibByteArray): Boolean;
+var
+  pk: TCryptoLibByteArray;
+begin
+  if ((FforSigning) or (FPublicKey = Nil)) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes
+      (@SNotInitializedForVerifying);
+  end;
+  pk := FPublicKey.GetEncoded();
+  Result := FEd25519Instance.VerifyPrehash(signature, 0, pk, 0, FContext,
+    FPreHash);
+end;
+
+end.

+ 181 - 0
CryptoLib/src/Crypto/Signers/ClpEd25519Signer.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 ClpEd25519Signer;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpIEd25519,
+  ClpEd25519,
+  ClpICipherParameters,
+  ClpIEd25519Signer,
+  ClpIEd25519PrivateKeyParameters,
+  ClpIEd25519PublicKeyParameters,
+  ClpEd25519PrivateKeyParameters,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SNotInitializedForSigning =
+    'Ed25519Signer not Initialised for Signature Generation.';
+  SNotInitializedForVerifying =
+    'Ed25519Signer not Initialised for Verification';
+
+type
+  TEd25519Signer = class(TInterfacedObject, IEd25519Signer)
+
+  strict private
+  var
+    FBuffer: TMemoryStream;
+    FforSigning: Boolean;
+    FEd25519Instance: IEd25519;
+    FPrivateKey: IEd25519PrivateKeyParameters;
+    FPublicKey: IEd25519PublicKeyParameters;
+
+    function Aggregate: TCryptoLibByteArray; inline;
+
+  strict protected
+    function GetAlgorithmName: String; virtual;
+
+  public
+    constructor Create();
+    destructor Destroy(); override;
+
+    procedure Init(forSigning: Boolean;
+      const parameters: ICipherParameters); virtual;
+    procedure Update(b: Byte); virtual;
+    procedure BlockUpdate(const buf: TCryptoLibByteArray;
+      off, len: Int32); virtual;
+    function GenerateSignature(): TCryptoLibByteArray; virtual;
+    function VerifySignature(const signature: TCryptoLibByteArray)
+      : Boolean; virtual;
+    procedure Reset(); virtual;
+
+    property AlgorithmName: String read GetAlgorithmName;
+
+  end;
+
+implementation
+
+{ TEd25519Signer }
+
+function TEd25519Signer.Aggregate: TCryptoLibByteArray;
+begin
+  FBuffer.Position := 0;
+  System.SetLength(Result, FBuffer.Size);
+  FBuffer.Read(Result[0], FBuffer.Size);
+end;
+
+procedure TEd25519Signer.BlockUpdate(const buf: TCryptoLibByteArray;
+  off, len: Int32);
+begin
+  FBuffer.Write(buf[off], len);
+end;
+
+constructor TEd25519Signer.Create;
+begin
+  Inherited Create();
+  FBuffer := TMemoryStream.Create();
+  FEd25519Instance := TEd25519.Create();
+end;
+
+destructor TEd25519Signer.Destroy;
+begin
+  FBuffer.Free;
+  inherited Destroy;
+end;
+
+function TEd25519Signer.GetAlgorithmName: String;
+begin
+  Result := 'Ed25519';
+end;
+
+procedure TEd25519Signer.Init(forSigning: Boolean;
+  const parameters: ICipherParameters);
+begin
+  FforSigning := forSigning;
+
+  if (forSigning) then
+  begin
+    // TODO Allow IAsymmetricCipherKeyPair to be an ICipherParameters?
+
+    FPrivateKey := parameters as IEd25519PrivateKeyParameters;
+    FPublicKey := FPrivateKey.GeneratePublicKey();
+  end
+  else
+  begin
+    FPrivateKey := Nil;
+    FPublicKey := parameters as IEd25519PublicKeyParameters;
+  end;
+
+  Reset();
+end;
+
+procedure TEd25519Signer.Reset;
+begin
+  FBuffer.Clear;
+  FBuffer.SetSize(Int64(0));
+end;
+
+procedure TEd25519Signer.Update(b: Byte);
+begin
+  FBuffer.Write(TCryptoLibByteArray.Create(b)[0], 1);
+end;
+
+function TEd25519Signer.GenerateSignature: TCryptoLibByteArray;
+var
+  signature, buf: TCryptoLibByteArray;
+  count: Int32;
+begin
+  if ((not FforSigning) or (FPrivateKey = Nil)) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes
+      (@SNotInitializedForSigning);
+  end;
+
+  System.SetLength(signature, TEd25519PrivateKeyParameters.SignatureSize);
+  buf := Aggregate();
+  count := System.Length(buf);
+
+  FPrivateKey.Sign(TEd25519.TEd25519Algorithm.Ed25519, FPublicKey, Nil, buf, 0,
+    count, signature, 0);
+  Reset();
+  Result := signature;
+end;
+
+function TEd25519Signer.VerifySignature(const signature
+  : TCryptoLibByteArray): Boolean;
+var
+  buf, pk: TCryptoLibByteArray;
+  count: Int32;
+begin
+  if ((FforSigning) or (FPublicKey = Nil)) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes
+      (@SNotInitializedForVerifying);
+  end;
+  pk := FPublicKey.GetEncoded();
+  buf := Aggregate();
+  count := System.Length(buf);
+  Result := FEd25519Instance.Verify(signature, 0, pk, 0, buf, 0, count);
+  Reset();
+end;
+
+end.

+ 97 - 0
CryptoLib/src/Interfaces/ClpIEd25519.pas

@@ -0,0 +1,97 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIEd25519;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIDigest,
+  ClpISecureRandom,
+  ClpCryptoLibTypes;
+
+type
+  IEd25519 = interface(IInterface)
+    ['{2C6CD9DD-8809-44E6-979D-1EBE465CE9E2}']
+
+    function CreatePreHash(): IDigest;
+
+    procedure GeneratePrivateKey(const random: ISecureRandom;
+      const k: TCryptoLibByteArray);
+
+    procedure GeneratePublicKey(const sk: TCryptoLibByteArray; skOff: Int32;
+      pk: TCryptoLibByteArray; pkOff: Int32);
+
+    procedure Sign(const sk: TCryptoLibByteArray; skOff: Int32;
+      const m: TCryptoLibByteArray; mOff, mLen: Int32;
+      const sig: TCryptoLibByteArray; sigOff: Int32); overload;
+
+    procedure Sign(const sk: TCryptoLibByteArray; skOff: Int32;
+      const pk: TCryptoLibByteArray; pkOff: Int32; const m: TCryptoLibByteArray;
+      mOff, mLen: Int32; const sig: TCryptoLibByteArray;
+      sigOff: Int32); overload;
+
+    procedure Sign(const sk: TCryptoLibByteArray; skOff: Int32;
+      const ctx, m: TCryptoLibByteArray; mOff, mLen: Int32;
+      const sig: TCryptoLibByteArray; sigOff: Int32); overload;
+
+    procedure Sign(const sk: TCryptoLibByteArray; skOff: Int32;
+      const pk: TCryptoLibByteArray; pkOff: Int32;
+      const ctx, m: TCryptoLibByteArray; mOff, mLen: Int32;
+      const sig: TCryptoLibByteArray; sigOff: Int32); overload;
+
+    procedure SignPreHash(const sk: TCryptoLibByteArray; skOff: Int32;
+      const ctx, ph: TCryptoLibByteArray; phOff: Int32;
+      const sig: TCryptoLibByteArray; sigOff: Int32); overload;
+
+    procedure SignPreHash(const sk: TCryptoLibByteArray; skOff: Int32;
+      const pk: TCryptoLibByteArray; pkOff: Int32;
+      const ctx, ph: TCryptoLibByteArray; phOff: Int32;
+      const sig: TCryptoLibByteArray; sigOff: Int32); overload;
+
+    procedure SignPreHash(const sk: TCryptoLibByteArray; skOff: Int32;
+      const ctx: TCryptoLibByteArray; const ph: IDigest;
+      const sig: TCryptoLibByteArray; sigOff: Int32); overload;
+
+    procedure SignPreHash(const sk: TCryptoLibByteArray; skOff: Int32;
+      const pk: TCryptoLibByteArray; pkOff: Int32;
+      const ctx: TCryptoLibByteArray; const ph: IDigest;
+      const sig: TCryptoLibByteArray; sigOff: Int32); overload;
+
+    function Verify(const sig: TCryptoLibByteArray; sigOff: Int32;
+      const pk: TCryptoLibByteArray; pkOff: Int32; const m: TCryptoLibByteArray;
+      mOff, mLen: Int32): Boolean; overload;
+
+    function Verify(const sig: TCryptoLibByteArray; sigOff: Int32;
+      const pk: TCryptoLibByteArray; pkOff: Int32;
+      const ctx, m: TCryptoLibByteArray; mOff, mLen: Int32): Boolean; overload;
+
+    function VerifyPreHash(const sig: TCryptoLibByteArray; sigOff: Int32;
+      const pk: TCryptoLibByteArray; pkOff: Int32;
+      const ctx, ph: TCryptoLibByteArray; phOff: Int32): Boolean; overload;
+
+    function VerifyPreHash(const sig: TCryptoLibByteArray; sigOff: Int32;
+      const pk: TCryptoLibByteArray; pkOff: Int32;
+      const ctx: TCryptoLibByteArray; const ph: IDigest): Boolean; overload;
+
+  end;
+
+implementation
+
+end.

+ 35 - 0
CryptoLib/src/Interfaces/ClpIEd25519Blake2B.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 ClpIEd25519Blake2B;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIEd25519;
+
+type
+  IEd25519Blake2B = interface(IEd25519)
+    ['{4EF6C436-D49D-4442-A014-848E08D81BE6}']
+
+  end;
+
+implementation
+
+end.

+ 35 - 0
CryptoLib/src/Interfaces/ClpIEd25519Blake2BKeyGenerationParameters.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 ClpIEd25519Blake2BKeyGenerationParameters;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIKeyGenerationParameters;
+
+type
+  IEd25519Blake2BKeyGenerationParameters = interface(IKeyGenerationParameters)
+    ['{83EED7AC-2214-444D-8411-CD5CDFC32972}']
+
+  end;
+
+implementation
+
+end.

+ 35 - 0
CryptoLib/src/Interfaces/ClpIEd25519Blake2BKeyPairGenerator.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 ClpIEd25519Blake2BKeyPairGenerator;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIEd25519KeyPairGenerator;
+
+type
+  IEd25519Blake2BKeyPairGenerator = interface(IEd25519KeyPairGenerator)
+    ['{1923A01B-2246-4F5B-8BD5-3C78C181029E}']
+
+  end;
+
+implementation
+
+end.

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

@@ -0,0 +1,49 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpIEd25519Blake2BPrivateKeyParameters;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpEd25519,
+  ClpIEd25519Blake2BPublicKeyParameters,
+  ClpIAsymmetricKeyParameter,
+  ClpCryptoLibTypes;
+
+type
+  IEd25519Blake2BPrivateKeyParameters = interface(IAsymmetricKeyParameter)
+    ['{AA0786F9-11D8-4B36-B9AE-A108FE678774}']
+
+    procedure Encode(const buf: TCryptoLibByteArray; off: Int32);
+    function GetEncoded(): TCryptoLibByteArray;
+    function GeneratePublicKey(): IEd25519Blake2BPublicKeyParameters;
+
+    procedure Sign(algorithm: TEd25519.TEd25519Algorithm;
+      const publicKey: IEd25519Blake2BPublicKeyParameters;
+      const ctx, msg: TCryptoLibByteArray; msgOff, msgLen: Int32;
+      const sig: TCryptoLibByteArray; sigOff: Int32);
+
+    function Equals(const other: IEd25519Blake2BPrivateKeyParameters)
+      : Boolean; overload;
+  end;
+
+implementation
+
+end.

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

@@ -0,0 +1,41 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpIEd25519Blake2BPublicKeyParameters;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIAsymmetricKeyParameter,
+  ClpCryptoLibTypes;
+
+type
+  IEd25519Blake2BPublicKeyParameters = interface(IAsymmetricKeyParameter)
+    ['{54BC984B-F087-463C-AB06-BCB8C61D9770}']
+
+    procedure Encode(const buf: TCryptoLibByteArray; off: Int32);
+    function GetEncoded(): TCryptoLibByteArray;
+
+    function Equals(const other: IEd25519Blake2BPublicKeyParameters)
+      : Boolean; overload;
+  end;
+
+implementation
+
+end.

+ 36 - 0
CryptoLib/src/Interfaces/ClpIEd25519Blake2BSigner.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 ClpIEd25519Blake2BSigner;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpISigner;
+
+type
+  IEd25519Blake2BSigner = interface(ISigner)
+
+    ['{3BF234D8-550D-4505-9C55-2C93733DCE30}']
+
+  end;
+
+implementation
+
+end.

+ 36 - 0
CryptoLib/src/Interfaces/ClpIEd25519CtxBlake2BSigner.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 ClpIEd25519CtxBlake2BSigner;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpISigner;
+
+type
+  IEd25519CtxBlake2BSigner = interface(ISigner)
+
+    ['{E3138C67-743D-4772-BF30-63D398AE4D2D}']
+
+  end;
+
+implementation
+
+end.

+ 36 - 0
CryptoLib/src/Interfaces/ClpIEd25519CtxSigner.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 ClpIEd25519CtxSigner;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpISigner;
+
+type
+  IEd25519CtxSigner = interface(ISigner)
+
+    ['{EF0302AE-A4FE-46B8-8839-8B7450EE977B}']
+
+  end;
+
+implementation
+
+end.

+ 35 - 0
CryptoLib/src/Interfaces/ClpIEd25519KeyGenerationParameters.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 ClpIEd25519KeyGenerationParameters;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIKeyGenerationParameters;
+
+type
+  IEd25519KeyGenerationParameters = interface(IKeyGenerationParameters)
+    ['{65D7E76D-588F-4499-BE57-ADA4273C68B9}']
+
+  end;
+
+implementation
+
+end.

+ 35 - 0
CryptoLib/src/Interfaces/ClpIEd25519KeyPairGenerator.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 ClpIEd25519KeyPairGenerator;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIAsymmetricCipherKeyPairGenerator;
+
+type
+  IEd25519KeyPairGenerator = interface(IAsymmetricCipherKeyPairGenerator)
+    ['{7A9A2591-E1F0-4D41-8DB3-8D56822B5AF0}']
+
+  end;
+
+implementation
+
+end.

+ 36 - 0
CryptoLib/src/Interfaces/ClpIEd25519PhBlake2BSigner.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 ClpIEd25519PhBlake2BSigner;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpISigner;
+
+type
+  IEd25519PhBlake2BSigner = interface(ISigner)
+
+    ['{C51DD3EF-C78A-4C0A-993E-F1B4BA414875}']
+
+  end;
+
+implementation
+
+end.

+ 36 - 0
CryptoLib/src/Interfaces/ClpIEd25519PhSigner.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 ClpIEd25519PhSigner;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpISigner;
+
+type
+  IEd25519PhSigner = interface(ISigner)
+
+    ['{7E2EBA92-1D10-474D-8342-2ED64D0DACE5}']
+
+  end;
+
+implementation
+
+end.

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

@@ -0,0 +1,49 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpIEd25519PrivateKeyParameters;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpEd25519,
+  ClpIEd25519PublicKeyParameters,
+  ClpIAsymmetricKeyParameter,
+  ClpCryptoLibTypes;
+
+type
+  IEd25519PrivateKeyParameters = interface(IAsymmetricKeyParameter)
+    ['{03CF8E9D-F462-4C77-B954-2519E31E625F}']
+
+    procedure Encode(const buf: TCryptoLibByteArray; off: Int32);
+    function GetEncoded(): TCryptoLibByteArray;
+    function GeneratePublicKey(): IEd25519PublicKeyParameters;
+
+    procedure Sign(algorithm: TEd25519.TEd25519Algorithm;
+      const publicKey: IEd25519PublicKeyParameters;
+      const ctx, msg: TCryptoLibByteArray; msgOff, msgLen: Int32;
+      const sig: TCryptoLibByteArray; sigOff: Int32);
+
+    function Equals(const other: IEd25519PrivateKeyParameters)
+      : Boolean; overload;
+  end;
+
+implementation
+
+end.

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

@@ -0,0 +1,41 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpIEd25519PublicKeyParameters;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIAsymmetricKeyParameter,
+  ClpCryptoLibTypes;
+
+type
+  IEd25519PublicKeyParameters = interface(IAsymmetricKeyParameter)
+    ['{84C0E096-F4BA-438D-9E20-3ECFAE341E63}']
+
+    procedure Encode(const buf: TCryptoLibByteArray; off: Int32);
+    function GetEncoded(): TCryptoLibByteArray;
+
+    function Equals(const other: IEd25519PublicKeyParameters): Boolean;
+      overload;
+  end;
+
+implementation
+
+end.

+ 36 - 0
CryptoLib/src/Interfaces/ClpIEd25519Signer.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 ClpIEd25519Signer;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpISigner;
+
+type
+  IEd25519Signer = interface(ISigner)
+
+    ['{A7DC401C-ABF9-4615-AEB0-705B278DBEB9}']
+
+  end;
+
+implementation
+
+end.

+ 43 - 0
CryptoLib/src/Interfaces/ClpIRawAgreement.pas

@@ -0,0 +1,43 @@
+{ *********************************************************************************** }
+{ *                              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 ClpIRawAgreement;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpICipherParameters,
+  ClpCryptoLibTypes;
+
+type
+  IRawAgreement = interface(IInterface)
+    ['{B3C55CE5-1F35-4C77-8CDB-757C07DBF4AA}']
+
+    procedure Init(const parameters: ICipherParameters);
+
+    function GetAgreementSize(): Int32;
+    property AgreementSize: Int32 read GetAgreementSize;
+
+    procedure CalculateAgreement(const publicKey: ICipherParameters;
+      const buf: TCryptoLibByteArray; off: Int32);
+  end;
+
+implementation
+
+end.

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

@@ -0,0 +1,37 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpIX25519Agreement;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIRawAgreement;
+
+type
+
+  IX25519Agreement = interface(IRawAgreement)
+
+    ['{5561516C-4BC6-4D97-BF1A-FBC35A3B7A03}']
+
+  end;
+
+implementation
+
+end.

+ 35 - 0
CryptoLib/src/Interfaces/ClpIX25519KeyGenerationParameters.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 ClpIX25519KeyGenerationParameters;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIKeyGenerationParameters;
+
+type
+  IX25519KeyGenerationParameters = interface(IKeyGenerationParameters)
+    ['{BDDAF238-C842-4449-A7B8-3A537E405A62}']
+
+  end;
+
+implementation
+
+end.

+ 35 - 0
CryptoLib/src/Interfaces/ClpIX25519KeyPairGenerator.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 ClpIX25519KeyPairGenerator;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIAsymmetricCipherKeyPairGenerator;
+
+type
+  IX25519KeyPairGenerator = interface(IAsymmetricCipherKeyPairGenerator)
+    ['{EC906E22-1587-4E06-85D0-697368365F97}']
+
+  end;
+
+implementation
+
+end.

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

@@ -0,0 +1,45 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpIX25519PrivateKeyParameters;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIX25519PublicKeyParameters,
+  ClpIAsymmetricKeyParameter,
+  ClpCryptoLibTypes;
+
+type
+  IX25519PrivateKeyParameters = interface(IAsymmetricKeyParameter)
+    ['{6C7D2CD5-33A1-4153-A84C-70455CA69729}']
+
+    procedure Encode(const buf: TCryptoLibByteArray; off: Int32);
+    function GetEncoded(): TCryptoLibByteArray;
+    function GeneratePublicKey(): IX25519PublicKeyParameters;
+    procedure GenerateSecret(const publicKey: IX25519PublicKeyParameters;
+      const buf: TCryptoLibByteArray; off: Int32);
+
+    function Equals(const other: IX25519PrivateKeyParameters): Boolean;
+      overload;
+  end;
+
+implementation
+
+end.

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

@@ -0,0 +1,40 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpIX25519PublicKeyParameters;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIAsymmetricKeyParameter,
+  ClpCryptoLibTypes;
+
+type
+  IX25519PublicKeyParameters = interface(IAsymmetricKeyParameter)
+    ['{52D136C4-4DD1-4AF1-9AB8-0783136EF04A}']
+
+    procedure Encode(const buf: TCryptoLibByteArray; off: Int32);
+    function GetEncoded(): TCryptoLibByteArray;
+
+    function Equals(const other: IX25519PublicKeyParameters): Boolean; overload;
+  end;
+
+implementation
+
+end.

+ 230 - 0
CryptoLib/src/Math/EC/Rfc7748/ClpX25519.pas

@@ -0,0 +1,230 @@
+unit ClpX25519;
+
+interface
+
+uses
+  ClpISecureRandom,
+  ClpX25519Field,
+  ClpEd25519,
+  ClpArrayUtils,
+  ClpConverters,
+  ClpCryptoLibTypes;
+
+type
+  TX25519 = class sealed(TObject)
+  strict private
+  const
+    C_A = Int32(486662);
+    C_A24 = Int32((C_A + 2) div 4);
+
+  public
+
+    const
+    PointSize = Int32(32);
+    ScalarSize = Int32(32);
+
+    class function CalculateAgreement(const k: TCryptoLibByteArray; kOff: Int32;
+      const u: TCryptoLibByteArray; uOff: Int32; const r: TCryptoLibByteArray;
+      rOff: Int32): Boolean; static; inline;
+
+    class function Decode32(const bs: TCryptoLibByteArray; off: Int32): UInt32;
+      static; inline;
+
+    class procedure DecodeScalar(const k: TCryptoLibByteArray; kOff: Int32;
+      const n: TCryptoLibUInt32Array); static; inline;
+
+    class procedure GeneratePrivateKey(const random: ISecureRandom;
+      const k: TCryptoLibByteArray); static; inline;
+
+    class procedure GeneratePublicKey(const k: TCryptoLibByteArray; kOff: Int32;
+      r: TCryptoLibByteArray; rOff: Int32); static; inline;
+
+    class procedure PointDouble(const x, z: TCryptoLibInt32Array); static;
+
+    class procedure Precompute(); static;
+
+    class procedure ScalarMult(const k: TCryptoLibByteArray; kOff: Int32;
+      const u: TCryptoLibByteArray; uOff: Int32; const r: TCryptoLibByteArray;
+      rOff: Int32); static;
+
+    class procedure ScalarMultBase(const k: TCryptoLibByteArray; kOff: Int32;
+      const r: TCryptoLibByteArray; rOff: Int32); static;
+
+  end;
+
+implementation
+
+{ TX25519 }
+
+class function TX25519.CalculateAgreement(const k: TCryptoLibByteArray;
+  kOff: Int32; const u: TCryptoLibByteArray; uOff: Int32;
+  const r: TCryptoLibByteArray; rOff: Int32): Boolean;
+begin
+  ScalarMult(k, kOff, u, uOff, r, rOff);
+  result := not TArrayUtils.AreAllZeroes(r, rOff, PointSize);
+end;
+
+class function TX25519.Decode32(const bs: TCryptoLibByteArray;
+  off: Int32): UInt32;
+begin
+  // UInt32 n := bs[off];
+  // System.Inc(off);
+  // n := n or (UInt32(bs[off]) shl 8);
+  // System.Inc(off);
+  // n := n or (UInt32(bs[off]) shl 16);
+  // System.Inc(off);
+  // n := n or (UInt32(bs[off]) shl 24);
+  // result := n;
+  result := TConverters.ReadBytesAsUInt32LE(PByte(bs), off);
+end;
+
+class procedure TX25519.DecodeScalar(const k: TCryptoLibByteArray; kOff: Int32;
+  const n: TCryptoLibUInt32Array);
+var
+  i: Int32;
+begin
+  for i := 0 to System.Pred(8) do
+  begin
+    n[i] := Decode32(k, kOff + i * 4);
+  end;
+
+  n[0] := n[0] and UInt32($FFFFFFF8);
+  n[7] := n[7] and UInt32($7FFFFFFF);
+  n[7] := n[7] or UInt32($40000000);
+end;
+
+class procedure TX25519.GeneratePrivateKey(const random: ISecureRandom;
+  const k: TCryptoLibByteArray);
+begin
+  random.NextBytes(k);
+
+  k[0] := k[0] and $F8;
+  k[ScalarSize - 1] := k[ScalarSize - 1] and $7F;
+  k[ScalarSize - 1] := k[ScalarSize - 1] or $40;
+end;
+
+class procedure TX25519.GeneratePublicKey(const k: TCryptoLibByteArray;
+  kOff: Int32; r: TCryptoLibByteArray; rOff: Int32);
+begin
+  ScalarMultBase(k, kOff, r, rOff);
+end;
+
+class procedure TX25519.PointDouble(const x, z: TCryptoLibInt32Array);
+var
+  A, B: TCryptoLibInt32Array;
+begin
+  A := TX25519Field.Create();
+  B := TX25519Field.Create();
+
+  TX25519Field.Apm(x, z, A, B);
+  TX25519Field.Sqr(A, A);
+  TX25519Field.Sqr(B, B);
+  TX25519Field.Mul(A, B, x);
+  TX25519Field.Sub(A, B, A);
+  TX25519Field.Mul(A, C_A24, z);
+  TX25519Field.Add(z, B, z);
+  TX25519Field.Mul(z, A, z);
+end;
+
+class procedure TX25519.Precompute;
+begin
+  TEd25519.Precompute();
+end;
+
+class procedure TX25519.ScalarMult(const k: TCryptoLibByteArray; kOff: Int32;
+  const u: TCryptoLibByteArray; uOff: Int32; const r: TCryptoLibByteArray;
+  rOff: Int32);
+var
+  n: TCryptoLibUInt32Array;
+  x1, x2, z2, x3, z3, t1, t2: TCryptoLibInt32Array;
+  bit, swap, word, shift, kt, i: Int32;
+begin
+  System.SetLength(n, 8);
+  DecodeScalar(k, kOff, n);
+
+  x1 := TX25519Field.Create();
+  TX25519Field.Decode(u, uOff, x1);
+  x2 := TX25519Field.Create();
+  TX25519Field.Copy(x1, 0, x2, 0);
+  z2 := TX25519Field.Create();
+  z2[0] := 1;
+  x3 := TX25519Field.Create();
+  x3[0] := 1;
+  z3 := TX25519Field.Create();
+
+  t1 := TX25519Field.Create();
+  t2 := TX25519Field.Create();
+
+{$IFDEF DEBUG}
+  System.Assert((n[7] shr 30) = UInt32(1));
+{$ENDIF DEBUG}
+  bit := 254;
+  swap := 1;
+  repeat
+    TX25519Field.Apm(x3, z3, t1, x3);
+    TX25519Field.Apm(x2, z2, z3, x2);
+    TX25519Field.Mul(t1, x2, t1);
+    TX25519Field.Mul(x3, z3, x3);
+    TX25519Field.Sqr(z3, z3);
+    TX25519Field.Sqr(x2, x2);
+
+    TX25519Field.Sub(z3, x2, t2);
+    TX25519Field.Mul(t2, C_A24, z2);
+    TX25519Field.Add(z2, x2, z2);
+    TX25519Field.Mul(z2, t2, z2);
+    TX25519Field.Mul(x2, z3, x2);
+
+    TX25519Field.Apm(t1, x3, x3, z3);
+    TX25519Field.Sqr(x3, x3);
+    TX25519Field.Sqr(z3, z3);
+    TX25519Field.Mul(z3, x1, z3);
+
+    System.Dec(bit);
+
+    word := bit shr 5;
+    shift := bit and $1F;
+    kt := Int32(n[word] shr shift) and 1;
+    swap := swap xor kt;
+    TX25519Field.CSwap(swap, x2, x3);
+    TX25519Field.CSwap(swap, z2, z3);
+    swap := kt;
+
+  until (bit < 3);
+
+{$IFDEF DEBUG}
+  System.Assert(swap = 0);
+{$ENDIF DEBUG}
+  i := 0;
+  while i < 3 do
+  begin
+    PointDouble(x2, z2);
+    System.Inc(i);
+  end;
+
+  TX25519Field.Inv(z2, z2);
+  TX25519Field.Mul(x2, z2, x2);
+
+  TX25519Field.Normalize(x2);
+  TX25519Field.Encode(x2, r, rOff);
+end;
+
+class procedure TX25519.ScalarMultBase(const k: TCryptoLibByteArray;
+  kOff: Int32; const r: TCryptoLibByteArray; rOff: Int32);
+var
+  y, z: TCryptoLibInt32Array;
+begin
+  y := TX25519Field.Create();
+  z := TX25519Field.Create();
+
+  TEd25519.ScalarMultBaseYZ(k, kOff, y, z);
+
+  TX25519Field.Apm(z, y, y, z);
+
+  TX25519Field.Inv(z, z);
+  TX25519Field.Mul(y, z, y);
+
+  TX25519Field.Normalize(y);
+  TX25519Field.Encode(y, r, rOff);
+end;
+
+end.

+ 924 - 0
CryptoLib/src/Math/EC/Rfc7748/ClpX25519Field.pas

@@ -0,0 +1,924 @@
+{ *********************************************************************************** }
+{ *                              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 ClpX25519Field;
+
+{$I ..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpBits,
+  ClpConverters,
+  ClpCryptoLibTypes;
+
+type
+  TX25519Field = class sealed(TObject)
+
+  strict private
+
+  const
+    M24 = Int32($00FFFFFF);
+    M25 = Int32($01FFFFFF);
+    M26 = Int32($03FFFFFF);
+
+    class var
+
+      FRootNegOne: TCryptoLibInt32Array;
+
+    class procedure Decode128(const bs: TCryptoLibByteArray; off: Int32;
+      const z: TCryptoLibInt32Array; zOff: Int32); static; inline;
+
+    class function Decode32(const bs: TCryptoLibByteArray; off: Int32): UInt32;
+      static; inline;
+
+    class procedure Encode32(n: UInt32; const bs: TCryptoLibByteArray;
+      off: Int32); static; inline;
+
+    class procedure Encode128(const x: TCryptoLibInt32Array; xOff: Int32;
+      const bs: TCryptoLibByteArray; off: Int32); static; inline;
+
+    class procedure PowPm5d8(const x, rx2, rz: TCryptoLibInt32Array); static;
+
+    class procedure Reduce(const z: TCryptoLibInt32Array; c: Int32); static;
+
+    class procedure Boot(); static;
+    class constructor X25519Field();
+
+  public
+
+    const
+    Size = Int32(10);
+
+    class procedure Add(const x, y, z: TCryptoLibInt32Array); static; inline;
+
+    class procedure AddOne(const z: TCryptoLibInt32Array); overload;
+      static; inline;
+
+    class procedure AddOne(const z: TCryptoLibInt32Array; zOff: Int32);
+      overload; static; inline;
+
+    class procedure Apm(const x, y, zp, zm: TCryptoLibInt32Array);
+      static; inline;
+
+    class procedure Carry(const z: TCryptoLibInt32Array); static;
+
+    class procedure CNegate(ANegate: Int32; const z: TCryptoLibInt32Array);
+      static; inline;
+
+    class procedure Copy(const x: TCryptoLibInt32Array; xOff: Int32;
+      const z: TCryptoLibInt32Array; zOff: Int32); static; inline;
+
+    class function Create(): TCryptoLibInt32Array; static; inline;
+
+    class function CreateTable(n: Int32): TCryptoLibInt32Array; static; inline;
+
+    class procedure CSwap(swap: Int32;
+      const a, b: TCryptoLibInt32Array); static;
+
+    class procedure Decode(const x: TCryptoLibByteArray; xOff: Int32;
+      const z: TCryptoLibInt32Array); static; inline;
+
+    class procedure Encode(const x: TCryptoLibInt32Array;
+      const z: TCryptoLibByteArray; zOff: Int32); static; inline;
+
+    class procedure Inv(const x, z: TCryptoLibInt32Array); static; inline;
+
+    class function IsZeroVar(const x: TCryptoLibInt32Array): Boolean;
+      static; inline;
+
+    class procedure Mul(const x: TCryptoLibInt32Array; y: Int32;
+      const z: TCryptoLibInt32Array); overload; static;
+
+    class procedure Mul(const x, y, z: TCryptoLibInt32Array); overload; static;
+
+    class procedure Negate(const x, z: TCryptoLibInt32Array); static; inline;
+
+    class procedure Normalize(const z: TCryptoLibInt32Array); static; inline;
+
+    class procedure One(const z: TCryptoLibInt32Array); static; inline;
+
+    class procedure Sqr(const x, z: TCryptoLibInt32Array); overload; static;
+
+    class procedure Sqr(const x: TCryptoLibInt32Array; n: Int32;
+      const z: TCryptoLibInt32Array); overload; static;
+
+    class function SqrtRatioVar(const u, v, z: TCryptoLibInt32Array)
+      : Boolean; static;
+
+    class procedure Sub(const x, y, z: TCryptoLibInt32Array); static; inline;
+
+    class procedure SubOne(const z: TCryptoLibInt32Array); static; inline;
+
+    class procedure Zero(const z: TCryptoLibInt32Array); static; inline;
+
+  end;
+
+implementation
+
+{ TX25519Field }
+
+class procedure TX25519Field.Boot;
+begin
+  FRootNegOne := TCryptoLibInt32Array.Create($020EA0B0, $0386C9D2, $00478C4E,
+    $0035697F, $005E8630, $01FBD7A7, $0340264F, $01F0B2B4, $00027E0E,
+    $00570649);
+end;
+
+class constructor TX25519Field.X25519Field;
+begin
+  TX25519Field.Boot();
+end;
+
+class procedure TX25519Field.Add(const x, y, z: TCryptoLibInt32Array);
+var
+  i: Int32;
+begin
+  for i := 0 to System.Pred(Size) do
+  begin
+    z[i] := x[i] + y[i];
+  end;
+end;
+
+class procedure TX25519Field.AddOne(const z: TCryptoLibInt32Array);
+begin
+  z[0] := z[0] + 1;
+end;
+
+class procedure TX25519Field.AddOne(const z: TCryptoLibInt32Array; zOff: Int32);
+begin
+  z[zOff] := z[zOff] + 1;
+end;
+
+class procedure TX25519Field.Apm(const x, y, zp, zm: TCryptoLibInt32Array);
+var
+  i, xi, yi: Int32;
+begin
+  for i := 0 to System.Pred(Size) do
+  begin
+    xi := x[i];
+    yi := y[i];
+    zp[i] := xi + yi;
+    zm[i] := xi - yi;
+  end;
+end;
+
+class procedure TX25519Field.Carry(const z: TCryptoLibInt32Array);
+var
+  z0, z1, z2, z3, z4, z5, z6, z7, z8, z9: Int32;
+begin
+  z0 := z[0];
+  z1 := z[1];
+  z2 := z[2];
+  z3 := z[3];
+  z4 := z[4];
+  z5 := z[5];
+  z6 := z[6];
+  z7 := z[7];
+  z8 := z[8];
+  z9 := z[9];
+
+  z3 := z3 + TBits.Asr32(z2, 25);
+  z2 := z2 and M25;
+  z5 := z5 + TBits.Asr32(z4, 25);
+  z4 := z4 and M25;
+  z8 := z8 + TBits.Asr32(z7, 25);
+  z7 := z7 and M25;
+  // z0 := z0 + (z9 shr 24) * 19; z9 := z9 and M24;
+  z0 := z0 + (TBits.Asr32(z9, 25) * 38);
+  z9 := z9 and M25;
+
+  z1 := z1 + TBits.Asr32(z0, 26);
+  z0 := z0 and M26;
+  z6 := z6 + TBits.Asr32(z5, 26);
+  z5 := z5 and M26;
+
+  z2 := z2 + TBits.Asr32(z1, 26);
+  z1 := z1 and M26;
+  z4 := z4 + TBits.Asr32(z3, 26);
+  z3 := z3 and M26;
+  z7 := z7 + TBits.Asr32(z6, 26);
+  z6 := z6 and M26;
+  z9 := z9 + TBits.Asr32(z8, 26);
+  z8 := z8 and M26;
+
+  z[0] := z0;
+  z[1] := z1;
+  z[2] := z2;
+  z[3] := z3;
+  z[4] := z4;
+  z[5] := z5;
+  z[6] := z6;
+  z[7] := z7;
+  z[8] := z8;
+  z[9] := z9;
+end;
+
+class procedure TX25519Field.CNegate(ANegate: Int32;
+  const z: TCryptoLibInt32Array);
+var
+  mask, i: Int32;
+begin
+{$IFDEF DEBUG}
+  System.Assert(TBits.Asr32(ANegate, 1) = 0);
+{$ENDIF DEBUG}
+  mask := 0 - ANegate;
+  for i := 0 to System.Pred(Size) do
+  begin
+    z[i] := (z[i] xor mask) - mask;
+  end;
+end;
+
+class procedure TX25519Field.Copy(const x: TCryptoLibInt32Array; xOff: Int32;
+  const z: TCryptoLibInt32Array; zOff: Int32);
+var
+  i: Int32;
+begin
+  for i := 0 to System.Pred(Size) do
+  begin
+    z[zOff + i] := x[xOff + i];
+  end;
+end;
+
+class function TX25519Field.Create: TCryptoLibInt32Array;
+begin
+  System.SetLength(Result, Size);
+end;
+
+class function TX25519Field.CreateTable(n: Int32): TCryptoLibInt32Array;
+begin
+  System.SetLength(Result, Size * n);
+end;
+
+class procedure TX25519Field.CSwap(swap: Int32;
+  const a, b: TCryptoLibInt32Array);
+var
+  mask, i, ai, bi, dummy: Int32;
+begin
+{$IFDEF DEBUG}
+  System.Assert(TBits.Asr32(swap, 1) = 0);
+  System.Assert(a <> b);
+{$ENDIF DEBUG}
+  mask := 0 - swap;
+  for i := 0 to System.Pred(Size) do
+  begin
+    ai := a[i];
+    bi := b[i];
+    dummy := mask and (ai xor bi);
+    a[i] := ai xor dummy;
+    b[i] := bi xor dummy;
+  end;
+end;
+
+class function TX25519Field.Decode32(const bs: TCryptoLibByteArray;
+  off: Int32): UInt32;
+begin
+  // UInt32 n := bs[off];
+  // System.Inc(off);
+  // n := n or (UInt32(bs[off]) shl 8);
+  // System.Inc(off);
+  // n := n or (UInt32(bs[off]) shl 16);
+  // System.Inc(off);
+  // n := n or (UInt32(bs[off]) shl 24);
+  // result := n;
+  Result := TConverters.ReadBytesAsUInt32LE(PByte(bs), off);
+end;
+
+class procedure TX25519Field.Decode128(const bs: TCryptoLibByteArray;
+  off: Int32; const z: TCryptoLibInt32Array; zOff: Int32);
+var
+  t0, t1, t2, t3: UInt32;
+begin
+  t0 := Decode32(bs, off + 0);
+  t1 := Decode32(bs, off + 4);
+  t2 := Decode32(bs, off + 8);
+  t3 := Decode32(bs, off + 12);
+
+  z[zOff + 0] := Int32(t0 and M26);
+  z[zOff + 1] := Int32((t1 shl 6) or (t0 shr 26)) and M26;
+  z[zOff + 2] := Int32((t2 shl 12) or (t1 shr 20)) and M25;
+  z[zOff + 3] := Int32((t3 shl 19) or (t2 shr 13)) and M26;
+  z[zOff + 4] := Int32(t3 shr 7);
+end;
+
+class procedure TX25519Field.Decode(const x: TCryptoLibByteArray; xOff: Int32;
+  const z: TCryptoLibInt32Array);
+begin
+  Decode128(x, xOff, z, 0);
+  Decode128(x, xOff + 16, z, 5);
+  z[9] := z[9] and M24;
+end;
+
+class procedure TX25519Field.Encode32(n: UInt32; const bs: TCryptoLibByteArray;
+  off: Int32);
+begin
+  // bs[  off] := Byte(n      );
+  // System.Inc(off);
+  // bs[off] := Byte(n shr  8);
+  // System.Inc(off);
+  // bs[off] := Byte(n shr  16);
+  // System.Inc(off);
+  // bs[off] := Byte(n shr  24);
+  TConverters.ReadUInt32AsBytesLE(n, bs, off);
+end;
+
+class procedure TX25519Field.Encode128(const x: TCryptoLibInt32Array;
+  xOff: Int32; const bs: TCryptoLibByteArray; off: Int32);
+var
+  x0, x1, x2, x3, x4, t0, t1, t2, t3: UInt32;
+begin
+  x0 := UInt32(x[xOff + 0]);
+  x1 := UInt32(x[xOff + 1]);
+  x2 := UInt32(x[xOff + 2]);
+  x3 := UInt32(x[xOff + 3]);
+  x4 := UInt32(x[xOff + 4]);
+
+  t0 := x0 or (x1 shl 26);
+  Encode32(t0, bs, off + 0);
+  t1 := (x1 shr 6) or (x2 shl 20);
+  Encode32(t1, bs, off + 4);
+  t2 := (x2 shr 12) or (x3 shl 13);
+  Encode32(t2, bs, off + 8);
+  t3 := (x3 shr 19) or (x4 shl 7);
+  Encode32(t3, bs, off + 12);
+end;
+
+class procedure TX25519Field.Encode(const x: TCryptoLibInt32Array;
+  const z: TCryptoLibByteArray; zOff: Int32);
+begin
+  Encode128(x, 0, z, zOff);
+  Encode128(x, 5, z, zOff + 16);
+end;
+
+class procedure TX25519Field.Inv(const x, z: TCryptoLibInt32Array);
+var
+  x2, t: TCryptoLibInt32Array;
+begin
+  // z = x^(p-2) = x^7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEB
+  // (250 1s) (1 0s) (1 1s) (1 0s) (2 1s)
+  // Addition chain: [1] [2] 3 5 10 15 25 50 75 125 [250]
+
+  x2 := Create();
+  t := Create();
+  PowPm5d8(x, x2, t);
+  Sqr(t, 3, t);
+  Mul(t, x2, z);
+end;
+
+class function TX25519Field.IsZeroVar(const x: TCryptoLibInt32Array): Boolean;
+var
+  d, i: Int32;
+begin
+  d := 0;
+  for i := 0 to System.Pred(Size) do
+  begin
+    d := d or x[i];
+  end;
+  Result := d = 0;
+end;
+
+class procedure TX25519Field.Mul(const x: TCryptoLibInt32Array; y: Int32;
+  const z: TCryptoLibInt32Array);
+var
+  x0, x1, x2, x3, x4, x5, x6, x7, x8, x9: Int32;
+  c0, c1, c2, c3: Int64;
+begin
+  x0 := x[0];
+  x1 := x[1];
+  x2 := x[2];
+  x3 := x[3];
+  x4 := x[4];
+  x5 := x[5];
+  x6 := x[6];
+  x7 := x[7];
+  x8 := x[8];
+  x9 := x[9];
+
+  c0 := Int64(x2) * y;
+  x2 := Int32(c0) and M25;
+  c0 := TBits.Asr64(c0, 25);
+  c1 := Int64(x4) * y;
+  x4 := Int32(c1) and M25;
+  c1 := TBits.Asr64(c1, 25);
+  c2 := Int64(x7) * y;
+  x7 := Int32(c2) and M25;
+  c2 := TBits.Asr64(c2, 25);
+  // c3 := Int64(x9) * y; x9 := Int32(c3) and M24; c3 := TBits.Asr64(c3 , 24);
+  // c3 := c3 * 19;
+  c3 := Int64(x9) * y;
+  x9 := Int32(c3) and M25;
+  c3 := TBits.Asr64(c3, 25);
+  c3 := c3 * 38;
+
+  c3 := c3 + (Int64(x0) * y);
+  z[0] := Int32(c3) and M26;
+  c3 := TBits.Asr64(c3, 26);
+  c1 := c1 + (Int64(x5) * y);
+  z[5] := Int32(c1) and M26;
+  c1 := TBits.Asr64(c1, 26);
+
+  c3 := c3 + (Int64(x1) * y);
+  z[1] := Int32(c3) and M26;
+  c3 := TBits.Asr64(c3, 26);
+  c0 := c0 + (Int64(x3) * y);
+  z[3] := Int32(c0) and M26;
+  c0 := TBits.Asr64(c0, 26);
+  c1 := c1 + (Int64(x6) * y);
+  z[6] := Int32(c1) and M26;
+  c1 := TBits.Asr64(c1, 26);
+  c2 := c2 + (Int64(x8) * y);
+  z[8] := Int32(c2) and M26;
+  c2 := TBits.Asr64(c2, 26);
+
+  z[2] := x2 + Int32(c3);
+  z[4] := x4 + Int32(c0);
+  z[7] := x7 + Int32(c1);
+  z[9] := x9 + Int32(c2);
+end;
+
+class procedure TX25519Field.Mul(const x, y, z: TCryptoLibInt32Array);
+var
+  x0, x1, x2, x3, x4, y0, y1, y2, y3, y4, u0, u1, u2, u3, u4, z8, z9: Int32;
+  a0, a1, a2, a3, a4, a5, a6, a7, a8, b0, b1, b2, b3, b4, b5, b6, b7, b8, c0,
+    c1, c2, c3, c4, c5, c6, c7, c8, v0, v1, v2, v3, v4, t: Int64;
+begin
+  x0 := x[0];
+  y0 := y[0];
+  x1 := x[1];
+  y1 := y[1];
+  x2 := x[2];
+  y2 := y[2];
+  x3 := x[3];
+  y3 := y[3];
+  x4 := x[4];
+  y4 := y[4];
+
+  u0 := x[5];
+  v0 := y[5];
+  u1 := x[6];
+  v1 := y[6];
+  u2 := x[7];
+  v2 := y[7];
+  u3 := x[8];
+  v3 := y[8];
+  u4 := x[9];
+  v4 := y[9];
+
+  a0 := Int64(x0) * y0;
+  a1 := Int64(x0) * y1 + Int64(x1) * y0;
+  a2 := Int64(x0) * y2 + Int64(x1) * y1 + Int64(x2) * y0;
+  a3 := Int64(x1) * y2 + Int64(x2) * y1;
+  a3 := a3 shl 1;
+  a3 := a3 + (Int64(x0) * y3 + Int64(x3) * y0);
+  a4 := Int64(x2) * y2;
+  a4 := a4 shl 1;
+  a4 := a4 + (Int64(x0) * y4 + Int64(x1) * y3 + Int64(x3) * y1 +
+    Int64(x4) * y0);
+  a5 := Int64(x1) * y4 + Int64(x2) * y3 + Int64(x3) * y2 + Int64(x4) * y1;
+  a5 := a5 shl 1;
+  a6 := Int64(x2) * y4 + Int64(x4) * y2;
+  a6 := a6 shl 1;
+  a6 := a6 + (Int64(x3) * y3);
+  a7 := Int64(x3) * y4 + Int64(x4) * y3;
+  a8 := Int64(x4) * y4;
+  a8 := a8 shl 1;
+
+  b0 := Int64(u0) * v0;
+  b1 := Int64(u0) * v1 + Int64(u1) * v0;
+  b2 := Int64(u0) * v2 + Int64(u1) * v1 + Int64(u2) * v0;
+  b3 := Int64(u1) * v2 + Int64(u2) * v1;
+  b3 := b3 shl 1;
+  b3 := b3 + (Int64(u0) * v3 + Int64(u3) * v0);
+  b4 := Int64(u2) * v2;
+  b4 := b4 shl 1;
+  b4 := b4 + (Int64(u0) * v4 + Int64(u1) * v3 + Int64(u3) * v1 +
+    Int64(u4) * v0);
+  b5 := Int64(u1) * v4 + Int64(u2) * v3 + Int64(u3) * v2 + Int64(u4) * v1;
+  // b5     := b5 shl 1;
+  b6 := Int64(u2) * v4 + Int64(u4) * v2;
+  b6 := b6 shl 1;
+  b6 := b6 + (Int64(u3) * v3);
+  b7 := Int64(u3) * v4 + Int64(u4) * v3;
+  b8 := Int64(u4) * v4;
+  // b8     := b8 shl 1;
+
+  a0 := a0 - (b5 * 76);
+  a1 := a1 - (b6 * 38);
+  a2 := a2 - (b7 * 38);
+  a3 := a3 - (b8 * 76);
+
+  a5 := a5 - b0;
+  a6 := a6 - b1;
+  a7 := a7 - b2;
+  a8 := a8 - b3;
+  // a9 := -b4;
+
+  x0 := x0 + u0;
+  y0 := y0 + v0;
+  x1 := x1 + u1;
+  y1 := y1 + v1;
+  x2 := x2 + u2;
+  y2 := y2 + v2;
+  x3 := x3 + u3;
+  y3 := y3 + v3;
+  x4 := x4 + u4;
+  y4 := y4 + v4;
+
+  c0 := Int64(x0) * y0;
+  c1 := Int64(x0) * y1 + Int64(x1) * y0;
+  c2 := Int64(x0) * y2 + Int64(x1) * y1 + Int64(x2) * y0;
+  c3 := Int64(x1) * y2 + Int64(x2) * y1;
+  c3 := c3 shl 1;
+  c3 := c3 + (Int64(x0) * y3 + Int64(x3) * y0);
+  c4 := Int64(x2) * y2;
+  c4 := c4 shl 1;
+  c4 := c4 + (Int64(x0) * y4 + Int64(x1) * y3 + Int64(x3) * y1 +
+    Int64(x4) * y0);
+  c5 := Int64(x1) * y4 + Int64(x2) * y3 + Int64(x3) * y2 + Int64(x4) * y1;
+  c5 := c5 shl 1;
+  c6 := Int64(x2) * y4 + Int64(x4) * y2;
+  c6 := c6 shl 1;
+  c6 := c6 + (Int64(x3) * y3);
+  c7 := Int64(x3) * y4 + Int64(x4) * y3;
+  c8 := Int64(x4) * y4;
+  c8 := c8 shl 1;
+
+  t := a8 + (c3 - a3);
+  z8 := Int32(t) and M26;
+  t := TBits.Asr64(t, 26);
+  // t       := t + (a9 + (c4 - a4));
+  t := t + ((c4 - a4) - b4);
+  // z9       := Int32(t) and M24; t := TBits.Asr64(t , 24);
+  // t        := a0 + (t + ((c5 - a5) shl 1)) * 19;
+  z9 := Int32(t) and M25;
+  t := TBits.Asr64(t, 25);
+  t := a0 + (t + c5 - a5) * 38;
+  z[0] := Int32(t) and M26;
+  t := TBits.Asr64(t, 26);
+  t := t + (a1 + (c6 - a6) * 38);
+  z[1] := Int32(t) and M26;
+  t := TBits.Asr64(t, 26);
+  t := t + (a2 + (c7 - a7) * 38);
+  z[2] := Int32(t) and M25;
+  t := TBits.Asr64(t, 25);
+  t := t + (a3 + (c8 - a8) * 38);
+  z[3] := Int32(t) and M26;
+  t := TBits.Asr64(t, 26);
+  // t       := t + (a4 - (a9 * 38));
+  t := t + (a4 + b4 * 38);
+  z[4] := Int32(t) and M25;
+  t := TBits.Asr64(t, 25);
+  t := t + (a5 + (c0 - a0));
+  z[5] := Int32(t) and M26;
+  t := TBits.Asr64(t, 26);
+  t := t + (a6 + (c1 - a1));
+  z[6] := Int32(t) and M26;
+  t := TBits.Asr64(t, 26);
+  t := t + (a7 + (c2 - a2));
+  z[7] := Int32(t) and M25;
+  t := TBits.Asr64(t, 25);
+  t := t + z8;
+  z[8] := Int32(t) and M26;
+  t := TBits.Asr64(t, 26);
+  z[9] := z9 + Int32(t);
+end;
+
+class procedure TX25519Field.Negate(const x, z: TCryptoLibInt32Array);
+var
+  i: Int32;
+begin
+  for i := 0 to System.Pred(Size) do
+  begin
+    z[i] := -x[i];
+  end;
+end;
+
+class procedure TX25519Field.Normalize(const z: TCryptoLibInt32Array);
+var
+  x: Int32;
+begin
+  x := TBits.Asr32(z[9], 23) and 1;
+  Reduce(z, x);
+  Reduce(z, -x);
+{$IFDEF DEBUG}
+  System.Assert(TBits.Asr32(z[9], 24) = 0);
+{$ENDIF DEBUG}
+end;
+
+class procedure TX25519Field.One(const z: TCryptoLibInt32Array);
+var
+  i: Int32;
+begin
+  z[0] := 1;
+  for i := 1 to System.Pred(Size) do
+  begin
+    z[i] := 0;
+  end;
+end;
+
+class procedure TX25519Field.PowPm5d8(const x, rx2, rz: TCryptoLibInt32Array);
+var
+  x2, x3, x5, x10, x15, x25, x50, x75, x125, x250, t: TCryptoLibInt32Array;
+begin
+  // z = x^((p-5)/8) = x^FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD
+  // (250 1s) (1 0s) (1 1s)
+  // Addition chain: [1] 2 3 5 10 15 25 50 75 125 [250]
+
+  x2 := rx2;
+  Sqr(x, x2);
+  Mul(x, x2, x2);
+  x3 := Create();
+  Sqr(x2, x3);
+  Mul(x, x3, x3);
+  x5 := x3;
+  Sqr(x3, 2, x5);
+  Mul(x2, x5, x5);
+  x10 := Create();
+  Sqr(x5, 5, x10);
+  Mul(x5, x10, x10);
+  x15 := Create();
+  Sqr(x10, 5, x15);
+  Mul(x5, x15, x15);
+  x25 := x5;
+  Sqr(x15, 10, x25);
+  Mul(x10, x25, x25);
+  x50 := x10;
+  Sqr(x25, 25, x50);
+  Mul(x25, x50, x50);
+  x75 := x15;
+  Sqr(x50, 25, x75);
+  Mul(x25, x75, x75);
+  x125 := x25;
+  Sqr(x75, 50, x125);
+  Mul(x50, x125, x125);
+  x250 := x50;
+  Sqr(x125, 125, x250);
+  Mul(x125, x250, x250);
+
+  t := x125;
+  Sqr(x250, 2, t);
+  Mul(t, x, rz);
+end;
+
+class procedure TX25519Field.Reduce(const z: TCryptoLibInt32Array; c: Int32);
+var
+  z9, t: Int32;
+begin
+  z9 := z[9];
+  t := z9;
+  z9 := t and M24;
+  t := TBits.Asr32(t, 24);
+  t := t + c;
+  t := t * 19;
+  t := t + z[0];
+  z[0] := t and M26;
+  t := TBits.Asr32(t, 26);
+  t := t + z[1];
+  z[1] := t and M26;
+  t := TBits.Asr32(t, 26);
+  t := t + z[2];
+  z[2] := t and M25;
+  t := TBits.Asr32(t, 25);
+  t := t + z[3];
+  z[3] := t and M26;
+  t := TBits.Asr32(t, 26);
+  t := t + z[4];
+  z[4] := t and M25;
+  t := TBits.Asr32(t, 25);
+  t := t + z[5];
+  z[5] := t and M26;
+  t := TBits.Asr32(t, 26);
+  t := t + z[6];
+  z[6] := t and M26;
+  t := TBits.Asr32(t, 26);
+  t := t + z[7];
+  z[7] := t and M25;
+  t := TBits.Asr32(t, 25);
+  t := t + z[8];
+  z[8] := t and M26;
+  t := TBits.Asr32(t, 26);
+  t := t + z9;
+  z[9] := t;
+end;
+
+class procedure TX25519Field.Sqr(const x, z: TCryptoLibInt32Array);
+var
+  x0, x1, x2, x3, x4, u0, u1, u2, u3, u4, x1_2, x2_2, x3_2, x4_2, u1_2, u2_2,
+    u3_2, u4_2, z8, z9: Int32;
+  a0, a1, a2, a3, a4, a5, a6, a7, a8, b0, b1, b2, b3, b4, b5, b6, b7, b8, c0,
+    c1, c2, c3, c4, c5, c6, c7, c8, t: Int64;
+begin
+  x0 := x[0];
+  x1 := x[1];
+  x2 := x[2];
+  x3 := x[3];
+  x4 := x[4];
+
+  u0 := x[5];
+  u1 := x[6];
+  u2 := x[7];
+  u3 := x[8];
+  u4 := x[9];
+
+  x1_2 := x1 * 2;
+  x2_2 := x2 * 2;
+  x3_2 := x3 * 2;
+  x4_2 := x4 * 2;
+
+  a0 := Int64(x0) * x0;
+  a1 := Int64(x0) * x1_2;
+  a2 := Int64(x0) * x2_2 + Int64(x1) * x1;
+  a3 := Int64(x1_2) * x2_2 + Int64(x0) * x3_2;
+  a4 := Int64(x2) * x2_2 + Int64(x0) * x4_2 + Int64(x1) * x3_2;
+  a5 := Int64(x1_2) * x4_2 + Int64(x2_2) * x3_2;
+  a6 := Int64(x2_2) * x4_2 + Int64(x3) * x3;
+  a7 := Int64(x3) * x4_2;
+  a8 := Int64(x4) * x4_2;
+
+  u1_2 := u1 * 2;
+  u2_2 := u2 * 2;
+  u3_2 := u3 * 2;
+  u4_2 := u4 * 2;
+
+  b0 := Int64(u0) * u0;
+  b1 := Int64(u0) * u1_2;
+  b2 := Int64(u0) * u2_2 + Int64(u1) * u1;
+  b3 := Int64(u1_2) * u2_2 + Int64(u0) * u3_2;
+  b4 := Int64(u2) * u2_2 + Int64(u0) * u4_2 + Int64(u1) * u3_2;
+  b5 := Int64(u1_2) * u4_2 + Int64(u2_2) * u3_2;
+  b6 := Int64(u2_2) * u4_2 + Int64(u3) * u3;
+  b7 := Int64(u3) * u4_2;
+  b8 := Int64(u4) * u4_2;
+
+  a0 := a0 - (b5 * 38);
+  a1 := a1 - (b6 * 38);
+  a2 := a2 - (b7 * 38);
+  a3 := a3 - (b8 * 38);
+
+  a5 := a5 - b0;
+  a6 := a6 - b1;
+  a7 := a7 - b2;
+  a8 := a8 - b3;
+  // Int64 a9 = -b4;
+
+  x0 := x0 + u0;
+  x1 := x1 + u1;
+  x2 := x2 + u2;
+  x3 := x3 + u3;
+  x4 := x4 + u4;
+
+  x1_2 := x1 * 2;
+  x2_2 := x2 * 2;
+  x3_2 := x3 * 2;
+  x4_2 := x4 * 2;
+
+  c0 := Int64(x0) * x0;
+  c1 := Int64(x0) * x1_2;
+  c2 := Int64(x0) * x2_2 + Int64(x1) * x1;
+  c3 := Int64(x1_2) * x2_2 + Int64(x0) * x3_2;
+  c4 := Int64(x2) * x2_2 + Int64(x0) * x4_2 + Int64(x1) * x3_2;
+  c5 := Int64(x1_2) * x4_2 + Int64(x2_2) * x3_2;
+  c6 := Int64(x2_2) * x4_2 + Int64(x3) * x3;
+  c7 := Int64(x3) * x4_2;
+  c8 := Int64(x4) * x4_2;
+
+  t := a8 + (c3 - a3);
+  z8 := Int32(t) and M26;
+  t := TBits.Asr64(t, 26);
+  // t  = t + (a9 + (c4 - a4));
+  t := t + ((c4 - a4) - b4);
+  // z9  := Int32(t) and M24; t := TBits.Asr64(t , 24);
+  // t  := a0 + (t + ((c5 - a5) shl 1)) * 19;
+  z9 := Int32(t) and M25;
+  t := TBits.Asr64(t, 25);
+  t := a0 + (t + c5 - a5) * 38;
+  z[0] := Int32(t) and M26;
+  t := TBits.Asr64(t, 26);
+  t := t + (a1 + (c6 - a6) * 38);
+  z[1] := Int32(t) and M26;
+  t := TBits.Asr64(t, 26);
+  t := t + (a2 + (c7 - a7) * 38);
+  z[2] := Int32(t) and M25;
+  t := TBits.Asr64(t, 25);
+  t := t + (a3 + (c8 - a8) * 38);
+  z[3] := Int32(t) and M26;
+  t := TBits.Asr64(t, 26);
+  // t       := t + (a4 - a9 * 38);
+  t := t + (a4 + b4 * 38);
+  z[4] := Int32(t) and M25;
+  t := TBits.Asr64(t, 25);
+  t := t + (a5 + (c0 - a0));
+  z[5] := Int32(t) and M26;
+  t := TBits.Asr64(t, 26);
+  t := t + (a6 + (c1 - a1));
+  z[6] := Int32(t) and M26;
+  t := TBits.Asr64(t, 26);
+  t := t + (a7 + (c2 - a2));
+  z[7] := Int32(t) and M25;
+  t := TBits.Asr64(t, 25);
+  t := t + z8;
+  z[8] := Int32(t) and M26;
+  t := TBits.Asr64(t, 26);
+  z[9] := z9 + Int32(t);
+end;
+
+class procedure TX25519Field.Sqr(const x: TCryptoLibInt32Array; n: Int32;
+  const z: TCryptoLibInt32Array);
+begin
+{$IFDEF DEBUG}
+  System.Assert(n > 0);
+{$ENDIF DEBUG}
+  Sqr(x, z);
+  System.Dec(n);
+
+  while (n > 0) do
+  begin
+    Sqr(z, z);
+    System.Dec(n);
+  end;
+end;
+
+class procedure TX25519Field.Sub(const x, y, z: TCryptoLibInt32Array);
+var
+  i: Int32;
+begin
+  for i := 0 to System.Pred(Size) do
+  begin
+    z[i] := x[i] - y[i];
+  end;
+end;
+
+class procedure TX25519Field.SubOne(const z: TCryptoLibInt32Array);
+begin
+  z[0] := z[0] - 1;
+end;
+
+class function TX25519Field.SqrtRatioVar(const u, v,
+  z: TCryptoLibInt32Array): Boolean;
+var
+  uv3, uv7, t, x, vx2: TCryptoLibInt32Array;
+begin
+  uv3 := Create();
+  uv7 := Create();
+
+  Mul(u, v, uv3);
+  Sqr(v, uv7);
+  Mul(uv3, uv7, uv3);
+  Sqr(uv7, uv7);
+  Mul(uv7, uv3, uv7);
+
+  t := Create();
+  x := Create();
+  PowPm5d8(uv7, t, x);
+  Mul(x, uv3, x);
+
+  vx2 := Create();
+  Sqr(x, vx2);
+  Mul(vx2, v, vx2);
+
+  Sub(vx2, u, t);
+  Normalize(t);
+  if (IsZeroVar(t)) then
+  begin
+    Copy(x, 0, z, 0);
+    Result := true;
+    Exit;
+  end;
+
+  Add(vx2, u, t);
+  Normalize(t);
+  if (IsZeroVar(t)) then
+  begin
+    Mul(x, FRootNegOne, z);
+    Result := true;
+    Exit;
+  end;
+
+  Result := false;
+end;
+
+class procedure TX25519Field.Zero(const z: TCryptoLibInt32Array);
+var
+  i: Int32;
+begin
+  for i := 0 to System.Pred(Size) do
+  begin
+    z[i] := 0;
+  end;
+end;
+
+end.

+ 1946 - 0
CryptoLib/src/Math/EC/Rfc8032/ClpEd25519.pas

@@ -0,0 +1,1946 @@
+{ *********************************************************************************** }
+{ *                              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 ClpEd25519;
+
+{$I ..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SyncObjs,
+  ClpNat,
+  ClpBits,
+  ClpNat256,
+  ClpInterleave,
+  ClpDigestUtilities,
+  ClpISecureRandom,
+  ClpIDigest,
+  ClpIEd25519,
+  ClpX25519Field,
+  ClpConverters,
+  ClpArrayUtils,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SInvalidCtx = 'ctx';
+  SDigestError = 'Digest Produced Insufficient Data';
+
+type
+  TEd25519 = class(TInterfacedObject, IEd25519)
+
+  strict private
+
+  type
+    IPointAccum = interface(IInterface)
+      ['{8A257C67-674F-4F62-B937-4E83B46CAF36}']
+      function GetX: TCryptoLibInt32Array;
+      procedure SetX(const value: TCryptoLibInt32Array);
+      property X: TCryptoLibInt32Array read GetX write SetX;
+
+      function GetY: TCryptoLibInt32Array;
+      procedure SetY(const value: TCryptoLibInt32Array);
+      property Y: TCryptoLibInt32Array read GetY write SetY;
+
+      function GetZ: TCryptoLibInt32Array;
+      procedure SetZ(const value: TCryptoLibInt32Array);
+      property Z: TCryptoLibInt32Array read GetZ write SetZ;
+
+      function GetU: TCryptoLibInt32Array;
+      procedure SetU(const value: TCryptoLibInt32Array);
+      property U: TCryptoLibInt32Array read GetU write SetU;
+
+      function GetV: TCryptoLibInt32Array;
+      procedure SetV(const value: TCryptoLibInt32Array);
+      property V: TCryptoLibInt32Array read GetV write SetV;
+
+    end;
+
+  type
+    TPointAccum = class sealed(TInterfacedObject, IPointAccum)
+    private
+      Fx, Fy, Fz, Fu, Fv: TCryptoLibInt32Array;
+
+      function GetX: TCryptoLibInt32Array; inline;
+      procedure SetX(const value: TCryptoLibInt32Array); inline;
+      function GetY: TCryptoLibInt32Array; inline;
+      procedure SetY(const value: TCryptoLibInt32Array); inline;
+      function GetZ: TCryptoLibInt32Array; inline;
+      procedure SetZ(const value: TCryptoLibInt32Array); inline;
+      function GetU: TCryptoLibInt32Array; inline;
+      procedure SetU(const value: TCryptoLibInt32Array); inline;
+      function GetV: TCryptoLibInt32Array; inline;
+      procedure SetV(const value: TCryptoLibInt32Array); inline;
+
+    public
+      property X: TCryptoLibInt32Array read GetX write SetX;
+      property Y: TCryptoLibInt32Array read GetY write SetY;
+      property Z: TCryptoLibInt32Array read GetZ write SetZ;
+      property U: TCryptoLibInt32Array read GetU write SetU;
+      property V: TCryptoLibInt32Array read GetV write SetV;
+
+      constructor Create();
+    end;
+
+  type
+    IPointExt = interface(IInterface)
+      ['{20C8CC66-D9E6-4626-B09D-BC500223F103}']
+      function GetX: TCryptoLibInt32Array;
+      procedure SetX(const value: TCryptoLibInt32Array);
+      property X: TCryptoLibInt32Array read GetX write SetX;
+
+      function GetY: TCryptoLibInt32Array;
+      procedure SetY(const value: TCryptoLibInt32Array);
+      property Y: TCryptoLibInt32Array read GetY write SetY;
+
+      function GetZ: TCryptoLibInt32Array;
+      procedure SetZ(const value: TCryptoLibInt32Array);
+      property Z: TCryptoLibInt32Array read GetZ write SetZ;
+
+      function GetT: TCryptoLibInt32Array;
+      procedure SetT(const value: TCryptoLibInt32Array);
+      property T: TCryptoLibInt32Array read GetT write SetT;
+
+    end;
+
+  type
+    TPointExt = class sealed(TInterfacedObject, IPointExt)
+    private
+      Fx, Fy, Fz, Ft: TCryptoLibInt32Array;
+
+      function GetX: TCryptoLibInt32Array; inline;
+      procedure SetX(const value: TCryptoLibInt32Array); inline;
+      function GetY: TCryptoLibInt32Array; inline;
+      procedure SetY(const value: TCryptoLibInt32Array); inline;
+      function GetZ: TCryptoLibInt32Array; inline;
+      procedure SetZ(const value: TCryptoLibInt32Array); inline;
+      function GetT: TCryptoLibInt32Array; inline;
+      procedure SetT(const value: TCryptoLibInt32Array); inline;
+
+    public
+      property X: TCryptoLibInt32Array read GetX write SetX;
+      property Y: TCryptoLibInt32Array read GetY write SetY;
+      property Z: TCryptoLibInt32Array read GetZ write SetZ;
+      property T: TCryptoLibInt32Array read GetT write SetT;
+
+      constructor Create();
+    end;
+
+  type
+    IPointPrecomp = interface(IInterface)
+      ['{9EADAD66-FE44-4A1E-8458-3AE7D2AF14C2}']
+      function GetYpx_h: TCryptoLibInt32Array;
+      procedure SetYpx_h(const value: TCryptoLibInt32Array);
+      property Ypx_h: TCryptoLibInt32Array read GetYpx_h write SetYpx_h;
+      function GetYmx_h: TCryptoLibInt32Array;
+      procedure SetYmx_h(const value: TCryptoLibInt32Array);
+      property Ymx_h: TCryptoLibInt32Array read GetYmx_h write SetYmx_h;
+      function GetXyd: TCryptoLibInt32Array;
+      procedure SetXyd(const value: TCryptoLibInt32Array);
+      property Xyd: TCryptoLibInt32Array read GetXyd write SetXyd;
+
+    end;
+
+  type
+    TPointPrecomp = class sealed(TInterfacedObject, IPointPrecomp)
+    private
+      Fypx_h, Fymx_h, Fxyd: TCryptoLibInt32Array;
+
+      function GetYpx_h: TCryptoLibInt32Array; inline;
+      procedure SetYpx_h(const value: TCryptoLibInt32Array); inline;
+      function GetYmx_h: TCryptoLibInt32Array; inline;
+      procedure SetYmx_h(const value: TCryptoLibInt32Array); inline;
+      function GetXyd: TCryptoLibInt32Array; inline;
+      procedure SetXyd(const value: TCryptoLibInt32Array); inline;
+
+    public
+      property Ypx_h: TCryptoLibInt32Array read GetYpx_h write SetYpx_h;
+      property Ymx_h: TCryptoLibInt32Array read GetYmx_h write SetYmx_h;
+      property Xyd: TCryptoLibInt32Array read GetXyd write SetXyd;
+
+      constructor Create();
+    end;
+
+  const
+    M28L = Int64($0FFFFFFF);
+    M32L = Int64($FFFFFFFF);
+
+    PointBytes = Int32(32);
+    ScalarUints = Int32(8);
+    ScalarBytes = Int32(ScalarUints * 4);
+
+    L0 = Int32($FCF5D3ED); // L0:26/--
+    L1 = Int32($012631A6); // L1:24/22
+    L2 = Int32($079CD658); // L2:27/--
+    L3 = Int32($FF9DEA2F); // L3:23/--
+    L4 = Int32($000014DF); // L4:12/11
+
+    WnafWidthBase = Int32(7);
+
+    PrecompBlocks = Int32(8);
+    PrecompTeeth = Int32(4);
+    PrecompSpacing = Int32(8);
+    PrecompPoints = Int32(1 shl (PrecompTeeth - 1));
+    PrecompMask = Int32(PrecompPoints - 1);
+
+  class var
+
+    FDom2Prefix: TCryptoLibByteArray;
+    FP, FL: TCryptoLibUInt32Array;
+    FB_x, FB_y, FC_d, FC_d2, FC_d4: TCryptoLibInt32Array;
+    FPrecompLock: TCriticalSection;
+    // TODO[ed25519] Convert to PointPrecomp
+    FPrecompBaseTable: TCryptoLibGenericArray<IPointExt>;
+    FPrecompBase: TCryptoLibInt32Array;
+
+    class function CalculateS(const r, k, s: TCryptoLibByteArray)
+      : TCryptoLibByteArray; static;
+
+    class function CheckContextVar(const ctx: TCryptoLibCustomByteArrayBuffer;
+      phflag: Byte): Boolean; static; inline;
+
+    class function CheckPointVar(const p: TCryptoLibByteArray): Boolean;
+      static; inline;
+
+    class function CheckScalarVar(const s: TCryptoLibByteArray): Boolean;
+      static; inline;
+
+    class function Decode24(const bs: TCryptoLibByteArray; off: Int32): UInt32;
+      static; inline;
+
+    class function Decode32(const bs: TCryptoLibByteArray; off: Int32): UInt32;
+      overload; static; inline;
+
+    class procedure Decode32(const bs: TCryptoLibByteArray; bsOff: Int32;
+      const n: TCryptoLibUInt32Array; nOff, nLen: Int32); overload;
+      static; inline;
+
+    class function DecodePointVar(const p: TCryptoLibByteArray; pOff: Int32;
+      ANegate: Boolean; const r: IPointExt): Boolean; static;
+
+    class procedure DecodeScalar(const k: TCryptoLibByteArray; kOff: Int32;
+      const n: TCryptoLibUInt32Array); static; inline;
+
+    class procedure Dom2(const d: IDigest; phflag: Byte;
+      const ctx: TCryptoLibCustomByteArrayBuffer); static; inline;
+
+    class procedure Encode24(n: UInt32; const bs: TCryptoLibByteArray;
+      off: Int32); static; inline;
+
+    class procedure Encode32(n: UInt32; const bs: TCryptoLibByteArray;
+      off: Int32); static; inline;
+
+    class procedure Encode56(n: UInt64; const bs: TCryptoLibByteArray;
+      off: Int32); static; inline;
+
+    class procedure EncodePoint(const p: IPointAccum;
+      const r: TCryptoLibByteArray; rOff: Int32); static;
+
+    class function GetWnaf(const n: TCryptoLibUInt32Array; width: Int32)
+      : TCryptoLibShortIntArray; static;
+
+    class procedure ImplSign(const d: IDigest;
+      const h, s, pk: TCryptoLibByteArray; pkOff: Int32;
+      const ctx: TCryptoLibCustomByteArrayBuffer; phflag: Byte;
+      const m: TCryptoLibByteArray; mOff, mLen: Int32;
+      const sig: TCryptoLibByteArray; sigOff: Int32); overload; static;
+
+    procedure ImplSign(const sk: TCryptoLibByteArray; skOff: Int32;
+      const ctx: TCryptoLibCustomByteArrayBuffer; phflag: Byte;
+      const m: TCryptoLibByteArray; mOff: Int32; mLen: Int32;
+      const sig: TCryptoLibByteArray; sigOff: Int32); overload;
+
+    procedure ImplSign(const sk: TCryptoLibByteArray; skOff: Int32;
+      const pk: TCryptoLibByteArray; pkOff: Int32;
+      const ctx: TCryptoLibCustomByteArrayBuffer; phflag: Byte;
+      const m: TCryptoLibByteArray; mOff: Int32; mLen: Int32;
+      const sig: TCryptoLibByteArray; sigOff: Int32); overload;
+
+    function ImplVerify(const sig: TCryptoLibByteArray; sigOff: Int32;
+      const pk: TCryptoLibByteArray; pkOff: Int32;
+      const ctx: TCryptoLibCustomByteArrayBuffer; phflag: Byte;
+      const m: TCryptoLibByteArray; mOff, mLen: Int32): Boolean;
+
+    class procedure PointAddVar(negate: Boolean; const p: IPointExt;
+      const r: IPointAccum); overload; static;
+
+    class procedure PointAddVar(negate: Boolean; const p, q, r: IPointExt);
+      overload; static;
+
+    class procedure PointAddPrecomp(const p: IPointPrecomp;
+      const r: IPointAccum); overload; static;
+
+    class function PointCopy(const p: IPointAccum): IPointExt; overload;
+      static; inline;
+
+    class function PointCopy(const p: IPointExt): IPointExt; overload;
+      static; inline;
+
+    class procedure PointDouble(const r: IPointAccum); static;
+
+    class procedure PointExtendXY(const p: IPointAccum); overload;
+      static; inline;
+
+    class procedure PointExtendXY(const p: IPointExt); overload; static; inline;
+
+    class procedure PointLookup(block, index: Int32;
+      const p: IPointPrecomp); static;
+
+    class function PointPrecompVar(const p: IPointExt; count: Int32)
+      : TCryptoLibGenericArray<IPointExt>; static;
+
+    class procedure PointSetNeutral(const p: IPointAccum); overload;
+      static; inline;
+
+    class procedure PointSetNeutral(const p: IPointExt); overload;
+      static; inline;
+
+    class procedure PruneScalar(const n: TCryptoLibByteArray; nOff: Int32;
+      const r: TCryptoLibByteArray); static; inline;
+
+    class function ReduceScalar(const n: TCryptoLibByteArray)
+      : TCryptoLibByteArray; static;
+
+    class procedure ScalarMultBase(const k: TCryptoLibByteArray;
+      const r: IPointAccum); static;
+
+    class procedure ScalarMultBaseEncoded(const k, r: TCryptoLibByteArray;
+      rOff: Int32); static; inline;
+
+    class procedure ScalarMultStraussVar(const nb, np: TCryptoLibUInt32Array;
+      const p: IPointExt; const r: IPointAccum); static;
+
+    class function ValidateDigestOutputSize(const ADigest: IDigest)
+      : TCryptoLibByteArray; static; inline;
+
+    class function ConstructCustomByteArrayBufferContext
+      (const AData: TCryptoLibByteArray; AIsNil: Boolean; ALength: Int32)
+      : TCryptoLibCustomByteArrayBuffer; static; inline;
+
+    class procedure Boot(); static;
+    class constructor CreateEd25519();
+    class destructor DestroyEd25519();
+
+  strict protected
+
+    function CreateDigest(): IDigest; virtual;
+
+  public
+
+    const
+    PreHashSize = Int32(64);
+    PublicKeySize = Int32(PointBytes);
+    SecretKeySize = Int32(32);
+    SignatureSize = Int32(PointBytes + ScalarBytes);
+
+  type
+{$SCOPEDENUMS ON}
+    TEd25519Algorithm = (Ed25519 = 0, Ed25519ctx = 1, Ed25519ph = 2);
+{$SCOPEDENUMS OFF}
+  constructor Create();
+
+  function CreatePreHash(): IDigest; inline;
+
+  procedure GeneratePrivateKey(const random: ISecureRandom;
+    const k: TCryptoLibByteArray); inline;
+
+  procedure GeneratePublicKey(const sk: TCryptoLibByteArray; skOff: Int32;
+    pk: TCryptoLibByteArray; pkOff: Int32);
+
+  class procedure Precompute(); static;
+
+  class procedure ScalarMultBaseYZ(const k: TCryptoLibByteArray; kOff: Int32;
+    const Y, Z: TCryptoLibInt32Array); static; inline;
+
+  procedure Sign(const sk: TCryptoLibByteArray; skOff: Int32;
+    const m: TCryptoLibByteArray; mOff, mLen: Int32;
+    const sig: TCryptoLibByteArray; sigOff: Int32); overload;
+
+  procedure Sign(const sk: TCryptoLibByteArray; skOff: Int32;
+    const pk: TCryptoLibByteArray; pkOff: Int32; const m: TCryptoLibByteArray;
+    mOff, mLen: Int32; const sig: TCryptoLibByteArray; sigOff: Int32); overload;
+
+  procedure Sign(const sk: TCryptoLibByteArray; skOff: Int32;
+    const ctx, m: TCryptoLibByteArray; mOff, mLen: Int32;
+    const sig: TCryptoLibByteArray; sigOff: Int32); overload;
+
+  procedure Sign(const sk: TCryptoLibByteArray; skOff: Int32;
+    const pk: TCryptoLibByteArray; pkOff: Int32;
+    const ctx, m: TCryptoLibByteArray; mOff, mLen: Int32;
+    const sig: TCryptoLibByteArray; sigOff: Int32); overload;
+
+  procedure SignPreHash(const sk: TCryptoLibByteArray; skOff: Int32;
+    const ctx, ph: TCryptoLibByteArray; phOff: Int32;
+    const sig: TCryptoLibByteArray; sigOff: Int32); overload;
+
+  procedure SignPreHash(const sk: TCryptoLibByteArray; skOff: Int32;
+    const pk: TCryptoLibByteArray; pkOff: Int32;
+    const ctx, ph: TCryptoLibByteArray; phOff: Int32;
+    const sig: TCryptoLibByteArray; sigOff: Int32); overload;
+
+  procedure SignPreHash(const sk: TCryptoLibByteArray; skOff: Int32;
+    const ctx: TCryptoLibByteArray; const ph: IDigest;
+    const sig: TCryptoLibByteArray; sigOff: Int32); overload;
+
+  procedure SignPreHash(const sk: TCryptoLibByteArray; skOff: Int32;
+    const pk: TCryptoLibByteArray; pkOff: Int32; const ctx: TCryptoLibByteArray;
+    const ph: IDigest; const sig: TCryptoLibByteArray; sigOff: Int32); overload;
+
+  function Verify(const sig: TCryptoLibByteArray; sigOff: Int32;
+    const pk: TCryptoLibByteArray; pkOff: Int32; const m: TCryptoLibByteArray;
+    mOff, mLen: Int32): Boolean; overload;
+
+  function Verify(const sig: TCryptoLibByteArray; sigOff: Int32;
+    const pk: TCryptoLibByteArray; pkOff: Int32;
+    const ctx, m: TCryptoLibByteArray; mOff, mLen: Int32): Boolean; overload;
+
+  function VerifyPreHash(const sig: TCryptoLibByteArray; sigOff: Int32;
+    const pk: TCryptoLibByteArray; pkOff: Int32;
+    const ctx, ph: TCryptoLibByteArray; phOff: Int32): Boolean; overload;
+
+  function VerifyPreHash(const sig: TCryptoLibByteArray; sigOff: Int32;
+    const pk: TCryptoLibByteArray; pkOff: Int32; const ctx: TCryptoLibByteArray;
+    const ph: IDigest): Boolean; overload;
+
+  end;
+
+implementation
+
+{ TEd25519.TPointExt }
+
+constructor TEd25519.TPointExt.Create;
+begin
+  Inherited Create();
+  Fx := TX25519Field.Create();
+  Fy := TX25519Field.Create();
+  Fz := TX25519Field.Create();
+  Ft := TX25519Field.Create();
+end;
+
+function TEd25519.TPointExt.GetT: TCryptoLibInt32Array;
+begin
+  result := Ft;
+end;
+
+function TEd25519.TPointExt.GetX: TCryptoLibInt32Array;
+begin
+  result := Fx;
+end;
+
+function TEd25519.TPointExt.GetY: TCryptoLibInt32Array;
+begin
+  result := Fy;
+end;
+
+function TEd25519.TPointExt.GetZ: TCryptoLibInt32Array;
+begin
+  result := Fz;
+end;
+
+procedure TEd25519.TPointExt.SetT(const value: TCryptoLibInt32Array);
+begin
+  Ft := value;
+end;
+
+procedure TEd25519.TPointExt.SetX(const value: TCryptoLibInt32Array);
+begin
+  Fx := value;
+end;
+
+procedure TEd25519.TPointExt.SetY(const value: TCryptoLibInt32Array);
+begin
+  Fy := value;
+end;
+
+procedure TEd25519.TPointExt.SetZ(const value: TCryptoLibInt32Array);
+begin
+  Fz := value;
+end;
+
+{ TEd25519.TPointAccum }
+
+constructor TEd25519.TPointAccum.Create;
+begin
+  Inherited Create();
+  Fx := TX25519Field.Create();
+  Fy := TX25519Field.Create();
+  Fz := TX25519Field.Create();
+  Fu := TX25519Field.Create();
+  Fv := TX25519Field.Create();
+end;
+
+function TEd25519.TPointAccum.GetU: TCryptoLibInt32Array;
+begin
+  result := Fu;
+end;
+
+function TEd25519.TPointAccum.GetV: TCryptoLibInt32Array;
+begin
+  result := Fv;
+end;
+
+function TEd25519.TPointAccum.GetX: TCryptoLibInt32Array;
+begin
+  result := Fx;
+end;
+
+function TEd25519.TPointAccum.GetY: TCryptoLibInt32Array;
+begin
+  result := Fy;
+end;
+
+function TEd25519.TPointAccum.GetZ: TCryptoLibInt32Array;
+begin
+  result := Fz;
+end;
+
+procedure TEd25519.TPointAccum.SetU(const value: TCryptoLibInt32Array);
+begin
+  Fu := value;
+end;
+
+procedure TEd25519.TPointAccum.SetV(const value: TCryptoLibInt32Array);
+begin
+  Fv := value;
+end;
+
+procedure TEd25519.TPointAccum.SetX(const value: TCryptoLibInt32Array);
+begin
+  Fx := value;
+end;
+
+procedure TEd25519.TPointAccum.SetY(const value: TCryptoLibInt32Array);
+begin
+  Fy := value;
+end;
+
+procedure TEd25519.TPointAccum.SetZ(const value: TCryptoLibInt32Array);
+begin
+  Fz := value;
+end;
+
+{ TEd25519.TPointPrecomp }
+
+constructor TEd25519.TPointPrecomp.Create;
+begin
+  Inherited Create();
+  Fypx_h := TX25519Field.Create();
+  Fymx_h := TX25519Field.Create();
+  Fxyd := TX25519Field.Create();
+end;
+
+function TEd25519.TPointPrecomp.GetXyd: TCryptoLibInt32Array;
+begin
+  result := Fxyd;
+end;
+
+function TEd25519.TPointPrecomp.GetYmx_h: TCryptoLibInt32Array;
+begin
+  result := Fymx_h;
+end;
+
+function TEd25519.TPointPrecomp.GetYpx_h: TCryptoLibInt32Array;
+begin
+  result := Fypx_h;
+end;
+
+procedure TEd25519.TPointPrecomp.SetXyd(const value: TCryptoLibInt32Array);
+begin
+  Fxyd := value;
+end;
+
+procedure TEd25519.TPointPrecomp.SetYmx_h(const value: TCryptoLibInt32Array);
+begin
+  Fymx_h := value;
+end;
+
+procedure TEd25519.TPointPrecomp.SetYpx_h(const value: TCryptoLibInt32Array);
+begin
+  Fypx_h := value;
+end;
+
+{ TEd25519 }
+
+class procedure TEd25519.Boot;
+begin
+  // 'SigEd25519 no Ed25519 collisions' as ByteArray using ASCII Encoding
+  FDom2Prefix := TCryptoLibByteArray.Create(83, 105, 103, 69, 100, 50, 53, 53,
+    49, 57, 32, 110, 111, 32, 69, 100, 50, 53, 53, 49, 57, 32, 99, 111, 108,
+    108, 105, 115, 105, 111, 110, 115);
+
+  FP := TCryptoLibUInt32Array.Create($FFFFFFED, $FFFFFFFF, $FFFFFFFF, $FFFFFFFF,
+    $FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $7FFFFFFF);
+  FL := TCryptoLibUInt32Array.Create($5CF5D3ED, $5812631A, $A2F79CD6, $14DEF9DE,
+    $00000000, $00000000, $00000000, $10000000);
+
+  FB_x := TCryptoLibInt32Array.Create($0325D51A, $018B5823, $007B2C95,
+    $0304A92D, $00D2598E, $01D6DC5C, $01388C7F, $013FEC0A, $029E6B72,
+    $0042D26D);
+  FB_y := TCryptoLibInt32Array.Create($02666658, $01999999, $00666666,
+    $03333333, $00CCCCCC, $02666666, $01999999, $00666666, $03333333,
+    $00CCCCCC);
+  FC_d := TCryptoLibInt32Array.Create($035978A3, $02D37284, $018AB75E,
+    $026A0A0E, $0000E014, $0379E898, $01D01E5D, $01E738CC, $03715B7F,
+    $00A406D9);
+  FC_d2 := TCryptoLibInt32Array.Create($02B2F159, $01A6E509, $01156EBD,
+    $00D4141D, $0001C029, $02F3D130, $03A03CBB, $01CE7198, $02E2B6FF,
+    $00480DB3);
+  FC_d4 := TCryptoLibInt32Array.Create($0165E2B2, $034DCA13, $002ADD7A,
+    $01A8283B, $00038052, $01E7A260, $03407977, $019CE331, $01C56DFF,
+    $00901B67);
+
+  if FPrecompLock = Nil then
+  begin
+    FPrecompLock := TCriticalSection.Create;
+  end;
+end;
+
+class function TEd25519.Decode32(const bs: TCryptoLibByteArray;
+  off: Int32): UInt32;
+begin
+  // UInt32 n := bs[off];
+  // System.Inc(off);
+  // n := n or (UInt32(bs[off]) shl 8);
+  // System.Inc(off);
+  // n := n or (UInt32(bs[off]) shl 16);
+  // System.Inc(off);
+  // n := n or (UInt32(bs[off]) shl 24);
+  // result := n;
+  result := TConverters.ReadBytesAsUInt32LE(PByte(bs), off);
+end;
+
+class procedure TEd25519.Decode32(const bs: TCryptoLibByteArray; bsOff: Int32;
+  const n: TCryptoLibUInt32Array; nOff, nLen: Int32);
+begin
+  // int32 i;
+  // for i := 0 to System.Pred(nLen) do
+  // begin
+  // n[nOff + i] := Decode32(bs, bsOff + (i * 4));
+  // end;
+  TConverters.le32_copy(PByte(bs), bsOff * System.SizeOf(Byte), PCardinal(n),
+    nOff * System.SizeOf(UInt32), nLen * System.SizeOf(UInt32));
+end;
+
+class procedure TEd25519.DecodeScalar(const k: TCryptoLibByteArray; kOff: Int32;
+  const n: TCryptoLibUInt32Array);
+begin
+  Decode32(k, kOff, n, 0, ScalarUints);
+end;
+
+class procedure TEd25519.Encode24(n: UInt32; const bs: TCryptoLibByteArray;
+  off: Int32);
+begin
+  bs[off] := Byte(n);
+  System.Inc(off);
+  bs[off] := Byte(n shr 8);
+  System.Inc(off);
+  bs[off] := Byte(n shr 16);
+end;
+
+class procedure TEd25519.Encode32(n: UInt32; const bs: TCryptoLibByteArray;
+  off: Int32);
+begin
+  // bs[  off] := Byte(n      );
+  // System.Inc(off);
+  // bs[off] := Byte(n shr  8);
+  // System.Inc(off);
+  // bs[off] := Byte(n shr  16);
+  // System.Inc(off);
+  // bs[off] := Byte(n shr  24);
+  TConverters.ReadUInt32AsBytesLE(n, bs, off);
+end;
+
+class procedure TEd25519.Encode56(n: UInt64; const bs: TCryptoLibByteArray;
+  off: Int32);
+begin
+  Encode32(UInt32(n), bs, off);
+  Encode24(UInt32(n shr 32), bs, off + 4);
+end;
+
+class function TEd25519.CalculateS(const r, k, s: TCryptoLibByteArray)
+  : TCryptoLibByteArray;
+var
+  T, U, V: TCryptoLibUInt32Array;
+  i: Int32;
+begin
+  System.SetLength(T, ScalarUints * 2);
+  DecodeScalar(r, 0, T);
+  System.SetLength(U, ScalarUints);
+  DecodeScalar(k, 0, U);
+  System.SetLength(V, ScalarUints);
+  DecodeScalar(s, 0, V);
+
+  TNat256.MulAddTo(U, V, T);
+
+  System.SetLength(result, ScalarBytes * 2);
+
+  for i := 0 to System.Pred(System.Length(T)) do
+  begin
+    Encode32(T[i], result, i * 4);
+  end;
+  result := ReduceScalar(result);
+end;
+
+class function TEd25519.CheckContextVar(const ctx
+  : TCryptoLibCustomByteArrayBuffer; phflag: Byte): Boolean;
+begin
+  result := ((ctx.IsNil) and (phflag = $00)) or
+    ((not ctx.IsNil) and (ctx.Length < 256));
+end;
+
+class function TEd25519.CheckPointVar(const p: TCryptoLibByteArray): Boolean;
+var
+  T: TCryptoLibUInt32Array;
+begin
+  System.SetLength(T, 8);
+  Decode32(p, 0, T, 0, 8);
+  T[7] := T[7] and $7FFFFFFF;
+  result := not(TNat256.Gte(T, FP));
+end;
+
+class function TEd25519.CheckScalarVar(const s: TCryptoLibByteArray): Boolean;
+var
+  n: TCryptoLibUInt32Array;
+begin
+  System.SetLength(n, ScalarUints);
+  DecodeScalar(s, 0, n);
+  result := not(TNat256.Gte(n, FL));
+end;
+
+constructor TEd25519.Create;
+begin
+  Inherited Create();
+end;
+
+function TEd25519.CreateDigest: IDigest;
+begin
+  result := TDigestUtilities.GetDigest('SHA-512');
+end;
+
+class constructor TEd25519.CreateEd25519;
+begin
+  TEd25519.Boot();
+end;
+
+function TEd25519.CreatePreHash: IDigest;
+begin
+  result := CreateDigest();
+end;
+
+class function TEd25519.Decode24(const bs: TCryptoLibByteArray;
+  off: Int32): UInt32;
+var
+  n: UInt32;
+begin
+  n := bs[off];
+  System.Inc(off);
+  n := n or (UInt32(bs[off]) shl 8);
+  System.Inc(off);
+  n := n or (UInt32(bs[off]) shl 16);
+  result := n;
+end;
+
+class procedure TEd25519.PointExtendXY(const p: IPointAccum);
+begin
+  TX25519Field.One(p.Z);
+  TX25519Field.Copy(p.X, 0, p.U, 0);
+  TX25519Field.Copy(p.Y, 0, p.V, 0);
+end;
+
+class procedure TEd25519.PointExtendXY(const p: IPointExt);
+begin
+  TX25519Field.One(p.Z);
+  TX25519Field.Mul(p.X, p.Y, p.T);
+end;
+
+class function TEd25519.DecodePointVar(const p: TCryptoLibByteArray;
+  pOff: Int32; ANegate: Boolean; const r: IPointExt): Boolean;
+var
+  py: TCryptoLibByteArray;
+  U, V: TCryptoLibInt32Array;
+  x_0: Int32;
+begin
+  py := TArrayUtils.CopyOfRange(p, pOff, pOff + PointBytes);
+  if (not CheckPointVar(py)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  x_0 := (py[PointBytes - 1] and $80) shr 7;
+  py[PointBytes - 1] := py[PointBytes - 1] and $7F;
+
+  TX25519Field.Decode(py, 0, r.Y);
+
+  U := TX25519Field.Create();
+  V := TX25519Field.Create();
+
+  TX25519Field.Sqr(r.Y, U);
+  TX25519Field.Mul(FC_d, U, V);
+  TX25519Field.SubOne(U);
+  TX25519Field.AddOne(V);
+
+  if (not(TX25519Field.SqrtRatioVar(U, V, r.X))) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  TX25519Field.Normalize(r.X);
+  if ((x_0 = 1) and (TX25519Field.IsZeroVar(r.X))) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  if (ANegate xor (x_0 <> (r.X[0] and 1))) then
+  begin
+    TX25519Field.negate(r.X, r.X);
+  end;
+
+  PointExtendXY(r);
+  result := true;
+end;
+
+class destructor TEd25519.DestroyEd25519;
+begin
+  FPrecompLock.Free;
+end;
+
+class procedure TEd25519.Dom2(const d: IDigest; phflag: Byte;
+  const ctx: TCryptoLibCustomByteArrayBuffer);
+begin
+  if (not(ctx.IsNil)) then
+  begin
+    d.BlockUpdate(FDom2Prefix, 0, System.Length(FDom2Prefix));
+    d.Update(phflag);
+    d.Update(Byte(ctx.Length));
+    if ctx.Data <> Nil then
+    begin
+      d.BlockUpdate(ctx.Data, 0, ctx.Length);
+    end;
+  end;
+end;
+
+class procedure TEd25519.EncodePoint(const p: IPointAccum;
+  const r: TCryptoLibByteArray; rOff: Int32);
+var
+  X, Y: TCryptoLibInt32Array;
+begin
+  X := TX25519Field.Create();
+  Y := TX25519Field.Create();
+
+  TX25519Field.Inv(p.Z, Y);
+  TX25519Field.Mul(p.X, Y, X);
+  TX25519Field.Mul(p.Y, Y, Y);
+  TX25519Field.Normalize(X);
+  TX25519Field.Normalize(Y);
+
+  TX25519Field.Encode(Y, r, rOff);
+  r[rOff + PointBytes - 1] := r[rOff + PointBytes - 1] or
+    Byte((X[0] and 1) shl 7);
+end;
+
+procedure TEd25519.GeneratePrivateKey(const random: ISecureRandom;
+  const k: TCryptoLibByteArray);
+begin
+  random.NextBytes(k);
+end;
+
+class procedure TEd25519.PruneScalar(const n: TCryptoLibByteArray; nOff: Int32;
+  const r: TCryptoLibByteArray);
+begin
+  System.Move(n[nOff], r[0], ScalarBytes * System.SizeOf(Byte));
+
+  r[0] := r[0] and $F8;
+  r[ScalarBytes - 1] := r[ScalarBytes - 1] and $7F;
+  r[ScalarBytes - 1] := r[ScalarBytes - 1] or $40;
+end;
+
+class procedure TEd25519.ScalarMultBaseEncoded(const k, r: TCryptoLibByteArray;
+  rOff: Int32);
+var
+  p: IPointAccum;
+begin
+  p := TPointAccum.Create();
+  ScalarMultBase(k, p);
+  EncodePoint(p, r, rOff);
+end;
+
+procedure TEd25519.GeneratePublicKey(const sk: TCryptoLibByteArray;
+  skOff: Int32; pk: TCryptoLibByteArray; pkOff: Int32);
+var
+  d: IDigest;
+  h, s: TCryptoLibByteArray;
+begin
+  d := CreateDigest();
+  System.SetLength(h, d.GetDigestSize());
+
+  d.BlockUpdate(sk, skOff, SecretKeySize);
+  d.DoFinal(h, 0);
+
+  System.SetLength(s, ScalarBytes);
+
+  PruneScalar(h, 0, s);
+
+  ScalarMultBaseEncoded(s, pk, pkOff);
+end;
+
+class function TEd25519.GetWnaf(const n: TCryptoLibUInt32Array; width: Int32)
+  : TCryptoLibShortIntArray;
+var
+  T: TCryptoLibUInt32Array;
+  ws: TCryptoLibShortIntArray;
+  i, tPos, j: Int32;
+  c, next, pow2, mask, LSign, carry, word, word16, bit, digit: UInt32;
+begin
+{$IFDEF DEBUG}
+  System.Assert((n[ScalarUints - 1] shr 31) = 0);
+{$ENDIF DEBUG}
+  System.SetLength(T, ScalarUints * 2);
+
+  c := 0;
+  tPos := System.Length(T);
+  i := ScalarUints;
+  System.Dec(i);
+  while (i >= 0) do
+  begin
+    next := n[i];
+    System.Dec(tPos);
+    T[tPos] := (next shr 16) or (c shl 16);
+    System.Dec(tPos);
+    c := next;
+    T[tPos] := c;
+    System.Dec(i);
+  end;
+
+  System.SetLength(ws, 256);
+
+  pow2 := UInt32(1) shl width;
+  mask := pow2 - UInt32(1);
+  LSign := pow2 shr 1;
+
+  carry := UInt32(0);
+  j := 0;
+
+  for i := 0 to System.Pred(System.Length(T)) do
+  begin
+    word := T[i];
+    while (j < 16) do
+    begin
+      word16 := word shr j;
+      bit := word16 and UInt32(1);
+
+      if (bit = carry) then
+      begin
+        System.Inc(j);
+        continue;
+      end;
+
+      digit := (word16 and mask) + carry;
+      carry := digit and LSign;
+      digit := digit - (carry shl 1);
+      carry := carry shr (width - 1);
+
+      ws[(i shl 4) + j] := ShortInt(digit);
+
+      j := j + width;
+    end;
+    System.Dec(j, 16);
+  end;
+
+{$IFDEF DEBUG}
+  System.Assert(carry = 0);
+{$ENDIF DEBUG}
+  result := ws;
+end;
+
+procedure TEd25519.ImplSign(const sk: TCryptoLibByteArray; skOff: Int32;
+  const pk: TCryptoLibByteArray; pkOff: Int32;
+  const ctx: TCryptoLibCustomByteArrayBuffer; phflag: Byte;
+  const m: TCryptoLibByteArray; mOff, mLen: Int32;
+  const sig: TCryptoLibByteArray; sigOff: Int32);
+var
+  d: IDigest;
+  h, s: TCryptoLibByteArray;
+begin
+  if (not CheckContextVar(ctx, phflag)) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SInvalidCtx);
+  end;
+
+  d := CreateDigest();
+  System.SetLength(h, d.GetDigestSize());
+
+  d.BlockUpdate(sk, skOff, SecretKeySize);
+  d.DoFinal(h, 0);
+
+  System.SetLength(s, ScalarBytes);
+  PruneScalar(h, 0, s);
+
+  ImplSign(d, h, s, pk, pkOff, ctx, phflag, m, mOff, mLen, sig, sigOff);
+
+end;
+
+procedure TEd25519.ImplSign(const sk: TCryptoLibByteArray; skOff: Int32;
+  const ctx: TCryptoLibCustomByteArrayBuffer; phflag: Byte;
+  const m: TCryptoLibByteArray; mOff, mLen: Int32;
+  const sig: TCryptoLibByteArray; sigOff: Int32);
+var
+  d: IDigest;
+  h, s, pk: TCryptoLibByteArray;
+begin
+  if (not CheckContextVar(ctx, phflag)) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SInvalidCtx);
+  end;
+
+  d := CreateDigest();
+  System.SetLength(h, d.GetDigestSize());
+
+  d.BlockUpdate(sk, skOff, SecretKeySize);
+  d.DoFinal(h, 0);
+
+  System.SetLength(s, ScalarBytes);
+  PruneScalar(h, 0, s);
+
+  System.SetLength(pk, PointBytes);
+  ScalarMultBaseEncoded(s, pk, 0);
+
+  ImplSign(d, h, s, pk, 0, ctx, phflag, m, mOff, mLen, sig, sigOff);
+end;
+
+class procedure TEd25519.ImplSign(const d: IDigest;
+  const h, s, pk: TCryptoLibByteArray; pkOff: Int32;
+  const ctx: TCryptoLibCustomByteArrayBuffer; phflag: Byte;
+  const m: TCryptoLibByteArray; mOff, mLen: Int32;
+  const sig: TCryptoLibByteArray; sigOff: Int32);
+var
+  r, bigR, k, bigS: TCryptoLibByteArray;
+begin
+  Dom2(d, phflag, ctx);
+  d.BlockUpdate(h, ScalarBytes, ScalarBytes);
+  d.BlockUpdate(m, mOff, mLen);
+  d.DoFinal(h, 0);
+
+  r := ReduceScalar(h);
+  System.SetLength(bigR, PointBytes);
+  ScalarMultBaseEncoded(r, bigR, 0);
+
+  Dom2(d, phflag, ctx);
+  d.BlockUpdate(bigR, 0, PointBytes);
+  d.BlockUpdate(pk, pkOff, PointBytes);
+  d.BlockUpdate(m, mOff, mLen);
+  d.DoFinal(h, 0);
+
+  k := ReduceScalar(h);
+  bigS := CalculateS(r, k, s);
+
+  System.Move(bigR[0], sig[sigOff], PointBytes * System.SizeOf(Byte));
+  System.Move(bigS[0], sig[sigOff + PointBytes],
+    ScalarBytes * System.SizeOf(Byte));
+end;
+
+function TEd25519.ImplVerify(const sig: TCryptoLibByteArray; sigOff: Int32;
+  const pk: TCryptoLibByteArray; pkOff: Int32;
+  const ctx: TCryptoLibCustomByteArrayBuffer; phflag: Byte;
+  const m: TCryptoLibByteArray; mOff, mLen: Int32): Boolean;
+var
+  r, s, h, k, check: TCryptoLibByteArray;
+  nS, nA: TCryptoLibUInt32Array;
+  pA: IPointExt;
+  pR: IPointAccum;
+  d: IDigest;
+begin
+  if (not CheckContextVar(ctx, phflag)) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SInvalidCtx);
+  end;
+
+  r := TArrayUtils.CopyOfRange(sig, sigOff, sigOff + PointBytes);
+  s := TArrayUtils.CopyOfRange(sig, sigOff + PointBytes,
+    sigOff + SignatureSize);
+
+  if (not CheckPointVar(r)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  if (not CheckScalarVar(s)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  pA := TPointExt.Create();
+  if (not DecodePointVar(pk, pkOff, true, pA)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  d := CreateDigest();
+  System.SetLength(h, d.GetDigestSize());
+
+  Dom2(d, phflag, ctx);
+  d.BlockUpdate(r, 0, PointBytes);
+  d.BlockUpdate(pk, pkOff, PointBytes);
+  d.BlockUpdate(m, mOff, mLen);
+  d.DoFinal(h, 0);
+
+  k := ReduceScalar(h);
+
+  System.SetLength(nS, ScalarUints);
+  DecodeScalar(s, 0, nS);
+
+  System.SetLength(nA, ScalarUints);
+
+  DecodeScalar(k, 0, nA);
+
+  pR := TPointAccum.Create();
+  ScalarMultStraussVar(nS, nA, pA, pR);
+
+  System.SetLength(check, PointBytes);
+
+  EncodePoint(pR, check, 0);
+
+  result := TArrayUtils.ConstantTimeAreEqual(check, r);
+end;
+
+class procedure TEd25519.PointAddPrecomp(const p: IPointPrecomp;
+  const r: IPointAccum);
+var
+  bigA, bigB, bigC, bigD, bigE, bigF, bigG: TCryptoLibInt32Array;
+begin
+  bigA := TX25519Field.Create();
+  bigB := TX25519Field.Create();
+  bigC := TX25519Field.Create();
+  bigD := r.U;
+  bigE := TX25519Field.Create();
+  bigF := TX25519Field.Create();
+  bigG := r.V;
+
+  TX25519Field.Apm(r.Y, r.X, bigB, bigA);
+  TX25519Field.Mul(bigA, p.Ymx_h, bigA);
+  TX25519Field.Mul(bigB, p.Ypx_h, bigB);
+  TX25519Field.Mul(r.U, r.V, bigC);
+  TX25519Field.Mul(bigC, p.Xyd, bigC);
+  TX25519Field.Apm(bigB, bigA, bigG, bigD);
+  TX25519Field.Apm(r.Z, bigC, bigF, bigE);
+  TX25519Field.carry(bigF);
+  TX25519Field.Mul(bigD, bigE, r.X);
+  TX25519Field.Mul(bigF, bigG, r.Y);
+  TX25519Field.Mul(bigE, bigF, r.Z);
+end;
+
+class procedure TEd25519.PointAddVar(negate: Boolean; const p, q, r: IPointExt);
+var
+  bigA, bigB, bigC, bigD, bigE, bigF, bigG, bigH, c, d, f,
+    g: TCryptoLibInt32Array;
+begin
+  bigA := TX25519Field.Create();
+  bigB := TX25519Field.Create();
+  bigC := TX25519Field.Create();
+  bigD := TX25519Field.Create();
+  bigE := TX25519Field.Create();
+  bigF := TX25519Field.Create();
+  bigG := TX25519Field.Create();
+  bigH := TX25519Field.Create();
+
+  if (negate) then
+  begin
+    c := bigD;
+    d := bigC;
+    f := bigG;
+    g := bigF;
+  end
+  else
+  begin
+    c := bigC;
+    d := bigD;
+    f := bigF;
+    g := bigG;
+  end;
+
+  TX25519Field.Apm(p.Y, p.X, bigB, bigA);
+  TX25519Field.Apm(q.Y, q.X, d, c);
+  TX25519Field.Mul(bigA, bigC, bigA);
+  TX25519Field.Mul(bigB, bigD, bigB);
+  TX25519Field.Mul(p.T, q.T, bigC);
+  TX25519Field.Mul(bigC, FC_d2, bigC);
+  TX25519Field.Mul(p.Z, q.Z, bigD);
+  TX25519Field.Add(bigD, bigD, bigD);
+  TX25519Field.Apm(bigB, bigA, bigH, bigE);
+  TX25519Field.Apm(bigD, bigC, g, f);
+  TX25519Field.carry(g);
+  TX25519Field.Mul(bigE, bigF, r.X);
+  TX25519Field.Mul(bigG, bigH, r.Y);
+  TX25519Field.Mul(bigF, bigG, r.Z);
+  TX25519Field.Mul(bigE, bigH, r.T);
+end;
+
+class procedure TEd25519.PointAddVar(negate: Boolean; const p: IPointExt;
+  const r: IPointAccum);
+var
+  bigA, bigB, bigC, bigD, bigE, bigF, bigG, bigH, c, d, f,
+    g: TCryptoLibInt32Array;
+begin
+  bigA := TX25519Field.Create();
+  bigB := TX25519Field.Create();
+  bigC := TX25519Field.Create();
+  bigD := TX25519Field.Create();
+  bigE := r.U;
+  bigF := TX25519Field.Create();
+  bigG := TX25519Field.Create();
+  bigH := r.V;
+
+  if (negate) then
+  begin
+    c := bigD;
+    d := bigC;
+    f := bigG;
+    g := bigF;
+  end
+  else
+  begin
+    c := bigC;
+    d := bigD;
+    f := bigF;
+    g := bigG;
+  end;
+
+  TX25519Field.Apm(r.Y, r.X, bigB, bigA);
+  TX25519Field.Apm(p.Y, p.X, d, c);
+  TX25519Field.Mul(bigA, bigC, bigA);
+  TX25519Field.Mul(bigB, bigD, bigB);
+  TX25519Field.Mul(r.U, r.V, bigC);
+  TX25519Field.Mul(bigC, p.T, bigC);
+  TX25519Field.Mul(bigC, FC_d2, bigC);
+  TX25519Field.Mul(r.Z, p.Z, bigD);
+  TX25519Field.Add(bigD, bigD, bigD);
+  TX25519Field.Apm(bigB, bigA, bigH, bigE);
+  TX25519Field.Apm(bigD, bigC, g, f);
+  TX25519Field.carry(g);
+  TX25519Field.Mul(bigE, bigF, r.X);
+  TX25519Field.Mul(bigG, bigH, r.Y);
+  TX25519Field.Mul(bigF, bigG, r.Z);
+end;
+
+class function TEd25519.PointCopy(const p: IPointAccum): IPointExt;
+var
+  r: IPointExt;
+begin
+  r := TPointExt.Create();
+  TX25519Field.Copy(p.X, 0, r.X, 0);
+  TX25519Field.Copy(p.Y, 0, r.Y, 0);
+  TX25519Field.Copy(p.Z, 0, r.Z, 0);
+  TX25519Field.Mul(p.U, p.V, r.T);
+  result := r;
+end;
+
+class function TEd25519.PointCopy(const p: IPointExt): IPointExt;
+var
+  r: IPointExt;
+begin
+  r := TPointExt.Create();
+  TX25519Field.Copy(p.X, 0, r.X, 0);
+  TX25519Field.Copy(p.Y, 0, r.Y, 0);
+  TX25519Field.Copy(p.Z, 0, r.Z, 0);
+  TX25519Field.Copy(p.T, 0, r.T, 0);
+  result := r;
+end;
+
+class procedure TEd25519.PointDouble(const r: IPointAccum);
+var
+  bigA, bigB, bigC, bigD, bigE, bigF, bigG: TCryptoLibInt32Array;
+begin
+  bigA := TX25519Field.Create();
+  bigB := TX25519Field.Create();
+  bigC := TX25519Field.Create();
+  bigD := r.U;
+  bigE := TX25519Field.Create();
+  bigF := TX25519Field.Create();
+  bigG := r.V;
+
+  TX25519Field.Sqr(r.X, bigA);
+  TX25519Field.Sqr(r.Y, bigB);
+  TX25519Field.Sqr(r.Z, bigC);
+  TX25519Field.Add(bigC, bigC, bigC);
+  TX25519Field.Apm(bigA, bigB, bigG, bigF);
+  TX25519Field.Add(r.X, r.Y, bigD);
+  TX25519Field.Sqr(bigD, bigD);
+  TX25519Field.Sub(bigG, bigD, bigD);
+  TX25519Field.Add(bigC, bigF, bigE);
+  TX25519Field.carry(bigE);
+  TX25519Field.Mul(bigD, bigE, r.X);
+  TX25519Field.Mul(bigF, bigG, r.Y);
+  TX25519Field.Mul(bigE, bigF, r.Z);
+end;
+
+class procedure TEd25519.PointLookup(block, index: Int32;
+  const p: IPointPrecomp);
+var
+  off, i, mask: Int32;
+begin
+{$IFDEF DEBUG}
+  System.Assert((0 <= block) and (block < PrecompBlocks));
+  System.Assert((0 <= index) and (index < PrecompPoints));
+{$ENDIF DEBUG}
+  off := block * PrecompPoints * 3 * TX25519Field.Size;
+
+  for i := 0 to System.Pred(PrecompPoints) do
+  begin
+    mask := TBits.Asr32(((i xor index) - 1), 31);
+    TNat.CMov(TX25519Field.Size, mask, FPrecompBase, off, p.Ypx_h, 0);
+    off := off + TX25519Field.Size;
+    TNat.CMov(TX25519Field.Size, mask, FPrecompBase, off, p.Ymx_h, 0);
+    off := off + TX25519Field.Size;
+    TNat.CMov(TX25519Field.Size, mask, FPrecompBase, off, p.Xyd, 0);
+    off := off + TX25519Field.Size;
+  end;
+end;
+
+class function TEd25519.PointPrecompVar(const p: IPointExt; count: Int32)
+  : TCryptoLibGenericArray<IPointExt>;
+var
+  d: IPointExt;
+  table: TCryptoLibGenericArray<IPointExt>;
+  i: Int32;
+begin
+{$IFDEF DEBUG}
+  System.Assert(count > 0);
+{$ENDIF DEBUG}
+  d := TPointExt.Create();
+  PointAddVar(false, p, p, d);
+
+  System.SetLength(table, count);
+
+  table[0] := PointCopy(p);
+  for i := 1 to System.Pred(count) do
+  begin
+    table[i] := TPointExt.Create() as IPointExt;
+    PointAddVar(false, table[i - 1], d, table[i]);
+  end;
+  result := table;
+end;
+
+class procedure TEd25519.PointSetNeutral(const p: IPointAccum);
+begin
+  TX25519Field.Zero(p.X);
+  TX25519Field.One(p.Y);
+  TX25519Field.One(p.Z);
+  TX25519Field.Zero(p.U);
+  TX25519Field.One(p.V);
+end;
+
+class procedure TEd25519.PointSetNeutral(const p: IPointExt);
+begin
+  TX25519Field.Zero(p.X);
+  TX25519Field.One(p.Y);
+  TX25519Field.One(p.Z);
+  TX25519Field.Zero(p.T);
+end;
+
+class procedure TEd25519.Precompute;
+var
+  bigB: IPointExt;
+  p: IPointAccum;
+  X, Y: TCryptoLibInt32Array;
+  off, b, T, s, k, Size, j, i: Int32;
+  // ds, points: TCryptoLibGenericArray<IPointExt>;
+  ds: array [0 .. (PrecompTeeth - 1)] of IPointExt;
+  points: array [0 .. (PrecompPoints - 1)] of IPointExt;
+  sum, q: IPointExt;
+  r: IPointPrecomp;
+begin
+  FPrecompLock.Acquire;
+  try
+
+    if (FPrecompBase <> Nil) then
+    begin
+      Exit;
+    end;
+
+    // Precomputed table for the base point in verification ladder
+    bigB := TPointExt.Create();
+    TX25519Field.Copy(FB_x, 0, bigB.X, 0);
+    TX25519Field.Copy(FB_y, 0, bigB.Y, 0);
+    PointExtendXY(bigB);
+
+    FPrecompBaseTable := PointPrecompVar(bigB, 1 shl (WnafWidthBase - 2));
+
+    p := TPointAccum.Create();
+    TX25519Field.Copy(FB_x, 0, p.X, 0);
+    TX25519Field.Copy(FB_y, 0, p.Y, 0);
+    PointExtendXY(p);
+
+    System.SetLength(FPrecompBase, PrecompBlocks * PrecompPoints * 3 *
+      TX25519Field.Size);
+
+    off := 0;
+    for b := 0 to System.Pred(PrecompBlocks) do
+    begin
+      // System.SetLength(ds, PrecompTeeth); // **
+
+      sum := TPointExt.Create() as IPointExt;
+      PointSetNeutral(sum);
+
+      for T := 0 to System.Pred(PrecompTeeth) do
+      begin
+        q := PointCopy(p);
+        PointAddVar(true, sum, q, sum);
+        PointDouble(p);
+
+        ds[T] := PointCopy(p);
+
+        if ((b + T) <> (PrecompBlocks + PrecompTeeth - 2)) then
+        begin
+          s := 1;
+          while s < PrecompSpacing do
+          begin
+            PointDouble(p);
+            System.Inc(s);
+          end;
+        end;
+      end;
+
+      // System.SetLength(points, PrecompPoints); // **
+
+      k := 0;
+      points[k] := sum;
+      System.Inc(k);
+
+      for T := 0 to System.Pred(PrecompTeeth - 1) do
+      begin
+        Size := 1 shl T;
+        j := 0;
+        while j < Size do
+        begin
+          points[k] := TPointExt.Create() as IPointExt;
+          PointAddVar(false, points[k - Size], ds[T], points[k]);
+          System.Inc(k);
+          System.Inc(j);
+        end;
+
+      end;
+{$IFDEF DEBUG}
+      System.Assert(k = PrecompPoints);
+{$ENDIF DEBUG}
+      for i := 0 to System.Pred(PrecompPoints) do
+      begin
+        q := points[i];
+
+        X := TX25519Field.Create();
+        Y := TX25519Field.Create();
+
+        TX25519Field.Add(q.Z, q.Z, X);
+        // TODO[ed25519] Batch inversion
+        TX25519Field.Inv(X, Y);
+        TX25519Field.Mul(q.X, Y, X);
+        TX25519Field.Mul(q.Y, Y, Y);
+
+        r := TPointPrecomp.Create();
+        TX25519Field.Apm(Y, X, r.Ypx_h, r.Ymx_h);
+        TX25519Field.Mul(X, Y, r.Xyd);
+        TX25519Field.Mul(r.Xyd, FC_d4, r.Xyd);
+
+        TX25519Field.Normalize(r.Ypx_h);
+        TX25519Field.Normalize(r.Ymx_h);
+        // TX25519Field.Normalize(r.xyd);
+
+        TX25519Field.Copy(r.Ypx_h, 0, FPrecompBase, off);
+        off := off + TX25519Field.Size;
+        TX25519Field.Copy(r.Ymx_h, 0, FPrecompBase, off);
+        off := off + TX25519Field.Size;
+        TX25519Field.Copy(r.Xyd, 0, FPrecompBase, off);
+        off := off + TX25519Field.Size;
+      end;
+    end;
+
+{$IFDEF DEBUG}
+    System.Assert(off = System.Length(FPrecompBase));
+{$ENDIF DEBUG}
+  finally
+    FPrecompLock.Release;
+  end;
+end;
+
+class function TEd25519.ReduceScalar(const n: TCryptoLibByteArray)
+  : TCryptoLibByteArray;
+var
+  x00, x01, x02, x03, x04, x05, x06, x07, x08, x09, x10, x11, x12, x13, x14,
+    x15, x16, x17, x18, T: Int64;
+begin
+  x00 := Decode32(n, 0) and Int64(M32L); // x00:32/--
+  x01 := (Decode24(n, 4) shl 4) and Int64(M32L); // x01:28/--
+  x02 := Decode32(n, 7) and Int64(M32L); // x02:32/--
+  x03 := (Decode24(n, 11) shl 4) and Int64(M32L); // x03:28/--
+  x04 := Decode32(n, 14) and Int64(M32L); // x04:32/--
+  x05 := (Decode24(n, 18) shl 4) and Int64(M32L); // x05:28/--
+  x06 := Decode32(n, 21) and Int64(M32L); // x06:32/--
+  x07 := (Decode24(n, 25) shl 4) and Int64(M32L); // x07:28/--
+  x08 := Decode32(n, 28) and Int64(M32L); // x08:32/--
+  x09 := (Decode24(n, 32) shl 4) and Int64(M32L); // x09:28/--
+  x10 := Decode32(n, 35) and Int64(M32L); // x10:32/--
+  x11 := (Decode24(n, 39) shl 4) and Int64(M32L); // x11:28/--
+  x12 := Decode32(n, 42) and Int64(M32L); // x12:32/--
+  x13 := (Decode24(n, 46) shl 4) and Int64(M32L); // x13:28/--
+  x14 := Decode32(n, 49) and Int64(M32L); // x14:32/--
+  x15 := (Decode24(n, 53) shl 4) and Int64(M32L); // x15:28/--
+  x16 := Decode32(n, 56) and Int64(M32L); // x16:32/--
+  x17 := (Decode24(n, 60) shl 4) and Int64(M32L); // x17:28/--
+  x18 := n[63] and Int64($FF); // x18:08/--
+
+  // x18 := x18 + (x17 shr  28); x17 := x17 and Int64(M28L);
+  x09 := x09 - (x18 * L0); // x09:34/28
+  x10 := x10 - (x18 * L1); // x10:33/30
+  x11 := x11 - (x18 * L2); // x11:35/28
+  x12 := x12 - (x18 * L3); // x12:32/31
+  x13 := x13 - (x18 * L4); // x13:28/21
+
+  x17 := x17 + TBits.Asr64(x16, 28); // x17:28/--
+  x16 := x16 and Int64(M28L); // x16:28/--
+  x08 := x08 - (x17 * L0); // x08:54/32
+  x09 := x09 - (x17 * L1); // x09:52/51
+  x10 := x10 - (x17 * L2); // x10:55/34
+  x11 := x11 - (x17 * L3); // x11:51/36
+  x12 := x12 - (x17 * L4); // x12:41/--
+
+  // x16 := x16 + (x15 shr  28); x15 := x15 and Int64(M28L);
+  x07 := x07 - (x16 * L0); // x07:54/28
+  x08 := x08 - (x16 * L1); // x08:54/53
+  x09 := x09 - (x16 * L2); // x09:55/53
+  x10 := x10 - (x16 * L3); // x10:55/52
+  x11 := x11 - (x16 * L4); // x11:51/41
+
+  x15 := x15 + TBits.Asr64(x14, 28); // x15:28/--
+  x14 := x14 and Int64(M28L); // x14:28/--
+  x06 := x06 - (x15 * L0); // x06:54/32
+  x07 := x07 - (x15 * L1); // x07:54/53
+  x08 := x08 - (x15 * L2); // x08:56/--
+  x09 := x09 - (x15 * L3); // x09:55/54
+  x10 := x10 - (x15 * L4); // x10:55/53
+
+  // x14 := x14 + (x13 shr  28); x13 := x13 and Int64(M28L);
+  x05 := x05 - (x14 * L0); // x05:54/28
+  x06 := x06 - (x14 * L1); // x06:54/53
+  x07 := x07 - (x14 * L2); // x07:56/--
+  x08 := x08 - (x14 * L3); // x08:56/51
+  x09 := x09 - (x14 * L4); // x09:56/--
+
+  x13 := x13 + TBits.Asr64(x12, 28); // x13:28/22
+  x12 := x12 and Int64(M28L); // x12:28/--
+  x04 := x04 - (x13 * L0); // x04:54/49
+  x05 := x05 - (x13 * L1); // x05:54/53
+  x06 := x06 - (x13 * L2); // x06:56/--
+  x07 := x07 - (x13 * L3); // x07:56/52
+  x08 := x08 - (x13 * L4); // x08:56/52
+
+  x12 := x12 + TBits.Asr64(x11, 28); // x12:28/24
+  x11 := x11 and Int64(M28L); // x11:28/--
+  x03 := x03 - (x12 * L0); // x03:54/49
+  x04 := x04 - (x12 * L1); // x04:54/51
+  x05 := x05 - (x12 * L2); // x05:56/--
+  x06 := x06 - (x12 * L3); // x06:56/52
+  x07 := x07 - (x12 * L4); // x07:56/53
+
+  x11 := x11 + TBits.Asr64(x10, 28); // x11:29/--
+  x10 := x10 and Int64(M28L); // x10:28/--
+  x02 := x02 - (x11 * L0); // x02:55/32
+  x03 := x03 - (x11 * L1); // x03:55/--
+  x04 := x04 - (x11 * L2); // x04:56/55
+  x05 := x05 - (x11 * L3); // x05:56/52
+  x06 := x06 - (x11 * L4); // x06:56/53
+
+  x10 := x10 + TBits.Asr64(x09, 28); // x10:29/--
+  x09 := x09 and Int64(M28L); // x09:28/--
+  x01 := x01 - (x10 * L0); // x01:55/28
+  x02 := x02 - (x10 * L1); // x02:55/54
+  x03 := x03 - (x10 * L2); // x03:56/55
+  x04 := x04 - (x10 * L3); // x04:57/--
+  x05 := x05 - (x10 * L4); // x05:56/53
+
+  x08 := x08 + TBits.Asr64(x07, 28); // x08:56/53
+  x07 := x07 and Int64(M28L); // x07:28/--
+  x09 := x09 + TBits.Asr64(x08, 28); // x09:29/25
+  x08 := x08 and Int64(M28L); // x08:28/--
+
+  T := TBits.Asr64(x08, 27) and Int64(1);
+  x09 := x09 + T; // x09:29/26
+
+  x00 := x00 - (x09 * L0); // x00:55/53
+  x01 := x01 - (x09 * L1); // x01:55/54
+  x02 := x02 - (x09 * L2); // x02:57/--
+  x03 := x03 - (x09 * L3); // x03:57/--
+  x04 := x04 - (x09 * L4); // x04:57/42
+
+  x01 := x01 + TBits.Asr64(x00, 28);
+  x00 := x00 and Int64(M28L);
+  x02 := x02 + TBits.Asr64(x01, 28);
+  x01 := x01 and Int64(M28L);
+  x03 := x03 + TBits.Asr64(x02, 28);
+  x02 := x02 and Int64(M28L);
+  x04 := x04 + TBits.Asr64(x03, 28);
+  x03 := x03 and Int64(M28L);
+  x05 := x05 + TBits.Asr64(x04, 28);
+  x04 := x04 and Int64(M28L);
+  x06 := x06 + TBits.Asr64(x05, 28);
+  x05 := x05 and Int64(M28L);
+  x07 := x07 + TBits.Asr64(x06, 28);
+  x06 := x06 and Int64(M28L);
+  x08 := x08 + TBits.Asr64(x07, 28);
+  x07 := x07 and Int64(M28L);
+  x09 := TBits.Asr64(x08, 28);
+  x08 := x08 and Int64(M28L);
+
+  x09 := x09 - T;
+
+{$IFDEF DEBUG}
+  System.Assert((x09 = Int64(0)) or (x09 = -Int64(1)));
+{$ENDIF DEBUG}
+  x00 := x00 + (x09 and L0);
+  x01 := x01 + (x09 and L1);
+  x02 := x02 + (x09 and L2);
+  x03 := x03 + (x09 and L3);
+  x04 := x04 + (x09 and L4);
+
+  x01 := x01 + TBits.Asr64(x00, 28);
+  x00 := x00 and Int64(M28L);
+  x02 := x02 + TBits.Asr64(x01, 28);
+  x01 := x01 and Int64(M28L);
+  x03 := x03 + TBits.Asr64(x02, 28);
+  x02 := x02 and Int64(M28L);
+  x04 := x04 + TBits.Asr64(x03, 28);
+  x03 := x03 and Int64(M28L);
+  x05 := x05 + TBits.Asr64(x04, 28);
+  x04 := x04 and Int64(M28L);
+  x06 := x06 + TBits.Asr64(x05, 28);
+  x05 := x05 and Int64(M28L);
+  x07 := x07 + TBits.Asr64(x06, 28);
+  x06 := x06 and Int64(M28L);
+  x08 := x08 + TBits.Asr64(x07, 28);
+  x07 := x07 and Int64(M28L);
+
+  System.SetLength(result, ScalarBytes);
+  Encode56(UInt64(x00 or (x01 shl 28)), result, 0);
+  Encode56(UInt64(x02 or (x03 shl 28)), result, 7);
+  Encode56(UInt64(x04 or (x05 shl 28)), result, 14);
+  Encode56(UInt64(x06 or (x07 shl 28)), result, 21);
+  Encode32(UInt32(x08), result, 28);
+end;
+
+class procedure TEd25519.ScalarMultBase(const k: TCryptoLibByteArray;
+  const r: IPointAccum);
+var
+  n: TCryptoLibUInt32Array;
+  w, c1, c2: UInt32;
+  i, cOff, b, LSign, abs: Int32;
+  p: IPointPrecomp;
+begin
+  Precompute();
+
+  PointSetNeutral(r);
+  System.SetLength(n, ScalarUints);
+  DecodeScalar(k, 0, n);
+
+  // Recode the scalar into signed-digit form, then group comb bits in each block
+
+  c1 := TNat.CAdd(ScalarUints, not(Int32(n[0])) and 1, n, FL, n);
+  System.Assert(c1 = 0);
+  c2 := TNat.ShiftDownBit(ScalarUints, n, UInt32(1));
+  System.Assert(c2 = (UInt32(1) shl 31));
+  for i := 0 to System.Pred(ScalarUints) do
+  begin
+    n[i] := TInterleave.Shuffle2(n[i]);
+  end;
+
+  p := TPointPrecomp.Create();
+
+  cOff := (PrecompSpacing - 1) * PrecompTeeth;
+  while true do
+
+  begin
+    for b := 0 to System.Pred(PrecompBlocks) do
+    begin
+      w := n[b] shr cOff;
+      LSign := Int32(w shr (PrecompTeeth - 1)) and 1;
+      abs := (Int32(w) xor -LSign) and PrecompMask;
+
+{$IFDEF DEBUG}
+      System.Assert((LSign = 0) or (LSign = 1));
+      System.Assert((0 <= abs) and (abs < PrecompPoints));
+{$ENDIF DEBUG}
+      PointLookup(b, abs, p);
+
+      TX25519Field.CSwap(LSign, p.Ypx_h, p.Ymx_h);
+      TX25519Field.CNegate(LSign, p.Xyd);
+
+      PointAddPrecomp(p, r);
+    end;
+    cOff := (cOff - PrecompTeeth);
+    if (cOff < 0) then
+    begin
+      break;
+    end;
+
+    PointDouble(r);
+  end;
+end;
+
+class procedure TEd25519.ScalarMultBaseYZ(const k: TCryptoLibByteArray;
+  kOff: Int32; const Y, Z: TCryptoLibInt32Array);
+var
+  n: TCryptoLibByteArray;
+  p: IPointAccum;
+begin
+  System.SetLength(n, ScalarBytes);
+  PruneScalar(k, kOff, n);
+
+  p := TPointAccum.Create();
+  ScalarMultBase(n, p);
+  TX25519Field.Copy(p.Y, 0, Y, 0);
+  TX25519Field.Copy(p.Z, 0, Z, 0);
+end;
+
+class procedure TEd25519.ScalarMultStraussVar(const nb,
+  np: TCryptoLibUInt32Array; const p: IPointExt; const r: IPointAccum);
+var
+  width, bit, wb, wp, LSign, index: Int32;
+  ws_b, ws_p: TCryptoLibShortIntArray;
+  tp: TCryptoLibGenericArray<IPointExt>;
+begin
+  Precompute();
+
+  width := 5;
+
+  ws_b := GetWnaf(nb, WnafWidthBase);
+  ws_p := GetWnaf(np, width);
+
+  tp := PointPrecompVar(p, 1 shl (width - 2));
+
+  PointSetNeutral(r);
+
+  bit := 255;
+  while ((bit > 0) and ((Byte(ws_b[bit]) or Byte(ws_p[bit])) = 0)) do
+  begin
+    System.Dec(bit);
+  end;
+
+  while true do
+  begin
+    wb := ws_b[bit];
+    if (wb <> 0) then
+    begin
+      LSign := TBits.Asr32(wb, 31);
+      index := TBits.Asr32((wb xor LSign), 1);
+
+      PointAddVar((LSign <> 0), FPrecompBaseTable[index], r);
+    end;
+
+    wp := ws_p[bit];
+    if (wp <> 0) then
+    begin
+      LSign := TBits.Asr32(wp, 31);
+      index := TBits.Asr32((wp xor LSign), 1);
+
+      PointAddVar((LSign <> 0), tp[index], r);
+    end;
+
+    System.Dec(bit);
+    if (bit < 0) then
+    begin
+      break;
+    end;
+
+    PointDouble(r);
+  end;
+end;
+
+class function TEd25519.ValidateDigestOutputSize(const ADigest: IDigest)
+  : TCryptoLibByteArray;
+begin
+  System.SetLength(result, PreHashSize);
+  if (PreHashSize <> ADigest.DoFinal(result, 0)) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SDigestError);
+  end;
+end;
+
+class function TEd25519.ConstructCustomByteArrayBufferContext
+  (const AData: TCryptoLibByteArray; AIsNil: Boolean; ALength: Int32)
+  : TCryptoLibCustomByteArrayBuffer;
+begin
+  result := Default (TCryptoLibCustomByteArrayBuffer);
+  result.Data := AData;
+  result.IsNil := AIsNil;
+  result.Length := ALength;
+end;
+
+procedure TEd25519.Sign(const sk: TCryptoLibByteArray; skOff: Int32;
+  const m: TCryptoLibByteArray; mOff, mLen: Int32;
+  const sig: TCryptoLibByteArray; sigOff: Int32);
+var
+  phflag: Byte;
+begin
+  phflag := $00;
+  ImplSign(sk, skOff, EmptyBytesNil, phflag, m, mOff, mLen, sig, sigOff);
+end;
+
+procedure TEd25519.Sign(const sk: TCryptoLibByteArray; skOff: Int32;
+  const pk: TCryptoLibByteArray; pkOff: Int32; const m: TCryptoLibByteArray;
+  mOff, mLen: Int32; const sig: TCryptoLibByteArray; sigOff: Int32);
+var
+  phflag: Byte;
+begin
+  phflag := $00;
+  ImplSign(sk, skOff, pk, pkOff, EmptyBytesNil, phflag, m, mOff, mLen,
+    sig, sigOff);
+end;
+
+procedure TEd25519.Sign(const sk: TCryptoLibByteArray; skOff: Int32;
+  const ctx, m: TCryptoLibByteArray; mOff, mLen: Int32;
+  const sig: TCryptoLibByteArray; sigOff: Int32);
+var
+  phflag: Byte;
+  LCtx: TCryptoLibCustomByteArrayBuffer;
+begin
+  phflag := $00;
+  LCtx := ConstructCustomByteArrayBufferContext(ctx, false, System.Length(ctx));
+  ImplSign(sk, skOff, LCtx, phflag, m, mOff, mLen, sig, sigOff);
+end;
+
+procedure TEd25519.Sign(const sk: TCryptoLibByteArray; skOff: Int32;
+  const pk: TCryptoLibByteArray; pkOff: Int32;
+  const ctx, m: TCryptoLibByteArray; mOff, mLen: Int32;
+  const sig: TCryptoLibByteArray; sigOff: Int32);
+var
+  phflag: Byte;
+  LCtx: TCryptoLibCustomByteArrayBuffer;
+begin
+  phflag := $00;
+  LCtx := ConstructCustomByteArrayBufferContext(ctx, false, System.Length(ctx));
+  ImplSign(sk, skOff, pk, pkOff, LCtx, phflag, m, mOff, mLen, sig, sigOff);
+end;
+
+procedure TEd25519.SignPreHash(const sk: TCryptoLibByteArray; skOff: Int32;
+  const ctx, ph: TCryptoLibByteArray; phOff: Int32;
+  const sig: TCryptoLibByteArray; sigOff: Int32);
+var
+  phflag: Byte;
+  LCtx: TCryptoLibCustomByteArrayBuffer;
+begin
+  phflag := $01;
+  LCtx := ConstructCustomByteArrayBufferContext(ctx, false, System.Length(ctx));
+  ImplSign(sk, skOff, LCtx, phflag, ph, phOff, PreHashSize, sig, sigOff);
+end;
+
+procedure TEd25519.SignPreHash(const sk: TCryptoLibByteArray; skOff: Int32;
+  const pk: TCryptoLibByteArray; pkOff: Int32;
+  const ctx, ph: TCryptoLibByteArray; phOff: Int32;
+  const sig: TCryptoLibByteArray; sigOff: Int32);
+var
+  phflag: Byte;
+  LCtx: TCryptoLibCustomByteArrayBuffer;
+begin
+  phflag := $01;
+  LCtx := ConstructCustomByteArrayBufferContext(ctx, false, System.Length(ctx));
+  ImplSign(sk, skOff, pk, pkOff, LCtx, phflag, ph, phOff, PreHashSize,
+    sig, sigOff);
+end;
+
+procedure TEd25519.SignPreHash(const sk: TCryptoLibByteArray; skOff: Int32;
+  const ctx: TCryptoLibByteArray; const ph: IDigest;
+  const sig: TCryptoLibByteArray; sigOff: Int32);
+var
+  phflag: Byte;
+  m: TCryptoLibByteArray;
+  LCtx: TCryptoLibCustomByteArrayBuffer;
+begin
+  phflag := $01;
+  m := ValidateDigestOutputSize(ph);
+  LCtx := ConstructCustomByteArrayBufferContext(ctx, false, System.Length(ctx));
+  ImplSign(sk, skOff, LCtx, phflag, m, 0, System.Length(m), sig, sigOff);
+end;
+
+procedure TEd25519.SignPreHash(const sk: TCryptoLibByteArray; skOff: Int32;
+  const pk: TCryptoLibByteArray; pkOff: Int32; const ctx: TCryptoLibByteArray;
+  const ph: IDigest; const sig: TCryptoLibByteArray; sigOff: Int32);
+var
+  phflag: Byte;
+  m: TCryptoLibByteArray;
+  LCtx: TCryptoLibCustomByteArrayBuffer;
+begin
+  phflag := $01;
+  m := ValidateDigestOutputSize(ph);
+  LCtx := ConstructCustomByteArrayBufferContext(ctx, false, System.Length(ctx));
+  ImplSign(sk, skOff, pk, pkOff, LCtx, phflag, m, 0, System.Length(m),
+    sig, sigOff);
+end;
+
+function TEd25519.Verify(const sig: TCryptoLibByteArray; sigOff: Int32;
+  const pk: TCryptoLibByteArray; pkOff: Int32; const m: TCryptoLibByteArray;
+  mOff, mLen: Int32): Boolean;
+var
+  phflag: Byte;
+begin
+  phflag := $00;
+  result := ImplVerify(sig, sigOff, pk, pkOff, EmptyBytesNil, phflag, m,
+    mOff, mLen);
+end;
+
+function TEd25519.Verify(const sig: TCryptoLibByteArray; sigOff: Int32;
+  const pk: TCryptoLibByteArray; pkOff: Int32;
+  const ctx, m: TCryptoLibByteArray; mOff, mLen: Int32): Boolean;
+var
+  phflag: Byte;
+  LCtx: TCryptoLibCustomByteArrayBuffer;
+begin
+  phflag := $00;
+  LCtx := ConstructCustomByteArrayBufferContext(ctx, false, System.Length(ctx));
+  result := ImplVerify(sig, sigOff, pk, pkOff, LCtx, phflag, m, mOff, mLen);
+end;
+
+function TEd25519.VerifyPreHash(const sig: TCryptoLibByteArray; sigOff: Int32;
+  const pk: TCryptoLibByteArray; pkOff: Int32;
+  const ctx, ph: TCryptoLibByteArray; phOff: Int32): Boolean;
+var
+  phflag: Byte;
+  LCtx: TCryptoLibCustomByteArrayBuffer;
+begin
+  phflag := $01;
+  LCtx := ConstructCustomByteArrayBufferContext(ctx, false, System.Length(ctx));
+  result := ImplVerify(sig, sigOff, pk, pkOff, LCtx, phflag, ph, phOff,
+    PreHashSize);
+end;
+
+function TEd25519.VerifyPreHash(const sig: TCryptoLibByteArray; sigOff: Int32;
+  const pk: TCryptoLibByteArray; pkOff: Int32; const ctx: TCryptoLibByteArray;
+  const ph: IDigest): Boolean;
+var
+  phflag: Byte;
+  m: TCryptoLibByteArray;
+  LCtx: TCryptoLibCustomByteArrayBuffer;
+begin
+  phflag := $01;
+  m := ValidateDigestOutputSize(ph);
+  LCtx := ConstructCustomByteArrayBufferContext(ctx, false, System.Length(ctx));
+  result := ImplVerify(sig, sigOff, pk, pkOff, LCtx, phflag, m, 0,
+    System.Length(m));
+end;
+
+end.

+ 48 - 0
CryptoLib/src/Math/EC/Rfc8032/ClpEd25519Blake2B.pas

@@ -0,0 +1,48 @@
+{ *********************************************************************************** }
+{ *                              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 ClpEd25519Blake2B;
+
+{$I ..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIDigest,
+  ClpEd25519,
+  ClpDigestUtilities,
+  ClpIEd25519Blake2B;
+
+type
+  TEd25519Blake2B = class sealed(TEd25519, IEd25519Blake2B)
+
+  strict protected
+
+    function CreateDigest(): IDigest; override;
+
+  end;
+
+implementation
+
+{ TEd25519Blake2B }
+
+function TEd25519Blake2B.CreateDigest: IDigest;
+begin
+  result := TDigestUtilities.GetDigest('BLAKE2B-512');
+end;
+
+end.

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

@@ -10,7 +10,7 @@
       <PathDelim Value="\"/>
       <SearchPaths>
         <IncludeFiles Value="..\..\Include"/>
-        <OtherUnitFiles Value="..\..\Asn1;..\..\Asn1\CryptoPro;..\..\Asn1\Nist;..\..\Asn1\Oiw;..\..\Asn1\Pkcs;..\..\Asn1\RossStandart;..\..\Asn1\Sec;..\..\Asn1\TeleTrust;..\..\Asn1\X9;..\..\Crypto;..\..\Crypto\Generators;..\..\Crypto\Parameters;..\..\Crypto\Prng;..\..\Crypto\Signers;..\..\Interfaces;..\..\Math;..\..\Math\EC;..\..\Math\EC\Abc;..\..\Math\EC\Endo;..\..\Math\EC\Multiplier;..\..\Math\Field;..\..\Math\Raw;..\..\Security;..\..\Utils;..\..\Utils\Encoders;..\..\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;..\..\Asn1\Bsi;..\..\Asn1\Eac;..\..\Crypto\Signers\SignersEncodings"/>
+        <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\Encoders;..\..\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;..\..\Asn1\Bsi;..\..\Asn1\Eac;..\..\Crypto\Signers\SignersEncodings;..\..\Math\EC\Custom\Djb;..\..\Math\EC\Rfc7748;..\..\Math\EC\Rfc8032;..\..\Asn1\Edec"/>
         <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="3" Minor="1"/>
-    <Files Count="284">
+    <Files Count="334">
       <Item1>
         <Filename Value="..\..\Asn1\ClpOidTokenizer.pas"/>
         <UnitName Value="ClpOidTokenizer"/>
@@ -1164,6 +1164,206 @@ Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring the devel
         <Filename Value="..\..\Crypto\Parameters\ClpIESParameterSpec.pas"/>
         <UnitName Value="ClpIESParameterSpec"/>
       </Item284>
+      <Item285>
+        <Filename Value="..\..\Math\EC\Custom\Djb\ClpCurve25519Custom.pas"/>
+        <UnitName Value="ClpCurve25519Custom"/>
+      </Item285>
+      <Item286>
+        <Filename Value="..\..\Interfaces\ClpICurve25519Custom.pas"/>
+        <UnitName Value="ClpICurve25519Custom"/>
+      </Item286>
+      <Item287>
+        <Filename Value="..\..\Crypto\Engines\ClpSpeckLegacyEngine.pas"/>
+        <UnitName Value="ClpSpeckLegacyEngine"/>
+      </Item287>
+      <Item288>
+        <Filename Value="..\..\Interfaces\ClpISpeckLegacyEngine.pas"/>
+        <UnitName Value="ClpISpeckLegacyEngine"/>
+      </Item288>
+      <Item289>
+        <Filename Value="..\..\Interfaces\ClpIEd25519.pas"/>
+        <UnitName Value="ClpIEd25519"/>
+      </Item289>
+      <Item290>
+        <Filename Value="..\..\Interfaces\ClpIEd25519Blake2B.pas"/>
+        <UnitName Value="ClpIEd25519Blake2B"/>
+      </Item290>
+      <Item291>
+        <Filename Value="..\..\Math\EC\Rfc7748\ClpX25519Field.pas"/>
+        <UnitName Value="ClpX25519Field"/>
+      </Item291>
+      <Item292>
+        <Filename Value="..\..\Math\EC\Rfc8032\ClpEd25519.pas"/>
+        <UnitName Value="ClpEd25519"/>
+      </Item292>
+      <Item293>
+        <Filename Value="..\..\Math\EC\Rfc8032\ClpEd25519Blake2B.pas"/>
+        <UnitName Value="ClpEd25519Blake2B"/>
+      </Item293>
+      <Item294>
+        <Filename Value="..\..\Math\EC\Rfc7748\ClpX25519.pas"/>
+        <UnitName Value="ClpX25519"/>
+      </Item294>
+      <Item295>
+        <Filename Value="..\..\Asn1\Edec\ClpEdECObjectIdentifiers.pas"/>
+        <UnitName Value="ClpEdECObjectIdentifiers"/>
+      </Item295>
+      <Item296>
+        <Filename Value="..\..\Interfaces\ClpIEd25519CtxBlake2BSigner.pas"/>
+        <UnitName Value="ClpIEd25519CtxBlake2BSigner"/>
+      </Item296>
+      <Item297>
+        <Filename Value="..\..\Interfaces\ClpIEd25519PhBlake2BSigner.pas"/>
+        <UnitName Value="ClpIEd25519PhBlake2BSigner"/>
+      </Item297>
+      <Item298>
+        <Filename Value="..\..\Interfaces\ClpIEd25519PhSigner.pas"/>
+        <UnitName Value="ClpIEd25519PhSigner"/>
+      </Item298>
+      <Item299>
+        <Filename Value="..\..\Interfaces\ClpIEd25519CtxSigner.pas"/>
+        <UnitName Value="ClpIEd25519CtxSigner"/>
+      </Item299>
+      <Item300>
+        <Filename Value="..\..\Interfaces\ClpIEd25519Blake2BSigner.pas"/>
+        <UnitName Value="ClpIEd25519Blake2BSigner"/>
+      </Item300>
+      <Item301>
+        <Filename Value="..\..\Interfaces\ClpIEd25519Signer.pas"/>
+        <UnitName Value="ClpIEd25519Signer"/>
+      </Item301>
+      <Item302>
+        <Filename Value="..\..\Interfaces\ClpIEd25519Blake2BKeyGenerationParameters.pas"/>
+        <UnitName Value="ClpIEd25519Blake2BKeyGenerationParameters"/>
+      </Item302>
+      <Item303>
+        <Filename Value="..\..\Interfaces\ClpIEd25519KeyGenerationParameters.pas"/>
+        <UnitName Value="ClpIEd25519KeyGenerationParameters"/>
+      </Item303>
+      <Item304>
+        <Filename Value="..\..\Interfaces\ClpIX25519KeyGenerationParameters.pas"/>
+        <UnitName Value="ClpIX25519KeyGenerationParameters"/>
+      </Item304>
+      <Item305>
+        <Filename Value="..\..\Interfaces\ClpIEd25519Blake2BKeyPairGenerator.pas"/>
+        <UnitName Value="ClpIEd25519Blake2BKeyPairGenerator"/>
+      </Item305>
+      <Item306>
+        <Filename Value="..\..\Interfaces\ClpIEd25519KeyPairGenerator.pas"/>
+        <UnitName Value="ClpIEd25519KeyPairGenerator"/>
+      </Item306>
+      <Item307>
+        <Filename Value="..\..\Interfaces\ClpIX25519KeyPairGenerator.pas"/>
+        <UnitName Value="ClpIX25519KeyPairGenerator"/>
+      </Item307>
+      <Item308>
+        <Filename Value="..\..\Interfaces\ClpIEd25519Blake2BPrivateKeyParameters.pas"/>
+        <UnitName Value="ClpIEd25519Blake2BPrivateKeyParameters"/>
+      </Item308>
+      <Item309>
+        <Filename Value="..\..\Interfaces\ClpIEd25519Blake2BPublicKeyParameters.pas"/>
+        <UnitName Value="ClpIEd25519Blake2BPublicKeyParameters"/>
+      </Item309>
+      <Item310>
+        <Filename Value="..\..\Interfaces\ClpIEd25519PrivateKeyParameters.pas"/>
+        <UnitName Value="ClpIEd25519PrivateKeyParameters"/>
+      </Item310>
+      <Item311>
+        <Filename Value="..\..\Interfaces\ClpIEd25519PublicKeyParameters.pas"/>
+        <UnitName Value="ClpIEd25519PublicKeyParameters"/>
+      </Item311>
+      <Item312>
+        <Filename Value="..\..\Interfaces\ClpIX25519PublicKeyParameters.pas"/>
+        <UnitName Value="ClpIX25519PublicKeyParameters"/>
+      </Item312>
+      <Item313>
+        <Filename Value="..\..\Interfaces\ClpIX25519PrivateKeyParameters.pas"/>
+        <UnitName Value="ClpIX25519PrivateKeyParameters"/>
+      </Item313>
+      <Item314>
+        <Filename Value="..\..\Interfaces\ClpIX25519Agreement.pas"/>
+        <UnitName Value="ClpIX25519Agreement"/>
+      </Item314>
+      <Item315>
+        <Filename Value="..\..\Interfaces\ClpIRawAgreement.pas"/>
+        <UnitName Value="ClpIRawAgreement"/>
+      </Item315>
+      <Item316>
+        <Filename Value="..\..\Crypto\Agreement\ClpX25519Agreement.pas"/>
+        <UnitName Value="ClpX25519Agreement"/>
+      </Item316>
+      <Item317>
+        <Filename Value="..\..\Crypto\Parameters\ClpEd25519Blake2BKeyGenerationParameters.pas"/>
+        <UnitName Value="ClpEd25519Blake2BKeyGenerationParameters"/>
+      </Item317>
+      <Item318>
+        <Filename Value="..\..\Crypto\Parameters\ClpEd25519KeyGenerationParameters.pas"/>
+        <UnitName Value="ClpEd25519KeyGenerationParameters"/>
+      </Item318>
+      <Item319>
+        <Filename Value="..\..\Crypto\Parameters\ClpX25519KeyGenerationParameters.pas"/>
+        <UnitName Value="ClpX25519KeyGenerationParameters"/>
+      </Item319>
+      <Item320>
+        <Filename Value="..\..\Crypto\Parameters\ClpEd25519Blake2BPrivateKeyParameters.pas"/>
+        <UnitName Value="ClpEd25519Blake2BPrivateKeyParameters"/>
+      </Item320>
+      <Item321>
+        <Filename Value="..\..\Crypto\Parameters\ClpEd25519Blake2BPublicKeyParameters.pas"/>
+        <UnitName Value="ClpEd25519Blake2BPublicKeyParameters"/>
+      </Item321>
+      <Item322>
+        <Filename Value="..\..\Crypto\Parameters\ClpEd25519PublicKeyParameters.pas"/>
+        <UnitName Value="ClpEd25519PublicKeyParameters"/>
+      </Item322>
+      <Item323>
+        <Filename Value="..\..\Crypto\Parameters\ClpEd25519PrivateKeyParameters.pas"/>
+        <UnitName Value="ClpEd25519PrivateKeyParameters"/>
+      </Item323>
+      <Item324>
+        <Filename Value="..\..\Crypto\Parameters\ClpX25519PublicKeyParameters.pas"/>
+        <UnitName Value="ClpX25519PublicKeyParameters"/>
+      </Item324>
+      <Item325>
+        <Filename Value="..\..\Crypto\Parameters\ClpX25519PrivateKeyParameters.pas"/>
+        <UnitName Value="ClpX25519PrivateKeyParameters"/>
+      </Item325>
+      <Item326>
+        <Filename Value="..\..\Crypto\Generators\ClpEd25519Blake2BKeyPairGenerator.pas"/>
+        <UnitName Value="ClpEd25519Blake2BKeyPairGenerator"/>
+      </Item326>
+      <Item327>
+        <Filename Value="..\..\Crypto\Generators\ClpEd25519KeyPairGenerator.pas"/>
+        <UnitName Value="ClpEd25519KeyPairGenerator"/>
+      </Item327>
+      <Item328>
+        <Filename Value="..\..\Crypto\Generators\ClpX25519KeyPairGenerator.pas"/>
+        <UnitName Value="ClpX25519KeyPairGenerator"/>
+      </Item328>
+      <Item329>
+        <Filename Value="..\..\Crypto\Signers\ClpEd25519PhBlake2BSigner.pas"/>
+        <UnitName Value="ClpEd25519PhBlake2BSigner"/>
+      </Item329>
+      <Item330>
+        <Filename Value="..\..\Crypto\Signers\ClpEd25519PhSigner.pas"/>
+        <UnitName Value="ClpEd25519PhSigner"/>
+      </Item330>
+      <Item331>
+        <Filename Value="..\..\Crypto\Signers\ClpEd25519Signer.pas"/>
+        <UnitName Value="ClpEd25519Signer"/>
+      </Item331>
+      <Item332>
+        <Filename Value="..\..\Crypto\Signers\ClpEd25519CtxBlake2BSigner.pas"/>
+        <UnitName Value="ClpEd25519CtxBlake2BSigner"/>
+      </Item332>
+      <Item333>
+        <Filename Value="..\..\Crypto\Signers\ClpEd25519CtxSigner.pas"/>
+        <UnitName Value="ClpEd25519CtxSigner"/>
+      </Item333>
+      <Item334>
+        <Filename Value="..\..\Crypto\Signers\ClpEd25519Blake2BSigner.pas"/>
+        <UnitName Value="ClpEd25519Blake2BSigner"/>
+      </Item334>
     </Files>
     <RequiredPkgs Count="3">
       <Item1>

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

@@ -99,7 +99,28 @@ uses
   ClpIXSalsa20Engine, ClpISalsa20Engine, ClpBufferedStreamCipher, 
   ClpSalsa20Engine, ClpXSalsa20Engine, ClpChaChaEngine, ClpIRijndaelEngine, 
   ClpRijndaelEngine, ClpIIESParameterSpec, ClpIAlgorithmParameterSpec, 
-  ClpIESParameterSpec;
+  ClpIESParameterSpec, ClpCurve25519Custom, ClpICurve25519Custom, 
+  ClpSpeckLegacyEngine, ClpISpeckLegacyEngine, ClpIEd25519, 
+  ClpIEd25519Blake2B, ClpX25519Field, ClpEd25519, ClpEd25519Blake2B, 
+  ClpX25519, ClpEdECObjectIdentifiers, ClpIEd25519CtxBlake2BSigner, 
+  ClpIEd25519PhBlake2BSigner, ClpIEd25519PhSigner, ClpIEd25519CtxSigner, 
+  ClpIEd25519Blake2BSigner, ClpIEd25519Signer, 
+  ClpIEd25519Blake2BKeyGenerationParameters, 
+  ClpIEd25519KeyGenerationParameters, ClpIX25519KeyGenerationParameters, 
+  ClpIEd25519Blake2BKeyPairGenerator, ClpIEd25519KeyPairGenerator, 
+  ClpIX25519KeyPairGenerator, ClpIEd25519Blake2BPrivateKeyParameters, 
+  ClpIEd25519Blake2BPublicKeyParameters, ClpIEd25519PrivateKeyParameters, 
+  ClpIEd25519PublicKeyParameters, ClpIX25519PublicKeyParameters, 
+  ClpIX25519PrivateKeyParameters, ClpIX25519Agreement, ClpIRawAgreement, 
+  ClpX25519Agreement, ClpEd25519Blake2BKeyGenerationParameters, 
+  ClpEd25519KeyGenerationParameters, ClpX25519KeyGenerationParameters, 
+  ClpEd25519Blake2BPrivateKeyParameters, ClpEd25519Blake2BPublicKeyParameters, 
+  ClpEd25519PublicKeyParameters, ClpEd25519PrivateKeyParameters, 
+  ClpX25519PublicKeyParameters, ClpX25519PrivateKeyParameters, 
+  ClpEd25519Blake2BKeyPairGenerator, ClpEd25519KeyPairGenerator, 
+  ClpX25519KeyPairGenerator, ClpEd25519PhBlake2BSigner, ClpEd25519PhSigner, 
+  ClpEd25519Signer, ClpEd25519CtxBlake2BSigner, ClpEd25519CtxSigner, 
+  ClpEd25519Blake2BSigner;
 
 implementation
 

+ 39 - 5
CryptoLib/src/Security/ClpGeneratorUtilities.pas

@@ -31,11 +31,18 @@ uses
   ClpIAsn1Objects,
   ClpDsaKeyPairGenerator,
   ClpIDsaKeyPairGenerator,
+  ClpEd25519KeyPairGenerator,
+  ClpIEd25519KeyPairGenerator,
+  ClpEd25519Blake2BKeyPairGenerator,
+  ClpIEd25519Blake2BKeyPairGenerator,
+  ClpX25519KeyPairGenerator,
+  ClpIX25519KeyPairGenerator,
   ClpIAsymmetricCipherKeyPairGenerator,
   ClpNistObjectIdentifiers,
   ClpIanaObjectIdentifiers,
   ClpPkcsObjectIdentifiers,
   ClpRosstandartObjectIdentifiers,
+  ClpEdECObjectIdentifiers,
   ClpStringUtils,
   ClpCryptoLibTypes;
 
@@ -125,10 +132,10 @@ class procedure TGeneratorUtilities.AddKgAlgorithm(const canonicalName: String;
 var
   alias: string;
 begin
-  FkgAlgorithms.Add(canonicalName, canonicalName);
+  FkgAlgorithms.Add(UpperCase(canonicalName), canonicalName);
   for alias in aliases do
   begin
-    FkgAlgorithms.Add(alias, canonicalName);
+    FkgAlgorithms.Add(UpperCase(alias), canonicalName);
   end;
 
 end;
@@ -138,10 +145,10 @@ class procedure TGeneratorUtilities.AddKpgAlgorithm(const canonicalName: String;
 var
   alias: string;
 begin
-  FkpgAlgorithms.Add(canonicalName, canonicalName);
+  FkpgAlgorithms.Add(UpperCase(canonicalName), canonicalName);
   for alias in aliases do
   begin
-    FkpgAlgorithms.Add(alias, canonicalName);
+    FkpgAlgorithms.Add(UpperCase(alias), canonicalName);
   end;
 
 end;
@@ -159,7 +166,7 @@ begin
 
   for alias in aliases do
   begin
-    FkgAlgorithms.Add(alias, mainName);
+    FkgAlgorithms.Add(UpperCase(alias), mainName);
   end;
 
 end;
@@ -243,8 +250,16 @@ begin
 
   AddKpgAlgorithm('DSA', []);
   AddKpgAlgorithm('ECDH', ['ECIES']);
+  AddKpgAlgorithm('ECDHC', []);
   AddKpgAlgorithm('ECDSA', []);
 
+  TEdECObjectIdentifiers.Boot;
+
+  AddKpgAlgorithm('Ed25519', ['Ed25519ctx', 'Ed25519ph',
+    TEdECObjectIdentifiers.id_Ed25519.ID]);
+  AddKpgAlgorithm('Ed25519Blake2B', ['Ed25519Blake2Bctx', 'Ed25519Blake2Bph']);
+  AddKpgAlgorithm('X25519', TEdECObjectIdentifiers.id_X25519.ID);
+
   AddDefaultKeySizeEntries(128, ['AES128', 'BLOWFISH', 'HMACMD2', 'HMACMD4',
     'HMACMD5', 'HMACRIPEMD128', 'SALSA20']);
   AddDefaultKeySizeEntries(160, ['HMACRIPEMD160', 'HMACSHA1']);
@@ -375,6 +390,25 @@ begin
     Exit;
   end;
 
+  if (canonicalName = 'Ed25519') then
+  begin
+    result := TEd25519KeyPairGenerator.Create() as IEd25519KeyPairGenerator;
+    Exit;
+  end;
+
+  if (canonicalName = 'Ed25519Blake2B') then
+  begin
+    result := TEd25519Blake2BKeyPairGenerator.Create()
+      as IEd25519Blake2BKeyPairGenerator;
+    Exit;
+  end;
+
+  if (canonicalName = 'X25519') then
+  begin
+    result := TX25519KeyPairGenerator.Create() as IX25519KeyPairGenerator;
+    Exit;
+  end;
+
   raise ESecurityUtilityCryptoLibException.CreateResFmt
     (@SKeyPairGeneratorAlgorithmNotSupported, [algorithm, canonicalName]);