Explorar o código

First Commit.

Ugochukwu Mmaduekwe %!s(int64=8) %!d(string=hai) anos
pai
achega
5b5a014ec7
Modificáronse 100 ficheiros con 22984 adicións e 0 borrados
  1. 302 0
      CryptoLib.Samples/Delphi.Samples/UsageSamples.dpr
  2. 73 0
      CryptoLib.Samples/FreePascal.Samples/UsageSamples.lpi
  3. 27 0
      CryptoLib.Samples/FreePascal.Samples/UsageSamples.lpr
  4. 398 0
      CryptoLib.Samples/src/UsageExamples.pas
  5. 453 0
      CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.dpr
  6. 138 0
      CryptoLib.Tests/FreePascal.Tests/CryptoLib.Tests.lpi
  7. 32 0
      CryptoLib.Tests/FreePascal.Tests/CryptoLib.lpr
  8. 609 0
      CryptoLib.Tests/src/Asn1/Asn1SequenceParserTests.pas
  9. 216 0
      CryptoLib.Tests/src/Asn1/DerApplicationSpecificTests.pas
  10. 210 0
      CryptoLib.Tests/src/Asn1/EqualsAndHashCodeTests.pas
  11. 225 0
      CryptoLib.Tests/src/Asn1/OIDTests.pas
  12. 1373 0
      CryptoLib.Tests/src/Math/BigIntegerTests.pas
  13. 302 0
      CryptoLib.Tests/src/Math/EC/Custom/Sec/SecP384R1FieldTests.pas
  14. 340 0
      CryptoLib.Tests/src/Math/ECAlgorithmsTests.pas
  15. 797 0
      CryptoLib.Tests/src/Math/ECPointTests.pas
  16. 399 0
      CryptoLib.Tests/src/Others/ECDsa5Tests.pas
  17. 655 0
      CryptoLib.Tests/src/Others/ECTests.pas
  18. 229 0
      CryptoLib.Tests/src/Others/NamedCurveTests.pas
  19. 227 0
      CryptoLib.Tests/src/Others/SignerUtilitiesTests.pas
  20. 247 0
      CryptoLib.Tests/src/Security/SecureRandomTests.pas
  21. 483 0
      CryptoLib.Tests/src/Utils/ClpFixedSecureRandom.pas
  22. 68 0
      CryptoLib.Tests/src/Utils/ClpIFixedSecureRandom.pas
  23. 153 0
      CryptoLib/src/Asn1/ClpAsn1Encodable.pas
  24. 140 0
      CryptoLib/src/Asn1/ClpAsn1EncodableVector.pas
  25. 64 0
      CryptoLib/src/Asn1/ClpAsn1Generator.pas
  26. 726 0
      CryptoLib/src/Asn1/ClpAsn1InputStream.pas
  27. 49 0
      CryptoLib/src/Asn1/ClpAsn1Null.pas
  28. 141 0
      CryptoLib/src/Asn1/ClpAsn1Object.pas
  29. 219 0
      CryptoLib/src/Asn1/ClpAsn1OctetString.pas
  30. 46 0
      CryptoLib/src/Asn1/ClpAsn1OutputStream.pas
  31. 419 0
      CryptoLib/src/Asn1/ClpAsn1Sequence.pas
  32. 530 0
      CryptoLib/src/Asn1/ClpAsn1Set.pas
  33. 456 0
      CryptoLib/src/Asn1/ClpAsn1StreamParser.pas
  34. 308 0
      CryptoLib/src/Asn1/ClpAsn1TaggedObject.pas
  35. 64 0
      CryptoLib/src/Asn1/ClpAsn1Tags.pas
  36. 48 0
      CryptoLib/src/Asn1/ClpBerApplicationSpecific.pas
  37. 70 0
      CryptoLib/src/Asn1/ClpBerApplicationSpecificParser.pas
  38. 84 0
      CryptoLib/src/Asn1/ClpBerBitString.pas
  39. 155 0
      CryptoLib/src/Asn1/ClpBerGenerator.pas
  40. 92 0
      CryptoLib/src/Asn1/ClpBerNull.pas
  41. 214 0
      CryptoLib/src/Asn1/ClpBerOctetString.pas
  42. 91 0
      CryptoLib/src/Asn1/ClpBerOctetStringParser.pas
  43. 48 0
      CryptoLib/src/Asn1/ClpBerOutputStream.pas
  44. 162 0
      CryptoLib/src/Asn1/ClpBerSequence.pas
  45. 56 0
      CryptoLib/src/Asn1/ClpBerSequenceGenerator.pas
  46. 66 0
      CryptoLib/src/Asn1/ClpBerSequenceParser.pas
  47. 179 0
      CryptoLib/src/Asn1/ClpBerSet.pas
  48. 66 0
      CryptoLib/src/Asn1/ClpBerSetParser.pas
  49. 206 0
      CryptoLib/src/Asn1/ClpBerTaggedObject.pas
  50. 115 0
      CryptoLib/src/Asn1/ClpBerTaggedObjectParser.pas
  51. 171 0
      CryptoLib/src/Asn1/ClpConstructedOctetStream.pas
  52. 202 0
      CryptoLib/src/Asn1/ClpDefiniteLengthInputStream.pas
  53. 363 0
      CryptoLib/src/Asn1/ClpDerApplicationSpecific.pas
  54. 417 0
      CryptoLib/src/Asn1/ClpDerBitString.pas
  55. 211 0
      CryptoLib/src/Asn1/ClpDerBmpString.pas
  56. 261 0
      CryptoLib/src/Asn1/ClpDerBoolean.pas
  57. 234 0
      CryptoLib/src/Asn1/ClpDerEnumerated.pas
  58. 363 0
      CryptoLib/src/Asn1/ClpDerExternal.pas
  59. 66 0
      CryptoLib/src/Asn1/ClpDerExternalParser.pas
  60. 164 0
      CryptoLib/src/Asn1/ClpDerGeneralString.pas
  61. 163 0
      CryptoLib/src/Asn1/ClpDerGenerator.pas
  62. 202 0
      CryptoLib/src/Asn1/ClpDerGraphicString.pas
  63. 253 0
      CryptoLib/src/Asn1/ClpDerIA5String.pas
  64. 209 0
      CryptoLib/src/Asn1/ClpDerInteger.pas
  65. 100 0
      CryptoLib/src/Asn1/ClpDerNull.pas
  66. 252 0
      CryptoLib/src/Asn1/ClpDerNumericString.pas
  67. 578 0
      CryptoLib/src/Asn1/ClpDerObjectIdentifier.pas
  68. 77 0
      CryptoLib/src/Asn1/ClpDerOctetString.pas
  69. 86 0
      CryptoLib/src/Asn1/ClpDerOctetStringParser.pas
  70. 199 0
      CryptoLib/src/Asn1/ClpDerOutputStream.pas
  71. 272 0
      CryptoLib/src/Asn1/ClpDerPrintableString.pas
  72. 177 0
      CryptoLib/src/Asn1/ClpDerSequence.pas
  73. 100 0
      CryptoLib/src/Asn1/ClpDerSequenceGenerator.pas
  74. 66 0
      CryptoLib/src/Asn1/ClpDerSequenceParser.pas
  75. 208 0
      CryptoLib/src/Asn1/ClpDerSet.pas
  76. 66 0
      CryptoLib/src/Asn1/ClpDerSetParser.pas
  77. 60 0
      CryptoLib/src/Asn1/ClpDerStringBase.pas
  78. 196 0
      CryptoLib/src/Asn1/ClpDerT61String.pas
  79. 128 0
      CryptoLib/src/Asn1/ClpDerTaggedObject.pas
  80. 206 0
      CryptoLib/src/Asn1/ClpDerUniversalString.pas
  81. 201 0
      CryptoLib/src/Asn1/ClpDerUtf8String.pas
  82. 202 0
      CryptoLib/src/Asn1/ClpDerVideotexString.pas
  83. 210 0
      CryptoLib/src/Asn1/ClpDerVisibleString.pas
  84. 158 0
      CryptoLib/src/Asn1/ClpIndefiniteLengthInputStream.pas
  85. 81 0
      CryptoLib/src/Asn1/ClpLimitedInputStream.pas
  86. 92 0
      CryptoLib/src/Asn1/ClpOidTokenizer.pas
  87. 351 0
      CryptoLib/src/Asn1/CryptoPro/ClpCryptoProObjectIdentifiers.pas
  88. 410 0
      CryptoLib/src/Asn1/CryptoPro/ClpECGost3410NamedCurves.pas
  89. 166 0
      CryptoLib/src/Asn1/Nist/ClpNistObjectIdentifiers.pas
  90. 70 0
      CryptoLib/src/Asn1/Oiw/ClpOiwObjectIdentifiers.pas
  91. 102 0
      CryptoLib/src/Asn1/Pkcs/ClpPkcsObjectIdentifiers.pas
  92. 305 0
      CryptoLib/src/Asn1/RossStandart/ClpRosstandartObjectIdentifiers.pas
  93. 420 0
      CryptoLib/src/Asn1/Sec/ClpSecNamedCurves.pas
  94. 352 0
      CryptoLib/src/Asn1/Sec/ClpSecObjectIdentifiers.pas
  95. 125 0
      CryptoLib/src/Asn1/TeleTrust/ClpTeleTrusTObjectIdentifiers.pas
  96. 171 0
      CryptoLib/src/Asn1/X9/ClpECNamedCurveTable.pas
  97. 230 0
      CryptoLib/src/Asn1/X9/ClpX9Curve.pas
  98. 308 0
      CryptoLib/src/Asn1/X9/ClpX9ECParameters.pas
  99. 81 0
      CryptoLib/src/Asn1/X9/ClpX9ECParametersHolder.pas
  100. 129 0
      CryptoLib/src/Asn1/X9/ClpX9ECPoint.pas

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

@@ -0,0 +1,302 @@
+program UsageSamples;
+
+{$APPTYPE CONSOLE}
+{$R *.res}
+
+{$WARN DUPLICATE_CTOR_DTOR OFF}
+
+uses
+  SysUtils,
+   ClpCryptoProObjectIdentifiers in '..\..\CryptoLib\src\Asn1\CryptoPro\ClpCryptoProObjectIdentifiers.pas',
+  ClpECGost3410NamedCurves in '..\..\CryptoLib\src\Asn1\CryptoPro\ClpECGost3410NamedCurves.pas',
+  ClpNistObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Nist\ClpNistObjectIdentifiers.pas',
+  ClpOiwObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Oiw\ClpOiwObjectIdentifiers.pas',
+  ClpPkcsObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Pkcs\ClpPkcsObjectIdentifiers.pas',
+  ClpRosstandartObjectIdentifiers in '..\..\CryptoLib\src\Asn1\RossStandart\ClpRosstandartObjectIdentifiers.pas',
+  ClpSecNamedCurves in '..\..\CryptoLib\src\Asn1\Sec\ClpSecNamedCurves.pas',
+  ClpSecObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Sec\ClpSecObjectIdentifiers.pas',
+  ClpTeleTrusTObjectIdentifiers in '..\..\CryptoLib\src\Asn1\TeleTrust\ClpTeleTrusTObjectIdentifiers.pas',
+  ClpECNamedCurveTable in '..\..\CryptoLib\src\Asn1\X9\ClpECNamedCurveTable.pas',
+  ClpX9Curve in '..\..\CryptoLib\src\Asn1\X9\ClpX9Curve.pas',
+  ClpX9ECParameters in '..\..\CryptoLib\src\Asn1\X9\ClpX9ECParameters.pas',
+  ClpX9ECParametersHolder in '..\..\CryptoLib\src\Asn1\X9\ClpX9ECParametersHolder.pas',
+  ClpX9ECPoint in '..\..\CryptoLib\src\Asn1\X9\ClpX9ECPoint.pas',
+  ClpX9FieldElement in '..\..\CryptoLib\src\Asn1\X9\ClpX9FieldElement.pas',
+  ClpX9FieldID in '..\..\CryptoLib\src\Asn1\X9\ClpX9FieldID.pas',
+  ClpX9IntegerConverter in '..\..\CryptoLib\src\Asn1\X9\ClpX9IntegerConverter.pas',
+  ClpX9ObjectIdentifiers in '..\..\CryptoLib\src\Asn1\X9\ClpX9ObjectIdentifiers.pas',
+  ClpAsn1Encodable in '..\..\CryptoLib\src\Asn1\ClpAsn1Encodable.pas',
+  ClpAsn1EncodableVector in '..\..\CryptoLib\src\Asn1\ClpAsn1EncodableVector.pas',
+  ClpAsn1InputStream in '..\..\CryptoLib\src\Asn1\ClpAsn1InputStream.pas',
+  ClpAsn1Null in '..\..\CryptoLib\src\Asn1\ClpAsn1Null.pas',
+  ClpAsn1Object in '..\..\CryptoLib\src\Asn1\ClpAsn1Object.pas',
+  ClpAsn1OctetString in '..\..\CryptoLib\src\Asn1\ClpAsn1OctetString.pas',
+  ClpAsn1OutputStream in '..\..\CryptoLib\src\Asn1\ClpAsn1OutputStream.pas',
+  ClpAsn1Sequence in '..\..\CryptoLib\src\Asn1\ClpAsn1Sequence.pas',
+  ClpAsn1Set in '..\..\CryptoLib\src\Asn1\ClpAsn1Set.pas',
+  ClpAsn1StreamParser in '..\..\CryptoLib\src\Asn1\ClpAsn1StreamParser.pas',
+  ClpAsn1TaggedObject in '..\..\CryptoLib\src\Asn1\ClpAsn1TaggedObject.pas',
+  ClpAsn1Tags in '..\..\CryptoLib\src\Asn1\ClpAsn1Tags.pas',
+  ClpBerApplicationSpecific in '..\..\CryptoLib\src\Asn1\ClpBerApplicationSpecific.pas',
+  ClpBerApplicationSpecificParser in '..\..\CryptoLib\src\Asn1\ClpBerApplicationSpecificParser.pas',
+  ClpBerBitString in '..\..\CryptoLib\src\Asn1\ClpBerBitString.pas',
+  ClpBerNull in '..\..\CryptoLib\src\Asn1\ClpBerNull.pas',
+  ClpBerOctetString in '..\..\CryptoLib\src\Asn1\ClpBerOctetString.pas',
+  ClpBerOctetStringParser in '..\..\CryptoLib\src\Asn1\ClpBerOctetStringParser.pas',
+  ClpBerOutputStream in '..\..\CryptoLib\src\Asn1\ClpBerOutputStream.pas',
+  ClpBerSequence in '..\..\CryptoLib\src\Asn1\ClpBerSequence.pas',
+  ClpBerSequenceParser in '..\..\CryptoLib\src\Asn1\ClpBerSequenceParser.pas',
+  ClpBerSet in '..\..\CryptoLib\src\Asn1\ClpBerSet.pas',
+  ClpBerSetParser in '..\..\CryptoLib\src\Asn1\ClpBerSetParser.pas',
+  ClpBerTaggedObject in '..\..\CryptoLib\src\Asn1\ClpBerTaggedObject.pas',
+  ClpBerTaggedObjectParser in '..\..\CryptoLib\src\Asn1\ClpBerTaggedObjectParser.pas',
+  ClpConstructedOctetStream in '..\..\CryptoLib\src\Asn1\ClpConstructedOctetStream.pas',
+  ClpDefiniteLengthInputStream in '..\..\CryptoLib\src\Asn1\ClpDefiniteLengthInputStream.pas',
+  ClpDerApplicationSpecific in '..\..\CryptoLib\src\Asn1\ClpDerApplicationSpecific.pas',
+  ClpDerBitString in '..\..\CryptoLib\src\Asn1\ClpDerBitString.pas',
+  ClpDerBmpString in '..\..\CryptoLib\src\Asn1\ClpDerBmpString.pas',
+  ClpDerBoolean in '..\..\CryptoLib\src\Asn1\ClpDerBoolean.pas',
+  ClpDerEnumerated in '..\..\CryptoLib\src\Asn1\ClpDerEnumerated.pas',
+  ClpDerExternal in '..\..\CryptoLib\src\Asn1\ClpDerExternal.pas',
+  ClpDerExternalParser in '..\..\CryptoLib\src\Asn1\ClpDerExternalParser.pas',
+  ClpDerGeneralString in '..\..\CryptoLib\src\Asn1\ClpDerGeneralString.pas',
+  ClpDerGraphicString in '..\..\CryptoLib\src\Asn1\ClpDerGraphicString.pas',
+  ClpDerIA5String in '..\..\CryptoLib\src\Asn1\ClpDerIA5String.pas',
+  ClpDerInteger in '..\..\CryptoLib\src\Asn1\ClpDerInteger.pas',
+  ClpDerNull in '..\..\CryptoLib\src\Asn1\ClpDerNull.pas',
+  ClpDerNumericString in '..\..\CryptoLib\src\Asn1\ClpDerNumericString.pas',
+  ClpDerObjectIdentifier in '..\..\CryptoLib\src\Asn1\ClpDerObjectIdentifier.pas',
+  ClpDerOctetString in '..\..\CryptoLib\src\Asn1\ClpDerOctetString.pas',
+  ClpDerOctetStringParser in '..\..\CryptoLib\src\Asn1\ClpDerOctetStringParser.pas',
+  ClpDerOutputStream in '..\..\CryptoLib\src\Asn1\ClpDerOutputStream.pas',
+  ClpDerPrintableString in '..\..\CryptoLib\src\Asn1\ClpDerPrintableString.pas',
+  ClpDerSequence in '..\..\CryptoLib\src\Asn1\ClpDerSequence.pas',
+  ClpDerSequenceParser in '..\..\CryptoLib\src\Asn1\ClpDerSequenceParser.pas',
+  ClpDerSet in '..\..\CryptoLib\src\Asn1\ClpDerSet.pas',
+  ClpDerSetParser in '..\..\CryptoLib\src\Asn1\ClpDerSetParser.pas',
+  ClpDerStringBase in '..\..\CryptoLib\src\Asn1\ClpDerStringBase.pas',
+  ClpDerT61String in '..\..\CryptoLib\src\Asn1\ClpDerT61String.pas',
+  ClpDerTaggedObject in '..\..\CryptoLib\src\Asn1\ClpDerTaggedObject.pas',
+  ClpDerUniversalString in '..\..\CryptoLib\src\Asn1\ClpDerUniversalString.pas',
+  ClpDerUtf8String in '..\..\CryptoLib\src\Asn1\ClpDerUtf8String.pas',
+  ClpDerVideotexString in '..\..\CryptoLib\src\Asn1\ClpDerVideotexString.pas',
+  ClpDerVisibleString in '..\..\CryptoLib\src\Asn1\ClpDerVisibleString.pas',
+  ClpIndefiniteLengthInputStream in '..\..\CryptoLib\src\Asn1\ClpIndefiniteLengthInputStream.pas',
+  ClpLimitedInputStream in '..\..\CryptoLib\src\Asn1\ClpLimitedInputStream.pas',
+  ClpOidTokenizer in '..\..\CryptoLib\src\Asn1\ClpOidTokenizer.pas',
+  ClpECKeyPairGenerator in '..\..\CryptoLib\src\Crypto\Generators\ClpECKeyPairGenerator.pas',
+  ClpECDomainParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpECDomainParameters.pas',
+  ClpECKeyGenerationParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpECKeyGenerationParameters.pas',
+  ClpECKeyParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpECKeyParameters.pas',
+  ClpECPrivateKeyParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpECPrivateKeyParameters.pas',
+  ClpECPublicKeyParameters in '..\..\CryptoLib\src\Crypto\Parameters\ClpECPublicKeyParameters.pas',
+  ClpCryptoApiRandomGenerator in '..\..\CryptoLib\src\Crypto\Prng\ClpCryptoApiRandomGenerator.pas',
+  ClpDigestRandomGenerator in '..\..\CryptoLib\src\Crypto\Prng\ClpDigestRandomGenerator.pas',
+  ClpAsymmetricCipherKeyPair in '..\..\CryptoLib\src\Crypto\ClpAsymmetricCipherKeyPair.pas',
+  ClpAsymmetricKeyParameter in '..\..\CryptoLib\src\Crypto\ClpAsymmetricKeyParameter.pas',
+  ClpKeyGenerationParameters in '..\..\CryptoLib\src\Crypto\ClpKeyGenerationParameters.pas',
+  ClpIAbstractECMultiplier in '..\..\CryptoLib\src\Interfaces\ClpIAbstractECMultiplier.pas',
+  ClpIAsn1ApplicationSpecificParser in '..\..\CryptoLib\src\Interfaces\ClpIAsn1ApplicationSpecificParser.pas',
+  ClpIAsn1Choice in '..\..\CryptoLib\src\Interfaces\ClpIAsn1Choice.pas',
+  ClpIAsn1EncodableVector in '..\..\CryptoLib\src\Interfaces\ClpIAsn1EncodableVector.pas',
+  ClpIAsn1InputStream in '..\..\CryptoLib\src\Interfaces\ClpIAsn1InputStream.pas',
+  ClpIAsn1Null in '..\..\CryptoLib\src\Interfaces\ClpIAsn1Null.pas',
+  ClpIAsn1OctetString in '..\..\CryptoLib\src\Interfaces\ClpIAsn1OctetString.pas',
+  ClpIAsn1OctetStringParser in '..\..\CryptoLib\src\Interfaces\ClpIAsn1OctetStringParser.pas',
+  ClpIAsn1OutputStream in '..\..\CryptoLib\src\Interfaces\ClpIAsn1OutputStream.pas',
+  ClpIAsn1Sequence in '..\..\CryptoLib\src\Interfaces\ClpIAsn1Sequence.pas',
+  ClpIAsn1SequenceParser in '..\..\CryptoLib\src\Interfaces\ClpIAsn1SequenceParser.pas',
+  ClpIAsn1Set in '..\..\CryptoLib\src\Interfaces\ClpIAsn1Set.pas',
+  ClpIAsn1SetParser in '..\..\CryptoLib\src\Interfaces\ClpIAsn1SetParser.pas',
+  ClpIAsn1StreamParser in '..\..\CryptoLib\src\Interfaces\ClpIAsn1StreamParser.pas',
+  ClpIAsn1String in '..\..\CryptoLib\src\Interfaces\ClpIAsn1String.pas',
+  ClpIAsn1TaggedObject in '..\..\CryptoLib\src\Interfaces\ClpIAsn1TaggedObject.pas',
+  ClpIAsn1TaggedObjectParser in '..\..\CryptoLib\src\Interfaces\ClpIAsn1TaggedObjectParser.pas',
+  ClpIAsymmetricCipherKeyPair in '..\..\CryptoLib\src\Interfaces\ClpIAsymmetricCipherKeyPair.pas',
+  ClpIAsymmetricCipherKeyPairGenerator in '..\..\CryptoLib\src\Interfaces\ClpIAsymmetricCipherKeyPairGenerator.pas',
+  ClpIAsymmetricKeyParameter in '..\..\CryptoLib\src\Interfaces\ClpIAsymmetricKeyParameter.pas',
+  ClpIBaseInputStream in '..\..\CryptoLib\src\Interfaces\ClpIBaseInputStream.pas',
+  ClpIBerApplicationSpecific in '..\..\CryptoLib\src\Interfaces\ClpIBerApplicationSpecific.pas',
+  ClpIBerApplicationSpecificParser in '..\..\CryptoLib\src\Interfaces\ClpIBerApplicationSpecificParser.pas',
+  ClpIBerBitString in '..\..\CryptoLib\src\Interfaces\ClpIBerBitString.pas',
+  ClpIBerNull in '..\..\CryptoLib\src\Interfaces\ClpIBerNull.pas',
+  ClpIBerOctetString in '..\..\CryptoLib\src\Interfaces\ClpIBerOctetString.pas',
+  ClpIBerOctetStringParser in '..\..\CryptoLib\src\Interfaces\ClpIBerOctetStringParser.pas',
+  ClpIBerOutputStream in '..\..\CryptoLib\src\Interfaces\ClpIBerOutputStream.pas',
+  ClpIBerSequence in '..\..\CryptoLib\src\Interfaces\ClpIBerSequence.pas',
+  ClpIBerSequenceParser in '..\..\CryptoLib\src\Interfaces\ClpIBerSequenceParser.pas',
+  ClpIBerSet in '..\..\CryptoLib\src\Interfaces\ClpIBerSet.pas',
+  ClpIBerSetParser in '..\..\CryptoLib\src\Interfaces\ClpIBerSetParser.pas',
+  ClpIBerTaggedObject in '..\..\CryptoLib\src\Interfaces\ClpIBerTaggedObject.pas',
+  ClpIBerTaggedObjectParser in '..\..\CryptoLib\src\Interfaces\ClpIBerTaggedObjectParser.pas',
+  ClpICipherParameters in '..\..\CryptoLib\src\Interfaces\ClpICipherParameters.pas',
+  ClpIConstructedOctetStream in '..\..\CryptoLib\src\Interfaces\ClpIConstructedOctetStream.pas',
+  ClpICryptoApiRandomGenerator in '..\..\CryptoLib\src\Interfaces\ClpICryptoApiRandomGenerator.pas',
+  ClpIDefiniteLengthInputStream in '..\..\CryptoLib\src\Interfaces\ClpIDefiniteLengthInputStream.pas',
+  ClpIDerApplicationSpecific in '..\..\CryptoLib\src\Interfaces\ClpIDerApplicationSpecific.pas',
+  ClpIDerBitString in '..\..\CryptoLib\src\Interfaces\ClpIDerBitString.pas',
+  ClpIDerBmpString in '..\..\CryptoLib\src\Interfaces\ClpIDerBmpString.pas',
+  ClpIDerBoolean in '..\..\CryptoLib\src\Interfaces\ClpIDerBoolean.pas',
+  ClpIDerEnumerated in '..\..\CryptoLib\src\Interfaces\ClpIDerEnumerated.pas',
+  ClpIDerExternal in '..\..\CryptoLib\src\Interfaces\ClpIDerExternal.pas',
+  ClpIDerExternalParser in '..\..\CryptoLib\src\Interfaces\ClpIDerExternalParser.pas',
+  ClpIDerGeneralString in '..\..\CryptoLib\src\Interfaces\ClpIDerGeneralString.pas',
+  ClpIDerGraphicString in '..\..\CryptoLib\src\Interfaces\ClpIDerGraphicString.pas',
+  ClpIDerIA5String in '..\..\CryptoLib\src\Interfaces\ClpIDerIA5String.pas',
+  ClpIDerInteger in '..\..\CryptoLib\src\Interfaces\ClpIDerInteger.pas',
+  ClpIDerNull in '..\..\CryptoLib\src\Interfaces\ClpIDerNull.pas',
+  ClpIDerNumericString in '..\..\CryptoLib\src\Interfaces\ClpIDerNumericString.pas',
+  ClpIDerObjectIdentifier in '..\..\CryptoLib\src\Interfaces\ClpIDerObjectIdentifier.pas',
+  ClpIDerOctetString in '..\..\CryptoLib\src\Interfaces\ClpIDerOctetString.pas',
+  ClpIDerOctetStringParser in '..\..\CryptoLib\src\Interfaces\ClpIDerOctetStringParser.pas',
+  ClpIDerPrintableString in '..\..\CryptoLib\src\Interfaces\ClpIDerPrintableString.pas',
+  ClpIDerSequence in '..\..\CryptoLib\src\Interfaces\ClpIDerSequence.pas',
+  ClpIDerSequenceParser in '..\..\CryptoLib\src\Interfaces\ClpIDerSequenceParser.pas',
+  ClpIDerSet in '..\..\CryptoLib\src\Interfaces\ClpIDerSet.pas',
+  ClpIDerSetParser in '..\..\CryptoLib\src\Interfaces\ClpIDerSetParser.pas',
+  ClpIDerStringBase in '..\..\CryptoLib\src\Interfaces\ClpIDerStringBase.pas',
+  ClpIDerT61String in '..\..\CryptoLib\src\Interfaces\ClpIDerT61String.pas',
+  ClpIDerTaggedObject in '..\..\CryptoLib\src\Interfaces\ClpIDerTaggedObject.pas',
+  ClpIDerUniversalString in '..\..\CryptoLib\src\Interfaces\ClpIDerUniversalString.pas',
+  ClpIDerUtf8String in '..\..\CryptoLib\src\Interfaces\ClpIDerUtf8String.pas',
+  ClpIDerVideotexString in '..\..\CryptoLib\src\Interfaces\ClpIDerVideotexString.pas',
+  ClpIDerVisibleString in '..\..\CryptoLib\src\Interfaces\ClpIDerVisibleString.pas',
+  ClpIDigestRandomGenerator in '..\..\CryptoLib\src\Interfaces\ClpIDigestRandomGenerator.pas',
+  ClpIECDomainParameters in '..\..\CryptoLib\src\Interfaces\ClpIECDomainParameters.pas',
+  ClpIECFieldElement in '..\..\CryptoLib\src\Interfaces\ClpIECFieldElement.pas',
+  ClpIECInterface in '..\..\CryptoLib\src\Interfaces\ClpIECInterface.pas',
+  ClpIECKeyGenerationParameters in '..\..\CryptoLib\src\Interfaces\ClpIECKeyGenerationParameters.pas',
+  ClpIECKeyPairGenerator in '..\..\CryptoLib\src\Interfaces\ClpIECKeyPairGenerator.pas',
+  ClpIECKeyParameters in '..\..\CryptoLib\src\Interfaces\ClpIECKeyParameters.pas',
+  ClpIECPrivateKeyParameters in '..\..\CryptoLib\src\Interfaces\ClpIECPrivateKeyParameters.pas',
+  ClpIECPublicKeyParameters in '..\..\CryptoLib\src\Interfaces\ClpIECPublicKeyParameters.pas',
+  ClpIExtensionField in '..\..\CryptoLib\src\Interfaces\ClpIExtensionField.pas',
+  ClpIFilterStream in '..\..\CryptoLib\src\Interfaces\ClpIFilterStream.pas',
+  ClpIFiniteField in '..\..\CryptoLib\src\Interfaces\ClpIFiniteField.pas',
+  ClpIFixedPointCombMultiplier in '..\..\CryptoLib\src\Interfaces\ClpIFixedPointCombMultiplier.pas',
+  ClpIFixedPointPreCompInfo in '..\..\CryptoLib\src\Interfaces\ClpIFixedPointPreCompInfo.pas',
+  ClpIGlvEndomorphism in '..\..\CryptoLib\src\Interfaces\ClpIGlvEndomorphism.pas',
+  ClpIGlvTypeBEndomorphism in '..\..\CryptoLib\src\Interfaces\ClpIGlvTypeBEndomorphism.pas',
+  ClpIGlvTypeBParameters in '..\..\CryptoLib\src\Interfaces\ClpIGlvTypeBParameters.pas',
+  ClpIIndefiniteLengthInputStream in '..\..\CryptoLib\src\Interfaces\ClpIIndefiniteLengthInputStream.pas',
+  ClpIKeyGenerationParameters in '..\..\CryptoLib\src\Interfaces\ClpIKeyGenerationParameters.pas',
+  ClpILimitedInputStream in '..\..\CryptoLib\src\Interfaces\ClpILimitedInputStream.pas',
+  ClpIOidTokenizer in '..\..\CryptoLib\src\Interfaces\ClpIOidTokenizer.pas',
+  ClpIPCGRandomNumberGenerator in '..\..\CryptoLib\src\Interfaces\ClpIPCGRandomNumberGenerator.pas',
+  ClpIPolynomial in '..\..\CryptoLib\src\Interfaces\ClpIPolynomial.pas',
+  ClpIPolynomialExtensionField in '..\..\CryptoLib\src\Interfaces\ClpIPolynomialExtensionField.pas',
+  ClpIPreCompInfo in '..\..\CryptoLib\src\Interfaces\ClpIPreCompInfo.pas',
+  ClpIProxiedInterface in '..\..\CryptoLib\src\Interfaces\ClpIProxiedInterface.pas',
+  ClpIRandom in '..\..\CryptoLib\src\Interfaces\ClpIRandom.pas',
+  ClpIRandomGenerator in '..\..\CryptoLib\src\Interfaces\ClpIRandomGenerator.pas',
+  ClpIRandomNumberGenerator in '..\..\CryptoLib\src\Interfaces\ClpIRandomNumberGenerator.pas',
+  ClpIScaleXPointMap in '..\..\CryptoLib\src\Interfaces\ClpIScaleXPointMap.pas',
+  ClpISecureRandom in '..\..\CryptoLib\src\Interfaces\ClpISecureRandom.pas',
+  ClpIWNafPreCompInfo in '..\..\CryptoLib\src\Interfaces\ClpIWNafPreCompInfo.pas',
+  ClpIX9Curve in '..\..\CryptoLib\src\Interfaces\ClpIX9Curve.pas',
+  ClpIX9ECParameters in '..\..\CryptoLib\src\Interfaces\ClpIX9ECParameters.pas',
+  ClpIX9ECParametersHolder in '..\..\CryptoLib\src\Interfaces\ClpIX9ECParametersHolder.pas',
+  ClpIX9ECPoint in '..\..\CryptoLib\src\Interfaces\ClpIX9ECPoint.pas',
+  ClpIX9FieldElement in '..\..\CryptoLib\src\Interfaces\ClpIX9FieldElement.pas',
+  ClpIX9FieldID in '..\..\CryptoLib\src\Interfaces\ClpIX9FieldID.pas',
+  ClpGlvTypeBEndomorphism in '..\..\CryptoLib\src\Math\EC\Endo\ClpGlvTypeBEndomorphism.pas',
+  ClpGlvTypeBParameters in '..\..\CryptoLib\src\Math\EC\Endo\ClpGlvTypeBParameters.pas',
+  ClpAbstractECMultiplier in '..\..\CryptoLib\src\Math\EC\Multiplier\ClpAbstractECMultiplier.pas',
+  ClpFixedPointCombMultiplier in '..\..\CryptoLib\src\Math\EC\Multiplier\ClpFixedPointCombMultiplier.pas',
+  ClpFixedPointPreCompInfo in '..\..\CryptoLib\src\Math\EC\Multiplier\ClpFixedPointPreCompInfo.pas',
+  ClpFixedPointUtilities in '..\..\CryptoLib\src\Math\EC\Multiplier\ClpFixedPointUtilities.pas',
+  ClpWNafPreCompInfo in '..\..\CryptoLib\src\Math\EC\Multiplier\ClpWNafPreCompInfo.pas',
+  ClpECAlgorithms in '..\..\CryptoLib\src\Math\EC\ClpECAlgorithms.pas',
+  ClpECCurve in '..\..\CryptoLib\src\Math\EC\ClpECCurve.pas',
+  ClpECFieldElement in '..\..\CryptoLib\src\Math\EC\ClpECFieldElement.pas',
+  ClpECPoint in '..\..\CryptoLib\src\Math\EC\ClpECPoint.pas',
+  ClpLongArray in '..\..\CryptoLib\src\Math\EC\ClpLongArray.pas',
+  ClpScaleXPointMap in '..\..\CryptoLib\src\Math\EC\ClpScaleXPointMap.pas',
+  ClpBigInteger in '..\..\CryptoLib\src\Math\ClpBigInteger.pas',
+  ClpDigestUtilities in '..\..\CryptoLib\src\Security\ClpDigestUtilities.pas',
+  ClpRandom in '..\..\CryptoLib\src\Security\ClpRandom.pas',
+  ClpSecureRandom in '..\..\CryptoLib\src\Security\ClpSecureRandom.pas',
+  ClpCollectionUtilities in '..\..\CryptoLib\src\Utils\Collections\ClpCollectionUtilities.pas',
+  ClpBase64 in '..\..\CryptoLib\src\Utils\Encoders\ClpBase64.pas',
+  ClpHex in '..\..\CryptoLib\src\Utils\Encoders\ClpHex.pas',
+  ClpStreamHelper in '..\..\CryptoLib\src\Utils\Helpers\ClpStreamHelper.pas',
+  ClpStringHelper in '..\..\CryptoLib\src\Utils\Helpers\ClpStringHelper.pas',
+  ClpBaseInputStream in '..\..\CryptoLib\src\Utils\IO\ClpBaseInputStream.pas',
+  ClpFilterStream in '..\..\CryptoLib\src\Utils\IO\ClpFilterStream.pas',
+  ClpStreams in '..\..\CryptoLib\src\Utils\IO\ClpStreams.pas',
+  ClpPcgRandomMinimal in '..\..\CryptoLib\src\Utils\Randoms\ClpPcgRandomMinimal.pas',
+  ClpPCGRandomNumberGenerator in '..\..\CryptoLib\src\Utils\Rng\ClpPCGRandomNumberGenerator.pas',
+  ClpRandomNumberGenerator in '..\..\CryptoLib\src\Utils\Rng\ClpRandomNumberGenerator.pas',
+  ClpArrayUtils in '..\..\CryptoLib\src\Utils\ClpArrayUtils.pas',
+  ClpBitConverter in '..\..\CryptoLib\src\Utils\ClpBitConverter.pas',
+  ClpBits in '..\..\CryptoLib\src\Utils\ClpBits.pas',
+  ClpConverters in '..\..\CryptoLib\src\Utils\ClpConverters.pas',
+  ClpCryptoLibTypes in '..\..\CryptoLib\src\Utils\ClpCryptoLibTypes.pas',
+  ClpTimes in '..\..\CryptoLib\src\Utils\ClpTimes.pas',
+  ClpWNafUtilities in '..\..\CryptoLib\src\Math\EC\Multiplier\ClpWNafUtilities.pas',
+  ClpBigIntegers in '..\..\CryptoLib\src\Utils\ClpBigIntegers.pas',
+  ClpMod in '..\..\CryptoLib\src\Math\Raw\ClpMod.pas',
+  ClpNat in '..\..\CryptoLib\src\Math\Raw\ClpNat.pas',
+  ClpNumberStyles in '..\..\CryptoLib\src\Math\ClpNumberStyles.pas',
+  ClpParametersWithRandom in '..\..\CryptoLib\src\Crypto\Parameters\ClpParametersWithRandom.pas',
+  ClpIParametersWithRandom in '..\..\CryptoLib\src\Interfaces\ClpIParametersWithRandom.pas',
+  ClpIDsa in '..\..\CryptoLib\src\Interfaces\ClpIDsa.pas',
+  ClpIDsaKCalculator in '..\..\CryptoLib\src\Interfaces\ClpIDsaKCalculator.pas',
+  ClpISigner in '..\..\CryptoLib\src\Interfaces\ClpISigner.pas',
+  ClpRandomDsaKCalculator in '..\..\CryptoLib\src\Crypto\Signers\ClpRandomDsaKCalculator.pas',
+  ClpIRandomDsaKCalculator in '..\..\CryptoLib\src\Interfaces\ClpIRandomDsaKCalculator.pas',
+  ClpECDsaSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpECDsaSigner.pas',
+  ClpIECDsaSigner in '..\..\CryptoLib\src\Interfaces\ClpIECDsaSigner.pas',
+  ClpDsaDigestSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpDsaDigestSigner.pas',
+  ClpIDsaDigestSigner in '..\..\CryptoLib\src\Interfaces\ClpIDsaDigestSigner.pas',
+  ClpSignerUtilities in '..\..\CryptoLib\src\Security\ClpSignerUtilities.pas',
+  ClpZTauElement in '..\..\CryptoLib\src\Math\EC\Abc\ClpZTauElement.pas',
+  ClpIZTauElement in '..\..\CryptoLib\src\Interfaces\ClpIZTauElement.pas',
+  ClpSimpleBigDecimal in '..\..\CryptoLib\src\Math\EC\Abc\ClpSimpleBigDecimal.pas',
+  ClpTnaf in '..\..\CryptoLib\src\Math\EC\Abc\ClpTnaf.pas',
+  ClpGlvMultiplier in '..\..\CryptoLib\src\Math\EC\Multiplier\ClpGlvMultiplier.pas',
+  ClpIGlvMultiplier in '..\..\CryptoLib\src\Interfaces\ClpIGlvMultiplier.pas',
+  ClpWTauNafMultiplier in '..\..\CryptoLib\src\Math\EC\Multiplier\ClpWTauNafMultiplier.pas',
+  ClpIWTauNafMultiplier in '..\..\CryptoLib\src\Interfaces\ClpIWTauNafMultiplier.pas',
+  ClpWTauNafPreCompInfo in '..\..\CryptoLib\src\Math\EC\Multiplier\ClpWTauNafPreCompInfo.pas',
+  ClpIWTauNafPreCompInfo in '..\..\CryptoLib\src\Interfaces\ClpIWTauNafPreCompInfo.pas',
+  ClpWNafL2RMultiplier in '..\..\CryptoLib\src\Math\EC\Multiplier\ClpWNafL2RMultiplier.pas',
+  ClpIWNafL2RMultiplier in '..\..\CryptoLib\src\Interfaces\ClpIWNafL2RMultiplier.pas',
+  ClpGF2Polynomial in '..\..\CryptoLib\src\Math\Field\ClpGF2Polynomial.pas',
+  ClpIGF2Polynomial in '..\..\CryptoLib\src\Interfaces\ClpIGF2Polynomial.pas',
+  ClpGenericPolynomialExtensionField in '..\..\CryptoLib\src\Math\Field\ClpGenericPolynomialExtensionField.pas',
+  ClpIGenericPolynomialExtensionField in '..\..\CryptoLib\src\Interfaces\ClpIGenericPolynomialExtensionField.pas',
+  ClpPrimeField in '..\..\CryptoLib\src\Math\Field\ClpPrimeField.pas',
+  ClpIPrimeField in '..\..\CryptoLib\src\Interfaces\ClpIPrimeField.pas',
+  ClpFiniteFields in '..\..\CryptoLib\src\Math\Field\ClpFiniteFields.pas',
+  ClpOSRandomNumberGenerator in '..\..\CryptoLib\src\Utils\Rng\ClpOSRandomNumberGenerator.pas',
+  ClpIOSRandomNumberGenerator in '..\..\CryptoLib\src\Interfaces\ClpIOSRandomNumberGenerator.pas',
+  ClpOSRandom in '..\..\CryptoLib\src\Utils\Randoms\ClpOSRandom.pas',
+  ClpStreamSorter in '..\..\CryptoLib\src\Utils\ClpStreamSorter.pas',
+  ClpAsn1Generator in '..\..\CryptoLib\src\Asn1\ClpAsn1Generator.pas',
+  ClpIAsn1Generator in '..\..\CryptoLib\src\Interfaces\ClpIAsn1Generator.pas',
+  ClpDerGenerator in '..\..\CryptoLib\src\Asn1\ClpDerGenerator.pas',
+  ClpIDerGenerator in '..\..\CryptoLib\src\Interfaces\ClpIDerGenerator.pas',
+  ClpDerSequenceGenerator in '..\..\CryptoLib\src\Asn1\ClpDerSequenceGenerator.pas',
+  ClpIDerSequenceGenerator in '..\..\CryptoLib\src\Interfaces\ClpIDerSequenceGenerator.pas',
+  ClpBerGenerator in '..\..\CryptoLib\src\Asn1\ClpBerGenerator.pas',
+  ClpIBerGenerator in '..\..\CryptoLib\src\Interfaces\ClpIBerGenerator.pas',
+  ClpIBerSequenceGenerator in '..\..\CryptoLib\src\Interfaces\ClpIBerSequenceGenerator.pas',
+  ClpBerSequenceGenerator in '..\..\CryptoLib\src\Asn1\ClpBerSequenceGenerator.pas',
+  ClpSetWeakRef in '..\..\CryptoLib\src\Utils\ClpSetWeakRef.pas',
+  UsageExamples in '..\src\UsageExamples.pas';
+
+begin
+  try
+    { TODO -oUser -cConsole Main : Insert code here }
+    TUsageExamples.GenerateKeyPairAndSign;
+    TUsageExamples.GetPublicKeyFromPrivateKey;
+    TUsageExamples.RecreatePublicAndPrivateKeyPairsFromByteArray;
+    TUsageExamples.RecreatePublicKeyFromXAndYCoordByteArray;
+    Readln;
+  except
+    on E: Exception do
+      Writeln(E.ClassName, ': ', E.Message);
+  end;
+
+end.

+ 73 - 0
CryptoLib.Samples/FreePascal.Samples/UsageSamples.lpi

@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="10"/>
+    <PathDelim Value="\"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasTitleStatement Value="False"/>
+        <MainUnitHasScaledStatement Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="UsageSamples"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <VersionInfo>
+      <StringTable ProductVersion=""/>
+    </VersionInfo>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+      </local>
+    </RunParams>
+    <RequiredPackages Count="1">
+      <Item1>
+        <PackageName Value="CryptoLib4PascalPackage"/>
+      </Item1>
+    </RequiredPackages>
+    <Units Count="2">
+      <Unit0>
+        <Filename Value="UsageSamples.lpr"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="..\src\UsageExamples.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit1>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="UsageSamples"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <OtherUnitFiles Value="..\src"/>
+      <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 27 - 0
CryptoLib.Samples/FreePascal.Samples/UsageSamples.lpr

@@ -0,0 +1,27 @@
+program UsageSamples;
+
+{$mode objfpc}{$H+}
+
+uses {$IFDEF UNIX} {$IFDEF UseCThreads}
+  cthreads, {$ENDIF} {$ENDIF}
+  SysUtils,
+  UsageExamples;
+
+begin
+  try
+    { TODO -oUser -cConsole Main : Insert code here }
+    TUsageExamples.GenerateKeyPairAndSign;
+    TUsageExamples.GetPublicKeyFromPrivateKey;
+    TUsageExamples.RecreatePublicAndPrivateKeyPairsFromByteArray;
+    TUsageExamples.RecreatePublicKeyFromXAndYCoordByteArray;
+    Readln;
+  except
+    on E: Exception do
+      Writeln(E.ClassName, ': ', E.Message);
+  end;
+
+end.
+
+
+
+

+ 398 - 0
CryptoLib.Samples/src/UsageExamples.pas

@@ -0,0 +1,398 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit UsageExamples;
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+interface
+
+uses
+  SysUtils,
+  ClpBigInteger,
+  ClpSecureRandom,
+  ClpISecureRandom,
+  ClpIX9ECParameters,
+  ClpIECDomainParameters,
+  ClpECDomainParameters,
+  ClpIECKeyPairGenerator,
+  ClpECKeyPairGenerator,
+  ClpIECKeyGenerationParameters,
+  ClpECKeyGenerationParameters,
+  ClpIAsymmetricCipherKeyPair,
+  ClpIECPrivateKeyParameters,
+  ClpIECPublicKeyParameters,
+  ClpECPublicKeyParameters,
+  ClpECPrivateKeyParameters,
+  ClpIECInterface,
+  ClpECPoint,
+  ClpISigner,
+  ClpSignerUtilities,
+  ClpSecNamedCurves;
+
+type
+  TUsageExamples = class sealed(TObject)
+
+  strict private
+
+  const
+
+    /// <summary>
+    /// supported curves are secp256k1, sect283k1, secp384r1 and secp521r1
+    /// </summary>
+    CurveName = 'secp256k1';
+
+    /// <summary>
+    /// supported signing algorithms are NONEwithECDSA, SHA-1withECDSA, <br />
+    /// SHA-224withECDSA, SHA-256withECDSA, SHA-384withECDSA,
+    /// SHA-512withECDSA and RIPEMD160withECDSA
+    /// </summary>
+    SigningAlgorithm = 'SHA-1withECDSA';
+
+  class var
+    FRandom: ISecureRandom;
+    FCurve: IX9ECParameters;
+    class function BytesToHexString(input: TBytes): String; static;
+    class constructor UsageExamples();
+
+  public
+    class procedure GenerateKeyPairAndSign(); static;
+    class procedure GetPublicKeyFromPrivateKey(); static;
+    class procedure RecreatePublicAndPrivateKeyPairsFromByteArray(); static;
+    class procedure RecreatePublicKeyFromXAndYCoordByteArray(); static;
+  end;
+
+implementation
+
+{ TUsageExamples }
+
+class function TUsageExamples.BytesToHexString(input: TBytes): String;
+var
+  index: Int32;
+begin
+  Result := '';
+  for index := System.Low(input) to System.High(input) do
+  begin
+    if index = 0 then
+    begin
+      Result := Result + IntToHex(input[index], 2);
+    end
+    else
+    begin
+      Result := Result + ',' + IntToHex(input[index], 2);
+    end;
+  end;
+  Result := '[' + Result + ']';
+end;
+
+class procedure TUsageExamples.GenerateKeyPairAndSign;
+var
+  domain: IECDomainParameters;
+  generator: IECKeyPairGenerator;
+  keygenParams: IECKeyGenerationParameters;
+  keypair: IAsymmetricCipherKeyPair;
+  privParams: IECPrivateKeyParameters;
+  pubParams: IECPublicKeyParameters;
+  signer: ISigner;
+  &message, sigBytes: TBytes;
+const
+  MethodName = 'GenerateKeyPairAndSign';
+begin
+
+  Writeln('MethodName is: ' + MethodName + sLineBreak);
+
+  domain := TECDomainParameters.Create(FCurve.Curve, FCurve.G, FCurve.N,
+    FCurve.H, FCurve.GetSeed);
+  generator := TECKeyPairGenerator.Create('ECDSA');
+  keygenParams := TECKeyGenerationParameters.Create(domain, FRandom);
+  generator.Init(keygenParams);
+
+  keypair := generator.GenerateKeyPair();
+  privParams := keypair.Private as IECPrivateKeyParameters; // for signing
+  pubParams := keypair.Public as IECPublicKeyParameters; // for verifying
+
+  Writeln('Algorithm Name is: ' + pubParams.AlgorithmName + sLineBreak);
+
+  Writeln('Public Key Normalized XCoord is: ' +
+    pubParams.Q.Normalize.AffineXCoord.ToBigInteger.ToString(16) + sLineBreak);
+  Writeln('Public Key Normalized YCoord is: ' +
+    pubParams.Q.Normalize.AffineYCoord.ToBigInteger.ToString(16) + sLineBreak);
+
+  Writeln('Private Key D Parameter is: ' + privParams.D.ToString(16) +
+    sLineBreak);
+
+  signer := TSignerUtilities.GetSigner(SigningAlgorithm);
+
+  Writeln('Signer Name is: ' + signer.AlgorithmName + sLineBreak);
+
+  // sign
+
+  signer.Init(true, privParams);
+
+  &message := TEncoding.UTF8.GetBytes('PascalECDSA');
+
+  signer.BlockUpdate(&message, 0, System.Length(&message));
+
+  sigBytes := signer.GenerateSignature();
+
+  Writeln('Generated Signature is: ' + BytesToHexString(sigBytes) + sLineBreak);
+
+  // verify
+
+  signer.Init(false, pubParams);
+
+  signer.BlockUpdate(&message, 0, System.Length(&message));
+
+  if (not signer.VerifySignature(sigBytes)) then
+  begin
+    Writeln(pubParams.AlgorithmName + ' verification failed' + sLineBreak);
+  end
+  else
+  begin
+    Writeln(pubParams.AlgorithmName + ' verification passed' + sLineBreak);
+  end;
+
+end;
+
+class procedure TUsageExamples.GetPublicKeyFromPrivateKey;
+var
+  domain: IECDomainParameters;
+  generator: IECKeyPairGenerator;
+  keygenParams: IECKeyGenerationParameters;
+  keypair: IAsymmetricCipherKeyPair;
+  privParams: IECPrivateKeyParameters;
+  pubParams, recreatedPubKeyParameters: IECPublicKeyParameters;
+  EncodedPublicKey, RecreatedEncodedPublicKey: TBytes;
+  qPoint: IECPoint;
+const
+  MethodName = 'GetPublicKeyFromPrivateKey';
+begin
+
+  Writeln('MethodName is: ' + MethodName + sLineBreak);
+
+  domain := TECDomainParameters.Create(FCurve.Curve, FCurve.G, FCurve.N,
+    FCurve.H, FCurve.GetSeed);
+  generator := TECKeyPairGenerator.Create('ECDSA');
+  keygenParams := TECKeyGenerationParameters.Create(domain, FRandom);
+  generator.Init(keygenParams);
+
+  keypair := generator.GenerateKeyPair();
+  privParams := keypair.Private as IECPrivateKeyParameters; // for signing
+  pubParams := keypair.Public as IECPublicKeyParameters; // for verifying
+
+  Writeln('Algorithm Name is: ' + pubParams.AlgorithmName + sLineBreak);
+
+  Writeln('Public Key Normalized XCoord is: ' +
+    pubParams.Q.Normalize.AffineXCoord.ToBigInteger.ToString(16) + sLineBreak);
+  Writeln('Public Key Normalized YCoord is: ' +
+    pubParams.Q.Normalize.AffineYCoord.ToBigInteger.ToString(16) + sLineBreak);
+
+  EncodedPublicKey := pubParams.Q.Normalize.GetEncoded;
+
+  Writeln('Encoded Public Key is: ' + BytesToHexString(EncodedPublicKey) +
+    sLineBreak);
+
+  Writeln('Private Key D Parameter is: ' + privParams.D.ToString(16) +
+    sLineBreak);
+
+  // get public key from private key
+
+  // Method One
+
+  qPoint := domain.G.Multiply(privParams.D);
+
+  RecreatedEncodedPublicKey := qPoint.GetEncoded();
+
+  if CompareMem(PByte(EncodedPublicKey), PByte(RecreatedEncodedPublicKey),
+    System.Length(EncodedPublicKey) * System.SizeOf(Byte)) then
+  begin
+    Writeln('Public Key Recreation From Private Key Was Successful' +
+      sLineBreak);
+  end
+  else
+  begin
+    Writeln('Public Key Recreation From Private Key Failed' + sLineBreak);
+  end;
+
+  recreatedPubKeyParameters := TECPublicKeyParameters.Create(qPoint, domain);
+
+  if pubParams.Equals(recreatedPubKeyParameters) then
+  begin
+    Writeln('Public Key Recreation Match With Original Public Key' +
+      sLineBreak);
+  end
+  else
+  begin
+    Writeln('Public Key Recreation DOES NOT Match With Original Public Key' +
+      sLineBreak);
+  end;
+
+  // or the easier method
+  // Method Two (** Preferred **)
+
+  if pubParams.Equals(TECKeyPairGenerator.GetCorrespondingPublicKey(privParams))
+  then
+  begin
+    Writeln('Public Key Recreation Match With Original Public Key' +
+      sLineBreak);
+  end
+  else
+  begin
+    Writeln('Public Key Recreation DOES NOT Match With Original Public Key' +
+      sLineBreak);
+  end;
+
+end;
+
+class procedure TUsageExamples.RecreatePublicAndPrivateKeyPairsFromByteArray;
+var
+  domain: IECDomainParameters;
+  generator: IECKeyPairGenerator;
+  keygenParams: IECKeyGenerationParameters;
+  keypair: IAsymmetricCipherKeyPair;
+  privParams, RegeneratedPrivateKey: IECPrivateKeyParameters;
+  pubParams, RegeneratedPublicKey: IECPublicKeyParameters;
+  PublicKeyByteArray, PrivateKeyByteArray: TBytes;
+  PrivD: TBigInteger;
+const
+  MethodName = 'RecreatePublicAndPrivateKeyPairsFromByteArray';
+begin
+
+  Writeln('MethodName is: ' + MethodName + sLineBreak);
+
+  domain := TECDomainParameters.Create(FCurve.Curve, FCurve.G, FCurve.N,
+    FCurve.H, FCurve.GetSeed);
+  generator := TECKeyPairGenerator.Create('ECDSA');
+  keygenParams := TECKeyGenerationParameters.Create(domain, FRandom);
+  generator.Init(keygenParams);
+
+  keypair := generator.GenerateKeyPair();
+  privParams := keypair.Private as IECPrivateKeyParameters; // for signing
+  pubParams := keypair.Public as IECPublicKeyParameters; // for verifying
+
+  Writeln('Algorithm Name is: ' + pubParams.AlgorithmName + sLineBreak);
+
+  Writeln('Public Key Normalized XCoord is: ' +
+    pubParams.Q.Normalize.AffineXCoord.ToBigInteger.ToString(16) + sLineBreak);
+  Writeln('Public Key Normalized YCoord is: ' +
+    pubParams.Q.Normalize.AffineYCoord.ToBigInteger.ToString(16) + sLineBreak);
+
+  Writeln('Private Key D Parameter is: ' + privParams.D.ToString(16) +
+    sLineBreak);
+
+  PublicKeyByteArray := pubParams.Q.GetEncoded;
+  // using ToByteArray here because bytes is unsigned in Pascal
+  PrivateKeyByteArray := privParams.D.ToByteArray;
+
+  RegeneratedPublicKey := TECPublicKeyParameters.Create('ECDSA',
+    FCurve.Curve.DecodePoint(PublicKeyByteArray), domain);
+
+  if pubParams.Equals(RegeneratedPublicKey) then
+  begin
+    Writeln('Public Key Recreation Match With Original Public Key' +
+      sLineBreak);
+  end
+  else
+  begin
+    Writeln('Public Key Recreation DOES NOT Match With Original Public Key' +
+      sLineBreak);
+  end;
+
+  PrivD := TBigInteger.Create(PrivateKeyByteArray);
+  RegeneratedPrivateKey := TECPrivateKeyParameters.Create('ECDSA',
+    PrivD, domain);
+
+  if privParams.Equals(RegeneratedPrivateKey) then
+  begin
+    Writeln('Private Key Recreation Match With Original Private Key' +
+      sLineBreak);
+  end
+  else
+  begin
+    Writeln('Private Key Recreation DOES NOT Match With Original Private Key' +
+      sLineBreak);
+  end;
+
+end;
+
+class procedure TUsageExamples.RecreatePublicKeyFromXAndYCoordByteArray;
+var
+  domain: IECDomainParameters;
+  generator: IECKeyPairGenerator;
+  keygenParams: IECKeyGenerationParameters;
+  keypair: IAsymmetricCipherKeyPair;
+  pubParams, RegeneratedPublicKey: IECPublicKeyParameters;
+  XCoordByteArray, YCoordByteArray: TBytes;
+  BigXCoord, BigYCoord, BigXCoordRecreated, BigYCoordRecreated: TBigInteger;
+  point: IECPoint;
+const
+  MethodName = 'RecreatePublicKeyFromXAndYCoordByteArray';
+begin
+
+  Writeln('MethodName is: ' + MethodName + sLineBreak);
+
+  domain := TECDomainParameters.Create(FCurve.Curve, FCurve.G, FCurve.N,
+    FCurve.H, FCurve.GetSeed);
+  generator := TECKeyPairGenerator.Create('ECDSA');
+  keygenParams := TECKeyGenerationParameters.Create(domain, FRandom);
+  generator.Init(keygenParams);
+
+  keypair := generator.GenerateKeyPair();
+  pubParams := keypair.Public as IECPublicKeyParameters; // for verifying
+
+  Writeln('Algorithm Name is: ' + pubParams.AlgorithmName + sLineBreak);
+
+  BigXCoord := pubParams.Q.Normalize.AffineXCoord.ToBigInteger;
+  BigYCoord := pubParams.Q.Normalize.AffineYCoord.ToBigInteger;
+
+  Writeln('Public Key Normalized XCoord is: ' + BigXCoord.ToString(16) +
+    sLineBreak);
+  Writeln('Public Key Normalized YCoord is: ' + BigYCoord.ToString(16) +
+    sLineBreak);
+
+  XCoordByteArray := BigXCoord.ToByteArray;
+  YCoordByteArray := BigYCoord.ToByteArray;
+
+  BigXCoordRecreated := TBigInteger.Create(1, XCoordByteArray);
+  BigYCoordRecreated := TBigInteger.Create(1, YCoordByteArray);
+
+  point := FCurve.Curve.CreatePoint(BigXCoordRecreated, BigYCoordRecreated);
+
+  RegeneratedPublicKey := TECPublicKeyParameters.Create(point, domain);
+
+  if pubParams.Equals(RegeneratedPublicKey) then
+  begin
+    Writeln('Public Key Recreation Match With Original Public Key' +
+      sLineBreak);
+  end
+  else
+  begin
+    Writeln('Public Key Recreation DOES NOT Match With Original Public Key' +
+      sLineBreak);
+  end;
+
+end;
+
+class constructor TUsageExamples.UsageExamples;
+begin
+  FRandom := TSecureRandom.Create();
+  FCurve := TSecNamedCurves.GetByName(CurveName);
+end;
+
+end.

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

@@ -0,0 +1,453 @@
+program CryptoLib.Tests;
+{
+
+  Delphi DUnit Test Project
+  -------------------------
+  This project contains the DUnit test framework and the GUI/Console test runners.
+  Add "CONSOLE_TESTRUNNER" to the conditional defines entry in the project options
+  to use the console test runner.  Otherwise the GUI test runner will be used by
+  default.
+
+}
+
+{$WARN DUPLICATE_CTOR_DTOR OFF}
+{$IFDEF CONSOLE_TESTRUNNER}
+{$APPTYPE CONSOLE}
+{$ENDIF}
+
+uses
+  Forms,
+  TestFramework,
+  GUITestRunner,
+  TextTestRunner,
+  ClpCryptoProObjectIdentifiers
+    in '..\..\CryptoLib\src\Asn1\CryptoPro\ClpCryptoProObjectIdentifiers.pas',
+  ClpECGost3410NamedCurves
+    in '..\..\CryptoLib\src\Asn1\CryptoPro\ClpECGost3410NamedCurves.pas',
+  ClpNistObjectIdentifiers
+    in '..\..\CryptoLib\src\Asn1\Nist\ClpNistObjectIdentifiers.pas',
+  ClpOiwObjectIdentifiers
+    in '..\..\CryptoLib\src\Asn1\Oiw\ClpOiwObjectIdentifiers.pas',
+  ClpPkcsObjectIdentifiers
+    in '..\..\CryptoLib\src\Asn1\Pkcs\ClpPkcsObjectIdentifiers.pas',
+  ClpRosstandartObjectIdentifiers
+    in '..\..\CryptoLib\src\Asn1\RossStandart\ClpRosstandartObjectIdentifiers.pas',
+  ClpSecNamedCurves in '..\..\CryptoLib\src\Asn1\Sec\ClpSecNamedCurves.pas',
+  ClpSecObjectIdentifiers
+    in '..\..\CryptoLib\src\Asn1\Sec\ClpSecObjectIdentifiers.pas',
+  ClpTeleTrusTObjectIdentifiers
+    in '..\..\CryptoLib\src\Asn1\TeleTrust\ClpTeleTrusTObjectIdentifiers.pas',
+  ClpECNamedCurveTable
+    in '..\..\CryptoLib\src\Asn1\X9\ClpECNamedCurveTable.pas',
+  ClpX9Curve in '..\..\CryptoLib\src\Asn1\X9\ClpX9Curve.pas',
+  ClpX9ECParameters in '..\..\CryptoLib\src\Asn1\X9\ClpX9ECParameters.pas',
+  ClpX9ECParametersHolder
+    in '..\..\CryptoLib\src\Asn1\X9\ClpX9ECParametersHolder.pas',
+  ClpX9ECPoint in '..\..\CryptoLib\src\Asn1\X9\ClpX9ECPoint.pas',
+  ClpX9FieldElement in '..\..\CryptoLib\src\Asn1\X9\ClpX9FieldElement.pas',
+  ClpX9FieldID in '..\..\CryptoLib\src\Asn1\X9\ClpX9FieldID.pas',
+  ClpX9IntegerConverter
+    in '..\..\CryptoLib\src\Asn1\X9\ClpX9IntegerConverter.pas',
+  ClpX9ObjectIdentifiers
+    in '..\..\CryptoLib\src\Asn1\X9\ClpX9ObjectIdentifiers.pas',
+  ClpAsn1Encodable in '..\..\CryptoLib\src\Asn1\ClpAsn1Encodable.pas',
+  ClpAsn1EncodableVector
+    in '..\..\CryptoLib\src\Asn1\ClpAsn1EncodableVector.pas',
+  ClpAsn1InputStream in '..\..\CryptoLib\src\Asn1\ClpAsn1InputStream.pas',
+  ClpAsn1Null in '..\..\CryptoLib\src\Asn1\ClpAsn1Null.pas',
+  ClpAsn1Object in '..\..\CryptoLib\src\Asn1\ClpAsn1Object.pas',
+  ClpAsn1OctetString in '..\..\CryptoLib\src\Asn1\ClpAsn1OctetString.pas',
+  ClpAsn1OutputStream in '..\..\CryptoLib\src\Asn1\ClpAsn1OutputStream.pas',
+  ClpAsn1Sequence in '..\..\CryptoLib\src\Asn1\ClpAsn1Sequence.pas',
+  ClpAsn1Set in '..\..\CryptoLib\src\Asn1\ClpAsn1Set.pas',
+  ClpAsn1StreamParser in '..\..\CryptoLib\src\Asn1\ClpAsn1StreamParser.pas',
+  ClpAsn1TaggedObject in '..\..\CryptoLib\src\Asn1\ClpAsn1TaggedObject.pas',
+  ClpAsn1Tags in '..\..\CryptoLib\src\Asn1\ClpAsn1Tags.pas',
+  ClpBerApplicationSpecific
+    in '..\..\CryptoLib\src\Asn1\ClpBerApplicationSpecific.pas',
+  ClpBerApplicationSpecificParser
+    in '..\..\CryptoLib\src\Asn1\ClpBerApplicationSpecificParser.pas',
+  ClpBerBitString in '..\..\CryptoLib\src\Asn1\ClpBerBitString.pas',
+  ClpBerNull in '..\..\CryptoLib\src\Asn1\ClpBerNull.pas',
+  ClpBerOctetString in '..\..\CryptoLib\src\Asn1\ClpBerOctetString.pas',
+  ClpBerOctetStringParser
+    in '..\..\CryptoLib\src\Asn1\ClpBerOctetStringParser.pas',
+  ClpBerOutputStream in '..\..\CryptoLib\src\Asn1\ClpBerOutputStream.pas',
+  ClpBerSequence in '..\..\CryptoLib\src\Asn1\ClpBerSequence.pas',
+  ClpBerSequenceParser in '..\..\CryptoLib\src\Asn1\ClpBerSequenceParser.pas',
+  ClpBerSet in '..\..\CryptoLib\src\Asn1\ClpBerSet.pas',
+  ClpBerSetParser in '..\..\CryptoLib\src\Asn1\ClpBerSetParser.pas',
+  ClpBerTaggedObject in '..\..\CryptoLib\src\Asn1\ClpBerTaggedObject.pas',
+  ClpBerTaggedObjectParser
+    in '..\..\CryptoLib\src\Asn1\ClpBerTaggedObjectParser.pas',
+  ClpConstructedOctetStream
+    in '..\..\CryptoLib\src\Asn1\ClpConstructedOctetStream.pas',
+  ClpDefiniteLengthInputStream
+    in '..\..\CryptoLib\src\Asn1\ClpDefiniteLengthInputStream.pas',
+  ClpDerApplicationSpecific
+    in '..\..\CryptoLib\src\Asn1\ClpDerApplicationSpecific.pas',
+  ClpDerBitString in '..\..\CryptoLib\src\Asn1\ClpDerBitString.pas',
+  ClpDerBmpString in '..\..\CryptoLib\src\Asn1\ClpDerBmpString.pas',
+  ClpDerBoolean in '..\..\CryptoLib\src\Asn1\ClpDerBoolean.pas',
+  ClpDerEnumerated in '..\..\CryptoLib\src\Asn1\ClpDerEnumerated.pas',
+  ClpDerExternal in '..\..\CryptoLib\src\Asn1\ClpDerExternal.pas',
+  ClpDerExternalParser in '..\..\CryptoLib\src\Asn1\ClpDerExternalParser.pas',
+  ClpDerGeneralString in '..\..\CryptoLib\src\Asn1\ClpDerGeneralString.pas',
+  ClpDerGraphicString in '..\..\CryptoLib\src\Asn1\ClpDerGraphicString.pas',
+  ClpDerIA5String in '..\..\CryptoLib\src\Asn1\ClpDerIA5String.pas',
+  ClpDerInteger in '..\..\CryptoLib\src\Asn1\ClpDerInteger.pas',
+  ClpDerNull in '..\..\CryptoLib\src\Asn1\ClpDerNull.pas',
+  ClpDerNumericString in '..\..\CryptoLib\src\Asn1\ClpDerNumericString.pas',
+  ClpDerObjectIdentifier
+    in '..\..\CryptoLib\src\Asn1\ClpDerObjectIdentifier.pas',
+  ClpDerOctetString in '..\..\CryptoLib\src\Asn1\ClpDerOctetString.pas',
+  ClpDerOctetStringParser
+    in '..\..\CryptoLib\src\Asn1\ClpDerOctetStringParser.pas',
+  ClpDerOutputStream in '..\..\CryptoLib\src\Asn1\ClpDerOutputStream.pas',
+  ClpDerPrintableString in '..\..\CryptoLib\src\Asn1\ClpDerPrintableString.pas',
+  ClpDerSequence in '..\..\CryptoLib\src\Asn1\ClpDerSequence.pas',
+  ClpDerSequenceParser in '..\..\CryptoLib\src\Asn1\ClpDerSequenceParser.pas',
+  ClpDerSet in '..\..\CryptoLib\src\Asn1\ClpDerSet.pas',
+  ClpDerSetParser in '..\..\CryptoLib\src\Asn1\ClpDerSetParser.pas',
+  ClpDerStringBase in '..\..\CryptoLib\src\Asn1\ClpDerStringBase.pas',
+  ClpDerT61String in '..\..\CryptoLib\src\Asn1\ClpDerT61String.pas',
+  ClpDerTaggedObject in '..\..\CryptoLib\src\Asn1\ClpDerTaggedObject.pas',
+  ClpDerUniversalString in '..\..\CryptoLib\src\Asn1\ClpDerUniversalString.pas',
+  ClpDerUtf8String in '..\..\CryptoLib\src\Asn1\ClpDerUtf8String.pas',
+  ClpDerVideotexString in '..\..\CryptoLib\src\Asn1\ClpDerVideotexString.pas',
+  ClpDerVisibleString in '..\..\CryptoLib\src\Asn1\ClpDerVisibleString.pas',
+  ClpIndefiniteLengthInputStream
+    in '..\..\CryptoLib\src\Asn1\ClpIndefiniteLengthInputStream.pas',
+  ClpLimitedInputStream in '..\..\CryptoLib\src\Asn1\ClpLimitedInputStream.pas',
+  ClpOidTokenizer in '..\..\CryptoLib\src\Asn1\ClpOidTokenizer.pas',
+  ClpECKeyPairGenerator
+    in '..\..\CryptoLib\src\Crypto\Generators\ClpECKeyPairGenerator.pas',
+  ClpECDomainParameters
+    in '..\..\CryptoLib\src\Crypto\Parameters\ClpECDomainParameters.pas',
+  ClpECKeyGenerationParameters
+    in '..\..\CryptoLib\src\Crypto\Parameters\ClpECKeyGenerationParameters.pas',
+  ClpECKeyParameters
+    in '..\..\CryptoLib\src\Crypto\Parameters\ClpECKeyParameters.pas',
+  ClpECPrivateKeyParameters
+    in '..\..\CryptoLib\src\Crypto\Parameters\ClpECPrivateKeyParameters.pas',
+  ClpECPublicKeyParameters
+    in '..\..\CryptoLib\src\Crypto\Parameters\ClpECPublicKeyParameters.pas',
+  ClpCryptoApiRandomGenerator
+    in '..\..\CryptoLib\src\Crypto\Prng\ClpCryptoApiRandomGenerator.pas',
+  ClpDigestRandomGenerator
+    in '..\..\CryptoLib\src\Crypto\Prng\ClpDigestRandomGenerator.pas',
+  ClpAsymmetricCipherKeyPair
+    in '..\..\CryptoLib\src\Crypto\ClpAsymmetricCipherKeyPair.pas',
+  ClpAsymmetricKeyParameter
+    in '..\..\CryptoLib\src\Crypto\ClpAsymmetricKeyParameter.pas',
+  ClpKeyGenerationParameters
+    in '..\..\CryptoLib\src\Crypto\ClpKeyGenerationParameters.pas',
+  ClpIAbstractECMultiplier
+    in '..\..\CryptoLib\src\Interfaces\ClpIAbstractECMultiplier.pas',
+  ClpIAsn1ApplicationSpecificParser
+    in '..\..\CryptoLib\src\Interfaces\ClpIAsn1ApplicationSpecificParser.pas',
+  ClpIAsn1Choice in '..\..\CryptoLib\src\Interfaces\ClpIAsn1Choice.pas',
+  ClpIAsn1EncodableVector
+    in '..\..\CryptoLib\src\Interfaces\ClpIAsn1EncodableVector.pas',
+  ClpIAsn1InputStream
+    in '..\..\CryptoLib\src\Interfaces\ClpIAsn1InputStream.pas',
+  ClpIAsn1Null in '..\..\CryptoLib\src\Interfaces\ClpIAsn1Null.pas',
+  ClpIAsn1OctetString
+    in '..\..\CryptoLib\src\Interfaces\ClpIAsn1OctetString.pas',
+  ClpIAsn1OctetStringParser
+    in '..\..\CryptoLib\src\Interfaces\ClpIAsn1OctetStringParser.pas',
+  ClpIAsn1OutputStream
+    in '..\..\CryptoLib\src\Interfaces\ClpIAsn1OutputStream.pas',
+  ClpIAsn1Sequence in '..\..\CryptoLib\src\Interfaces\ClpIAsn1Sequence.pas',
+  ClpIAsn1SequenceParser
+    in '..\..\CryptoLib\src\Interfaces\ClpIAsn1SequenceParser.pas',
+  ClpIAsn1Set in '..\..\CryptoLib\src\Interfaces\ClpIAsn1Set.pas',
+  ClpIAsn1SetParser in '..\..\CryptoLib\src\Interfaces\ClpIAsn1SetParser.pas',
+  ClpIAsn1StreamParser
+    in '..\..\CryptoLib\src\Interfaces\ClpIAsn1StreamParser.pas',
+  ClpIAsn1String in '..\..\CryptoLib\src\Interfaces\ClpIAsn1String.pas',
+  ClpIAsn1TaggedObject
+    in '..\..\CryptoLib\src\Interfaces\ClpIAsn1TaggedObject.pas',
+  ClpIAsn1TaggedObjectParser
+    in '..\..\CryptoLib\src\Interfaces\ClpIAsn1TaggedObjectParser.pas',
+  ClpIAsymmetricCipherKeyPair
+    in '..\..\CryptoLib\src\Interfaces\ClpIAsymmetricCipherKeyPair.pas',
+  ClpIAsymmetricCipherKeyPairGenerator
+    in '..\..\CryptoLib\src\Interfaces\ClpIAsymmetricCipherKeyPairGenerator.pas',
+  ClpIAsymmetricKeyParameter
+    in '..\..\CryptoLib\src\Interfaces\ClpIAsymmetricKeyParameter.pas',
+  ClpIBaseInputStream
+    in '..\..\CryptoLib\src\Interfaces\ClpIBaseInputStream.pas',
+  ClpIBerApplicationSpecific
+    in '..\..\CryptoLib\src\Interfaces\ClpIBerApplicationSpecific.pas',
+  ClpIBerApplicationSpecificParser
+    in '..\..\CryptoLib\src\Interfaces\ClpIBerApplicationSpecificParser.pas',
+  ClpIBerBitString in '..\..\CryptoLib\src\Interfaces\ClpIBerBitString.pas',
+  ClpIBerNull in '..\..\CryptoLib\src\Interfaces\ClpIBerNull.pas',
+  ClpIBerOctetString in '..\..\CryptoLib\src\Interfaces\ClpIBerOctetString.pas',
+  ClpIBerOctetStringParser
+    in '..\..\CryptoLib\src\Interfaces\ClpIBerOctetStringParser.pas',
+  ClpIBerOutputStream
+    in '..\..\CryptoLib\src\Interfaces\ClpIBerOutputStream.pas',
+  ClpIBerSequence in '..\..\CryptoLib\src\Interfaces\ClpIBerSequence.pas',
+  ClpIBerSequenceParser
+    in '..\..\CryptoLib\src\Interfaces\ClpIBerSequenceParser.pas',
+  ClpIBerSet in '..\..\CryptoLib\src\Interfaces\ClpIBerSet.pas',
+  ClpIBerSetParser in '..\..\CryptoLib\src\Interfaces\ClpIBerSetParser.pas',
+  ClpIBerTaggedObject
+    in '..\..\CryptoLib\src\Interfaces\ClpIBerTaggedObject.pas',
+  ClpIBerTaggedObjectParser
+    in '..\..\CryptoLib\src\Interfaces\ClpIBerTaggedObjectParser.pas',
+  ClpICipherParameters
+    in '..\..\CryptoLib\src\Interfaces\ClpICipherParameters.pas',
+  ClpIConstructedOctetStream
+    in '..\..\CryptoLib\src\Interfaces\ClpIConstructedOctetStream.pas',
+  ClpICryptoApiRandomGenerator
+    in '..\..\CryptoLib\src\Interfaces\ClpICryptoApiRandomGenerator.pas',
+  ClpIDefiniteLengthInputStream
+    in '..\..\CryptoLib\src\Interfaces\ClpIDefiniteLengthInputStream.pas',
+  ClpIDerApplicationSpecific
+    in '..\..\CryptoLib\src\Interfaces\ClpIDerApplicationSpecific.pas',
+  ClpIDerBitString in '..\..\CryptoLib\src\Interfaces\ClpIDerBitString.pas',
+  ClpIDerBmpString in '..\..\CryptoLib\src\Interfaces\ClpIDerBmpString.pas',
+  ClpIDerBoolean in '..\..\CryptoLib\src\Interfaces\ClpIDerBoolean.pas',
+  ClpIDerEnumerated in '..\..\CryptoLib\src\Interfaces\ClpIDerEnumerated.pas',
+  ClpIDerExternal in '..\..\CryptoLib\src\Interfaces\ClpIDerExternal.pas',
+  ClpIDerExternalParser
+    in '..\..\CryptoLib\src\Interfaces\ClpIDerExternalParser.pas',
+  ClpIDerGeneralString
+    in '..\..\CryptoLib\src\Interfaces\ClpIDerGeneralString.pas',
+  ClpIDerGraphicString
+    in '..\..\CryptoLib\src\Interfaces\ClpIDerGraphicString.pas',
+  ClpIDerIA5String in '..\..\CryptoLib\src\Interfaces\ClpIDerIA5String.pas',
+  ClpIDerInteger in '..\..\CryptoLib\src\Interfaces\ClpIDerInteger.pas',
+  ClpIDerNull in '..\..\CryptoLib\src\Interfaces\ClpIDerNull.pas',
+  ClpIDerNumericString
+    in '..\..\CryptoLib\src\Interfaces\ClpIDerNumericString.pas',
+  ClpIDerObjectIdentifier
+    in '..\..\CryptoLib\src\Interfaces\ClpIDerObjectIdentifier.pas',
+  ClpIDerOctetString in '..\..\CryptoLib\src\Interfaces\ClpIDerOctetString.pas',
+  ClpIDerOctetStringParser
+    in '..\..\CryptoLib\src\Interfaces\ClpIDerOctetStringParser.pas',
+  ClpIDerPrintableString
+    in '..\..\CryptoLib\src\Interfaces\ClpIDerPrintableString.pas',
+  ClpIDerSequence in '..\..\CryptoLib\src\Interfaces\ClpIDerSequence.pas',
+  ClpIDerSequenceParser
+    in '..\..\CryptoLib\src\Interfaces\ClpIDerSequenceParser.pas',
+  ClpIDerSet in '..\..\CryptoLib\src\Interfaces\ClpIDerSet.pas',
+  ClpIDerSetParser in '..\..\CryptoLib\src\Interfaces\ClpIDerSetParser.pas',
+  ClpIDerStringBase in '..\..\CryptoLib\src\Interfaces\ClpIDerStringBase.pas',
+  ClpIDerT61String in '..\..\CryptoLib\src\Interfaces\ClpIDerT61String.pas',
+  ClpIDerTaggedObject
+    in '..\..\CryptoLib\src\Interfaces\ClpIDerTaggedObject.pas',
+  ClpIDerUniversalString
+    in '..\..\CryptoLib\src\Interfaces\ClpIDerUniversalString.pas',
+  ClpIDerUtf8String in '..\..\CryptoLib\src\Interfaces\ClpIDerUtf8String.pas',
+  ClpIDerVideotexString
+    in '..\..\CryptoLib\src\Interfaces\ClpIDerVideotexString.pas',
+  ClpIDerVisibleString
+    in '..\..\CryptoLib\src\Interfaces\ClpIDerVisibleString.pas',
+  ClpIDigestRandomGenerator
+    in '..\..\CryptoLib\src\Interfaces\ClpIDigestRandomGenerator.pas',
+  ClpIECDomainParameters
+    in '..\..\CryptoLib\src\Interfaces\ClpIECDomainParameters.pas',
+  ClpIECFieldElement in '..\..\CryptoLib\src\Interfaces\ClpIECFieldElement.pas',
+  ClpIECInterface in '..\..\CryptoLib\src\Interfaces\ClpIECInterface.pas',
+  ClpIECKeyGenerationParameters
+    in '..\..\CryptoLib\src\Interfaces\ClpIECKeyGenerationParameters.pas',
+  ClpIECKeyPairGenerator
+    in '..\..\CryptoLib\src\Interfaces\ClpIECKeyPairGenerator.pas',
+  ClpIECKeyParameters
+    in '..\..\CryptoLib\src\Interfaces\ClpIECKeyParameters.pas',
+  ClpIECPrivateKeyParameters
+    in '..\..\CryptoLib\src\Interfaces\ClpIECPrivateKeyParameters.pas',
+  ClpIECPublicKeyParameters
+    in '..\..\CryptoLib\src\Interfaces\ClpIECPublicKeyParameters.pas',
+  ClpIExtensionField in '..\..\CryptoLib\src\Interfaces\ClpIExtensionField.pas',
+  ClpIFilterStream in '..\..\CryptoLib\src\Interfaces\ClpIFilterStream.pas',
+  ClpIFiniteField in '..\..\CryptoLib\src\Interfaces\ClpIFiniteField.pas',
+  ClpIFixedPointCombMultiplier
+    in '..\..\CryptoLib\src\Interfaces\ClpIFixedPointCombMultiplier.pas',
+  ClpIFixedPointPreCompInfo
+    in '..\..\CryptoLib\src\Interfaces\ClpIFixedPointPreCompInfo.pas',
+  ClpIGlvEndomorphism
+    in '..\..\CryptoLib\src\Interfaces\ClpIGlvEndomorphism.pas',
+  ClpIGlvTypeBEndomorphism
+    in '..\..\CryptoLib\src\Interfaces\ClpIGlvTypeBEndomorphism.pas',
+  ClpIGlvTypeBParameters
+    in '..\..\CryptoLib\src\Interfaces\ClpIGlvTypeBParameters.pas',
+  ClpIIndefiniteLengthInputStream
+    in '..\..\CryptoLib\src\Interfaces\ClpIIndefiniteLengthInputStream.pas',
+  ClpIKeyGenerationParameters
+    in '..\..\CryptoLib\src\Interfaces\ClpIKeyGenerationParameters.pas',
+  ClpILimitedInputStream
+    in '..\..\CryptoLib\src\Interfaces\ClpILimitedInputStream.pas',
+  ClpIOidTokenizer in '..\..\CryptoLib\src\Interfaces\ClpIOidTokenizer.pas',
+  ClpIPCGRandomNumberGenerator
+    in '..\..\CryptoLib\src\Interfaces\ClpIPCGRandomNumberGenerator.pas',
+  ClpIPolynomial in '..\..\CryptoLib\src\Interfaces\ClpIPolynomial.pas',
+  ClpIPolynomialExtensionField
+    in '..\..\CryptoLib\src\Interfaces\ClpIPolynomialExtensionField.pas',
+  ClpIPreCompInfo in '..\..\CryptoLib\src\Interfaces\ClpIPreCompInfo.pas',
+  ClpIProxiedInterface
+    in '..\..\CryptoLib\src\Interfaces\ClpIProxiedInterface.pas',
+  ClpIRandom in '..\..\CryptoLib\src\Interfaces\ClpIRandom.pas',
+  ClpIRandomGenerator
+    in '..\..\CryptoLib\src\Interfaces\ClpIRandomGenerator.pas',
+  ClpIRandomNumberGenerator
+    in '..\..\CryptoLib\src\Interfaces\ClpIRandomNumberGenerator.pas',
+  ClpIScaleXPointMap in '..\..\CryptoLib\src\Interfaces\ClpIScaleXPointMap.pas',
+  ClpISecureRandom in '..\..\CryptoLib\src\Interfaces\ClpISecureRandom.pas',
+  ClpIWNafPreCompInfo
+    in '..\..\CryptoLib\src\Interfaces\ClpIWNafPreCompInfo.pas',
+  ClpIX9Curve in '..\..\CryptoLib\src\Interfaces\ClpIX9Curve.pas',
+  ClpIX9ECParameters in '..\..\CryptoLib\src\Interfaces\ClpIX9ECParameters.pas',
+  ClpIX9ECParametersHolder
+    in '..\..\CryptoLib\src\Interfaces\ClpIX9ECParametersHolder.pas',
+  ClpIX9ECPoint in '..\..\CryptoLib\src\Interfaces\ClpIX9ECPoint.pas',
+  ClpIX9FieldElement in '..\..\CryptoLib\src\Interfaces\ClpIX9FieldElement.pas',
+  ClpIX9FieldID in '..\..\CryptoLib\src\Interfaces\ClpIX9FieldID.pas',
+  ClpGlvTypeBEndomorphism
+    in '..\..\CryptoLib\src\Math\EC\Endo\ClpGlvTypeBEndomorphism.pas',
+  ClpGlvTypeBParameters
+    in '..\..\CryptoLib\src\Math\EC\Endo\ClpGlvTypeBParameters.pas',
+  ClpAbstractECMultiplier
+    in '..\..\CryptoLib\src\Math\EC\Multiplier\ClpAbstractECMultiplier.pas',
+  ClpFixedPointCombMultiplier
+    in '..\..\CryptoLib\src\Math\EC\Multiplier\ClpFixedPointCombMultiplier.pas',
+  ClpFixedPointPreCompInfo
+    in '..\..\CryptoLib\src\Math\EC\Multiplier\ClpFixedPointPreCompInfo.pas',
+  ClpFixedPointUtilities
+    in '..\..\CryptoLib\src\Math\EC\Multiplier\ClpFixedPointUtilities.pas',
+  ClpWNafPreCompInfo
+    in '..\..\CryptoLib\src\Math\EC\Multiplier\ClpWNafPreCompInfo.pas',
+  ClpECAlgorithms in '..\..\CryptoLib\src\Math\EC\ClpECAlgorithms.pas',
+  ClpECCurve in '..\..\CryptoLib\src\Math\EC\ClpECCurve.pas',
+  ClpECFieldElement in '..\..\CryptoLib\src\Math\EC\ClpECFieldElement.pas',
+  ClpECPoint in '..\..\CryptoLib\src\Math\EC\ClpECPoint.pas',
+  ClpLongArray in '..\..\CryptoLib\src\Math\EC\ClpLongArray.pas',
+  ClpScaleXPointMap in '..\..\CryptoLib\src\Math\EC\ClpScaleXPointMap.pas',
+  ClpBigInteger in '..\..\CryptoLib\src\Math\ClpBigInteger.pas',
+  ClpDigestUtilities in '..\..\CryptoLib\src\Security\ClpDigestUtilities.pas',
+  ClpRandom in '..\..\CryptoLib\src\Security\ClpRandom.pas',
+  ClpSecureRandom in '..\..\CryptoLib\src\Security\ClpSecureRandom.pas',
+  ClpCollectionUtilities
+    in '..\..\CryptoLib\src\Utils\Collections\ClpCollectionUtilities.pas',
+  ClpBase64 in '..\..\CryptoLib\src\Utils\Encoders\ClpBase64.pas',
+  ClpHex in '..\..\CryptoLib\src\Utils\Encoders\ClpHex.pas',
+  ClpStreamHelper in '..\..\CryptoLib\src\Utils\Helpers\ClpStreamHelper.pas',
+  ClpStringHelper in '..\..\CryptoLib\src\Utils\Helpers\ClpStringHelper.pas',
+  ClpBaseInputStream in '..\..\CryptoLib\src\Utils\IO\ClpBaseInputStream.pas',
+  ClpFilterStream in '..\..\CryptoLib\src\Utils\IO\ClpFilterStream.pas',
+  ClpStreams in '..\..\CryptoLib\src\Utils\IO\ClpStreams.pas',
+  ClpPcgRandomMinimal
+    in '..\..\CryptoLib\src\Utils\Randoms\ClpPcgRandomMinimal.pas',
+  ClpPCGRandomNumberGenerator
+    in '..\..\CryptoLib\src\Utils\Rng\ClpPCGRandomNumberGenerator.pas',
+  ClpRandomNumberGenerator
+    in '..\..\CryptoLib\src\Utils\Rng\ClpRandomNumberGenerator.pas',
+  ClpArrayUtils in '..\..\CryptoLib\src\Utils\ClpArrayUtils.pas',
+  ClpBitConverter in '..\..\CryptoLib\src\Utils\ClpBitConverter.pas',
+  ClpBits in '..\..\CryptoLib\src\Utils\ClpBits.pas',
+  ClpConverters in '..\..\CryptoLib\src\Utils\ClpConverters.pas',
+  ClpCryptoLibTypes in '..\..\CryptoLib\src\Utils\ClpCryptoLibTypes.pas',
+  ClpTimes in '..\..\CryptoLib\src\Utils\ClpTimes.pas',
+  OIDTests in '..\src\Asn1\OIDTests.pas',
+  ClpWNafUtilities
+    in '..\..\CryptoLib\src\Math\EC\Multiplier\ClpWNafUtilities.pas',
+  SecureRandomTests in '..\src\Security\SecureRandomTests.pas',
+  ClpBigIntegers in '..\..\CryptoLib\src\Utils\ClpBigIntegers.pas',
+  ClpMod in '..\..\CryptoLib\src\Math\Raw\ClpMod.pas',
+  ClpNat in '..\..\CryptoLib\src\Math\Raw\ClpNat.pas',
+  ClpNumberStyles in '..\..\CryptoLib\src\Math\ClpNumberStyles.pas',
+  ClpParametersWithRandom
+    in '..\..\CryptoLib\src\Crypto\Parameters\ClpParametersWithRandom.pas',
+  ClpIParametersWithRandom
+    in '..\..\CryptoLib\src\Interfaces\ClpIParametersWithRandom.pas',
+  ClpIDsa in '..\..\CryptoLib\src\Interfaces\ClpIDsa.pas',
+  ClpIDsaKCalculator in '..\..\CryptoLib\src\Interfaces\ClpIDsaKCalculator.pas',
+  ClpISigner in '..\..\CryptoLib\src\Interfaces\ClpISigner.pas',
+  ClpRandomDsaKCalculator
+    in '..\..\CryptoLib\src\Crypto\Signers\ClpRandomDsaKCalculator.pas',
+  ClpIRandomDsaKCalculator
+    in '..\..\CryptoLib\src\Interfaces\ClpIRandomDsaKCalculator.pas',
+  ClpECDsaSigner in '..\..\CryptoLib\src\Crypto\Signers\ClpECDsaSigner.pas',
+  ClpIECDsaSigner in '..\..\CryptoLib\src\Interfaces\ClpIECDsaSigner.pas',
+  ClpDsaDigestSigner
+    in '..\..\CryptoLib\src\Crypto\Signers\ClpDsaDigestSigner.pas',
+  ClpIDsaDigestSigner
+    in '..\..\CryptoLib\src\Interfaces\ClpIDsaDigestSigner.pas',
+  ClpSignerUtilities in '..\..\CryptoLib\src\Security\ClpSignerUtilities.pas',
+  ClpZTauElement in '..\..\CryptoLib\src\Math\EC\Abc\ClpZTauElement.pas',
+  ClpIZTauElement in '..\..\CryptoLib\src\Interfaces\ClpIZTauElement.pas',
+  ClpSimpleBigDecimal
+    in '..\..\CryptoLib\src\Math\EC\Abc\ClpSimpleBigDecimal.pas',
+  ClpTnaf in '..\..\CryptoLib\src\Math\EC\Abc\ClpTnaf.pas',
+  ClpGlvMultiplier
+    in '..\..\CryptoLib\src\Math\EC\Multiplier\ClpGlvMultiplier.pas',
+  ClpIGlvMultiplier in '..\..\CryptoLib\src\Interfaces\ClpIGlvMultiplier.pas',
+  ClpWTauNafMultiplier
+    in '..\..\CryptoLib\src\Math\EC\Multiplier\ClpWTauNafMultiplier.pas',
+  ClpIWTauNafMultiplier
+    in '..\..\CryptoLib\src\Interfaces\ClpIWTauNafMultiplier.pas',
+  ClpWTauNafPreCompInfo
+    in '..\..\CryptoLib\src\Math\EC\Multiplier\ClpWTauNafPreCompInfo.pas',
+  ClpIWTauNafPreCompInfo
+    in '..\..\CryptoLib\src\Interfaces\ClpIWTauNafPreCompInfo.pas',
+  ClpWNafL2RMultiplier
+    in '..\..\CryptoLib\src\Math\EC\Multiplier\ClpWNafL2RMultiplier.pas',
+  ClpIWNafL2RMultiplier
+    in '..\..\CryptoLib\src\Interfaces\ClpIWNafL2RMultiplier.pas',
+  ClpGF2Polynomial in '..\..\CryptoLib\src\Math\Field\ClpGF2Polynomial.pas',
+  ClpIGF2Polynomial in '..\..\CryptoLib\src\Interfaces\ClpIGF2Polynomial.pas',
+  ClpGenericPolynomialExtensionField
+    in '..\..\CryptoLib\src\Math\Field\ClpGenericPolynomialExtensionField.pas',
+  ClpIGenericPolynomialExtensionField
+    in '..\..\CryptoLib\src\Interfaces\ClpIGenericPolynomialExtensionField.pas',
+  ClpPrimeField in '..\..\CryptoLib\src\Math\Field\ClpPrimeField.pas',
+  ClpIPrimeField in '..\..\CryptoLib\src\Interfaces\ClpIPrimeField.pas',
+  ClpFiniteFields in '..\..\CryptoLib\src\Math\Field\ClpFiniteFields.pas',
+  EqualsAndHashCodeTests in '..\src\Asn1\EqualsAndHashCodeTests.pas',
+  BigIntegerTests in '..\src\Math\BigIntegerTests.pas',
+  ECAlgorithmsTests in '..\src\Math\ECAlgorithmsTests.pas',
+  ECPointTests in '..\src\Math\ECPointTests.pas',
+  ClpOSRandomNumberGenerator
+    in '..\..\CryptoLib\src\Utils\Rng\ClpOSRandomNumberGenerator.pas',
+  ClpIOSRandomNumberGenerator
+    in '..\..\CryptoLib\src\Interfaces\ClpIOSRandomNumberGenerator.pas',
+  ClpOSRandom in '..\..\CryptoLib\src\Utils\Randoms\ClpOSRandom.pas',
+  ClpFixedSecureRandom in '..\src\Utils\ClpFixedSecureRandom.pas',
+  ClpIFixedSecureRandom in '..\src\Utils\ClpIFixedSecureRandom.pas',
+  ECDsa5Tests in '..\src\Others\ECDsa5Tests.pas',
+  NamedCurveTests in '..\src\Others\NamedCurveTests.pas',
+  SignerUtilitiesTests in '..\src\Others\SignerUtilitiesTests.pas',
+  ClpStreamSorter in '..\..\CryptoLib\src\Utils\ClpStreamSorter.pas',
+  DerApplicationSpecificTests in '..\src\Asn1\DerApplicationSpecificTests.pas',
+  SecP384R1FieldTests in '..\src\Math\EC\Custom\Sec\SecP384R1FieldTests.pas',
+  ECTests in '..\src\Others\ECTests.pas',
+  ClpAsn1Generator in '..\..\CryptoLib\src\Asn1\ClpAsn1Generator.pas',
+  ClpIAsn1Generator in '..\..\CryptoLib\src\Interfaces\ClpIAsn1Generator.pas',
+  ClpDerGenerator in '..\..\CryptoLib\src\Asn1\ClpDerGenerator.pas',
+  ClpIDerGenerator in '..\..\CryptoLib\src\Interfaces\ClpIDerGenerator.pas',
+  ClpDerSequenceGenerator
+    in '..\..\CryptoLib\src\Asn1\ClpDerSequenceGenerator.pas',
+  ClpIDerSequenceGenerator
+    in '..\..\CryptoLib\src\Interfaces\ClpIDerSequenceGenerator.pas',
+  Asn1SequenceParserTests in '..\src\Asn1\Asn1SequenceParserTests.pas',
+  ClpBerGenerator in '..\..\CryptoLib\src\Asn1\ClpBerGenerator.pas',
+  ClpIBerGenerator in '..\..\CryptoLib\src\Interfaces\ClpIBerGenerator.pas',
+  ClpIBerSequenceGenerator
+    in '..\..\CryptoLib\src\Interfaces\ClpIBerSequenceGenerator.pas',
+  ClpBerSequenceGenerator
+    in '..\..\CryptoLib\src\Asn1\ClpBerSequenceGenerator.pas',
+  ClpSetWeakRef in '..\..\CryptoLib\src\Utils\ClpSetWeakRef.pas';
+
+begin
+
+  Application.Initialize;
+  if IsConsole then
+    TextTestRunner.RunRegisteredTests
+  else
+    GUITestRunner.RunRegisteredTests;
+
+end.

+ 138 - 0
CryptoLib.Tests/FreePascal.Tests/CryptoLib.Tests.lpi

@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="10"/>
+    <PathDelim Value="\"/>
+    <General>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="CryptoLib.Tests"/>
+      <ResourceType Value="res"/>
+      <UseXPManifest Value="True"/>
+    </General>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+      </local>
+    </RunParams>
+    <RequiredPackages Count="4">
+      <Item1>
+        <PackageName Value="CryptoLib4PascalPackage"/>
+      </Item1>
+      <Item2>
+        <PackageName Value="fpcunittestrunner"/>
+      </Item2>
+      <Item3>
+        <PackageName Value="LCL"/>
+      </Item3>
+      <Item4>
+        <PackageName Value="FCL"/>
+      </Item4>
+    </RequiredPackages>
+    <Units Count="16">
+      <Unit0>
+        <Filename Value="CryptoLib.lpr"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="CryptoLib.Tests"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="..\src\Asn1\Asn1SequenceParserTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="..\src\Asn1\DerApplicationSpecificTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit2>
+      <Unit3>
+        <Filename Value="..\src\Asn1\EqualsAndHashCodeTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit3>
+      <Unit4>
+        <Filename Value="..\src\Asn1\OIDTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit4>
+      <Unit5>
+        <Filename Value="..\src\Math\BigIntegerTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit5>
+      <Unit6>
+        <Filename Value="..\src\Math\ECAlgorithmsTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit6>
+      <Unit7>
+        <Filename Value="..\src\Math\ECPointTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit7>
+      <Unit8>
+        <Filename Value="..\src\Math\EC\Custom\Sec\SecP384R1FieldTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit8>
+      <Unit9>
+        <Filename Value="..\src\Others\ECDsa5Tests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit9>
+      <Unit10>
+        <Filename Value="..\src\Others\ECTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit10>
+      <Unit11>
+        <Filename Value="..\src\Others\NamedCurveTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit11>
+      <Unit12>
+        <Filename Value="..\src\Others\SignerUtilitiesTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit12>
+      <Unit13>
+        <Filename Value="..\src\Security\SecureRandomTests.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit13>
+      <Unit14>
+        <Filename Value="..\src\Utils\ClpFixedSecureRandom.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit14>
+      <Unit15>
+        <Filename Value="..\src\Utils\ClpIFixedSecureRandom.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit15>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value=".\bin\CryptoLib"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <OtherUnitFiles Value="..\src\Asn1;..\src\Math;..\src\Math\EC\Custom\Sec;..\src\Others;..\src\Security;..\src\Utils"/>
+      <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+    <Linking>
+      <Options>
+        <Win32>
+          <GraphicApplication Value="True"/>
+        </Win32>
+      </Options>
+    </Linking>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

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

@@ -0,0 +1,32 @@
+program CryptoLib.Tests;
+
+{$mode objfpc}{$H+}
+
+uses
+  Interfaces,
+  Forms,
+  GuiTestRunner,
+  Asn1SequenceParserTests,
+  DerApplicationSpecificTests,
+  EqualsAndHashCodeTests,
+  OIDTests,
+  BigIntegerTests,
+  ECAlgorithmsTests,
+  ECPointTests,
+  SecP384R1FieldTests,
+  ECDsa5Tests,
+  ECTests,
+  NamedCurveTests,
+  SignerUtilitiesTests,
+  SecureRandomTests,
+  ClpFixedSecureRandom,
+  ClpIFixedSecureRandom;
+
+{$R *.res}
+
+begin
+  Application.Initialize;
+  Application.CreateForm(TGuiTestRunner, TestRunner);
+  Application.Run;
+end.
+

+ 609 - 0
CryptoLib.Tests/src/Asn1/Asn1SequenceParserTests.pas

@@ -0,0 +1,609 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit Asn1SequenceParserTests;
+
+interface
+
+uses
+  Classes,
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpBigInteger,
+  ClpHex,
+  ClpCryptoLibTypes,
+  ClpArrayUtils,
+  ClpDerInteger,
+  ClpIDerInteger,
+  ClpIAsn1Null,
+  ClpIAsn1StreamParser,
+  ClpAsn1StreamParser,
+  ClpIBerSequenceGenerator,
+  ClpBerSequenceGenerator,
+  ClpDerSequenceGenerator,
+  ClpIDerSequenceGenerator,
+  ClpIAsn1SequenceParser,
+  ClpDerObjectIdentifier,
+  ClpIDerObjectIdentifier;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  TTestAsn1SequenceParser = class(TCryptoLibTestCase)
+  private
+
+  var
+    FseqData, FnestedSeqData, FexpTagSeqData, FimplTagSeqData,
+      FnestedSeqExpTagData, FnestedSeqImpTagData, FberSeqData,
+      FberDerNestedSeqData, FberNestedSeqData, FberExpTagSeqData,
+      FberSeqWithDERNullData: TCryptoLibByteArray;
+
+    procedure doTestNestedReading(data: TCryptoLibByteArray);
+    procedure doTestParseWithNull(data: TCryptoLibByteArray);
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+    procedure TestDerWriting;
+    procedure TestNestedDerWriting;
+    procedure TestDerExplicitTaggedSequenceWriting;
+    procedure TestDerImplicitTaggedSequenceWriting;
+    procedure TestNestedExplicitTagDerWriting;
+    procedure TestNestedImplicitTagDerWriting;
+    procedure TestBerWriting;
+    procedure TestNestedBerDerWriting;
+    procedure TestNestedBerWriting;
+    procedure TestDerReading;
+    procedure TestNestedDerReading;
+    procedure TestBerReading;
+    procedure TestNestedBerDerReading;
+    procedure TestNestedBerReading;
+    procedure TestBerExplicitTaggedSequenceWriting;
+    procedure TestSequenceWithDerNullReading;
+
+  end;
+
+implementation
+
+{ TTestAsn1SequenceParser }
+
+procedure TTestAsn1SequenceParser.doTestNestedReading
+  (data: TCryptoLibByteArray);
+var
+  aIn: IAsn1StreamParser;
+  seq, s: IAsn1SequenceParser;
+  o: IInterface;
+  count: Int32;
+begin
+  aIn := TAsn1StreamParser.Create(data);
+  seq := aIn.ReadObject() as IAsn1SequenceParser;
+
+  count := 0;
+
+  CheckNotNull(seq, 'null sequence returned');
+
+  o := seq.ReadObject();
+  while (o <> Nil) do
+  begin
+    case count of
+
+      0:
+        begin
+          CheckTrue(Supports(o, IDerInteger));
+        end;
+      1:
+        begin
+          CheckTrue(Supports(o, IDerObjectIdentifier));
+        end;
+      2:
+        begin
+          CheckTrue(Supports(o, IAsn1SequenceParser));
+
+          s := o as IAsn1SequenceParser;
+
+          // NB: Must exhaust the nested parser
+          while (s.ReadObject() <> Nil) do
+          begin
+            // Ignore
+          end;
+
+        end;
+    end;
+
+    System.Inc(count);
+    o := seq.ReadObject();
+  end;
+
+  CheckEquals(3, count, 'wrong number of objects in sequence');
+end;
+
+procedure TTestAsn1SequenceParser.doTestParseWithNull
+  (data: TCryptoLibByteArray);
+var
+  aIn: IAsn1StreamParser;
+  seq: IAsn1SequenceParser;
+  o: IInterface;
+  count: Int32;
+begin
+  aIn := TAsn1StreamParser.Create(data);
+  seq := aIn.ReadObject() as IAsn1SequenceParser;
+
+  count := 0;
+
+  CheckNotNull(seq, 'null sequence returned');
+
+  o := seq.ReadObject();
+  while (o <> Nil) do
+  begin
+    case count of
+
+      0:
+        begin
+          CheckTrue(Supports(o, IAsn1Null));
+        end;
+      1:
+        begin
+          CheckTrue(Supports(o, IDerInteger));
+        end;
+      2:
+        begin
+          CheckTrue(Supports(o, IDerObjectIdentifier));
+        end;
+    end;
+
+    System.Inc(count);
+    o := seq.ReadObject();
+  end;
+
+  CheckEquals(3, count, 'wrong number of objects in sequence');
+end;
+
+procedure TTestAsn1SequenceParser.SetUp;
+begin
+  inherited;
+  FseqData := THex.Decode('3006020100060129');
+  FnestedSeqData := THex.Decode('300b0201000601293003020101');
+  FexpTagSeqData := THex.Decode('a1083006020100060129');
+  FimplTagSeqData := THex.Decode('a106020100060129');
+  FnestedSeqExpTagData := THex.Decode('300d020100060129a1053003020101');
+  FnestedSeqImpTagData := THex.Decode('300b020100060129a103020101');
+
+  FberSeqData := THex.Decode('30800201000601290000');
+  FberDerNestedSeqData := THex.Decode('308002010006012930030201010000');
+  FberNestedSeqData := THex.Decode('3080020100060129308002010100000000');
+  FberExpTagSeqData := THex.Decode('a180308002010006012900000000');
+  FberSeqWithDERNullData := THex.Decode('308005000201000601290000');
+end;
+
+procedure TTestAsn1SequenceParser.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestAsn1SequenceParser.TestBerExplicitTaggedSequenceWriting;
+var
+  bOut: TMemoryStream;
+  seqGen: IBerSequenceGenerator;
+  temp: TCryptoLibByteArray;
+begin
+  bOut := TMemoryStream.Create();
+  try
+    seqGen := TBerSequenceGenerator.Create(bOut, 1, true);
+
+    seqGen.AddObject(TDerInteger.Create(TBigInteger.Zero));
+
+    seqGen.AddObject(TDerObjectIdentifier.Create('1.1'));
+
+    seqGen.Close();
+
+    bOut.Position := 0;
+    System.SetLength(temp, bOut.Size);
+    bOut.Read(temp[0], bOut.Size);
+
+    CheckTrue(TArrayUtils.AreEqual(FberExpTagSeqData, temp),
+      'explicit BER tag writing test failed.');
+  finally
+    bOut.Free;
+  end;
+end;
+
+procedure TTestAsn1SequenceParser.TestBerReading;
+var
+  aIn: IAsn1StreamParser;
+  seq: IAsn1SequenceParser;
+  count: Int32;
+  o: IInterface;
+begin
+  aIn := TAsn1StreamParser.Create(FberSeqData);
+
+  seq := aIn.ReadObject() as IAsn1SequenceParser;
+  count := 0;
+
+  CheckNotNull(seq, 'null sequence returned');
+
+  o := seq.ReadObject();
+  while (o <> Nil) do
+  begin
+    case count of
+
+      0:
+        begin
+          CheckTrue(Supports(o, IDerInteger));
+
+        end;
+      1:
+        begin
+          CheckTrue(Supports(o, IDerObjectIdentifier));
+
+        end;
+    end;
+
+    System.Inc(count);
+    o := seq.ReadObject();
+  end;
+
+  CheckEquals(2, count, 'wrong number of objects in sequence');
+end;
+
+procedure TTestAsn1SequenceParser.TestBerWriting;
+var
+  bOut: TMemoryStream;
+  seqGen: IBerSequenceGenerator;
+  temp: TCryptoLibByteArray;
+begin
+  bOut := TMemoryStream.Create();
+  try
+    seqGen := TBerSequenceGenerator.Create(bOut);
+
+    seqGen.AddObject(TDerInteger.Create(TBigInteger.Zero));
+
+    seqGen.AddObject(TDerObjectIdentifier.Create('1.1'));
+
+    seqGen.Close();
+    bOut.Position := 0;
+    System.SetLength(temp, bOut.Size);
+    bOut.Read(temp[0], bOut.Size);
+    CheckTrue(TArrayUtils.AreEqual(FberSeqData, temp),
+      'basic BER writing test failed.');
+  finally
+    bOut.Free;
+  end;
+end;
+
+procedure TTestAsn1SequenceParser.TestDerExplicitTaggedSequenceWriting;
+var
+  bOut: TMemoryStream;
+  temp: TCryptoLibByteArray;
+  seqGen: IDerSequenceGenerator;
+begin
+  bOut := TMemoryStream.Create();
+  try
+    seqGen := TDerSequenceGenerator.Create(bOut, 1, true);
+
+    seqGen.AddObject(TDerInteger.Create(TBigInteger.Zero));
+
+    seqGen.AddObject(TDerObjectIdentifier.Create('1.1'));
+
+    seqGen.Close();
+
+    bOut.Position := 0;
+    System.SetLength(temp, bOut.Size);
+    bOut.Read(temp[0], bOut.Size);
+
+    CheckTrue(TArrayUtils.AreEqual(FexpTagSeqData, temp),
+      'explicit tag writing test failed.');
+  finally
+    bOut.Free;
+  end;
+end;
+
+procedure TTestAsn1SequenceParser.TestDerImplicitTaggedSequenceWriting;
+var
+  bOut: TMemoryStream;
+  seqGen: IDerSequenceGenerator;
+  temp: TCryptoLibByteArray;
+begin
+  bOut := TMemoryStream.Create();
+  try
+    seqGen := TDerSequenceGenerator.Create(bOut, 1, false);
+
+    seqGen.AddObject(TDerInteger.Create(TBigInteger.Zero));
+
+    seqGen.AddObject(TDerObjectIdentifier.Create('1.1'));
+
+    seqGen.Close();
+
+    bOut.Position := 0;
+    System.SetLength(temp, bOut.Size);
+    bOut.Read(temp[0], bOut.Size);
+
+    CheckTrue(TArrayUtils.AreEqual(FimplTagSeqData, temp),
+      'implicit tag writing test failed.');
+  finally
+    bOut.Free;
+  end;
+end;
+
+procedure TTestAsn1SequenceParser.TestDerReading;
+var
+  aIn: IAsn1StreamParser;
+  seq: IAsn1SequenceParser;
+  count: Int32;
+  o: IInterface;
+begin
+  aIn := TAsn1StreamParser.Create(FseqData);
+
+  seq := aIn.ReadObject() as IAsn1SequenceParser;
+  count := 0;
+
+  CheckNotNull(seq, 'null sequence returned');
+
+  o := seq.ReadObject();
+  while (o <> Nil) do
+  begin
+    case count of
+
+      0:
+        begin
+          CheckTrue(Supports(o, IDerInteger));
+
+        end;
+      1:
+        begin
+          CheckTrue(Supports(o, IDerObjectIdentifier));
+
+        end;
+    end;
+
+    System.Inc(count);
+    o := seq.ReadObject();
+  end;
+
+  CheckEquals(2, count, 'wrong number of objects in sequence');
+end;
+
+procedure TTestAsn1SequenceParser.TestDerWriting;
+var
+  bOut: TMemoryStream;
+  seqGen: IDerSequenceGenerator;
+  temp: TCryptoLibByteArray;
+begin
+  bOut := TMemoryStream.Create();
+  try
+    seqGen := TDerSequenceGenerator.Create(bOut);
+
+    seqGen.AddObject(TDerInteger.Create(TBigInteger.Zero));
+
+    seqGen.AddObject(TDerObjectIdentifier.Create('1.1'));
+
+    seqGen.Close();
+    bOut.Position := 0;
+    System.SetLength(temp, bOut.Size);
+    bOut.Read(temp[0], bOut.Size);
+    CheckTrue(TArrayUtils.AreEqual(FseqData, temp),
+      'basic DER writing test failed.');
+  finally
+    bOut.Free;
+  end;
+end;
+
+procedure TTestAsn1SequenceParser.TestNestedBerDerReading;
+begin
+  doTestNestedReading(FberDerNestedSeqData);
+end;
+
+procedure TTestAsn1SequenceParser.TestNestedBerDerWriting;
+var
+  bOut: TMemoryStream;
+  seqGen1: IBerSequenceGenerator;
+  seqGen2: IDerSequenceGenerator;
+  temp: TCryptoLibByteArray;
+begin
+  bOut := TMemoryStream.Create();
+  try
+    seqGen1 := TBerSequenceGenerator.Create(bOut);
+
+    seqGen1.AddObject(TDerInteger.Create(TBigInteger.Zero));
+
+    seqGen1.AddObject(TDerObjectIdentifier.Create('1.1'));
+
+    seqGen2 := TDerSequenceGenerator.Create(seqGen1.GetRawOutputStream());
+
+    seqGen2.AddObject(TDerInteger.Create(TBigInteger.ValueOf(1)));
+
+    seqGen2.Close();
+
+    seqGen1.Close();
+
+    bOut.Position := 0;
+    System.SetLength(temp, bOut.Size);
+    bOut.Read(temp[0], bOut.Size);
+    CheckTrue(TArrayUtils.AreEqual(FberDerNestedSeqData, temp),
+      'nested BER/DER writing test failed.');
+  finally
+    bOut.Free;
+  end;
+end;
+
+procedure TTestAsn1SequenceParser.TestNestedBerReading;
+begin
+  doTestNestedReading(FberNestedSeqData);
+end;
+
+procedure TTestAsn1SequenceParser.TestNestedBerWriting;
+var
+  bOut: TMemoryStream;
+  seqGen1, seqGen2: IBerSequenceGenerator;
+  temp: TCryptoLibByteArray;
+begin
+  bOut := TMemoryStream.Create();
+  try
+    seqGen1 := TBerSequenceGenerator.Create(bOut);
+
+    seqGen1.AddObject(TDerInteger.Create(TBigInteger.Zero));
+
+    seqGen1.AddObject(TDerObjectIdentifier.Create('1.1'));
+
+    seqGen2 := TBerSequenceGenerator.Create(seqGen1.GetRawOutputStream());
+
+    seqGen2.AddObject(TDerInteger.Create(TBigInteger.ValueOf(1)));
+
+    seqGen2.Close();
+
+    seqGen1.Close();
+
+    bOut.Position := 0;
+    System.SetLength(temp, bOut.Size);
+    bOut.Read(temp[0], bOut.Size);
+    CheckTrue(TArrayUtils.AreEqual(FberNestedSeqData, temp),
+      'nested BER writing test failed.');
+  finally
+    bOut.Free;
+  end;
+end;
+
+procedure TTestAsn1SequenceParser.TestNestedDerReading;
+begin
+  doTestNestedReading(FnestedSeqData);
+end;
+
+procedure TTestAsn1SequenceParser.TestNestedDerWriting;
+var
+  bOut: TMemoryStream;
+  seqGen1, seqGen2: IDerSequenceGenerator;
+  temp: TCryptoLibByteArray;
+begin
+  bOut := TMemoryStream.Create();
+  try
+    seqGen1 := TDerSequenceGenerator.Create(bOut);
+
+    seqGen1.AddObject(TDerInteger.Create(TBigInteger.Zero));
+
+    seqGen1.AddObject(TDerObjectIdentifier.Create('1.1'));
+
+    seqGen2 := TDerSequenceGenerator.Create(seqGen1.GetRawOutputStream());
+
+    seqGen2.AddObject(TDerInteger.Create(TBigInteger.One));
+
+    seqGen2.Close();
+
+    seqGen1.Close();
+
+    bOut.Position := 0;
+    System.SetLength(temp, bOut.Size);
+    bOut.Read(temp[0], bOut.Size);
+    CheckTrue(TArrayUtils.AreEqual(FnestedSeqData, temp),
+      'nested DER writing test failed.');
+  finally
+    bOut.Free;
+  end;
+end;
+
+procedure TTestAsn1SequenceParser.TestNestedExplicitTagDerWriting;
+var
+  bOut: TMemoryStream;
+  seqGen1, seqGen2: IDerSequenceGenerator;
+  temp: TCryptoLibByteArray;
+begin
+  bOut := TMemoryStream.Create();
+  try
+    seqGen1 := TDerSequenceGenerator.Create(bOut);
+
+    seqGen1.AddObject(TDerInteger.Create(TBigInteger.Zero));
+
+    seqGen1.AddObject(TDerObjectIdentifier.Create('1.1'));
+
+    seqGen2 := TDerSequenceGenerator.Create
+      (seqGen1.GetRawOutputStream(), 1, true);
+
+    seqGen2.AddObject(TDerInteger.Create(TBigInteger.ValueOf(1)));
+
+    seqGen2.Close();
+
+    seqGen1.Close();
+
+    bOut.Position := 0;
+    System.SetLength(temp, bOut.Size);
+    bOut.Read(temp[0], bOut.Size);
+    CheckTrue(TArrayUtils.AreEqual(FnestedSeqExpTagData, temp),
+      'nested explicit tagged DER writing test failed.');
+  finally
+    bOut.Free;
+  end;
+end;
+
+procedure TTestAsn1SequenceParser.TestNestedImplicitTagDerWriting;
+var
+  bOut: TMemoryStream;
+  seqGen1, seqGen2: IDerSequenceGenerator;
+  temp: TCryptoLibByteArray;
+begin
+  bOut := TMemoryStream.Create();
+  try
+    seqGen1 := TDerSequenceGenerator.Create(bOut);
+
+    seqGen1.AddObject(TDerInteger.Create(TBigInteger.Zero));
+
+    seqGen1.AddObject(TDerObjectIdentifier.Create('1.1'));
+
+    seqGen2 := TDerSequenceGenerator.Create(seqGen1.GetRawOutputStream(),
+      1, false);
+
+    seqGen2.AddObject(TDerInteger.Create(TBigInteger.ValueOf(1)));
+
+    seqGen2.Close();
+
+    seqGen1.Close();
+
+    bOut.Position := 0;
+    System.SetLength(temp, bOut.Size);
+    bOut.Read(temp[0], bOut.Size);
+    CheckTrue(TArrayUtils.AreEqual(FnestedSeqImpTagData, temp),
+      'nested implicit tagged DER writing test failed.');
+  finally
+    bOut.Free;
+  end;
+end;
+
+procedure TTestAsn1SequenceParser.TestSequenceWithDerNullReading;
+begin
+  doTestParseWithNull(FberSeqWithDERNullData);
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestAsn1SequenceParser);
+{$ELSE}
+  RegisterTest(TTestAsn1SequenceParser.Suite);
+{$ENDIF FPC}
+
+end.

+ 216 - 0
CryptoLib.Tests/src/Asn1/DerApplicationSpecificTests.pas

@@ -0,0 +1,216 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit DerApplicationSpecificTests;
+
+interface
+
+uses
+  Classes,
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpHex,
+  ClpArrayUtils,
+  ClpCryptoLibTypes,
+  ClpDerVisibleString,
+  ClpIDerVisibleString,
+  ClpDerTaggedObject,
+  ClpIDerTaggedObject,
+  ClpDerApplicationSpecific,
+  ClpIDerApplicationSpecific,
+  ClpDerInteger,
+  ClpIDerInteger,
+  ClpAsn1Object,
+  ClpAsn1Tags;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  TTestDerApplicationSpecific = class(TCryptoLibTestCase)
+  private
+
+  var
+    FimpData, FcertData, FsampleData: TCryptoLibByteArray;
+
+    procedure TestTaggedObject();
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+    procedure TestDerApplicationSpecific;
+
+  end;
+
+implementation
+
+{ TTestDerApplicationSpecific }
+
+procedure TTestDerApplicationSpecific.SetUp;
+begin
+  inherited;
+  FimpData := THex.Decode('430109');
+
+  FcertData := THex.Decode
+    ('7F218201897F4E8201495F290100420E44454356434145504153533030317F49' +
+    '81FD060A04007F00070202020202811CD7C134AA264366862A18302575D1D787' +
+    'B09F075797DA89F57EC8C0FF821C68A5E62CA9CE6C1C299803A6C1530B514E18' +
+    '2AD8B0042A59CAD29F43831C2580F63CCFE44138870713B1A92369E33E2135D2' +
+    '66DBB372386C400B8439040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C' +
+    '1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D376' +
+    '1402CD851CD7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A793' +
+    '9F863904393EE8E06DB6C7F528F8B4260B49AA93309824D92CDB1807E5437EE2' +
+    'E26E29B73A7111530FA86B350037CB9415E153704394463797139E148701015F' +
+    '200E44454356434145504153533030317F4C0E060904007F0007030102015301' +
+    'C15F25060007000400015F24060009000400015F37384CCF25C59F3612EEE188' +
+    '75F6C5F2E2D21F0395683B532A26E4C189B71EFE659C3F26E0EB9AEAE9986310' +
+    '7F9B0DADA16414FFA204516AEE2B');
+
+  FsampleData := THex.Decode
+    ('613280020780a106060456000104a203020101a305a103020101be80288006025101020109a080b2800a01000000000000000000');
+end;
+
+procedure TTestDerApplicationSpecific.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestDerApplicationSpecific.TestDerApplicationSpecific;
+var
+  encoded: TCryptoLibByteArray;
+  appSpec, tagged, certObj: IDerApplicationSpecific;
+  recVal, val: IDerInteger;
+begin
+  TestTaggedObject();
+
+  appSpec := TAsn1Object.FromByteArray(FsampleData) as IDerApplicationSpecific;
+
+  if (1 <> appSpec.ApplicationTag) then
+  begin
+    Fail('wrong tag detected');
+  end;
+
+  val := TDerInteger.Create(9);
+
+  tagged := TDerApplicationSpecific.Create(false, 3, val);
+
+  if ((not TArrayUtils.AreEqual(FimpData, tagged.GetEncoded()))) then
+  begin
+    Fail('implicit encoding failed');
+  end;
+
+  recVal := tagged.GetObject(TAsn1Tags.Integer) as IDerInteger;
+
+  if ((not val.Equals(recVal))) then
+  begin
+    Fail('implicit read back failed');
+  end;
+
+  certObj := TAsn1Object.FromByteArray(FcertData) as IDerApplicationSpecific;
+
+  if ((not certObj.IsConstructed()) or (certObj.ApplicationTag <> 33)) then
+  begin
+    Fail('parsing of certificate data failed');
+  end;
+
+  encoded := certObj.GetDerEncoded();
+
+  if ((not TArrayUtils.AreEqual(FcertData, encoded))) then
+  begin
+    Fail('re-encoding of certificate data failed');
+  end;
+end;
+
+procedure TTestDerApplicationSpecific.TestTaggedObject;
+var
+  isExplicit: Boolean;
+  type1: IDerVisibleString;
+  type2, type4: IDerApplicationSpecific;
+  type3, type5: IDerTaggedObject;
+begin
+  // boolean explicit, int tagNo, ASN1Encodable obj
+  // isExplicit := false;
+
+  // Type1 :::= VisibleString
+  type1 := TDerVisibleString.Create('Jones');
+  if (not TArrayUtils.AreEqual(THex.Decode('1A054A6F6E6573'),
+    type1.GetEncoded())) then
+  begin
+    Fail('ERROR: expected value doesn''t match!');
+  end;
+
+  // Type2 :::= [APPLICATION 3] IMPLICIT Type1
+  isExplicit := false;
+  type2 := TDerApplicationSpecific.Create(isExplicit, 3, type1);
+  // type2.isConstructed()
+  if (not TArrayUtils.AreEqual(THex.Decode('43054A6F6E6573'),
+    type2.GetEncoded())) then
+  begin
+    Fail('ERROR: expected value doesn''t match!');
+  end;
+
+  // Type3 :::= [2] Type2
+  isExplicit := true;
+  type3 := TDerTaggedObject.Create(isExplicit, 2, type2);
+  if (not TArrayUtils.AreEqual(THex.Decode('A20743054A6F6E6573'),
+    type3.GetEncoded())) then
+  begin
+    Fail('ERROR: expected value doesn''t match!');
+  end;
+
+  // Type4 :::= [APPLICATION 7] IMPLICIT Type3
+  isExplicit := false;
+  type4 := TDerApplicationSpecific.Create(isExplicit, 7, type3);
+  if (not TArrayUtils.AreEqual(THex.Decode('670743054A6F6E6573'),
+    type4.GetEncoded())) then
+  begin
+    Fail('ERROR: expected value doesn''t match!');
+  end;
+
+  // Type5 :::= [2] IMPLICIT Type2
+  isExplicit := false;
+  type5 := TDerTaggedObject.Create(isExplicit, 2, type2);
+  // type5.isConstructed()
+  if (not TArrayUtils.AreEqual(THex.Decode('82054A6F6E6573'),
+    type5.GetEncoded())) then
+  begin
+    Fail('ERROR: expected value doesn''t match!');
+  end;
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestDerApplicationSpecific);
+{$ELSE}
+  RegisterTest(TTestDerApplicationSpecific.Suite);
+{$ENDIF FPC}
+
+end.

+ 210 - 0
CryptoLib.Tests/src/Asn1/EqualsAndHashCodeTests.pas

@@ -0,0 +1,210 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit EqualsAndHashCodeTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+{$HINTS OFF}
+
+uses
+  Classes,
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpHex,
+  ClpCryptoLibTypes,
+  ClpIProxiedInterface,
+  ClpBerOctetString,
+  ClpBerSequence,
+  ClpDerPrintableString,
+  ClpBerSet,
+  ClpBerTaggedObject,
+  ClpDerApplicationSpecific,
+  ClpDerBitString,
+  ClpDerBmpString,
+  ClpDerBoolean,
+  ClpDerEnumerated,
+  ClpDerGeneralString,
+  ClpDerIA5String,
+  ClpDerInteger,
+  ClpDerNull,
+  ClpDerNumericString,
+  ClpDerObjectIdentifier,
+  ClpDerOctetString,
+  ClpDerSequence,
+  ClpDerSet,
+  ClpDerT61String,
+  ClpDerTaggedObject,
+  ClpDerUniversalString,
+  ClpDerUtf8String,
+  ClpDerVisibleString,
+  ClpDerGraphicString,
+  ClpDerVideotexString,
+  ClpIAsn1OutputStream,
+  ClpAsn1OutputStream,
+  ClpAsn1InputStream,
+  ClpIAsn1InputStream,
+  ClpAsn1Object;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  TTestEqualsAndHashCode = class(TCryptoLibTestCase)
+  private
+
+  var
+    Fdata: TCryptoLibByteArray;
+    Fvalues: TCryptoLibGenericArray<IAsn1Object>;
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+    procedure TestEqualsAndHashCode;
+
+  end;
+
+implementation
+
+{ TTestEqualsAndHashCode }
+
+procedure TTestEqualsAndHashCode.SetUp;
+begin
+  Fdata := TCryptoLibByteArray.Create(0, 1, 0, 1, 0, 0, 1);
+  Fvalues := TCryptoLibGenericArray<IAsn1Object>.Create(
+
+    TBerOctetString.Create(Fdata),
+
+    TDerApplicationSpecific.Create(0, Fdata), TDerBitString.Create(Fdata),
+
+    TDerBoolean.True, TDerBoolean.False, TDerEnumerated.Create(100),
+    TDerBmpString.Create('hello world'),
+
+    TDerGeneralString.Create('hello world'), TDerIA5String.Create('hello'),
+    TDerInteger.Create(1000), TDerNull.Instance,
+    TDerNumericString.Create('123456'),
+    TDerObjectIdentifier.Create('1.1.1.10000.1'), TDerOctetString.Create(Fdata),
+    TDerPrintableString.Create('hello world'),
+
+    TDerT61String.Create('hello world'),
+
+    TDerUniversalString.Create(Fdata),
+
+    TDerUtf8String.Create('hello world'),
+    TDerVisibleString.Create('hello world'),
+    TDerGraphicString.Create(THex.Decode('deadbeef')),
+    TDerVideotexString.Create(TEncoding.ASCII.GetBytes('Hello World')),
+
+    TBerTaggedObject.Create(0, TDerPrintableString.Create('hello world')),
+
+    TDerTaggedObject.Create(0, TDerPrintableString.Create('hello world')),
+    //
+    TBerSequence.Create(TDerPrintableString.Create('hello world')),
+    TBerSet.Create(TDerPrintableString.Create('hello world')),
+    TDerSequence.Create(TDerPrintableString.Create('hello world')),
+    TDerSet.Create(TDerPrintableString.Create('hello world'))
+
+    );
+
+end;
+
+procedure TTestEqualsAndHashCode.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestEqualsAndHashCode.TestEqualsAndHashCode;
+var
+  bOut: TMemoryStream;
+  aOut: TAsn1OutputStream;
+  aIn: TAsn1InputStream;
+  o: IAsn1Object;
+  temp: TCryptoLibByteArray;
+  i: Int32;
+begin
+  bOut := TMemoryStream.Create();
+  aOut := TAsn1OutputStream.Create(bOut);
+  try
+
+    i := 0;
+    while i <> System.Length(Fvalues) do
+    begin
+      aOut.WriteObject(Fvalues[i]);
+      System.Inc(i);
+    end;
+
+    System.SetLength(temp, bOut.Size);
+    bOut.Position := 0;
+    bOut.Read(temp[0], bOut.Size);
+    aIn := TAsn1InputStream.Create(temp);
+
+    try
+      i := 0;
+      while i <> System.Length(Fvalues) do
+      begin
+
+        o := aIn.ReadObject();
+
+        if (not o.Equals(Fvalues[i])) then
+        begin
+          Fail(Format('Failed equality test for %s',
+            [(o as TAsn1Object).ClassName]));
+        end;
+
+        if (not(o.GetHashCode() = Fvalues[i].GetHashCode())) then
+        begin
+          Fail(Format('Failed hashCode test for %s',
+            [(o as TAsn1Object).ClassName]));
+        end;
+
+        System.Inc(i);
+      end;
+    finally
+      aIn.Free;
+    end;
+
+  finally
+    bOut.Free;
+    aOut.Free;
+  end;
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestEqualsAndHashCode);
+{$ELSE}
+  RegisterTest(TTestEqualsAndHashCode.Suite);
+{$ENDIF FPC}
+
+end.

+ 225 - 0
CryptoLib.Tests/src/Asn1/OIDTests.pas

@@ -0,0 +1,225 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit OIDTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$NOTES OFF}
+{$ENDIF FPC}
+
+uses
+  Classes,
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpHex,
+  ClpCryptoLibTypes,
+  ClpAsn1Object,
+  ClpDerObjectIdentifier,
+  ClpIDerObjectIdentifier;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  TTestOID = class(TCryptoLibTestCase)
+  private
+
+  var
+    Foid: string;
+    Freq1, Freq2: TCryptoLibByteArray;
+
+    procedure recodeCheck(const oid: String; enc: TBytes);
+    procedure validOidCheck(const oid: String);
+    procedure invalidOidCheck;
+    procedure branchCheck(const stem, branch: String);
+    procedure onCheck(const stem, test: String; expected: Boolean);
+    procedure constructorMethod;
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+    procedure TestOID;
+
+  end;
+
+implementation
+
+{ TTestOID }
+
+procedure TTestOID.branchCheck(const stem, branch: String);
+var
+  expected, actual: String;
+  instance: IDerObjectIdentifier;
+begin
+  expected := stem + '.' + branch;
+  instance := TDerObjectIdentifier.Create(stem);
+  actual := instance.branch(branch).Id;
+
+  CheckEquals(expected, actual, 'failed "branch" check for ' + stem + '/'
+    + branch);
+end;
+
+procedure TTestOID.constructorMethod;
+var
+temp: IDerObjectIdentifier;
+begin
+ temp := TDerObjectIdentifier.Create(Foid);
+end;
+
+procedure TTestOID.invalidOidCheck;
+var
+{$IFNDEF FPC}
+  Method: TTestMethod;
+{$ELSE}
+  Method: TRunMethod;
+{$ENDIF FPC}
+begin
+
+  Method := constructorMethod;
+  CheckException(Method, EFormatCryptoLibException,
+    'Expected "EFormatCryptoLibException" But None Gotten');
+end;
+
+procedure TTestOID.onCheck(const stem, test: String; expected: Boolean);
+var
+  tempDer, tempDer2: IDerObjectIdentifier;
+  actual: Boolean;
+begin
+  tempDer := TDerObjectIdentifier.Create(test);
+  tempDer2 := TDerObjectIdentifier.Create(stem);
+  actual := tempDer.On(tempDer2);
+  CheckEquals(expected, actual, 'failed "on" check for ' + stem + '"/"' + test);
+end;
+
+procedure TTestOID.recodeCheck(const oid: String; enc: TBytes);
+var
+  o, encO: IDerObjectIdentifier;
+  bytes: TBytes;
+begin
+  o := TDerObjectIdentifier.Create(oid);
+  encO := TAsn1Object.FromByteArray(enc) as IDerObjectIdentifier;
+
+  bytes := o.GetDerEncoded();
+
+  CheckEquals(o.Id, encO.Id, Format('Expected %s but got %s. on recodeCheck',
+    [o.Id, encO.Id]));
+
+  CheckEquals(true, o.Equals(encO), 'object comparison failed');
+
+  CheckEquals(true, CompareMem(bytes, enc, System.Length(enc) *
+    System.SizeOf(Byte)), 'bytearray comparison failed');
+end;
+
+procedure TTestOID.SetUp;
+begin
+  Freq1 := THex.Decode('0603813403');
+  Freq2 := THex.Decode('06082A36FFFFFFDD6311');
+end;
+
+procedure TTestOID.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestOID.TestOID;
+begin
+  recodeCheck('2.100.3', Freq1);
+  recodeCheck('1.2.54.34359733987.17', Freq2);
+
+  validOidCheck('0.1');
+  validOidCheck
+    ('1.1.127.32512.8323072.2130706432.545460846592.139637976727552.35747322042253312.9151314442816847872');
+  validOidCheck('1.2.123.12345678901.1.1.1');
+
+  validOidCheck('2.25.196556539987194312349856245628873852187.1');
+
+  Foid := '0';
+  invalidOidCheck;
+  Foid := '1';
+  invalidOidCheck;
+  Foid := '2';
+  invalidOidCheck;
+  Foid := '3.1';
+  invalidOidCheck;
+  Foid := '..1';
+  invalidOidCheck;
+  Foid := '192.168.1.1';
+  invalidOidCheck;
+  Foid := '.123452';
+  invalidOidCheck;
+  Foid := '1.';
+  invalidOidCheck;
+  Foid := '1.345.23.34..234';
+  invalidOidCheck;
+  Foid := '1.345.23.34.234.';
+  invalidOidCheck;
+  Foid := '.12.345.77.234';
+  invalidOidCheck;
+  Foid := '.12.345.77.234.';
+  invalidOidCheck;
+  Foid := '1.2.3.4.A.5';
+  invalidOidCheck;
+  Foid := '1,2';
+  invalidOidCheck;
+
+  branchCheck('1.1', '2.2');
+
+  onCheck('1.1', '1.1', false);
+  onCheck('1.1', '1.2', false);
+  onCheck('1.1', '1.2.1', false);
+  onCheck('1.1', '2.1', false);
+  onCheck('1.1', '1.11', false);
+  onCheck('1.12', '1.1.2', false);
+  onCheck('1.1', '1.1.1', true);
+  onCheck('1.1', '1.1.2', true);
+end;
+
+procedure TTestOID.validOidCheck(const oid: String);
+var
+  o: IDerObjectIdentifier;
+begin
+  o := TDerObjectIdentifier.Create(oid);
+  o := TAsn1Object.FromByteArray(o.GetEncoded()) as IDerObjectIdentifier;
+  CheckEquals(oid, o.Id, Format('Expected %s but got %s.', [oid, o.Id]));
+
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestOID);
+{$ELSE}
+  RegisterTest(TTestOID.Suite);
+{$ENDIF FPC}
+
+end.

+ 1373 - 0
CryptoLib.Tests/src/Math/BigIntegerTests.pas

@@ -0,0 +1,1373 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit BigIntegerTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+// Disable Overflow and RangeChecks.
+{$OVERFLOWCHECKS OFF}
+{$RANGECHECKS OFF}
+{$HINTS OFF}
+{$NOTES OFF}
+{$ENDIF FPC}
+
+uses
+  Classes,
+  Math,
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpCryptoLibTypes,
+  ClpArrayUtils,
+  ClpHex,
+  ClpSecureRandom,
+  ClpISecureRandom,
+  ClpBigInteger;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  TTestBigInteger = class(TCryptoLibTestCase)
+  private
+
+  var
+    FminusTwo, FminusOne, Fzero, Fone, Ftwo, Fthree: TBigInteger;
+    FfirstPrimes, FnonPrimes, FmersennePrimeExponents, FnonPrimeExponents
+      : TCryptoLibInt32Array;
+    FRandom: ISecureRandom;
+
+    function val(n: Int64): TBigInteger;
+    function mersenne(e: Int32): TBigInteger;
+    procedure CheckEqualsBigInteger(a, b: TBigInteger; const msg: String = '');
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+    procedure TestMonoBug81857();
+    procedure TestAbs();
+    procedure TestAdd();
+    procedure TestAnd();
+    procedure TestAndNot();
+    procedure TestBitCount();
+    procedure TestBitLength();
+    procedure TestClearBit();
+    procedure TestCompareTo();
+    procedure TestConstructors();
+    procedure TestDivide();
+    procedure TestDivideAndRemainder();
+    procedure TestFlipBit();
+    procedure TestGcd();
+    procedure TestGetLowestSetBit();
+    procedure TestInt32Value();
+    procedure TestIsProbablePrime();
+    procedure TestInt64Value();
+    procedure TestMax();
+    procedure TestMin();
+    procedure TestMod();
+    procedure TestModInverse();
+    procedure TestModPow();
+    procedure TestMultiply();
+    procedure TestNegate();
+    procedure TestNextProbablePrime();
+    procedure TestNot();
+    procedure TestOr();
+    procedure TestPow();
+    procedure TestRemainder();
+    procedure TestSetBit();
+    procedure TestShiftLeft();
+    procedure TestShiftRight();
+    procedure TestSignValue();
+    procedure TestSubtract();
+    procedure TestTestBit();
+    procedure TestToByteArray();
+    procedure TestToByteArrayUnsigned();
+    procedure TestToString();
+    procedure TestValueOf();
+    procedure TestXor();
+  end;
+
+implementation
+
+{ TTestBigInteger }
+
+function TTestBigInteger.val(n: Int64): TBigInteger;
+begin
+  result := TBigInteger.ValueOf(n);
+end;
+
+procedure TTestBigInteger.CheckEqualsBigInteger(a, b: TBigInteger;
+  const msg: String);
+begin
+  CheckEquals(True, a.Equals(b), msg);
+end;
+
+function TTestBigInteger.mersenne(e: Int32): TBigInteger;
+begin
+  result := Ftwo.Pow(e).Subtract(Fone);
+end;
+
+procedure TTestBigInteger.SetUp;
+begin
+  FminusTwo := TBigInteger.Two.Negate();
+  FminusOne := TBigInteger.One.Negate();
+  Fzero := TBigInteger.Zero;
+  Fone := TBigInteger.One;
+  Ftwo := TBigInteger.Two;
+  Fthree := TBigInteger.Three;
+
+  FfirstPrimes := TCryptoLibInt32Array.Create(2, 3, 5, 7, 11, 13, 17,
+    19, 23, 29);
+  FnonPrimes := TCryptoLibInt32Array.Create(0, 1, 4, 10, 20, 21, 22,
+    25, 26, 27);
+
+  FmersennePrimeExponents := TCryptoLibInt32Array.Create(2, 3, 5, 7, 13, 17, 19,
+    31, 61, 89);
+  FnonPrimeExponents := TCryptoLibInt32Array.Create(1, 4, 6, 9, 11, 15, 23,
+    29, 37, 41);
+  FRandom := TSecureRandom.Create();
+end;
+
+procedure TTestBigInteger.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestBigInteger.TestAbs;
+begin
+  CheckEqualsBigInteger(Fzero, Fzero.Abs());
+  CheckEqualsBigInteger(Fone, Fone.Abs());
+  CheckEqualsBigInteger(Fone, FminusOne.Abs());
+  CheckEqualsBigInteger(Ftwo, Ftwo.Abs());
+  CheckEqualsBigInteger(Ftwo, FminusTwo.Abs());
+end;
+
+procedure TTestBigInteger.TestAdd;
+var
+  i, j: Int32;
+begin
+  for i := -10 to 10 do
+  begin
+    for j := -10 to 10 do
+    begin
+
+      CheckEqualsBigInteger(val(i + j), val(i).Add(val(j)),
+        Format('Problem: %d.Add(%d) should be %d', [i, j, (i + j)]));
+
+    end;
+  end;
+end;
+
+procedure TTestBigInteger.TestAnd;
+var
+  i, j: Int32;
+begin
+  for i := -10 to 10 do
+  begin
+    for j := -10 to 10 do
+    begin
+
+      CheckEqualsBigInteger(val(i and j), val(i).&And(val(j)),
+        Format('Problem: %d.AND(%d) should be %d', [i, j, (i and j)]));
+
+    end;
+  end;
+end;
+
+procedure TTestBigInteger.TestAndNot;
+var
+  i, j: Int32;
+begin
+  for i := -10 to 10 do
+  begin
+    for j := -10 to 10 do
+    begin
+
+      CheckEqualsBigInteger(val(i and (not j)), val(i).AndNot(val(j)),
+        Format('Problem: %d AND NOT (%d) should be %d',
+        [i, j, (i and (not j))]));
+
+    end;
+  end;
+end;
+
+procedure TTestBigInteger.TestBitCount;
+var
+  i, bitCount, bit: Int32;
+  pow2, test: TBigInteger;
+begin
+  CheckEquals(0, Fzero.bitCount);
+  CheckEquals(1, Fone.bitCount);
+  CheckEquals(0, FminusOne.bitCount);
+  CheckEquals(1, Ftwo.bitCount);
+  CheckEquals(1, FminusTwo.bitCount);
+
+  for i := 0 to System.Pred(100) do
+
+  begin
+    pow2 := Fone.ShiftLeft(i);
+
+    CheckEquals(1, pow2.bitCount);
+    CheckEquals(i, pow2.Negate().bitCount);
+  end;
+
+  i := 0;
+  while i < 10 do
+  begin
+    test := TBigInteger.Create(128, 0, FRandom);
+    bitCount := 0;
+
+    for bit := 0 to System.Pred(test.BitLength) do
+    begin
+      if (test.TestBit(bit)) then
+      begin
+        System.Inc(bitCount);
+      end;
+    end;
+
+    CheckEquals(bitCount, test.bitCount);
+    System.Inc(i);
+  end;
+end;
+
+procedure TTestBigInteger.TestBitLength;
+var
+  i, bit: Int32;
+  odd, pow2: TBigInteger;
+begin
+  CheckEquals(0, Fzero.BitLength);
+  CheckEquals(1, Fone.BitLength);
+  CheckEquals(0, FminusOne.BitLength);
+  CheckEquals(2, Ftwo.BitLength);
+  CheckEquals(1, FminusTwo.BitLength);
+
+  for i := 0 to System.Pred(100) do
+
+  begin
+    bit := i + FRandom.Next(64);
+    odd := TBigInteger.Create(bit, FRandom).SetBit(bit + 1).SetBit(0);
+    pow2 := Fone.ShiftLeft(bit);
+    CheckEquals(bit + 2, odd.BitLength);
+    CheckEquals(bit + 2, odd.Negate().BitLength);
+    CheckEquals(bit + 1, pow2.BitLength);
+    CheckEquals(bit, pow2.Negate().BitLength);
+  end;
+end;
+
+procedure TTestBigInteger.TestClearBit;
+var
+  i, j, pos: Int32;
+  n, m, pow2, minusPow2, bigI, negI: TBigInteger;
+  test: Boolean;
+  data: string;
+begin
+  CheckEqualsBigInteger(Fzero, Fzero.ClearBit(0));
+  CheckEqualsBigInteger(Fzero, Fone.ClearBit(0));
+  CheckEqualsBigInteger(Ftwo, Ftwo.ClearBit(0));
+
+  CheckEqualsBigInteger(Fzero, Fzero.ClearBit(1));
+  CheckEqualsBigInteger(Fone, Fone.ClearBit(1));
+  CheckEqualsBigInteger(Fzero, Ftwo.ClearBit(1));
+
+  // TODO Tests for clearing bits in negative numbers
+
+  // TODO Tests for clearing extended bits
+
+  i := 0;
+  while i < 10 do
+  begin
+    n := TBigInteger.Create(128, FRandom);
+
+    j := 0;
+    while j < 10 do
+    begin
+      pos := FRandom.Next(128);
+      m := n.ClearBit(pos);
+      test := m.ShiftRight(pos).Remainder(Ftwo).Equals(Fone);
+
+      CheckFalse(test);
+      System.Inc(j);
+    end;
+    System.Inc(i);
+  end;
+
+  for i := 0 to System.Pred(100) do
+  begin
+    pow2 := Fone.ShiftLeft(i);
+    minusPow2 := pow2.Negate();
+
+    CheckEqualsBigInteger(Fzero, pow2.ClearBit(i));
+    CheckEqualsBigInteger(minusPow2.ShiftLeft(1), minusPow2.ClearBit(i));
+
+    bigI := TBigInteger.ValueOf(i);
+    negI := bigI.Negate();
+
+    for j := 0 to System.Pred(10) do
+    begin
+      data := Format('i:=%d, j:=%d', [i, j]);
+      CheckEqualsBigInteger(bigI.AndNot(Fone.ShiftLeft(j)),
+        bigI.ClearBit(j), data);
+      CheckEqualsBigInteger(negI.AndNot(Fone.ShiftLeft(j)),
+        negI.ClearBit(j), data);
+    end;
+  end;
+end;
+
+procedure TTestBigInteger.TestCompareTo;
+begin
+  CheckEquals(0, FminusTwo.CompareTo(FminusTwo));
+  CheckEquals(-1, FminusTwo.CompareTo(FminusOne));
+  CheckEquals(-1, FminusTwo.CompareTo(Fzero));
+  CheckEquals(-1, FminusTwo.CompareTo(Fone));
+  CheckEquals(-1, FminusTwo.CompareTo(Ftwo));
+
+  CheckEquals(1, FminusOne.CompareTo(FminusTwo));
+  CheckEquals(0, FminusOne.CompareTo(FminusOne));
+  CheckEquals(-1, FminusOne.CompareTo(Fzero));
+  CheckEquals(-1, FminusOne.CompareTo(Fone));
+  CheckEquals(-1, FminusOne.CompareTo(Ftwo));
+
+  CheckEquals(1, Fzero.CompareTo(FminusTwo));
+  CheckEquals(1, Fzero.CompareTo(FminusOne));
+  CheckEquals(0, Fzero.CompareTo(Fzero));
+  CheckEquals(-1, Fzero.CompareTo(Fone));
+  CheckEquals(-1, Fzero.CompareTo(Ftwo));
+
+  CheckEquals(1, Fone.CompareTo(FminusTwo));
+  CheckEquals(1, Fone.CompareTo(FminusOne));
+  CheckEquals(1, Fone.CompareTo(Fzero));
+  CheckEquals(0, Fone.CompareTo(Fone));
+  CheckEquals(-1, Fone.CompareTo(Ftwo));
+
+  CheckEquals(1, Ftwo.CompareTo(FminusTwo));
+  CheckEquals(1, Ftwo.CompareTo(FminusOne));
+  CheckEquals(1, Ftwo.CompareTo(Fzero));
+  CheckEquals(1, Ftwo.CompareTo(Fone));
+  CheckEquals(0, Ftwo.CompareTo(Ftwo));
+end;
+
+procedure TTestBigInteger.TestConstructors;
+var
+  i: Int32;
+begin
+  CheckEqualsBigInteger(TBigInteger.Zero,
+    TBigInteger.Create(TCryptoLibByteArray.Create(0)));
+  CheckEqualsBigInteger(TBigInteger.Zero,
+    TBigInteger.Create(TCryptoLibByteArray.Create(0, 0)));
+
+  for i := 0 to System.Pred(10) do
+
+  begin
+    CheckTrue(TBigInteger.Create(i + 3, 0, FRandom).TestBit(0));
+  end;
+
+  // TODO Other constructors
+end;
+
+procedure TTestBigInteger.TestDivide;
+var
+  i, product, productPlus, rep, shift: Int32;
+  bigProduct, bigProductPlus, expected, a, b, c, d, e, bShift: TBigInteger;
+  divisor: Int32;
+  data: string;
+begin
+  for i := -5 to System.Pred(5) do
+
+  begin
+    try
+
+      val(i).Divide(Fzero);
+      Fail('expected EArithmeticCryptoLibException');
+
+    except
+      on e: EArithmeticCryptoLibException do
+      begin
+
+      end;
+
+    end;
+
+  end;
+
+  product := 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9;
+  productPlus := product + 1;
+
+  bigProduct := val(product);
+  bigProductPlus := val(productPlus);
+  for divisor := 1 to System.Pred(10) do
+  begin
+    // Exact division
+    expected := val(product div divisor);
+
+    CheckEqualsBigInteger(expected, bigProduct.Divide(val(divisor)));
+    CheckEqualsBigInteger(expected.Negate(), bigProduct.Negate()
+      .Divide(val(divisor)));
+    CheckEqualsBigInteger(expected.Negate(),
+      bigProduct.Divide(val(divisor).Negate()));
+    CheckEqualsBigInteger(expected, bigProduct.Negate()
+      .Divide(val(divisor).Negate()));
+
+    expected := val((product + 1) div divisor);
+
+    CheckEqualsBigInteger(expected, bigProductPlus.Divide(val(divisor)));
+    CheckEqualsBigInteger(expected.Negate(), bigProductPlus.Negate()
+      .Divide(val(divisor)));
+    CheckEqualsBigInteger(expected.Negate(),
+      bigProductPlus.Divide(val(divisor).Negate()));
+    CheckEqualsBigInteger(expected, bigProductPlus.Negate()
+      .Divide(val(divisor).Negate()));
+  end;
+
+  for rep := 0 to System.Pred(10) do
+
+  begin
+    a := TBigInteger.Create(100 - rep, 0, FRandom);
+    b := TBigInteger.Create(100 + rep, 0, FRandom);
+    c := TBigInteger.Create(10 + rep, 0, FRandom);
+    d := a.Multiply(b).Add(c);
+    e := d.Divide(a);
+
+    CheckEqualsBigInteger(b, e);
+  end;
+
+  // Special tests for power of two since uses different code path internally
+  i := 0;
+  while i < 100 do
+  begin
+    shift := FRandom.Next(64);
+    a := Fone.ShiftLeft(shift);
+    b := TBigInteger.Create(64 + FRandom.Next(64), FRandom);
+    bShift := b.ShiftRight(shift);
+
+    data := Format('shift:=%d, b:=%s', [shift, b.ToString(16)]);
+
+    CheckEqualsBigInteger(bShift, b.Divide(a), data);
+    CheckEqualsBigInteger(bShift.Negate(), b.Divide(a.Negate()), data);
+    CheckEqualsBigInteger(bShift.Negate(), b.Negate().Divide(a), data);
+    CheckEqualsBigInteger(bShift, b.Negate().Divide(a.Negate()), data);
+    System.Inc(i);
+  end;
+
+  // Regression
+
+  shift := 63;
+  a := Fone.ShiftLeft(shift);
+  b := TBigInteger.Create(1, THex.Decode('2504b470dc188499'));
+  bShift := b.ShiftRight(shift);
+
+  data := Format('shift:=%d, b:=%s', [shift, b.ToString(16)]);
+  CheckEqualsBigInteger(bShift, b.Divide(a), data);
+  CheckEqualsBigInteger(bShift.Negate(), b.Divide(a.Negate()), data);
+  CheckEqualsBigInteger(bShift.Negate(), b.Negate().Divide(a), data);
+  CheckEqualsBigInteger(bShift, b.Negate().Divide(a.Negate()), data);
+
+end;
+
+procedure TTestBigInteger.TestDivideAndRemainder;
+var
+  qr, es: TCryptoLibGenericArray<TBigInteger>;
+  n, a, b, c, d, bShift, bMod: TBigInteger;
+  rep, shift: Int32;
+  data: string;
+begin
+  // TODO More basic tests
+
+  n := TBigInteger.Create(48, FRandom);
+  qr := n.DivideAndRemainder(n);
+  CheckEqualsBigInteger(Fone, qr[0]);
+  CheckEqualsBigInteger(Fzero, qr[1]);
+
+  qr := n.DivideAndRemainder(Fone);
+  CheckEqualsBigInteger(n, qr[0]);
+  CheckEqualsBigInteger(Fzero, qr[1]);
+
+  for rep := 0 to System.Pred(10) do
+
+  begin
+    a := TBigInteger.Create(100 - rep, 0, FRandom);
+    b := TBigInteger.Create(100 + rep, 0, FRandom);
+    c := TBigInteger.Create(10 + rep, 0, FRandom);
+    d := a.Multiply(b).Add(c);
+    es := d.DivideAndRemainder(a);
+
+    CheckEqualsBigInteger(b, es[0]);
+    CheckEqualsBigInteger(c, es[1]);
+  end;
+
+  // Special tests for power of two since uses different code path internally
+  rep := 0;
+  while rep < 100 do
+  begin
+    shift := FRandom.Next(64);
+    a := Fone.ShiftLeft(shift);
+    b := TBigInteger.Create(64 + FRandom.Next(64), FRandom);
+    bShift := b.ShiftRight(shift);
+    bMod := b.&And(a.Subtract(Fone));
+
+    data := Format('shift:=%d, b:=%s', [shift, b.ToString(16)]);
+
+    qr := b.DivideAndRemainder(a);
+    CheckEqualsBigInteger(bShift, qr[0], data);
+    CheckEqualsBigInteger(bMod, qr[1], data);
+
+    qr := b.DivideAndRemainder(a.Negate());
+    CheckEqualsBigInteger(bShift.Negate(), qr[0], data);
+    CheckEqualsBigInteger(bMod, qr[1], data);
+
+    qr := b.Negate().DivideAndRemainder(a);
+    CheckEqualsBigInteger(bShift.Negate(), qr[0], data);
+    CheckEqualsBigInteger(bMod.Negate(), qr[1], data);
+
+    qr := b.Negate().DivideAndRemainder(a.Negate());
+    CheckEqualsBigInteger(bShift, qr[0], data);
+    CheckEqualsBigInteger(bMod.Negate(), qr[1], data);
+    System.Inc(rep);
+  end;
+end;
+
+procedure TTestBigInteger.TestFlipBit;
+var
+  i, j, x, pos: Int32;
+  a, b, pow2, minusPow2, bigI, negI: TBigInteger;
+  data: string;
+begin
+
+  i := 0;
+  while i < 10 do
+  begin
+    a := TBigInteger.Create(128, 0, FRandom);
+    b := a;
+
+    x := 0;
+    while x < 100 do
+    begin
+      // Note: Intentionally greater than initial size
+      pos := FRandom.Next(256);
+
+      a := a.FlipBit(pos);
+      if b.TestBit(pos) then
+      begin
+        b := b.ClearBit(pos);
+      end
+      else
+      begin
+        b := b.SetBit(pos);
+      end;
+
+      System.Inc(x);
+    end;
+
+    CheckEqualsBigInteger(a, b);
+    System.Inc(i);
+  end;
+
+  for i := 0 to System.Pred(100) do
+  begin
+    pow2 := Fone.ShiftLeft(i);
+    minusPow2 := pow2.Negate();
+
+    CheckEqualsBigInteger(Fzero, pow2.FlipBit(i));
+    CheckEqualsBigInteger(minusPow2.ShiftLeft(1), minusPow2.FlipBit(i));
+
+    bigI := TBigInteger.ValueOf(i);
+    negI := bigI.Negate();
+
+    for j := 0 to System.Pred(10) do
+    begin
+
+      data := Format('i:=%d, j:=%d', [i, j]);
+      CheckEqualsBigInteger(bigI.&Xor(Fone.ShiftLeft(j)),
+        bigI.FlipBit(j), data);
+      CheckEqualsBigInteger(negI.&Xor(Fone.ShiftLeft(j)),
+        negI.FlipBit(j), data);
+    end;
+  end;
+end;
+
+procedure TTestBigInteger.TestGcd;
+var
+  i: Int32;
+  fac, p1, p2, gcd: TBigInteger;
+begin
+  i := 0;
+  while i < 10 do
+  begin
+    fac := TBigInteger.Create(32, FRandom).Add(Ftwo);
+    p1 := TBigInteger.ProbablePrime(63, FRandom);
+    p2 := TBigInteger.ProbablePrime(64, FRandom);
+
+    gcd := fac.Multiply(p1).gcd(fac.Multiply(p2));
+
+    CheckEqualsBigInteger(fac, gcd);
+    System.Inc(i);
+  end;
+end;
+
+procedure TTestBigInteger.TestGetLowestSetBit;
+var
+  i, bit1, bit2, bit3: Int32;
+  test: TBigInteger;
+begin
+  for i := 1 to 100 do
+
+  begin
+    test := TBigInteger.Create(i + 1, 0, FRandom).Add(Fone);
+    bit1 := test.GetLowestSetBit();
+    CheckEqualsBigInteger(test, test.ShiftRight(bit1).ShiftLeft(bit1));
+    bit2 := test.ShiftLeft(i + 1).GetLowestSetBit();
+    CheckEquals(i + 1, bit2 - bit1);
+    bit3 := test.ShiftLeft(3 * i).GetLowestSetBit();
+    CheckEquals(3 * i, bit3 - bit1);
+  end;
+end;
+
+procedure TTestBigInteger.TestInt32Value;
+var
+  tests: TCryptoLibInt32Array;
+  test: Int32;
+begin
+  tests := TCryptoLibInt32Array.Create(System.Low(Int32), -1234, -10, -1, 0,
+    (not 0), 1, 10, 5678, System.High(Int32));
+
+  for test in tests do
+  begin
+    CheckEquals(test, val(test).Int32Value);
+  end;
+
+  // TODO Tests for large numbers
+end;
+
+procedure TTestBigInteger.TestInt64Value;
+var
+  tests: TCryptoLibInt64Array;
+  test: Int64;
+begin
+  tests := TCryptoLibInt64Array.Create(System.Low(Int64), Int64(-1234),
+    Int64(-10), Int64(-1), Int64(0), (not Int64(0)), Int64(1), Int64(10),
+    Int64(5678), Int64(System.High(Int64)));
+
+  for test in tests do
+  begin
+    CheckEquals(test, (val(test).Int64Value));
+  end;
+
+  // TODO Tests for large numbers
+end;
+
+procedure TTestBigInteger.TestIsProbablePrime;
+var
+  p, c, e: Int32;
+begin
+  CheckFalse(Fzero.IsProbablePrime(100));
+  CheckTrue(Fzero.IsProbablePrime(0));
+  CheckTrue(Fzero.IsProbablePrime(-10));
+  CheckFalse(FminusOne.IsProbablePrime(100));
+  CheckTrue(FminusTwo.IsProbablePrime(100));
+  CheckTrue(val(-17).IsProbablePrime(100));
+  CheckTrue(val(67).IsProbablePrime(100));
+  CheckTrue(val(773).IsProbablePrime(100));
+
+  for p in FfirstPrimes do
+  begin
+    CheckTrue(val(p).IsProbablePrime(100));
+    CheckTrue(val(-p).IsProbablePrime(100));
+  end;
+
+  for c in FnonPrimes do
+
+  begin
+    CheckFalse(val(c).IsProbablePrime(100));
+    CheckFalse(val(-c).IsProbablePrime(100));
+  end;
+
+  for e in FmersennePrimeExponents do
+  begin
+    CheckTrue(mersenne(e).IsProbablePrime(100));
+    CheckTrue(mersenne(e).Negate().IsProbablePrime(100));
+  end;
+
+  for e in FnonPrimeExponents do
+
+  begin
+    CheckFalse(mersenne(e).IsProbablePrime(100));
+    CheckFalse(mersenne(e).Negate().IsProbablePrime(100));
+  end;
+
+  // TODO Other examples of 'tricky' values?
+end;
+
+procedure TTestBigInteger.TestMax;
+var
+  i, j: Int32;
+begin
+  for i := -10 to 10 do
+  begin
+
+    for j := -10 to 10 do
+    begin
+      CheckEqualsBigInteger(val(Math.Max(i, j)), val(i).Max(val(j)));
+    end;
+  end;
+end;
+
+procedure TTestBigInteger.TestMin;
+var
+  i, j: Int32;
+begin
+  for i := -10 to 10 do
+  begin
+
+    for j := -10 to 10 do
+    begin
+      CheckEqualsBigInteger(val(Math.Min(i, j)), val(i).Min(val(j)));
+    end;
+  end;
+end;
+
+procedure TTestBigInteger.TestMod;
+var
+  rep, diff: Int32;
+  a, b, c, d, e, pow2: TBigInteger;
+begin
+  // TODO Basic tests
+
+  rep := 0;
+  while rep < 100 do
+
+  begin
+    diff := FRandom.Next(25);
+    a := TBigInteger.Create(100 - diff, 0, FRandom);
+    b := TBigInteger.Create(100 + diff, 0, FRandom);
+    c := TBigInteger.Create(10 + diff, 0, FRandom);
+
+    d := a.Multiply(b).Add(c);
+    e := d.&Mod(a);
+    CheckEqualsBigInteger(c, e);
+
+    pow2 := Fone.ShiftLeft(FRandom.Next(128));
+    CheckEqualsBigInteger(b.&And(pow2.Subtract(Fone)), b.&Mod(pow2));
+    System.Inc(rep);
+  end;
+end;
+
+procedure TTestBigInteger.TestModInverse;
+var
+  i: Int32;
+  p, q, inv, inv2, m, d, x, check: TBigInteger;
+begin
+  i := 0;
+  while i < 10 do
+
+  begin
+    p := TBigInteger.ProbablePrime(64, FRandom);
+    q := TBigInteger.Create(63, FRandom).Add(Fone);
+    inv := q.ModInverse(p);
+    inv2 := inv.ModInverse(p);
+
+    CheckEqualsBigInteger(q, inv2);
+    CheckEqualsBigInteger(Fone, q.Multiply(inv).&Mod(p));
+    System.Inc(i);
+  end;
+
+  // ModInverse a power of 2 for a range of powers
+  for i := 1 to 128 do
+  begin
+    m := Fone.ShiftLeft(i);
+    d := TBigInteger.Create(i, FRandom).SetBit(0);
+    x := d.ModInverse(m);
+    check := x.Multiply(d).&Mod(m);
+
+    CheckEqualsBigInteger(Fone, check);
+  end;
+end;
+
+procedure TTestBigInteger.TestModPow;
+var
+  i: Int32;
+  m, x, y, n, n3, resX, resY, res, res3, a, b: TBigInteger;
+begin
+  try
+
+    Ftwo.ModPow(Fone, Fzero);
+    Fail('expected EArithmeticCryptoLibException');
+
+  except
+    on e: EArithmeticCryptoLibException do
+    begin
+
+    end;
+
+  end;
+
+  CheckEqualsBigInteger(Fzero, Fzero.ModPow(Fzero, Fone));
+  CheckEqualsBigInteger(Fone, Fzero.ModPow(Fzero, Ftwo));
+  CheckEqualsBigInteger(Fzero, Ftwo.ModPow(Fone, Fone));
+  CheckEqualsBigInteger(Fone, Ftwo.ModPow(Fzero, Ftwo));
+
+  for i := 0 to System.Pred(100) do
+
+  begin
+    m := TBigInteger.ProbablePrime(10 + i, FRandom);
+    x := TBigInteger.Create(m.BitLength - 1, FRandom);
+
+    CheckEqualsBigInteger(x, x.ModPow(m, m));
+    if (x.SignValue <> 0) then
+    begin
+      CheckEqualsBigInteger(Fzero, Fzero.ModPow(x, m));
+      CheckEqualsBigInteger(Fone, x.ModPow(m.Subtract(Fone), m));
+    end;
+
+    y := TBigInteger.Create(m.BitLength - 1, FRandom);
+    n := TBigInteger.Create(m.BitLength - 1, FRandom);
+    n3 := n.ModPow(Fthree, m);
+
+    resX := n.ModPow(x, m);
+    resY := n.ModPow(y, m);
+    res := resX.Multiply(resY).&Mod(m);
+    res3 := res.ModPow(Fthree, m);
+
+    CheckEqualsBigInteger(res3, n3.ModPow(x.Add(y), m));
+
+    a := x.Add(Fone); // Make sure it's not zero
+    b := y.Add(Fone); // Make sure it's not zero
+
+    CheckEqualsBigInteger(a.ModPow(b, m).ModInverse(m),
+      a.ModPow(b.Negate(), m));
+  end;
+
+end;
+
+procedure TTestBigInteger.TestMonoBug81857;
+var
+  b, exp, &Mod, expected, manual: TBigInteger;
+begin
+  b := TBigInteger.Create('18446744073709551616');
+  exp := TBigInteger.Two;
+  &Mod := TBigInteger.Create('48112959837082048697');
+  expected := TBigInteger.Create('4970597831480284165');
+
+  manual := b.Multiply(b).&Mod(&Mod);
+  CheckEquals(True, expected.Equals(manual), 'b * b % mod');
+end;
+
+procedure TTestBigInteger.TestMultiply;
+var
+  i, aLen, bLen, shift: Int32;
+  One, a, b, c, ab, bc, bShift: TBigInteger;
+begin
+  One := TBigInteger.One;
+
+  CheckEqualsBigInteger(One, One.Negate().Multiply(One.Negate()));
+
+  i := 0;
+  while i < 100 do
+  begin
+    aLen := 64 + FRandom.Next(64);
+    bLen := 64 + FRandom.Next(64);
+
+    a := TBigInteger.Create(aLen, FRandom).SetBit(aLen);
+    b := TBigInteger.Create(bLen, FRandom).SetBit(bLen);
+    c := TBigInteger.Create(32, FRandom);
+
+    ab := a.Multiply(b);
+    bc := b.Multiply(c);
+
+    CheckEqualsBigInteger(ab.Add(bc), a.Add(c).Multiply(b));
+    CheckEqualsBigInteger(ab.Subtract(bc), a.Subtract(c).Multiply(b));
+    System.Inc(i);
+  end;
+
+  // Special tests for power of two since uses different code path internally
+  i := 0;
+  while i < 100 do
+  begin
+    shift := FRandom.Next(64);
+    a := One.ShiftLeft(shift);
+    b := TBigInteger.Create(64 + FRandom.Next(64), FRandom);
+    bShift := b.ShiftLeft(shift);
+
+    CheckEqualsBigInteger(bShift, a.Multiply(b));
+    CheckEqualsBigInteger(bShift.Negate(), a.Multiply(b.Negate()));
+    CheckEqualsBigInteger(bShift.Negate(), a.Negate().Multiply(b));
+    CheckEqualsBigInteger(bShift, a.Negate().Multiply(b.Negate()));
+
+    CheckEqualsBigInteger(bShift, b.Multiply(a));
+    CheckEqualsBigInteger(bShift.Negate(), b.Multiply(a.Negate()));
+    CheckEqualsBigInteger(bShift.Negate(), b.Negate().Multiply(a));
+    CheckEqualsBigInteger(bShift, b.Negate().Multiply(a.Negate()));
+    System.Inc(i);
+  end;
+end;
+
+procedure TTestBigInteger.TestNegate;
+var
+  i: Int32;
+begin
+  for i := -10 to 10 do
+  begin
+    CheckEqualsBigInteger(val(-i), val(i).Negate());
+  end;
+end;
+
+procedure TTestBigInteger.TestNextProbablePrime;
+var
+  firstPrime, nextPrime, check: TBigInteger;
+begin
+  firstPrime := TBigInteger.ProbablePrime(32, FRandom);
+  nextPrime := firstPrime.NextProbablePrime();
+
+  CheckTrue(firstPrime.IsProbablePrime(10));
+  CheckTrue(nextPrime.IsProbablePrime(10));
+
+  check := firstPrime.Add(Fone);
+
+  while (check.CompareTo(nextPrime) < 0) do
+  begin
+    CheckFalse(check.IsProbablePrime(10));
+    check := check.Add(Fone);
+  end;
+end;
+
+procedure TTestBigInteger.TestNot;
+var
+  i: Int32;
+begin
+  for i := -10 to 10 do
+  begin
+    CheckEqualsBigInteger(val(not i), val(i).&Not(),
+      Format('Problem: (not %d) should be %d', [i, (not i)]));
+
+  end;
+end;
+
+procedure TTestBigInteger.TestOr;
+var
+  i, j: Int32;
+begin
+  for i := -10 to 10 do
+  begin
+    for j := -10 to 10 do
+    begin
+      CheckEqualsBigInteger(val(i or j), val(i).&Or(val(j)),
+        Format('Problem: %d.OR(%d) should be %d', [i, j, (i or j)]));
+    end;
+
+  end;
+end;
+
+procedure TTestBigInteger.TestPow;
+var
+  i: Int32;
+  n, result: TBigInteger;
+begin
+  CheckEqualsBigInteger(Fone, Fzero.&Pow(0));
+  CheckEqualsBigInteger(Fzero, Fzero.&Pow(123));
+  CheckEqualsBigInteger(Fone, Fone.&Pow(0));
+  CheckEqualsBigInteger(Fone, Fone.&Pow(123));
+
+  CheckEqualsBigInteger(Ftwo.&Pow(147), Fone.ShiftLeft(147));
+  CheckEqualsBigInteger(Fone.ShiftLeft(7).Pow(11), Fone.ShiftLeft(77));
+
+  n := TBigInteger.Create('1234567890987654321');
+  result := Fone;
+  for i := 0 to System.Pred(10) do
+
+  begin
+
+    try
+
+      val(i).&Pow(-1);
+      Fail('expected EArithmeticCryptoLibException');
+
+    except
+      on e: EArithmeticCryptoLibException do
+      begin
+        // expected
+      end;
+
+    end;
+
+    CheckEqualsBigInteger(result, n.&Pow(i));
+
+    result := result.Multiply(n);
+  end;
+end;
+
+procedure TTestBigInteger.TestRemainder;
+var
+  rep: Int32;
+  a, b, c, d, e: TBigInteger;
+begin
+  // TODO Basic tests
+  for rep := 0 to System.Pred(10) do
+
+  begin
+    a := TBigInteger.Create(100 - rep, 0, FRandom);
+    b := TBigInteger.Create(100 + rep, 0, FRandom);
+    c := TBigInteger.Create(10 + rep, 0, FRandom);
+    d := a.Multiply(b).Add(c);
+    e := d.Remainder(a);
+
+    CheckEqualsBigInteger(c, e);
+  end;
+end;
+
+procedure TTestBigInteger.TestSetBit;
+var
+  i, j, pos: Int32;
+  test: Boolean;
+  m, n, pow2, minusPow2, bigI, negI: TBigInteger;
+  data: string;
+begin
+
+  CheckEqualsBigInteger(Fone, Fzero.SetBit(0));
+  CheckEqualsBigInteger(Fone, Fone.SetBit(0));
+  CheckEqualsBigInteger(Fthree, Ftwo.SetBit(0));
+
+  CheckEqualsBigInteger(Ftwo, Fzero.SetBit(1));
+  CheckEqualsBigInteger(Fthree, Fone.SetBit(1));
+  CheckEqualsBigInteger(Ftwo, Ftwo.SetBit(1));
+
+  // TODO Tests for setting bits in negative numbers
+
+  // TODO Tests for setting extended bits
+
+  i := 0;
+  while i < 10 do
+
+  begin
+    n := TBigInteger.Create(128, FRandom);
+
+    j := 0;
+    while j < 10 do
+    begin
+      pos := FRandom.Next(128);
+      m := n.SetBit(pos);
+      test := m.ShiftRight(pos).Remainder(Ftwo).Equals(Fone);
+
+      CheckTrue(test);
+      System.Inc(j);
+    end;
+    System.Inc(i);
+  end;
+
+  for i := 0 to System.Pred(100) do
+  begin
+    pow2 := Fone.ShiftLeft(i);
+    minusPow2 := pow2.Negate();
+
+    CheckEqualsBigInteger(pow2, pow2.SetBit(i));
+    CheckEqualsBigInteger(minusPow2, minusPow2.SetBit(i));
+
+    bigI := TBigInteger.ValueOf(i);
+    negI := bigI.Negate();
+
+    for j := 0 to System.Pred(10) do
+    begin
+      data := Format('i:=%d, j:=%d', [i, j]);
+      CheckEqualsBigInteger(bigI.&Or(Fone.ShiftLeft(j)), bigI.SetBit(j), data);
+      CheckEqualsBigInteger(negI.&Or(Fone.ShiftLeft(j)), negI.SetBit(j), data);
+    end;
+  end;
+end;
+
+procedure TTestBigInteger.TestShiftLeft;
+var
+  i, j, shift { , bits } : Int32;
+  a, b, c, negA: TBigInteger;
+  bt: TBytes;
+begin
+  for i := 0 to System.Pred(100) do
+  begin
+    shift := FRandom.Next(128);
+    System.SetLength(bt, 1000);
+    FRandom.NextBytes(bt);
+
+    a := TBigInteger.Create(128 + i, FRandom).Add(Fone);
+    // bits := a.bitCount; // Make sure nBits is set
+
+    negA := a.Negate();
+    // bits := negA.bitCount; // Make sure nBits is set
+
+    b := a.ShiftLeft(shift);
+    c := negA.ShiftLeft(shift);
+
+    CheckEquals(a.bitCount, b.bitCount);
+    CheckEquals(negA.bitCount + shift, c.bitCount);
+    CheckEquals(a.BitLength + shift, b.BitLength);
+    CheckEquals(negA.BitLength + shift, c.BitLength);
+
+    j := 0;
+    while j < shift do
+    begin
+
+      CheckFalse(b.TestBit(j));
+      System.Inc(j);
+    end;
+
+    while j < b.BitLength do
+
+    begin
+      CheckEquals(a.TestBit(j - shift), b.TestBit(j));
+      System.Inc(j);
+    end;
+  end;
+end;
+
+procedure TTestBigInteger.TestShiftRight;
+var
+  i, j, shift: Int32;
+  a, b: TBigInteger;
+begin
+  for i := 0 to System.Pred(10) do
+  begin
+    shift := FRandom.Next(128);
+    a := TBigInteger.Create(256 + i, FRandom).SetBit(256 + i);
+    b := a.ShiftRight(shift);
+
+    CheckEquals(a.BitLength - shift, b.BitLength);
+
+    for j := 0 to System.Pred(b.BitLength) do
+    begin
+      CheckEquals(a.TestBit(j + shift), b.TestBit(j));
+    end;
+  end;
+end;
+
+procedure TTestBigInteger.TestSignValue;
+var
+  i: Int32;
+begin
+  for i := -10 to 10 do
+  begin
+    if i < 0 then
+    begin
+      CheckEquals(-1, val(i).SignValue);
+    end
+    else if i > 0 then
+    begin
+      CheckEquals(1, val(i).SignValue);
+    end
+    else
+    begin
+      CheckEquals(0, val(i).SignValue);
+    end;
+
+  end;
+end;
+
+procedure TTestBigInteger.TestSubtract;
+var
+  i, j: Int32;
+begin
+  for i := -10 to 10 do
+  begin
+    for j := -10 to 10 do
+    begin
+      CheckEqualsBigInteger(val(i - j), val(i).Subtract(val(j)),
+        Format('Problem: %d.Subtract(%d) should be %d', [i, j, (i - j)]));
+    end;
+
+  end;
+end;
+
+procedure TTestBigInteger.TestTestBit;
+var
+  i, j, pos: Int32;
+  n: TBigInteger;
+  test: Boolean;
+begin
+  i := 0;
+  while i < 10 do
+
+  begin
+    n := TBigInteger.Create(128, FRandom);
+
+    CheckFalse(n.TestBit(128));
+    CheckTrue(n.Negate().TestBit(128));
+
+    j := 0;
+    while j < 10 do
+    begin
+      pos := FRandom.Next(128);
+      test := n.ShiftRight(pos).Remainder(Ftwo).Equals(Fone);
+
+      CheckEquals(test, n.TestBit(pos));
+      System.Inc(j);
+    end;
+
+    System.Inc(i);
+  end;
+end;
+
+procedure TTestBigInteger.TestToByteArray;
+var
+  z, temp, b: TCryptoLibByteArray;
+  i: Int32;
+  x, y: TBigInteger;
+begin
+  z := TBigInteger.Zero.ToByteArray();
+  System.SetLength(temp, 1);
+  CheckTrue(TArrayUtils.AreEqual(temp, z));
+  for i := 16 to 48 do
+  begin
+    x := TBigInteger.ProbablePrime(i, FRandom);
+    b := x.ToByteArray();
+    CheckEquals(((i div 8) + 1), System.Length(b));
+    y := TBigInteger.Create(b);
+    CheckEqualsBigInteger(x, y);
+
+    x := x.Negate();
+    b := x.ToByteArray();
+    CheckEquals(((i div 8) + 1), System.Length(b));
+    y := TBigInteger.Create(b);
+    CheckEqualsBigInteger(x, y);
+  end;
+end;
+
+procedure TTestBigInteger.TestToByteArrayUnsigned;
+var
+  z, temp, b: TCryptoLibByteArray;
+  i: Int32;
+  x, y: TBigInteger;
+begin
+  z := TBigInteger.Zero.ToByteArrayUnsigned();
+  System.SetLength(temp, 0);
+  CheckTrue(TArrayUtils.AreEqual(temp, z));
+  for i := 16 to 48 do
+  begin
+    x := TBigInteger.ProbablePrime(i, FRandom);
+    b := x.ToByteArrayUnsigned();
+    CheckEquals(((i + 7) div 8), System.Length(b));
+    y := TBigInteger.Create(1, b);
+    CheckEqualsBigInteger(x, y);
+
+    x := x.Negate();
+    b := x.ToByteArrayUnsigned();
+    CheckEquals(((i div 8) + 1), System.Length(b));
+    y := TBigInteger.Create(b);
+    CheckEqualsBigInteger(x, y);
+  end;
+end;
+
+procedure TTestBigInteger.TestToString;
+var
+  s, str: string;
+  radices: TCryptoLibInt32Array;
+  tests: TCryptoLibGenericArray<TBigInteger>;
+  i, trials, len, radix: Int32;
+  n, n1, n2: TBigInteger;
+begin
+  s := '12345667890987654321';
+
+  CheckEquals(s, TBigInteger.Create(s).ToString());
+  CheckEquals(s, TBigInteger.Create(s, 10).ToString(10));
+  CheckEquals(s, TBigInteger.Create(s, 16).ToString(16));
+
+  CheckEquals('-e4437ed6010e88286f547fa90abfe4c3',
+    TBigInteger.Create('-e4437ed6010e88286f547fa90abfe4c3', 16).ToString(16));
+
+  for i := 0 to System.Pred(100) do
+  begin
+
+    n := TBigInteger.Create(i, FRandom);
+
+    CheckEqualsBigInteger(n, TBigInteger.Create(n.ToString(2), 2));
+    CheckEqualsBigInteger(n, TBigInteger.Create(n.ToString(8), 8));
+    CheckEqualsBigInteger(n, TBigInteger.Create(n.ToString(10), 10));
+    CheckEqualsBigInteger(n, TBigInteger.Create(n.ToString(16), 16));
+  end;
+
+  // Radix version
+  radices := TCryptoLibInt32Array.Create(2, 8, 10, 16);
+  trials := 256;
+
+  System.SetLength(tests, trials);
+  for i := 0 to System.Pred(trials) do
+
+  begin
+    len := FRandom.Next(i + 1);
+    tests[i] := TBigInteger.Create(len, FRandom);
+  end;
+
+  for radix in radices do
+  begin
+
+    for i := 0 to System.Pred(trials) do
+    begin
+      n1 := tests[i];
+      str := n1.ToString(radix);
+      n2 := TBigInteger.Create(str, radix);
+      CheckEqualsBigInteger(n1, n2);
+    end;
+  end;
+end;
+
+procedure TTestBigInteger.TestValueOf;
+var
+  i: Int32;
+begin
+  CheckEquals(-1, TBigInteger.ValueOf(-1).SignValue);
+  CheckEquals(0, TBigInteger.ValueOf(0).SignValue);
+  CheckEquals(1, TBigInteger.ValueOf(1).SignValue);
+
+  for i := -5 to System.Pred(5) do
+  begin
+    CheckEquals(i, TBigInteger.ValueOf(i).Int32Value);
+  end;
+end;
+
+procedure TTestBigInteger.TestXor;
+var
+  i, j: Int32;
+begin
+  for i := -10 to 10 do
+  begin
+    for j := -10 to 10 do
+    begin
+
+      CheckEqualsBigInteger(val(i xor j), val(i).&Xor(val(j)),
+        Format('Problem: %d.XOR(%d) should be %d', [i, j, (i xor j)]));
+
+    end;
+  end;
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestBigInteger);
+{$ELSE}
+  RegisterTest(TTestBigInteger.Suite);
+{$ENDIF FPC}
+
+end.

+ 302 - 0
CryptoLib.Tests/src/Math/EC/Custom/Sec/SecP384R1FieldTests.pas

@@ -0,0 +1,302 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit SecP384R1FieldTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+{$HINTS OFF}
+
+uses
+  Classes,
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpSecureRandom,
+  ClpISecureRandom,
+  ClpCryptoLibTypes,
+  ClpIX9ECParameters,
+  ClpSecObjectIdentifiers,
+  ClpConverters,
+  ClpSecNamedCurves,
+  ClpIECFieldElement,
+  ClpBigInteger;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  TTestSecP384R1Field = class(TCryptoLibTestCase)
+  private
+  var
+    FRandom: ISecureRandom;
+    FDP: IX9ECParameters;
+    FQ: TBigInteger;
+
+    procedure AssertAreBigIntegersEqual(a, b: TBigInteger);
+    function FE(x: TBigInteger): IECFieldElement;
+    function GenerateMultiplyInput_Random(): IECFieldElement;
+    function GenerateSquareInput_CarryBug(): IECFieldElement;
+    function Nat_Create(len: Int32): TCryptoLibUInt32Array;
+    function Nat_ToBigInteger(len: Int32; x: TCryptoLibUInt32Array)
+      : TBigInteger;
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+    procedure TestMultiply1();
+    procedure TestMultiply2();
+    procedure TestSquare();
+    procedure TestSquare_CarryBug();
+
+    /// <summary>
+    /// Based on another example input demonstrating the carry propagation
+    /// bug in Nat192.square, as <br />reported by Joseph Friel on
+    /// dev-crypto.
+    /// </summary>
+    procedure TestSquare_CarryBug_Reported();
+
+  end;
+
+implementation
+
+{ TTestSecP384R1Field }
+
+procedure TTestSecP384R1Field.AssertAreBigIntegersEqual(a, b: TBigInteger);
+begin
+  CheckEquals(True, a.Equals(b));
+end;
+
+function TTestSecP384R1Field.FE(x: TBigInteger): IECFieldElement;
+begin
+  result := FDP.Curve.FromBigInteger(x);
+end;
+
+function TTestSecP384R1Field.GenerateMultiplyInput_Random: IECFieldElement;
+begin
+  result := FE(TBigInteger.Create(FDP.Curve.FieldSize + 32, FRandom).&Mod(FQ));
+end;
+
+function TTestSecP384R1Field.GenerateSquareInput_CarryBug: IECFieldElement;
+var
+  x: TCryptoLibUInt32Array;
+begin
+  x := Nat_Create(12);
+  x[0] := UInt32(FRandom.NextInt32()) shr 1;
+  x[6] := 2;
+  x[10] := $FFFF0000;
+  x[11] := $FFFFFFFF;
+
+  result := FE(Nat_ToBigInteger(12, x));
+end;
+
+function TTestSecP384R1Field.Nat_Create(len: Int32): TCryptoLibUInt32Array;
+begin
+  System.SetLength(result, len);
+end;
+
+function TTestSecP384R1Field.Nat_ToBigInteger(len: Int32;
+  x: TCryptoLibUInt32Array): TBigInteger;
+var
+  bs, temp: TCryptoLibByteArray;
+  i: Int32;
+  x_i: UInt32;
+begin
+  System.SetLength(bs, len shl 2);
+  for i := 0 to System.Pred(len) do
+
+  begin
+    x_i := x[i];
+    if (x_i <> 0) then
+    begin
+      temp := TConverters.ReadUInt32AsBytesBE(x_i);
+      System.Move(temp[0], bs[(len - 1 - i) shl 2], System.Length(temp) *
+        SizeOf(Byte));
+
+    end;
+  end;
+  result := TBigInteger.Create(1, bs);
+end;
+
+procedure TTestSecP384R1Field.SetUp;
+begin
+  inherited;
+  FRandom := TSecureRandom.Create();
+  FDP := TSecNamedCurves.GetByOid(TSecObjectIdentifiers.SecP384r1);
+  FQ := FDP.Curve.Field.Characteristic;
+end;
+
+procedure TTestSecP384R1Field.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestSecP384R1Field.TestMultiply1;
+var
+  Count, i: Int32;
+  x, y, z: IECFieldElement;
+  bigX, bigY, bigR, bigZ: TBigInteger;
+begin
+  Count := 1000;
+
+  i := 0;
+
+  while i < Count do
+  begin
+
+    x := GenerateMultiplyInput_Random();
+    y := GenerateMultiplyInput_Random();
+
+    bigX := x.ToBigInteger();
+    bigY := y.ToBigInteger();
+    bigR := bigX.Multiply(bigY).&Mod(FQ);
+
+    z := x.Multiply(y);
+    bigZ := z.ToBigInteger();
+
+    AssertAreBigIntegersEqual(bigR, bigZ);
+
+    System.Inc(i);
+  end;
+
+end;
+
+procedure TTestSecP384R1Field.TestMultiply2;
+var
+  Count, i, J, K: Int32;
+  ecFieldElements: TCryptoLibGenericArray<IECFieldElement>;
+  bigIntegers: TCryptoLibGenericArray<TBigInteger>;
+  bigR, bigZ: TBigInteger;
+  z: IECFieldElement;
+begin
+  Count := 100;
+  System.SetLength(ecFieldElements, Count);
+  System.SetLength(bigIntegers, Count);
+
+  for i := 0 to System.Pred(System.Length(ecFieldElements)) do
+
+  begin
+    ecFieldElements[i] := GenerateMultiplyInput_Random();
+    bigIntegers[i] := ecFieldElements[i].ToBigInteger();
+  end;
+
+  for J := 0 to System.Pred(System.Length(ecFieldElements)) do
+  begin
+    for K := 0 to System.Pred(System.Length(ecFieldElements)) do
+    begin
+      bigR := bigIntegers[J].Multiply(bigIntegers[K]).&Mod(FQ);
+
+      z := ecFieldElements[J].Multiply(ecFieldElements[K]);
+      bigZ := z.ToBigInteger();
+
+      AssertAreBigIntegersEqual(bigR, bigZ);
+    end;
+  end;
+end;
+
+procedure TTestSecP384R1Field.TestSquare;
+var
+  Count, i: Int32;
+  x, z: IECFieldElement;
+  bigX, bigY, bigZ: TBigInteger;
+begin
+  Count := 1000;
+  i := 0;
+
+  while i < Count do
+
+  begin
+    x := GenerateMultiplyInput_Random();
+
+    bigX := x.ToBigInteger();
+    bigY := bigX.Multiply(bigX).&Mod(FQ);
+
+    z := x.Square();
+    bigZ := z.ToBigInteger();
+
+    AssertAreBigIntegersEqual(bigY, bigZ);
+    System.Inc(i);
+  end;
+end;
+
+procedure TTestSecP384R1Field.TestSquare_CarryBug;
+var
+  Count, i: Int32;
+  x, z: IECFieldElement;
+  bigX, bigR, bigZ: TBigInteger;
+begin
+  Count := 100;
+  i := 0;
+
+  while i < Count do
+
+  begin
+    x := GenerateSquareInput_CarryBug();
+
+    bigX := x.ToBigInteger();
+    bigR := bigX.Multiply(bigX).&Mod(FQ);
+
+    z := x.Square();
+    bigZ := z.ToBigInteger();
+
+    AssertAreBigIntegersEqual(bigR, bigZ);
+    System.Inc(i);
+  end;
+end;
+
+procedure TTestSecP384R1Field.TestSquare_CarryBug_Reported;
+var
+  x, z: IECFieldElement;
+  bigX, bigR, bigZ: TBigInteger;
+begin
+  x := FE(TBigInteger.Create
+    ('2fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd',
+    16));
+
+  bigX := x.ToBigInteger();
+  bigR := bigX.Multiply(bigX).&Mod(FQ);
+
+  z := x.Square();
+  bigZ := z.ToBigInteger();
+
+  AssertAreBigIntegersEqual(bigR, bigZ);
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestSecP384R1Field);
+{$ELSE}
+  RegisterTest(TTestSecP384R1Field.Suite);
+{$ENDIF FPC}
+
+end.

+ 340 - 0
CryptoLib.Tests/src/Math/ECAlgorithmsTests.pas

@@ -0,0 +1,340 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ECAlgorithmsTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$WARNINGS OFF}
+{$ENDIF FPC}
+
+uses
+  Classes,
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  Generics.Collections,
+  ClpSecureRandom,
+  ClpISecureRandom,
+  ClpECCurve,
+  ClpIECInterface,
+  ClpBigInteger,
+  ClpECNamedCurveTable,
+  ClpECAlgorithms,
+  ClpX9ECParameters,
+  ClpIX9ECParameters,
+  ClpCryptoLibTypes;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  TTestECAlgorithms = class(TCryptoLibTestCase)
+  private
+
+    class var
+
+      FRandom: ISecureRandom;
+
+  var
+  const
+    Scale = Int32(4);
+
+    procedure DoTestSumOfMultiplies(x9: IX9ECParameters);
+    procedure DoTestSumOfTwoMultiplies(x9: IX9ECParameters);
+    procedure AssertPointsEqual(const msg: String; a, b: IECPoint);
+    function CopyPoints(ps: TCryptoLibGenericArray<IECPoint>; len: Int32)
+      : TCryptoLibGenericArray<IECPoint>;
+    function CopyScalars(ks: TCryptoLibGenericArray<TBigInteger>; len: Int32)
+      : TCryptoLibGenericArray<TBigInteger>;
+
+    function GetRandomPoint(x9: IX9ECParameters): IECPoint;
+    function GetRandomScalar(x9: IX9ECParameters): TBigInteger;
+
+    function GetTestCurves(): TCryptoLibGenericArray<IX9ECParameters>;
+
+    procedure AddTestCurves(x9s: TList<IX9ECParameters>; x9: IX9ECParameters);
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+    procedure TestSumOfMultiplies;
+    procedure TestSumOfMultipliesComplete;
+    procedure TestSumOfTwoMultiplies;
+    procedure TestSumOfTwoMultipliesComplete;
+
+  end;
+
+implementation
+
+{ TTestECAlgorithms }
+
+procedure TTestECAlgorithms.AddTestCurves(x9s: TList<IX9ECParameters>;
+  x9: IX9ECParameters);
+var
+  curve, c: IECCurve;
+  coord, i: Int32;
+  coords: TCryptoLibInt32Array;
+begin
+  curve := x9.curve;
+
+  coords := TECCurve.GetAllCoordinateSystems();
+  for i := 0 to System.Pred(System.Length(coords)) do
+
+  begin
+    coord := coords[i];
+    if (curve.CoordinateSystem = coord) then
+    begin
+      x9s.Add(x9);
+    end
+    else if (curve.SupportsCoordinateSystem(coord)) then
+    begin
+      c := curve.Configure().SetCoordinateSystem(coord).CreateCurve();
+      x9s.Add(TX9ECParameters.Create(c, c.ImportPoint(x9.G), x9.N, x9.H));
+    end;
+  end;
+end;
+
+procedure TTestECAlgorithms.AssertPointsEqual(const msg: String;
+  a, b: IECPoint);
+begin
+  CheckEquals(True, a.Equals(b), msg);
+end;
+
+function TTestECAlgorithms.CopyPoints(ps: TCryptoLibGenericArray<IECPoint>;
+  len: Int32): TCryptoLibGenericArray<IECPoint>;
+begin
+  System.SetLength(Result, len);
+  Result := System.Copy(ps, 0, len);
+end;
+
+function TTestECAlgorithms.CopyScalars(ks: TCryptoLibGenericArray<TBigInteger>;
+  len: Int32): TCryptoLibGenericArray<TBigInteger>;
+begin
+  System.SetLength(Result, len);
+  Result := System.Copy(ks, 0, len);
+end;
+
+procedure TTestECAlgorithms.DoTestSumOfMultiplies(x9: IX9ECParameters);
+var
+  points, results: TCryptoLibGenericArray<IECPoint>;
+  scalars: TCryptoLibGenericArray<TBigInteger>;
+  i: Int32;
+  u, v: IECPoint;
+begin
+  System.SetLength(points, Scale);
+  System.SetLength(scalars, Scale);
+
+  for i := 0 to System.Pred(Scale) do
+
+  begin
+    points[i] := GetRandomPoint(x9);
+    scalars[i] := GetRandomScalar(x9);
+  end;
+
+  u := x9.curve.Infinity;
+
+  for i := 0 to System.Pred(Scale) do
+  begin
+    u := u.Add(points[i].Multiply(scalars[i]));
+
+    v := TECAlgorithms.SumOfMultiplies(CopyPoints(points, i + 1),
+      CopyScalars(scalars, i + 1));
+
+    results := TCryptoLibGenericArray<IECPoint>.Create(u, v);
+    x9.curve.NormalizeAll(results);
+
+    AssertPointsEqual('ECAlgorithms.SumOfMultiplies is incorrect', results[0],
+      results[1]);
+  end;
+end;
+
+procedure TTestECAlgorithms.DoTestSumOfTwoMultiplies(x9: IX9ECParameters);
+var
+  i: Int32;
+  p, q, u, v, w: IECPoint;
+  a, b: TBigInteger;
+  results: TCryptoLibGenericArray<IECPoint>;
+begin
+  p := GetRandomPoint(x9);
+  a := GetRandomScalar(x9);
+
+  i := 0;
+  while i < Scale do
+  begin
+    q := GetRandomPoint(x9);
+    b := GetRandomScalar(x9);
+
+    u := p.Multiply(a).Add(q.Multiply(b));
+    v := TECAlgorithms.ShamirsTrick(p, a, q, b);
+    w := TECAlgorithms.SumOfTwoMultiplies(p, a, q, b);
+
+    results := TCryptoLibGenericArray<IECPoint>.Create(u, v, w);
+    x9.curve.NormalizeAll(results);
+
+    AssertPointsEqual('TECAlgorithms.ShamirsTrick is incorrect', results[0],
+      results[1]);
+    AssertPointsEqual('TECAlgorithms.SumOfTwoMultiplies is incorrect',
+      results[0], results[2]);
+
+    p := q;
+    a := b;
+    System.Inc(i);
+  end;
+end;
+
+function TTestECAlgorithms.GetRandomPoint(x9: IX9ECParameters): IECPoint;
+begin
+  Result := x9.G.Multiply(GetRandomScalar(x9));
+end;
+
+function TTestECAlgorithms.GetRandomScalar(x9: IX9ECParameters): TBigInteger;
+begin
+  Result := TBigInteger.Create(x9.N.BitLength, FRandom);
+end;
+
+function TTestECAlgorithms.GetTestCurves
+  : TCryptoLibGenericArray<IX9ECParameters>;
+var
+  name: string;
+var
+  x9s: TList<IX9ECParameters>;
+  tempList: TList<String>;
+  tempDict: TDictionary<String, String>;
+  names: TCryptoLibStringArray;
+  x9: IX9ECParameters;
+  s: string;
+begin
+  x9s := TList<IX9ECParameters>.Create();
+  try
+
+    tempList := TList<String>.Create();
+    try
+      tempList.AddRange(TECNamedCurveTable.names); // get all collections
+      // tempList.AddRange(TCustomNamedCurves.Names);
+      tempDict := TDictionary<String, String>.Create();
+      try
+        for s in tempList do
+        begin
+          if not tempDict.ContainsKey(s) then // make sure they are unique
+          begin
+            tempDict.Add(s, s);
+          end;
+        end;
+        names := tempDict.Values.ToArray; // save unique instances to array
+      finally
+        tempDict.Free;
+      end;
+    finally
+      tempList.Free;
+    end;
+
+    for name in names do
+    begin
+      x9 := TECNamedCurveTable.GetByName(name);
+      if (x9 <> Nil) then
+      begin
+        AddTestCurves(x9s, x9);
+      end;
+
+      // x9 := TCustomNamedCurves.GetByName(name);
+      // if (x9 <> Nil) then
+      // begin
+      // AddTestCurves(x9s, x9);
+      // end;
+    end;
+    Result := x9s.ToArray;
+  finally
+    x9s.Free;
+  end;
+end;
+
+procedure TTestECAlgorithms.SetUp;
+begin
+  FRandom := TSecureRandom.Create();
+end;
+
+procedure TTestECAlgorithms.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestECAlgorithms.TestSumOfMultiplies;
+var
+  x9: IX9ECParameters;
+begin
+  // x9 := TCustomNamedCurves.GetByName('secp256r1'); // original
+  x9 := TECNamedCurveTable.GetByName('secp256k1');
+  CheckNotNull(x9);
+  DoTestSumOfMultiplies(x9);
+end;
+
+procedure TTestECAlgorithms.TestSumOfMultipliesComplete;
+var
+  x9: IX9ECParameters;
+begin
+  for x9 in GetTestCurves() do
+  begin
+    DoTestSumOfMultiplies(x9);
+  end;
+
+end;
+
+procedure TTestECAlgorithms.TestSumOfTwoMultiplies;
+var
+  x9: IX9ECParameters;
+begin
+  // x9 := TCustomNamedCurves.GetByName('secp256r1');  // original
+  x9 := TECNamedCurveTable.GetByName('secp256k1');
+  CheckNotNull(x9);
+  DoTestSumOfTwoMultiplies(x9);
+end;
+
+procedure TTestECAlgorithms.TestSumOfTwoMultipliesComplete;
+var
+  x9: IX9ECParameters;
+begin
+  for x9 in GetTestCurves() do
+  begin
+    DoTestSumOfTwoMultiplies(x9);
+  end;
+
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestECAlgorithms);
+{$ELSE}
+  RegisterTest(TTestECAlgorithms.Suite);
+{$ENDIF FPC}
+
+end.

+ 797 - 0
CryptoLib.Tests/src/Math/ECPointTests.pas

@@ -0,0 +1,797 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ECPointTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$WARNINGS OFF}
+{$ENDIF FPC}
+
+uses
+  Classes,
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  Generics.Collections,
+  ClpArrayUtils,
+  ClpECNamedCurveTable,
+  ClpCryptoLibTypes,
+  ClpSecureRandom,
+  ClpISecureRandom,
+  ClpBigInteger,
+  ClpBigIntegers,
+  ClpECCurve,
+  ClpECAlgorithms,
+  ClpIFiniteField,
+  ClpIX9ECParameters,
+  ClpIECFieldElement,
+  ClpIECInterface;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+  // /**
+  // * Nested class containing sample literature values for <code>Fp</code>.
+  // */
+  TFp = class
+
+  public
+  var
+
+    Fq, Fa, Fb, Fn, Fh: TBigInteger;
+    Fcurve: IECCurve;
+    FInfinity: IECPoint;
+    FpointSource: TCryptoLibInt32Array;
+    Fp: TCryptoLibGenericArray<IECPoint>;
+
+    constructor Create();
+    procedure CreatePoints();
+
+  end;
+
+type
+  // /**
+  // * Nested class containing sample literature values for <code>F2m</code>.
+  // */
+  TF2m = class
+
+  public const
+    // Irreducible polynomial for TPB z^4 + z + 1
+    m = Int32(4);
+
+    k1 = Int32(1);
+
+  var
+
+    FaTpb, FbTpb, Fn, Fh: TBigInteger;
+    Fcurve: IECCurve;
+    FInfinity: IECPoint;
+    FpointSource: TCryptoLibStringArray;
+    Fp: TCryptoLibGenericArray<IECPoint>;
+
+    constructor Create();
+    procedure CreatePoints();
+
+  end;
+
+type
+
+  TTestECPoint = class(TCryptoLibTestCase)
+  private
+
+  var
+    // /**
+    // * Random source used to generate random points
+    // */
+    FRandom: ISecureRandom;
+    FpInstance: TFp;
+    F2mInstance: TF2m;
+
+    procedure AssertPointsEqual(const msg: String; a, b: IECPoint);
+    // procedure AssertBigIntegersEqual(a, b: TBigInteger);
+    // procedure AssertIFiniteFieldsEqual(a, b: IFiniteField);
+    // procedure AssertOptionalValuesAgree(a, b: TBigInteger); overload;
+    // procedure AssertOptionalValuesAgree(a, b: TCryptoLibByteArray); overload;
+
+    procedure AssertECFieldElementsEqual(a, b: IECFieldElement);
+
+    // /**
+    // * Tests <code>ECPoint.add()</code> against literature values.
+    // *
+    // * @param p
+    // *            The array of literature values.
+    // * @param infinity
+    // *            The point at infinity on the respective curve.
+    // */
+    procedure ImplTestAdd(p: TCryptoLibGenericArray<IECPoint>;
+      infinity: IECPoint);
+
+    // /**
+    // * Tests <code>ECPoint.twice()</code> against literature values.
+    // *
+    // * @param p
+    // *            The array of literature values.
+    // */
+    procedure ImplTestTwice(p: TCryptoLibGenericArray<IECPoint>);
+
+    procedure ImplTestThreeTimes(p: TCryptoLibGenericArray<IECPoint>);
+
+    // /**
+    // * Goes through all points on an elliptic curve and checks, if adding a
+    // * point <code>k</code>-times is the same as multiplying the point by
+    // * <code>k</code>, for all <code>k</code>. Should be called for points
+    // * on very small elliptic curves only.
+    // *
+    // * @param p
+    // *            The base point on the elliptic curve.
+    // * @param infinity
+    // *            The point at infinity on the elliptic curve.
+    // */
+    procedure ImplTestAllPoints(p, infinity: IECPoint);
+    // /**
+    // * Checks, if the point multiplication algorithm of the given point yields
+    // * the same result as point multiplication done by the reference
+    // * implementation given in <code>multiply()</code>. This method chooses a
+    // * random number by which the given point <code>p</code> is multiplied.
+    // *
+    // * @param p
+    // *            The point to be multiplied.
+    // * @param numBits
+    // *            The bitlength of the random number by which <code>p</code>
+    // *            is multiplied.
+    // */
+    procedure ImplTestMultiply(p: IECPoint; numBits: Int32);
+    // /**
+    // * Checks, if the point multiplication algorithm of the given point yields
+    // * the same result as point multiplication done by the reference
+    // * implementation given in <code>multiply()</code>. This method tests
+    // * multiplication of <code>p</code> by every number of bitlength
+    // * <code>numBits</code> or less.
+    // *
+    // * @param p
+    // *            The point to be multiplied.
+    // * @param numBits
+    // *            Try every multiplier up to this bitlength
+    // */
+    procedure ImplTestMultiplyAll(p: IECPoint; numBits: Int32);
+    // /**
+    // * Tests <code>ECPoint.add()</code> and <code>ECPoint.subtract()</code>
+    // * for the given point and the given point at infinity.
+    // *
+    // * @param p
+    // *            The point on which the tests are performed.
+    // * @param infinity
+    // *            The point at infinity on the same curve as <code>p</code>.
+    // */
+    procedure ImplTestAddSubtract(p, infinity: IECPoint);
+    // /**
+    // * Test encoding with and without point compression.
+    // *
+    // * @param p
+    // *            The point to be encoded and decoded.
+    // */
+    procedure ImplTestEncoding(p: IECPoint);
+
+    procedure ImplAddSubtractMultiplyTwiceEncodingTest(curve: IECCurve;
+      q: IECPoint; n: TBigInteger);
+
+    procedure ImplSqrtTest(c: IECCurve);
+
+    procedure ImplAddSubtractMultiplyTwiceEncodingTestAllCoords
+      (x9ECParameters: IX9ECParameters);
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+
+    /// <summary>
+    /// Tests, if inconsistent points can be created, i.e. points with
+    /// exactly one null coordinate (not permitted).
+    /// </summary>
+    procedure TestPointCreationConsistency();
+    // /**
+    // * Calls <code>implTestAdd()</code> for <code>Fp</code> and
+    // * <code>F2m</code>.
+    // */
+    procedure TestAdd();
+
+    // /**
+    // * Calls <code>implTestTwice()</code> for <code>Fp</code> and
+    // * <code>F2m</code>.
+    // */
+    procedure TestTwice();
+    // /**
+    // * Calls <code>implTestThreeTimes()</code> for <code>Fp</code> and
+    // * <code>F2m</code>.
+    // */
+    procedure TestThreeTimes();
+
+    // /**
+    // * Calls <code>implTestAllPoints()</code> for the small literature curves,
+    // * both for <code>Fp</code> and <code>F2m</code>.
+    // */
+    procedure TestAllPoints();
+    // /**
+    // * Calls <code>implTestAddSubtract()</code> for literature values, both
+    // * for <code>Fp</code> and <code>F2m</code>.
+    // */
+    procedure TestAddSubtractMultiplySimple();
+
+    // /**
+    // * Calls <code>implTestAddSubtract()</code>,
+    // * <code>implTestMultiply</code> and <code>implTestEncoding</code> for
+    // * the standard elliptic curves as given in <code>SecNamedCurves</code>.
+    // */
+    procedure TestAddSubtractMultiplyTwiceEncoding();
+
+  end;
+
+implementation
+
+{ TTestECPoint }
+
+procedure TTestECPoint.AssertECFieldElementsEqual(a, b: IECFieldElement);
+begin
+  CheckEquals(True, a.Equals(b));
+end;
+
+// procedure TTestECPoint.AssertBigIntegersEqual(a, b: TBigInteger);
+// begin
+// CheckEquals(True, a.Equals(b));
+// end;
+
+// procedure TTestECPoint.AssertIFiniteFieldsEqual(a, b: IFiniteField);
+// begin
+// CheckEquals(True, (a as TObject).Equals(b as TObject));
+// end;
+//
+// procedure TTestECPoint.AssertOptionalValuesAgree(a, b: TBigInteger);
+// begin
+// if ((a.IsInitialized) and (b.IsInitialized)) then
+// begin
+// AssertBigIntegersEqual(a, b);
+// end;
+// end;
+//
+// procedure TTestECPoint.AssertOptionalValuesAgree(a, b: TCryptoLibByteArray);
+// begin
+// if ((a <> Nil) and (b <> Nil)) then
+// begin
+// CheckTrue(TArrayUtils.AreEqual(a, b));
+// end;
+// end;
+
+procedure TTestECPoint.AssertPointsEqual(const msg: String; a, b: IECPoint);
+begin
+  CheckEquals(True, a.Equals(b), msg);
+  CheckEquals(True, b.Equals(a), msg);
+end;
+
+procedure TTestECPoint.ImplAddSubtractMultiplyTwiceEncodingTest(curve: IECCurve;
+  q: IECPoint; n: TBigInteger);
+var
+  infinity, p: IECPoint;
+  i: Int32;
+begin
+  // Get point at infinity on the curve
+  infinity := curve.infinity;
+
+  ImplTestAddSubtract(q, infinity);
+  ImplTestMultiply(q, n.BitLength);
+  ImplTestMultiply(infinity, n.BitLength);
+  //
+  p := q;
+  i := 0;
+  while i < 10 do
+  begin
+    ImplTestEncoding(p);
+    p := p.Twice();
+    System.Inc(i);
+  end;
+end;
+
+procedure TTestECPoint.ImplAddSubtractMultiplyTwiceEncodingTestAllCoords
+  (x9ECParameters: IX9ECParameters);
+var
+  n, b: TBigInteger;
+  G, sg, q: IECPoint;
+  c, sc: IECCurve;
+  coords: TCryptoLibInt32Array;
+  i, coord: Int32;
+begin
+  n := x9ECParameters.n;
+  G := x9ECParameters.G;
+  c := x9ECParameters.curve;
+
+  coords := TECCurve.GetAllCoordinateSystems();
+  i := 0;
+  while i < System.Length(coords) do
+  begin
+    coord := coords[i];
+    if (c.SupportsCoordinateSystem(coord)) then
+    begin
+      sc := c;
+      sg := G;
+
+      if (sc.CoordinateSystem <> coord) then
+      begin
+        sc := c.Configure().SetCoordinateSystem(coord).CreateCurve();
+        sg := sc.ImportPoint(G);
+      end;
+
+      // The generator is multiplied by random b to get random q
+      b := TBigInteger.Create(n.BitLength, FRandom);
+
+      q := sg.Multiply(b).Normalize();
+
+      ImplAddSubtractMultiplyTwiceEncodingTest(sc, q, n);
+
+      ImplSqrtTest(sc);
+    end;
+    System.Inc(i);
+  end;
+end;
+
+procedure TTestECPoint.ImplSqrtTest(c: IECCurve);
+var
+  p, pMinusOne, legendreExponent, nonSquare, x: TBigInteger;
+  m, count, i: Int32;
+  root, fe, sq, check: IECFieldElement;
+begin
+  if (TECAlgorithms.IsFpCurve(c)) then
+  begin
+    p := c.Field.Characteristic;
+    pMinusOne := p.Subtract(TBigInteger.One);
+    legendreExponent := p.ShiftRight(1);
+
+    count := 0;
+    while (count < 10) do
+    begin
+      nonSquare := TBigIntegers.CreateRandomInRange(TBigInteger.Two,
+        pMinusOne, FRandom);
+      if (not nonSquare.ModPow(legendreExponent, p).Equals(TBigInteger.One))
+      then
+      begin
+        root := c.FromBigInteger(nonSquare).Sqrt();
+        CheckNull(root);
+        System.Inc(count);
+      end;
+    end
+  end
+  else if (TECAlgorithms.IsF2mCurve(c)) then
+  begin
+    m := c.FieldSize;
+    x := TBigInteger.Create(m, FRandom);
+    fe := c.FromBigInteger(x);
+    i := 0;
+    while i < 100 do
+    begin
+      sq := fe.Square();
+      check := sq.Sqrt();
+      AssertECFieldElementsEqual(fe, check);
+      fe := sq;
+      System.Inc(i);
+    end;
+  end;
+end;
+
+procedure TTestECPoint.ImplTestAdd(p: TCryptoLibGenericArray<IECPoint>;
+  infinity: IECPoint);
+var
+  i: Int32;
+begin
+  AssertPointsEqual('p0 plus p1 does not equal p2', p[2], p[0].Add(p[1]));
+  AssertPointsEqual('p1 plus p0 does not equal p2', p[2], p[1].Add(p[0]));
+  for i := 0 to System.Pred(System.Length(p)) do
+  begin
+    AssertPointsEqual('Adding infinity failed', p[i], p[i].Add(infinity));
+    AssertPointsEqual('Adding to infinity failed', p[i], infinity.Add(p[i]));
+  end;
+end;
+
+procedure TTestECPoint.ImplTestAddSubtract(p, infinity: IECPoint);
+begin
+  AssertPointsEqual('Twice and Add inconsistent', p.Twice(), p.Add(p));
+  AssertPointsEqual('Twice p - p is not p', p, p.Twice().Subtract(p));
+  AssertPointsEqual('TwicePlus(p, -p) is not p', p, p.TwicePlus(p.Negate()));
+  AssertPointsEqual('p - p is not infinity', infinity, p.Subtract(p));
+  AssertPointsEqual('p plus infinity is not p', p, p.Add(infinity));
+  AssertPointsEqual('infinity plus p is not p', p, infinity.Add(p));
+  AssertPointsEqual('infinity plus infinity is not infinity ', infinity,
+    infinity.Add(infinity));
+  AssertPointsEqual('Twice infinity is not infinity ', infinity,
+    infinity.Twice());
+end;
+
+procedure TTestECPoint.ImplTestAllPoints(p, infinity: IECPoint);
+var
+  adder, multiplier: IECPoint;
+  i: TBigInteger;
+begin
+  adder := infinity;
+  multiplier := infinity;
+
+  i := TBigInteger.One;
+
+  repeat
+    adder := adder.Add(p);
+    multiplier := p.Multiply(i);
+    AssertPointsEqual('Results of Add() and Multiply() are inconsistent ' +
+      i.ToString, adder, multiplier);
+    i := i.Add(TBigInteger.One);
+  until ((adder.Equals(infinity)));
+
+end;
+
+procedure TTestECPoint.ImplTestEncoding(p: IECPoint);
+var
+  unCompBarr, compBarr: TCryptoLibByteArray;
+  decUnComp, decComp: IECPoint;
+begin
+  // Not Point Compression
+  unCompBarr := p.GetEncoded(false);
+  decUnComp := p.curve.DecodePoint(unCompBarr);
+  AssertPointsEqual('Error decoding uncompressed point', p, decUnComp);
+
+  // Point compression
+  compBarr := p.GetEncoded(True);
+  decComp := p.curve.DecodePoint(compBarr);
+  AssertPointsEqual('Error decoding compressed point', p, decComp);
+end;
+
+procedure TTestECPoint.ImplTestMultiply(p: IECPoint; numBits: Int32);
+var
+  k: TBigInteger;
+  reff, q: IECPoint;
+begin
+  k := TBigInteger.Create(numBits, FRandom);
+  reff := TECAlgorithms.ReferenceMultiply(p, k);
+  q := p.Multiply(k);
+  AssertPointsEqual('ECPoint.Multiply is incorrect', reff, q);
+end;
+
+procedure TTestECPoint.ImplTestMultiplyAll(p: IECPoint; numBits: Int32);
+var
+  bound, k: TBigInteger;
+  reff, q: IECPoint;
+begin
+  bound := TBigInteger.One.ShiftLeft(numBits);
+  k := TBigInteger.Zero;
+
+  repeat
+    reff := TECAlgorithms.ReferenceMultiply(p, k);
+    q := p.Multiply(k);
+    AssertPointsEqual('ECPoint.Multiply is incorrect', reff, q);
+    k := k.Add(TBigInteger.One);
+  until (not(k.CompareTo(bound) < 0));
+
+end;
+
+procedure TTestECPoint.ImplTestThreeTimes(p: TCryptoLibGenericArray<IECPoint>);
+var
+  Lp, _3P: IECPoint;
+begin
+  Lp := p[0];
+  _3P := Lp.Add(Lp).Add(Lp);
+  AssertPointsEqual('ThreeTimes incorrect', _3P, Lp.ThreeTimes());
+  AssertPointsEqual('TwicePlus incorrect', _3P, Lp.TwicePlus(Lp));
+end;
+
+procedure TTestECPoint.ImplTestTwice(p: TCryptoLibGenericArray<IECPoint>);
+begin
+  AssertPointsEqual('Twice incorrect', p[3], p[0].Twice());
+  AssertPointsEqual('Add same point incorrect', p[3], p[0].Add(p[0]));
+end;
+
+procedure TTestECPoint.SetUp;
+begin
+  inherited;
+  FRandom := TSecureRandom.Create();
+  FpInstance := TFp.Create;
+  FpInstance.CreatePoints;
+  F2mInstance := TF2m.Create;
+  F2mInstance.CreatePoints;
+end;
+
+procedure TTestECPoint.TearDown;
+begin
+  inherited;
+  FpInstance.Free;
+  F2mInstance.Free;
+end;
+
+procedure TTestECPoint.TestAdd;
+begin
+  ImplTestAdd(FpInstance.Fp, FpInstance.FInfinity);
+  ImplTestAdd(F2mInstance.Fp, F2mInstance.FInfinity);
+end;
+
+procedure TTestECPoint.TestAddSubtractMultiplySimple;
+var
+  fpBits, iFp, f2mBits, iF2m: Int32;
+begin
+  fpBits := FpInstance.Fcurve.Order.BitLength;
+  for iFp := 0 to System.Pred(System.Length(FpInstance.FpointSource) div 2) do
+  begin
+    ImplTestAddSubtract(FpInstance.Fp[iFp], FpInstance.FInfinity);
+
+    ImplTestMultiplyAll(FpInstance.Fp[iFp], fpBits);
+    ImplTestMultiplyAll(FpInstance.FInfinity, fpBits);
+  end;
+
+  f2mBits := F2mInstance.Fcurve.Order.BitLength;
+  for iF2m := 0 to System.Pred(System.Length(F2mInstance.FpointSource) div 2) do
+  begin
+    ImplTestAddSubtract(F2mInstance.Fp[iF2m], F2mInstance.FInfinity);
+
+    ImplTestMultiplyAll(F2mInstance.Fp[iF2m], f2mBits);
+    ImplTestMultiplyAll(F2mInstance.FInfinity, f2mBits);
+  end;
+end;
+
+procedure TTestECPoint.TestAddSubtractMultiplyTwiceEncoding;
+var
+  tempList: TList<String>;
+  tempDict: TDictionary<String, String>;
+  uniqNames: TCryptoLibStringArray;
+  s, name: string;
+  x9A { , x9B } : IX9ECParameters;
+  // pA, pB: IECPoint;
+  // k: TBigInteger;
+begin
+
+  tempList := TList<String>.Create();
+  try
+    tempList.AddRange(TECNamedCurveTable.names); // get all collections
+    // tempList.AddRange(CustomNamedCurves.Names);
+    tempDict := TDictionary<String, String>.Create();
+    try
+      for s in tempList do
+      begin
+        if not tempDict.ContainsKey(s) then // make sure they are unique
+        begin
+          tempDict.Add(s, s);
+        end;
+      end;
+      uniqNames := tempDict.Values.ToArray; // save unique instances to array
+    finally
+      tempDict.Free;
+    end;
+  finally
+    tempList.Free;
+  end;
+
+  for name in uniqNames do
+  begin
+    x9A := TECNamedCurveTable.GetByName(name);
+    // x9B := TCustomNamedCurves.GetByName(name);
+
+    // if ((x9A <> Nil) and (x9B <> Nil)) then
+    // begin
+    // AssertIFiniteFieldsEqual(x9A.curve.Field, x9B.curve.Field);
+    // AssertBigIntegersEqual(x9A.curve.a.ToBigInteger(),
+    // x9B.curve.a.ToBigInteger());
+    // AssertBigIntegersEqual(x9A.curve.b.ToBigInteger(),
+    // x9B.curve.b.ToBigInteger());
+    // AssertOptionalValuesAgree(x9A.curve.Cofactor, x9B.curve.Cofactor);
+    // AssertOptionalValuesAgree(x9A.curve.Order, x9B.curve.Order);
+    //
+    // AssertPointsEqual('Custom curve base-point inconsistency', x9A.G, x9B.G);
+    //
+    // AssertBigIntegersEqual(x9A.H, x9B.H);
+    // AssertBigIntegersEqual(x9A.n, x9B.n);
+    // AssertOptionalValuesAgree(x9A.GetSeed(), x9B.GetSeed());
+    //
+    // k := TBigInteger.Create(x9A.n.BitLength, FRandom);
+    // pA := x9A.G.Multiply(k);
+    // pB := x9B.G.Multiply(k);
+    // AssertPointsEqual('Custom curve multiplication inconsistency', pA, pB);
+    // end;
+
+    if (x9A <> Nil) then
+    begin
+      ImplAddSubtractMultiplyTwiceEncodingTestAllCoords(x9A);
+    end;
+
+    // if (x9B <> Nil) then
+    // begin
+    // ImplAddSubtractMultiplyTwiceEncodingTestAllCoords(x9B);
+    // end;
+  end;
+end;
+
+procedure TTestECPoint.TestAllPoints;
+var
+  i: Int32;
+begin
+  i := 0;
+  while i < System.Length(FpInstance.Fp) do
+  begin
+    ImplTestAllPoints(FpInstance.Fp[0], FpInstance.FInfinity);
+    System.Inc(i);
+  end;
+
+  i := 0;
+  while i < System.Length(F2mInstance.Fp) do
+  begin
+    ImplTestAllPoints(F2mInstance.Fp[0], F2mInstance.FInfinity);
+    System.Inc(i);
+  end;
+end;
+
+procedure TTestECPoint.TestPointCreationConsistency;
+var
+  bad: IECPoint;
+begin
+  try
+    bad := FpInstance.Fcurve.CreatePoint(TBigInteger.ValueOf(12),
+      Default (TBigInteger));
+    Fail('expected EArgumentCryptoLibException');
+  except
+    on e: EArgumentCryptoLibException do
+    begin
+      // expected
+    end;
+
+  end;
+
+  try
+    bad := FpInstance.Fcurve.CreatePoint(Default (TBigInteger),
+      TBigInteger.ValueOf(12));
+    Fail('expected EArgumentCryptoLibException');
+  except
+    on e: EArgumentCryptoLibException do
+    begin
+      // expected
+    end;
+
+  end;
+
+  try
+    bad := FpInstance.Fcurve.CreatePoint(TBigInteger.Create('1011'),
+      Default (TBigInteger));
+    Fail('expected EArgumentCryptoLibException');
+  except
+    on e: EArgumentCryptoLibException do
+    begin
+      // expected
+    end;
+
+  end;
+
+  try
+    bad := FpInstance.Fcurve.CreatePoint(Default (TBigInteger),
+      TBigInteger.Create('1011'));
+    Fail('expected EArgumentCryptoLibException');
+  except
+    on e: EArgumentCryptoLibException do
+    begin
+      // expected
+    end;
+
+  end;
+
+end;
+
+procedure TTestECPoint.TestThreeTimes;
+begin
+  ImplTestThreeTimes(FpInstance.Fp);
+  ImplTestThreeTimes(F2mInstance.Fp);
+end;
+
+procedure TTestECPoint.TestTwice;
+begin
+  ImplTestTwice(FpInstance.Fp);
+  ImplTestTwice(F2mInstance.Fp);
+end;
+
+{ TFp }
+
+constructor TFp.Create;
+begin
+  Fq := TBigInteger.Create('29');
+
+  Fa := TBigInteger.Create('4');
+
+  Fb := TBigInteger.Create('20');
+
+  Fn := TBigInteger.Create('38');
+
+  Fh := TBigInteger.Create('1');
+
+  Fcurve := TFpCurve.Create(Fq, Fa, Fb, Fn, Fh);
+
+  FInfinity := Fcurve.infinity;
+
+  FpointSource := TCryptoLibInt32Array.Create(5, 22, 16, 27, 13, 6, 14, 6);
+
+  System.SetLength(Fp, System.Length(FpointSource) div 2);
+
+end;
+
+procedure TFp.CreatePoints;
+var
+  i: Int32;
+begin
+  for i := 0 to System.Pred(System.Length(FpointSource) div 2) do
+
+  begin
+    Fp[i] := Fcurve.CreatePoint
+      (TBigInteger.Create(FpointSource[2 * i].ToString()),
+      TBigInteger.Create(FpointSource[2 * i + 1].ToString()));
+  end;
+end;
+
+{ TF2m }
+
+constructor TF2m.Create;
+begin
+  // a = z^3
+  FaTpb := TBigInteger.Create('1000', 2);
+
+  // b = z^3 + 1
+  FbTpb := TBigInteger.Create('1001', 2);
+
+  Fn := TBigInteger.Create('23');
+
+  Fh := TBigInteger.Create('1');
+
+  Fcurve := TF2mCurve.Create(m, k1, FaTpb, FbTpb, Fn, Fh);
+
+  FInfinity := Fcurve.infinity;
+
+  FpointSource := TCryptoLibStringArray.Create('0010', '1111', '1100', '1100',
+    '0001', '0001', '1011', '0010');
+
+  System.SetLength(Fp, System.Length(FpointSource) div 2);
+end;
+
+procedure TF2m.CreatePoints;
+var
+  i: Int32;
+begin
+  for i := 0 to System.Pred(System.Length(FpointSource) div 2) do
+
+  begin
+    Fp[i] := Fcurve.CreatePoint(TBigInteger.Create(FpointSource[2 * i], 2),
+      TBigInteger.Create(FpointSource[(2 * i) + 1], 2));
+  end;
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestECPoint);
+{$ELSE}
+  RegisterTest(TTestECPoint.Suite);
+{$ENDIF FPC}
+
+end.

+ 399 - 0
CryptoLib.Tests/src/Others/ECDsa5Tests.pas

@@ -0,0 +1,399 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ECDsa5Tests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+uses
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpBigInteger,
+  ClpHex,
+  ClpFixedSecureRandom,
+  ClpISecureRandom,
+  ClpSecureRandom,
+  ClpCryptoLibTypes,
+  ClpECCurve,
+  ClpIECDomainParameters,
+  ClpIECPrivateKeyParameters,
+  ClpIECPublicKeyParameters,
+  ClpECPrivateKeyParameters,
+  ClpECPublicKeyParameters,
+  ClpECKeyPairGenerator,
+  ClpECKeyGenerationParameters,
+  ClpIAsymmetricCipherKeyPairGenerator,
+  ClpIAsymmetricCipherKeyPair,
+  ClpIAsymmetricKeyParameter,
+  ClpParametersWithRandom,
+  ClpIECInterface,
+  ClpSignerUtilities,
+  ClpECDomainParameters,
+  ClpAsn1Object,
+  ClpISigner,
+  ClpIAsn1Sequence,
+  ClpIDerInteger;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  TTestECDsa5 = class(TCryptoLibTestCase)
+
+  private
+    function derDecode(encoding: TCryptoLibByteArray)
+      : TCryptoLibGenericArray<TBigInteger>;
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+    procedure TestDecode();
+
+    /// <summary>
+    /// X9.62 - 1998, <br />J.3.2, Page 155, ECDSA over the field Fp <br />an
+    /// example with 239 bit prime
+    /// </summary>
+    procedure TestECDsa239BitPrime();
+
+    /// <summary>
+    /// X9.62 - 1998, <br />J.2.1, Page 100, ECDSA over the field F2m <br />
+    /// an example with 191 bit binary field
+    /// </summary>
+    procedure TestECDsa239BitBinary();
+
+    procedure TestGeneration();
+
+  end;
+
+implementation
+
+{ TTestECDsa5 }
+
+function TTestECDsa5.derDecode(encoding: TCryptoLibByteArray)
+  : TCryptoLibGenericArray<TBigInteger>;
+var
+  s: IAsn1Sequence;
+begin
+  s := TAsn1Object.FromByteArray(encoding) as IAsn1Sequence;
+
+  result := TCryptoLibGenericArray<TBigInteger>.Create
+    ((s[0] as IDerInteger).Value, (s[1] as IDerInteger).Value);
+end;
+
+procedure TTestECDsa5.SetUp;
+begin
+  inherited;
+
+end;
+
+procedure TTestECDsa5.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestECDsa5.TestDecode;
+var
+  curve: IECCurve;
+  p: IECPoint;
+  x, y: TBigInteger;
+
+begin
+  curve := TFpCurve.Create
+    (TBigInteger.Create
+    ('6277101735386680763835789423207666416083908700390324961279'), // q
+    TBigInteger.Create('fffffffffffffffffffffffffffffffefffffffffffffffc', 16),
+    // a
+    TBigInteger.Create('64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1', 16));
+  // b
+
+  p := curve.DecodePoint
+    (THex.Decode('03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012'));
+
+  x := p.XCoord.ToBigInteger(); // p.getAffineX();
+
+  if (not x.Equals(TBigInteger.Create
+    ('188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012', 16))) then
+  begin
+    Fail('x uncompressed incorrectly');
+  end;
+
+  y := p.YCoord.ToBigInteger(); // p.getAffineX();
+  if (not y.Equals(TBigInteger.Create
+    ('7192b95ffc8da78631011ed6b24cdd573f977a11e794811', 16))) then
+  begin
+    Fail('y uncompressed incorrectly');
+  end;
+end;
+
+procedure TTestECDsa5.TestECDsa239BitBinary;
+var
+  r, s: TBigInteger;
+  kData, &message, sigBytes: TCryptoLibByteArray;
+  k: ISecureRandom;
+  curve: IECCurve;
+  parameters: IECDomainParameters;
+  sKey: IECPrivateKeyParameters;
+  vKey: IECPublicKeyParameters;
+  sgr: ISigner;
+  sig: TCryptoLibGenericArray<TBigInteger>;
+begin
+  r := TBigInteger.Create
+    ('21596333210419611985018340039034612628818151486841789642455876922391552');
+  s := TBigInteger.Create
+    ('197030374000731686738334997654997227052849804072198819102649413465737174');
+
+  kData := TBigInteger.Create
+    ('171278725565216523967285789236956265265265235675811949404040041670216363')
+    .ToByteArrayUnsigned();
+
+  k := TFixedSecureRandom.From(TCryptoLibMatrixByteArray.Create(kData));
+
+  curve := TF2mCurve.Create(239, // m
+    36, // k
+    TBigInteger.Create
+    ('32010857077C5431123A46B808906756F543423E8D27877578125778AC76', 16), // a
+    TBigInteger.Create
+    ('790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16', 16)); // b
+
+  parameters := TECDomainParameters.Create(curve,
+    curve.DecodePoint(THex.Decode
+    ('0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305')
+    ), // G
+    TBigInteger.Create
+    ('220855883097298041197912187592864814557886993776713230936715041207411783'),
+    // n
+    TBigInteger.ValueOf(4)); // 4); // h
+
+  sKey := TECPrivateKeyParameters.Create('ECDSA',
+    TBigInteger.Create
+    ('145642755521911534651321230007534120304391871461646461466464667494947990'),
+    // d
+    parameters);
+
+  vKey := TECPublicKeyParameters.Create('ECDSA',
+    curve.DecodePoint(THex.Decode
+    ('045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5')
+    ), // Q
+    parameters);
+
+  sgr := TSignerUtilities.GetSigner('ECDSA');
+
+  sgr.Init(true, TParametersWithRandom.Create(sKey, k));
+
+  &message := TEncoding.UTF8.GetBytes('abc');
+
+  sgr.BlockUpdate(&message, 0, System.Length(&message));
+
+  sigBytes := sgr.GenerateSignature();
+
+  sgr.Init(false, vKey);
+
+  sgr.BlockUpdate(&message, 0, System.Length(&message));
+
+  if (not sgr.VerifySignature(sigBytes)) then
+  begin
+    Fail('239 Bit EC verification failed');
+  end;
+
+  sig := derDecode(sigBytes);
+
+  if (not r.Equals(sig[0])) then
+  begin
+    Fail('r component wrong.' + sLineBreak + ' expecting: ' + r.ToString +
+      sLineBreak + ' got      : ' + sig[0].ToString);
+  end;
+
+  if (not s.Equals(sig[1])) then
+  begin
+    Fail('s component wrong.' + sLineBreak + ' expecting: ' + s.ToString +
+      sLineBreak + ' got      : ' + sig[1].ToString);
+  end;
+end;
+
+procedure TTestECDsa5.TestECDsa239BitPrime;
+var
+  r, s: TBigInteger;
+  kData, &message, sigBytes: TCryptoLibByteArray;
+  k: ISecureRandom;
+  curve: IECCurve;
+  spec: IECDomainParameters;
+  sKey: IECPrivateKeyParameters;
+  vKey: IECPublicKeyParameters;
+  sgr: ISigner;
+  sig: TCryptoLibGenericArray<TBigInteger>;
+begin
+  r := TBigInteger.Create
+    ('308636143175167811492622547300668018854959378758531778147462058306432176');
+  s := TBigInteger.Create
+    ('323813553209797357708078776831250505931891051755007842781978505179448783');
+
+  kData := TBigInteger.Create
+    ('700000017569056646655505781757157107570501575775705779575555657156756655')
+    .ToByteArrayUnsigned();
+
+  k := TFixedSecureRandom.From(TCryptoLibMatrixByteArray.Create(kData));
+
+  curve := TFpCurve.Create
+    (TBigInteger.Create
+    ('883423532389192164791648750360308885314476597252960362792450860609699839'),
+    // q
+    TBigInteger.Create
+    ('7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc', 16), // a
+    TBigInteger.Create
+    ('6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a', 16)); // b
+
+  spec := TECDomainParameters.Create(curve,
+
+    curve.DecodePoint(THex.Decode
+    ('020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf')), // G
+    TBigInteger.Create
+    ('883423532389192164791648750360308884807550341691627752275345424702807307'),
+    // n
+    TBigInteger.One); // h
+
+  sKey := TECPrivateKeyParameters.Create('ECDSA',
+    TBigInteger.Create
+    ('876300101507107567501066130761671078357010671067781776716671676178726717'),
+    // d
+    spec);
+
+  vKey := TECPublicKeyParameters.Create('ECDSA',
+
+    curve.DecodePoint(THex.Decode
+    ('025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70')), // Q
+    spec);
+
+  sgr := TSignerUtilities.GetSigner('ECDSA');
+
+  sgr.Init(true, TParametersWithRandom.Create(sKey, k));
+
+  &message := TEncoding.UTF8.GetBytes('abc');
+
+  sgr.BlockUpdate(&message, 0, System.Length(&message));
+
+  sigBytes := sgr.GenerateSignature();
+
+  sgr.Init(false, vKey);
+
+  sgr.BlockUpdate(&message, 0, System.Length(&message));
+
+  if (not sgr.VerifySignature(sigBytes)) then
+  begin
+    Fail('239 Bit EC verification failed');
+  end;
+
+  sig := derDecode(sigBytes);
+
+  if (not r.Equals(sig[0])) then
+  begin
+    Fail('r component wrong.' + sLineBreak + ' expecting: ' + r.ToString +
+      sLineBreak + ' got      : ' + sig[0].ToString);
+  end;
+
+  if (not s.Equals(sig[1])) then
+  begin
+    Fail('s component wrong.' + sLineBreak + ' expecting: ' + s.ToString +
+      sLineBreak + ' got      : ' + sig[1].ToString);
+  end;
+end;
+
+procedure TTestECDsa5.TestGeneration;
+var
+  data, sigBytes: TCryptoLibByteArray;
+  s: ISigner;
+  g: IAsymmetricCipherKeyPairGenerator;
+  curve: IECCurve;
+  ecSpec: IECDomainParameters;
+  p: IAsymmetricCipherKeyPair;
+  sKey, vKey: IAsymmetricKeyParameter;
+
+begin
+  //
+  // ECDSA generation test
+  //
+  data := TCryptoLibByteArray.Create(1, 2, 3, 4, 5, 6, 7, 8, 9, 0);
+  s := TSignerUtilities.GetSigner('ECDSA');
+  g := TECKeyPairGenerator.Create('ECDSA');
+
+  curve := TFpCurve.Create
+    (TBigInteger.Create
+    ('883423532389192164791648750360308885314476597252960362792450860609699839'),
+    // q
+    TBigInteger.Create
+    ('7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc', 16), // a
+    TBigInteger.Create
+    ('6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a', 16)); // b
+
+  ecSpec := TECDomainParameters.Create(curve,
+    curve.DecodePoint(THex.Decode
+    ('020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf')), // G
+    TBigInteger.Create
+    ('883423532389192164791648750360308884807550341691627752275345424702807307'),
+    // n
+    TBigInteger.One); // 1); // h
+
+  g.Init(TECKeyGenerationParameters.Create(ecSpec, TSecureRandom.Create()));
+
+  p := g.GenerateKeyPair();
+
+  sKey := p.Private;
+  vKey := p.Public;
+
+  s.Init(true, sKey);
+
+  s.BlockUpdate(data, 0, System.Length(data));
+
+  sigBytes := s.GenerateSignature();
+
+  s := TSignerUtilities.GetSigner('ECDSA');
+
+  s.Init(false, vKey);
+
+  s.BlockUpdate(data, 0, System.Length(data));
+
+  if (not s.VerifySignature(sigBytes)) then
+  begin
+    Fail('ECDSA verification failed');
+  end;
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestECDsa5);
+{$ELSE}
+  RegisterTest(TTestECDsa5.Suite);
+{$ENDIF FPC}
+
+end.

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

@@ -0,0 +1,655 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ECTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$ENDIF FPC}
+
+uses
+  Classes,
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpFixedSecureRandom,
+  ClpSecureRandom,
+  ClpISecureRandom,
+  ClpECDsaSigner,
+  ClpIECDsaSigner,
+  ClpParametersWithRandom,
+  ClpIParametersWithRandom,
+  ClpECPublicKeyParameters,
+  ClpIECPublicKeyParameters,
+  ClpECPrivateKeyParameters,
+  ClpIECPrivateKeyParameters,
+  ClpECDomainParameters,
+  ClpIECDomainParameters,
+  ClpIECKeyPairGenerator,
+  ClpECKeyPairGenerator,
+  ClpIECKeyGenerationParameters,
+  ClpECKeyGenerationParameters,
+  ClpIAsymmetricCipherKeyPair,
+  ClpECCurve,
+  ClpIECInterface,
+  ClpHex,
+  ClpCryptoLibTypes,
+  ClpBigInteger,
+  ClpBigIntegers,
+  ClpArrayUtils;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  /// <summary>
+  /// ECDSA tests are taken from X9.62.
+  /// </summary>
+  TTestEC = class(TCryptoLibTestCase)
+  private
+
+  var
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+
+    /// <summary>
+    /// X9.62 - 1998, <br />J.3.1, Page 152, ECDSA over the field Fp <br />an
+    /// example with 192 bit prime
+    /// </summary>
+    procedure TestECDsa192bitPrime;
+    procedure TestDecode();
+
+    /// <summary>
+    /// X9.62 - 1998, J.3.2, Page 155, ECDSA over the field Fp <br />an
+    /// example with 239 bit prime
+    /// </summary>
+    procedure TestECDsa239bitPrime();
+
+    /// <summary>
+    /// X9.62 - 1998, <br />J.2.1, Page 100, ECDSA over the field F2m <br />
+    /// an example with 191 bit binary field
+    /// </summary>
+    procedure TestECDsa191bitBinary();
+
+    /// <summary>
+    /// X9.62 - 1998, <br />J.2.1, Page 100, ECDSA over the field F2m <br />
+    /// an example with 191 bit binary field
+    /// </summary>
+    procedure TestECDsa239bitBinary();
+
+    /// <summary>
+    /// General test for long digest.
+    /// </summary>
+    procedure TestECDsa239bitBinaryAndLargeDigest();
+
+    /// <summary>
+    /// key generation test
+    /// </summary>
+    procedure TestECDsaKeyGenTest();
+
+  end;
+
+implementation
+
+{ TTestEC }
+
+procedure TTestEC.SetUp;
+begin
+  inherited;
+
+end;
+
+procedure TTestEC.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestEC.TestDecode;
+var
+  curve: IFpCurve;
+  p: IECPoint;
+  encoding: TCryptoLibByteArray;
+begin
+  curve := TFpCurve.Create
+    (TBigInteger.Create
+    ('6277101735386680763835789423207666416083908700390324961279'), // q
+    TBigInteger.Create('fffffffffffffffffffffffffffffffefffffffffffffffc', 16),
+    // a
+    TBigInteger.Create('64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1', 16));
+  // b
+
+  p := curve.DecodePoint
+    (THex.Decode('03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012'))
+    .Normalize();
+
+  if (not p.AffineXCoord.ToBigInteger()
+    .Equals(TBigInteger.Create
+    ('188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012', 16))) then
+  begin
+    Fail('x uncompressed incorrectly');
+  end;
+
+  if (not p.AffineYCoord.ToBigInteger()
+    .Equals(TBigInteger.Create
+    ('7192b95ffc8da78631011ed6b24cdd573f977a11e794811', 16))) then
+  begin
+    Fail('y uncompressed incorrectly');
+  end;
+
+  encoding := p.GetEncoded();
+
+  if (not TArrayUtils.AreEqual(encoding,
+    THex.Decode('03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012'))) then
+  begin
+    Fail('point compressed incorrectly');
+  end;
+end;
+
+procedure TTestEC.TestECDsa191bitBinary;
+var
+  r, s: TBigInteger;
+  kData, &message: TCryptoLibByteArray;
+  k: ISecureRandom;
+  curve: IF2mCurve;
+  parameters: IECDomainParameters;
+  priKey: IECPrivateKeyParameters;
+  pubKey: IECPublicKeyParameters;
+  ecdsa: IECDsaSigner;
+  param: IParametersWithRandom;
+  sig: TCryptoLibGenericArray<TBigInteger>;
+begin
+  r := TBigInteger.Create
+    ('87194383164871543355722284926904419997237591535066528048');
+  s := TBigInteger.Create
+    ('308992691965804947361541664549085895292153777025772063598');
+
+  kData := TBigIntegers.AsUnsignedByteArray
+    (TBigInteger.Create
+    ('1542725565216523985789236956265265265235675811949404040041'));
+
+  k := TFixedSecureRandom.From(TCryptoLibMatrixByteArray.Create(kData));
+
+  curve := TF2mCurve.Create(191, // m
+    9, // k
+    TBigInteger.Create('2866537B676752636A68F56554E12640276B649EF7526267', 16),
+    // a
+    TBigInteger.Create('2E45EF571F00786F67B0081B9495A3D95462F5DE0AA185EC', 16));
+  // b
+
+  parameters := TECDomainParameters.Create(curve,
+    curve.DecodePoint(THex.Decode
+    ('0436B3DAF8A23206F9C4F299D7B21A9C369137F2C84AE1AA0D765BE73433B3F95E332932E70EA245CA2418EA0EF98018FB')
+    ), // G
+    TBigInteger.Create
+    ('1569275433846670190958947355803350458831205595451630533029'), // n
+    TBigInteger.Two); // h
+
+  priKey := TECPrivateKeyParameters.Create('ECDSA',
+    TBigInteger.Create
+    ('1275552191113212300012030439187146164646146646466749494799'), // d
+    parameters);
+
+  ecdsa := TECDsaSigner.Create();
+  param := TParametersWithRandom.Create(priKey, k);
+
+  ecdsa.Init(true, param);
+
+  &message := TBigInteger.Create
+    ('968236873715988614170569073515315707566766479517').ToByteArray();
+  sig := ecdsa.GenerateSignature(&message);
+
+  if (not r.Equals(sig[0])) then
+  begin
+    Fail('r component wrong.' + sLineBreak + ' expecting: ' + r.ToString +
+      sLineBreak + ' got      : ' + sig[0].ToString);
+  end;
+
+  if (not s.Equals(sig[1])) then
+  begin
+    Fail('s component wrong.' + sLineBreak + ' expecting: ' + s.ToString +
+      sLineBreak + ' got      : ' + sig[1].ToString);
+  end;
+
+  // Verify the signature
+  pubKey := TECPublicKeyParameters.Create('ECDSA',
+    curve.DecodePoint(THex.Decode
+    ('045DE37E756BD55D72E3768CB396FFEB962614DEA4CE28A2E755C0E0E02F5FB132CAF416EF85B229BBB8E1352003125BA1')
+    ), // Q
+    parameters);
+
+  ecdsa.Init(false, pubKey);
+  if (not ecdsa.VerifySignature(&message, sig[0], sig[1])) then
+  begin
+    Fail('signature fails');
+  end;
+end;
+
+procedure TTestEC.TestECDsa192bitPrime;
+var
+  r, s, n: TBigInteger;
+  kData, &message: TCryptoLibByteArray;
+  k: ISecureRandom;
+  curve: IFpCurve;
+  parameters: IECDomainParameters;
+  priKey: IECPrivateKeyParameters;
+  pubKey: IECPublicKeyParameters;
+  param: IParametersWithRandom;
+  ecdsa: IECDsaSigner;
+  sig: TCryptoLibGenericArray<TBigInteger>;
+
+begin
+  r := TBigInteger.Create
+    ('3342403536405981729393488334694600415596881826869351677613');
+  s := TBigInteger.Create
+    ('5735822328888155254683894997897571951568553642892029982342');
+
+  kData := TBigIntegers.AsUnsignedByteArray
+    (TBigInteger.Create
+    ('6140507067065001063065065565667405560006161556565665656654'));
+
+  k := TFixedSecureRandom.From(TCryptoLibMatrixByteArray.Create(kData));
+
+  n := TBigInteger.Create
+    ('6277101735386680763835789423176059013767194773182842284081');
+
+  curve := TFpCurve.Create
+    (TBigInteger.Create
+    ('6277101735386680763835789423207666416083908700390324961279'), // q
+    TBigInteger.Create('fffffffffffffffffffffffffffffffefffffffffffffffc', 16),
+    // a
+    TBigInteger.Create('64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1', 16),
+    // b
+    n, TBigInteger.One);
+
+  parameters := TECDomainParameters.Create(curve,
+    curve.DecodePoint(THex.Decode
+    ('03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012')), // G
+    n);
+
+  priKey := TECPrivateKeyParameters.Create('ECDSA',
+    TBigInteger.Create
+    ('651056770906015076056810763456358567190100156695615665659'), // d
+    parameters);
+
+  param := TParametersWithRandom.Create(priKey, k);
+
+  ecdsa := TECDsaSigner.Create();
+
+  ecdsa.Init(true, param);
+
+  &message := TBigInteger.Create
+    ('968236873715988614170569073515315707566766479517').ToByteArray();
+  sig := ecdsa.GenerateSignature(&message);
+
+  if (not r.Equals(sig[0])) then
+  begin
+    Fail('r component wrong.' + sLineBreak + ' expecting: ' + r.ToString +
+      sLineBreak + ' got      : ' + sig[0].ToString);
+  end;
+
+  if (not s.Equals(sig[1])) then
+  begin
+    Fail('s component wrong.' + sLineBreak + ' expecting: ' + s.ToString +
+      sLineBreak + ' got      : ' + sig[1].ToString);
+  end;
+
+  // Verify the signature
+  pubKey := TECPublicKeyParameters.Create('ECDSA',
+    curve.DecodePoint(THex.Decode
+    ('0262b12d60690cdcf330babab6e69763b471f994dd702d16a5')), // Q
+    parameters);
+
+  ecdsa.Init(false, pubKey);
+  if (not ecdsa.VerifySignature(&message, sig[0], sig[1])) then
+  begin
+    Fail('verification fails');
+  end;
+end;
+
+procedure TTestEC.TestECDsa239bitBinary;
+var
+  sig: TCryptoLibGenericArray<TBigInteger>;
+  k: ISecureRandom;
+  r, s: TBigInteger;
+  kData: TCryptoLibByteArray;
+  curve: IF2mCurve;
+  parameters: IECDomainParameters;
+  priKey: IECPrivateKeyParameters;
+  pubKey: IECPublicKeyParameters;
+  ecdsa: IECDsaSigner;
+  param: IParametersWithRandom;
+  &message: TCryptoLibByteArray;
+begin
+  r := TBigInteger.Create
+    ('21596333210419611985018340039034612628818151486841789642455876922391552');
+  s := TBigInteger.Create
+    ('197030374000731686738334997654997227052849804072198819102649413465737174');
+
+  kData := TBigIntegers.AsUnsignedByteArray
+    (TBigInteger.Create
+    ('171278725565216523967285789236956265265265235675811949404040041670216363')
+    );
+
+  k := TFixedSecureRandom.From(TCryptoLibMatrixByteArray.Create(kData));
+
+  curve := TF2mCurve.Create(239, // m
+    36, // k
+    TBigInteger.Create
+    ('32010857077C5431123A46B808906756F543423E8D27877578125778AC76', 16), // a
+    TBigInteger.Create
+    ('790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16', 16)); // b
+
+  parameters := TECDomainParameters.Create(curve,
+    curve.DecodePoint(THex.Decode
+    ('0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305')
+    ), // G
+    TBigInteger.Create
+    ('220855883097298041197912187592864814557886993776713230936715041207411783'),
+    // n
+    TBigInteger.ValueOf(4)); // h
+
+  priKey := TECPrivateKeyParameters.Create('ECDSA',
+    TBigInteger.Create
+    ('145642755521911534651321230007534120304391871461646461466464667494947990'),
+    // d
+    parameters);
+
+  ecdsa := TECDsaSigner.Create();
+  param := TParametersWithRandom.Create(priKey, k);
+
+  ecdsa.Init(true, param);
+
+  &message := TBigInteger.Create
+    ('968236873715988614170569073515315707566766479517').ToByteArray();
+  sig := ecdsa.GenerateSignature(&message);
+
+  if (not r.Equals(sig[0])) then
+  begin
+    Fail('r component wrong.' + sLineBreak + ' expecting: ' + r.ToString +
+      sLineBreak + ' got      : ' + sig[0].ToString);
+  end;
+
+  if (not s.Equals(sig[1])) then
+  begin
+    Fail('s component wrong.' + sLineBreak + ' expecting: ' + s.ToString +
+      sLineBreak + ' got      : ' + sig[1].ToString);
+  end;
+
+  // Verify the signature
+  pubKey := TECPublicKeyParameters.Create('ECDSA',
+    curve.DecodePoint(THex.Decode
+    ('045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5')
+    ), // Q
+    parameters);
+
+  ecdsa.Init(false, pubKey);
+  if (not ecdsa.VerifySignature(&message, sig[0], sig[1])) then
+  begin
+    Fail('signature fails');
+  end;
+end;
+
+procedure TTestEC.TestECDsa239bitBinaryAndLargeDigest;
+var
+  r, s: TBigInteger;
+  kData, &message: TCryptoLibByteArray;
+  k: ISecureRandom;
+  curve: IF2mCurve;
+  parameters: IECDomainParameters;
+  priKey: IECPrivateKeyParameters;
+  ecdsa: IECDsaSigner;
+  param: IParametersWithRandom;
+  sig: TCryptoLibGenericArray<TBigInteger>;
+  pubKey: IECPublicKeyParameters;
+begin
+  r := TBigInteger.Create
+    ('21596333210419611985018340039034612628818151486841789642455876922391552');
+  s := TBigInteger.Create
+    ('144940322424411242416373536877786566515839911620497068645600824084578597');
+
+  kData := TBigIntegers.AsUnsignedByteArray
+    (TBigInteger.Create
+    ('171278725565216523967285789236956265265265235675811949404040041670216363')
+    );
+
+  k := TFixedSecureRandom.From(TCryptoLibMatrixByteArray.Create(kData));
+
+  curve := TF2mCurve.Create(239, // m
+    36, // k
+    TBigInteger.Create
+    ('32010857077C5431123A46B808906756F543423E8D27877578125778AC76', 16), // a
+    TBigInteger.Create
+    ('790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16', 16)); // b
+
+  parameters := TECDomainParameters.Create(curve,
+    curve.DecodePoint(THex.Decode
+    ('0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305')
+    ), // G
+    TBigInteger.Create
+    ('220855883097298041197912187592864814557886993776713230936715041207411783'),
+    // n
+    TBigInteger.ValueOf(4)); // h
+
+  priKey := TECPrivateKeyParameters.Create('ECDSA',
+    TBigInteger.Create
+    ('145642755521911534651321230007534120304391871461646461466464667494947990'),
+    // d
+    parameters);
+
+  ecdsa := TECDsaSigner.Create();
+  param := TParametersWithRandom.Create(priKey, k);
+
+  ecdsa.Init(true, param);
+
+  &message := TBigInteger.Create
+    ('968236873715988614170569073515315707566766479517968236873715988614170569073515315707566766479517968236873715988614170569073515315707566766479517')
+    .ToByteArray();
+  sig := ecdsa.GenerateSignature(&message);
+
+  if (not r.Equals(sig[0])) then
+  begin
+    Fail('r component wrong.' + sLineBreak + ' expecting: ' + r.ToString +
+      sLineBreak + ' got      : ' + sig[0].ToString);
+  end;
+
+  if (not s.Equals(sig[1])) then
+  begin
+    Fail('s component wrong.' + sLineBreak + ' expecting: ' + s.ToString +
+      sLineBreak + ' got      : ' + sig[1].ToString);
+  end;
+
+  // Verify the signature
+  pubKey := TECPublicKeyParameters.Create('ECDSA',
+    curve.DecodePoint(THex.Decode
+    ('045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5')
+    ), // Q
+    parameters);
+
+  ecdsa.Init(false, pubKey);
+  if (not ecdsa.VerifySignature(&message, sig[0], sig[1])) then
+  begin
+    Fail('signature fails');
+  end;
+end;
+
+procedure TTestEC.TestECDsa239bitPrime;
+var
+  &message, kData: TCryptoLibByteArray;
+  r, s, n: TBigInteger;
+  k: ISecureRandom;
+  curve: IFpCurve;
+  parameters: IECDomainParameters;
+  priKey: IECPrivateKeyParameters;
+  pubKey: IECPublicKeyParameters;
+  ecdsa: IECDsaSigner;
+  param: IParametersWithRandom;
+  sig: TCryptoLibGenericArray<TBigInteger>;
+begin
+  r := TBigInteger.Create
+    ('308636143175167811492622547300668018854959378758531778147462058306432176');
+  s := TBigInteger.Create
+    ('323813553209797357708078776831250505931891051755007842781978505179448783');
+
+  kData := TBigIntegers.AsUnsignedByteArray
+    (TBigInteger.Create
+    ('700000017569056646655505781757157107570501575775705779575555657156756655')
+    );
+
+  k := TFixedSecureRandom.From(TCryptoLibMatrixByteArray.Create(kData));
+
+  n := TBigInteger.Create
+    ('883423532389192164791648750360308884807550341691627752275345424702807307');
+
+  curve := TFpCurve.Create
+    (TBigInteger.Create
+    ('883423532389192164791648750360308885314476597252960362792450860609699839'),
+    // q
+    TBigInteger.Create
+    ('7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc', 16), // a
+    TBigInteger.Create
+    ('6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a', 16), // b
+    n, TBigInteger.One);
+
+  parameters := TECDomainParameters.Create(curve,
+    curve.DecodePoint(THex.Decode
+    ('020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf')), // G
+    n);
+
+  priKey := TECPrivateKeyParameters.Create('ECDSA',
+    TBigInteger.Create
+    ('876300101507107567501066130761671078357010671067781776716671676178726717'),
+    // d
+    parameters);
+
+  ecdsa := TECDsaSigner.Create();
+  param := TParametersWithRandom.Create(priKey, k);
+
+  ecdsa.Init(true, param);
+
+  &message := TBigInteger.Create
+    ('968236873715988614170569073515315707566766479517').ToByteArray();
+  sig := ecdsa.GenerateSignature(&message);
+
+  if (not r.Equals(sig[0])) then
+  begin
+    Fail('r component wrong.' + sLineBreak + ' expecting: ' + r.ToString +
+      sLineBreak + ' got      : ' + sig[0].ToString);
+  end;
+
+  if (not s.Equals(sig[1])) then
+  begin
+    Fail('s component wrong.' + sLineBreak + ' expecting: ' + s.ToString +
+      sLineBreak + ' got      : ' + sig[1].ToString);
+  end;
+
+  // Verify the signature
+  pubKey := TECPublicKeyParameters.Create('ECDSA',
+    curve.DecodePoint(THex.Decode
+    ('025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70')), // Q
+    parameters);
+
+  ecdsa.Init(false, pubKey);
+  if (not ecdsa.VerifySignature(&message, sig[0], sig[1])) then
+  begin
+    Fail('signature fails');
+  end;
+end;
+
+procedure TTestEC.TestECDsaKeyGenTest;
+var
+  random: ISecureRandom;
+  n: TBigInteger;
+  curve: IFpCurve;
+  parameters: IECDomainParameters;
+  pGen: IECKeyPairGenerator;
+  genParam: IECKeyGenerationParameters;
+  pair: IAsymmetricCipherKeyPair;
+  param: IParametersWithRandom;
+  ecdsa: IECDsaSigner;
+  &message: TCryptoLibByteArray;
+  sig: TCryptoLibGenericArray<TBigInteger>;
+begin
+  random := TSecureRandom.Create();
+
+  n := TBigInteger.Create
+    ('883423532389192164791648750360308884807550341691627752275345424702807307');
+
+  curve := TFpCurve.Create
+    (TBigInteger.Create
+    ('883423532389192164791648750360308885314476597252960362792450860609699839'),
+    // q
+    TBigInteger.Create
+    ('7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc', 16), // a
+    TBigInteger.Create
+    ('6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a', 16), // b
+    n, TBigInteger.One);
+
+  parameters := TECDomainParameters.Create(curve,
+    curve.DecodePoint(THex.Decode
+    ('020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf')), // G
+    n);
+
+  pGen := TECKeyPairGenerator.Create();
+  genParam := TECKeyGenerationParameters.Create(parameters, random);
+
+  pGen.Init(genParam);
+
+  pair := pGen.GenerateKeyPair();
+
+  param := TParametersWithRandom.Create(pair.Private, random);
+
+  ecdsa := TECDsaSigner.Create();
+
+  ecdsa.Init(true, param);
+
+  &message := TBigInteger.Create
+    ('968236873715988614170569073515315707566766479517').ToByteArray();
+  sig := ecdsa.GenerateSignature(&message);
+
+  ecdsa.Init(false, pair.Public);
+
+  if (not ecdsa.VerifySignature(&message, sig[0], sig[1])) then
+  begin
+    Fail('signature fails');
+  end;
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestEC);
+{$ELSE}
+  RegisterTest(TTestEC.Suite);
+{$ENDIF FPC}
+
+end.

+ 229 - 0
CryptoLib.Tests/src/Others/NamedCurveTests.pas

@@ -0,0 +1,229 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit NamedCurveTests;
+
+interface
+
+{$HINTS OFF}
+
+uses
+  Classes,
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpSecureRandom,
+  ClpISigner,
+  ClpSecNamedCurves,
+  ClpIX9ECParameters,
+  ClpECDomainParameters,
+  ClpECNamedCurveTable,
+  ClpECGost3410NamedCurves,
+  ClpIECDomainParameters,
+  ClpSignerUtilities,
+  ClpECKeyPairGenerator,
+  ClpECKeyGenerationParameters,
+  ClpIAsymmetricKeyParameter,
+  ClpIAsymmetricCipherKeyPairGenerator,
+  ClpIAsymmetricCipherKeyPair,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SUnknownCurveName = 'Unknown Curve Name: %s';
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  TTestNamedCurve = class(TCryptoLibTestCase)
+  private
+    function GetCurveParameters(const name: String): IECDomainParameters;
+    procedure doTestECDsa(const name: String);
+    // procedure doTestECGost(const name: String);
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+    procedure TestPerform;
+  end;
+
+implementation
+
+{ TTestNamedCurve }
+
+procedure TTestNamedCurve.doTestECDsa(const name: String);
+var
+  ecSpec: IECDomainParameters;
+  g: IAsymmetricCipherKeyPairGenerator;
+  sgr: ISigner;
+  pair: IAsymmetricCipherKeyPair;
+  sKey, vKey: IAsymmetricKeyParameter;
+  &message, sigBytes: TCryptoLibByteArray;
+begin
+  ecSpec := GetCurveParameters(name);
+
+  g := TECKeyPairGenerator.Create('ECDSA');
+
+  g.Init(TECKeyGenerationParameters.Create(ecSpec, TSecureRandom.Create()));
+
+  sgr := TSignerUtilities.GetSigner('ECDSA');
+  pair := g.GenerateKeyPair();
+  sKey := pair.Private;
+  vKey := pair.Public;
+
+  sgr.Init(true, sKey);
+
+  &message := TEncoding.UTF8.GetBytes('abc');
+
+  sgr.BlockUpdate(&message, 0, System.Length(&message));
+
+  sigBytes := sgr.GenerateSignature();
+
+  sgr.Init(false, vKey);
+
+  sgr.BlockUpdate(&message, 0, System.Length(&message));
+
+  if (not sgr.VerifySignature(sigBytes)) then
+  begin
+    Fail(name + ' verification failed');
+  end;
+end;
+
+// procedure TTestNamedCurve.doTestECGost(const name: String);
+// var
+// sgr: ISigner;
+// keyAlgorithm: String;
+// ecSpec: IECDomainParameters;
+// g: IAsymmetricCipherKeyPairGenerator;
+// pair: IAsymmetricCipherKeyPair;
+// sKey, vKey: IAsymmetricKeyParameter;
+// &message, sigBytes: TCryptoLibByteArray;
+// begin
+// if System.Pos('Tc26-Gost-3410', name) > 0 then
+// begin
+// // TODO Implement ECGOST3410-2012 in SignerUtilies/GeneratorUtilities etc.
+// // Current test cases don't work for GOST34.10 2012
+// Exit;
+// end
+// else
+// begin
+// keyAlgorithm := 'ECGOST3410';
+//
+// sgr := TSignerUtilities.GetSigner('ECGOST3410');
+// end;
+//
+// ecSpec := GetCurveParameters(name);
+//
+// g := TECKeyPairGenerator.Create(keyAlgorithm);
+//
+// g.Init(TECKeyGenerationParameters.Create(ecSpec, TSecureRandom.Create()));
+//
+// pair := g.GenerateKeyPair();
+// sKey := pair.Private;
+// vKey := pair.Public;
+//
+// sgr.Init(true, sKey);
+//
+// &message := TEncoding.UTF8.GetBytes('abc');
+//
+// sgr.BlockUpdate(&message, 0, System.Length(&message));
+//
+// sigBytes := sgr.GenerateSignature();
+//
+// sgr.Init(false, vKey);
+//
+// sgr.BlockUpdate(&message, 0, System.Length(&message));
+//
+// if (not sgr.VerifySignature(sigBytes)) then
+// begin
+// Fail(name + ' verification failed');
+// end;
+//
+// end;
+
+function TTestNamedCurve.GetCurveParameters(const name: String)
+  : IECDomainParameters;
+var
+  ecdp: IECDomainParameters;
+  ecP: IX9ECParameters;
+begin
+  ecdp := TECGost3410NamedCurves.GetByName(name);
+
+  if (ecdp <> Nil) then
+  begin
+    result := ecdp;
+    Exit;
+  end;
+
+  ecP := TECNamedCurveTable.GetByName(name);
+
+  if (ecP = Nil) then
+  begin
+    raise Exception.CreateResFmt(@SUnknownCurveName, [name]);
+  end;
+
+  result := TECDomainParameters.Create(ecP.Curve, ecP.g, ecP.N, ecP.H,
+    ecP.GetSeed());
+end;
+
+procedure TTestNamedCurve.SetUp;
+begin
+  inherited;
+
+end;
+
+procedure TTestNamedCurve.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestNamedCurve.TestPerform;
+var
+  name: string;
+begin
+  for name in TSecNamedCurves.Names do
+  begin
+    doTestECDsa(name);
+  end;
+
+  // for name in TECGost3410NamedCurves.Names do
+  // begin
+  // doTestECGost(name);
+  // end;
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestNamedCurve);
+{$ELSE}
+  RegisterTest(TTestNamedCurve.Suite);
+{$ENDIF FPC}
+
+end.

+ 227 - 0
CryptoLib.Tests/src/Others/SignerUtilitiesTests.pas

@@ -0,0 +1,227 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit SignerUtilitiesTests;
+
+interface
+
+uses
+  Classes,
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  // ClpBase64,
+  ClpBigInteger,
+  ClpCryptoLibTypes,
+  ClpISigner,
+  ClpECCurve,
+  ClpECPoint,
+  ClpIRandom,
+  ClpSignerUtilities,
+  ClpSecureRandom,
+  ClpECDomainParameters,
+  ClpICipherParameters,
+  ClpIECDomainParameters,
+  ClpECPublicKeyParameters,
+  ClpECPrivateKeyParameters,
+  ClpIECPublicKeyParameters,
+  ClpIECPrivateKeyParameters,
+  ClpIECInterface;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  TTestSignerUtilities = class(TCryptoLibTestCase)
+  private
+
+  var
+    //
+    // ECDSA parameters
+    //
+
+    FECParraGX, FECParraGY, FECParraH, FECParraN, FECPubQX, FECPubQY,
+      FECPrivD: TBigInteger;
+    Fcurve: IECCurve;
+    FecDomain: IECDomainParameters;
+    FecPub: IECPublicKeyParameters;
+    FecPriv: IECPrivateKeyParameters;
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+    procedure TestAlgorithms;
+
+  end;
+
+implementation
+
+{ TTestSignerUtilities }
+
+procedure TTestSignerUtilities.SetUp;
+begin
+  inherited;
+  // FECParraGX := TBigInteger.Create
+  // (TBase64.Decode('D/qWPNyogWzMM7hkK+35BcPTWFc9Pyf7vTs8uaqv'));
+  // FECParraGY := TBigInteger.Create
+  // (TBase64.Decode('AhQXGxb1olGRv6s1LPRfuatMF+cx3ZTGgzSE/Q5R'));
+  // FECParraH := TBigInteger.Create(TBase64.Decode('AQ:=:='));
+  // FECParraN := TBigInteger.Create
+  // (TBase64.Decode('f///////////////f///nl6an12QcfvRUiaIkJ0L'));
+  // FECPubQX := TBigInteger.Create
+  // (TBase64.Decode('HWWi17Yb+Bm3PYr/DMjLOYNFhyOwX1QY7ZvqqM+l'));
+  // FECPubQY := TBigInteger.Create
+  // (TBase64.Decode('JrlJfxu3WGhqwtL/55BOs/wsUeiDFsvXcGhB8DGx'));
+  // FECPrivD := TBigInteger.Create
+  // (TBase64.Decode('GYQmd/NF1B+He1iMkWt3by2Az6Eu07t0ynJ4YCAo'));
+
+  FECParraGX := TBigInteger.Create(TCryptoLibByteArray.Create(15, 250, 150, 60,
+    220, 168, 129, 108, 204, 51, 184, 100, 43, 237, 249, 5, 195, 211, 88, 87,
+    61, 63, 39, 251, 189, 59, 60, 185, 170, 175));
+  FECParraGY := TBigInteger.Create(TCryptoLibByteArray.Create(2, 20, 23, 27, 22,
+    245, 162, 81, 145, 191, 171, 53, 44, 244, 95, 185, 171, 76, 23, 231, 49,
+    221, 148, 198, 131, 52, 132, 253, 14, 81));
+
+  FECParraH := TBigInteger.Create(TCryptoLibByteArray.Create(1));
+  FECParraN := TBigInteger.Create(TCryptoLibByteArray.Create(127, 255, 255, 255,
+    255, 255, 255, 255, 255, 255, 255, 255, 127, 255, 255, 158, 94, 154, 159,
+    93, 144, 113, 251, 209, 82, 38, 136, 144, 157, 11));
+  FECPubQX := TBigInteger.Create(TCryptoLibByteArray.Create(29, 101, 162, 215,
+    182, 27, 248, 25, 183, 61, 138, 255, 12, 200, 203, 57, 131, 69, 135, 35,
+    176, 95, 84, 24, 237, 155, 234, 168, 207, 165));
+  FECPubQY := TBigInteger.Create(TCryptoLibByteArray.Create(38, 185, 73, 127,
+    27, 183, 88, 104, 106, 194, 210, 255, 231, 144, 78, 179, 252, 44, 81, 232,
+    131, 22, 203, 215, 112, 104, 65, 240, 49, 177));
+  FECPrivD := TBigInteger.Create(TCryptoLibByteArray.Create(25, 132, 38, 119,
+    243, 69, 212, 31, 135, 123, 88, 140, 145, 107, 119, 111, 45, 128, 207, 161,
+    46, 211, 187, 116, 202, 114, 120, 96, 32, 40));
+
+  Fcurve := TFpCurve.Create
+    (TBigInteger.Create
+    ('883423532389192164791648750360308885314476597252960362792450860609699839'),
+    // q
+    TBigInteger.Create
+    ('7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc', 16), // a
+    TBigInteger.Create
+    ('6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a', 16)); // b
+
+  FecDomain := TECDomainParameters.Create(Fcurve,
+    TFpPoint.Create(Fcurve, Fcurve.FromBigInteger(FECParraGX),
+    Fcurve.FromBigInteger(FECParraGY)), FECParraN);
+
+  FecPub := TECPublicKeyParameters.Create(TFpPoint.Create(Fcurve,
+    Fcurve.FromBigInteger(FECPubQX), Fcurve.FromBigInteger(FECPubQY)),
+    FecDomain);
+
+  FecPriv := TECPrivateKeyParameters.Create(FECPrivD, FecDomain);
+
+end;
+
+procedure TTestSignerUtilities.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestSignerUtilities.TestAlgorithms;
+var
+  shortMsg, longMsg, sig: TCryptoLibByteArray;
+  LRandom: IRandom;
+  algorithm, upper, cipherName: string;
+  signer: ISigner;
+  withPos: Int32;
+  signParams, verifyParams: ICipherParameters;
+  b: Byte;
+begin
+  //
+  // signer loop
+  //
+  shortMsg := TCryptoLibByteArray.Create(1, 4, 5, 6, 8, 8, 4, 2, 1, 3);
+  System.SetLength(longMsg, 100);
+
+  LRandom := TSecureRandom.Create();
+  LRandom.NextBytes(longMsg);
+
+  for algorithm in TSignerUtilities.Algorithms do
+  begin
+
+    signer := TSignerUtilities.GetSigner(algorithm);
+
+    upper := AnsiUpperCase(algorithm);
+    withPos := System.Pos('WITH', upper);
+
+    if withPos = 0 then
+
+    begin
+      cipherName := upper;
+    end
+    else
+    begin
+      cipherName := System.Copy(upper, withPos + System.length('WITH'),
+        System.length(upper) - withPos + System.length('WITH'));
+    end;
+
+    if (cipherName = 'ECDSA') then
+    begin
+      signParams := FecPriv;
+      verifyParams := FecPub;
+    end
+    else
+    begin
+      Fail('Unknown algorithm encountered: ' + cipherName);
+    end;
+
+    signer.Init(true, signParams);
+    for b in shortMsg do
+    begin
+      signer.Update(b);
+    end;
+    signer.BlockUpdate(longMsg, 0, System.length(longMsg));
+    sig := signer.GenerateSignature();
+
+    signer.Init(false, verifyParams);
+    for b in shortMsg do
+    begin
+      signer.Update(b);
+    end;
+    signer.BlockUpdate(longMsg, 0, System.length(longMsg));
+
+    CheckTrue(signer.VerifySignature(sig), cipherName + ' signer ' + algorithm +
+      ' failed.');
+  end;
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestSignerUtilities);
+{$ELSE}
+  RegisterTest(TTestSignerUtilities.Suite);
+{$ENDIF FPC}
+
+end.

+ 247 - 0
CryptoLib.Tests/src/Security/SecureRandomTests.pas

@@ -0,0 +1,247 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit SecureRandomTests;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+// Disable Overflow and RangeChecks.
+{$OVERFLOWCHECKS OFF}
+{$RANGECHECKS OFF}
+{$HINTS OFF}
+{$NOTES OFF}
+{$ENDIF FPC}
+
+uses
+  Classes,
+  SysUtils,
+{$IFDEF FPC}
+  fpcunit,
+  testregistry,
+{$ELSE}
+  TestFramework,
+{$ENDIF FPC}
+  ClpCryptoLibTypes,
+  ClpSecureRandom,
+  ClpISecureRandom,
+  ClpCryptoApiRandomGenerator,
+  ClpICryptoApiRandomGenerator;
+
+type
+
+  TCryptoLibTestCase = class abstract(TTestCase)
+
+  end;
+
+type
+
+  TTestSecureRandom = class(TCryptoLibTestCase)
+  private
+
+    procedure CheckSecureRandom(random: ISecureRandom);
+    function RunChiSquaredTests(random: ISecureRandom): Boolean;
+    function MeasureChiSquared(random: ISecureRandom; rounds: Int32): Double;
+
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  published
+    procedure TestCryptoApi();
+    procedure TestDefault();
+    procedure TestSha1Prng();
+    procedure TestSha256Prng();
+
+  end;
+
+implementation
+
+{ TTestSecureRandom }
+
+procedure TTestSecureRandom.CheckSecureRandom(random: ISecureRandom);
+begin
+  // Note: This will periodically (< 1e-6 probability) give a false alarm.
+  // That's randomness for you!
+  CheckEquals(true, RunChiSquaredTests(random),
+    'Chi2 test detected possible non-randomness');
+end;
+
+function TTestSecureRandom.MeasureChiSquared(random: ISecureRandom;
+  rounds: Int32): Double;
+var
+  opts, bs: TCryptoLibByteArray;
+  counts: TCryptoLibInt32Array;
+  I, b, total, k: Integer;
+  mask, shift: Byte;
+  chi2, diff, diff2, temp: Double;
+begin
+  opts := random.GenerateSeed(2);
+  System.SetLength(counts, 256);
+  System.SetLength(bs, 256);
+
+  I := 0;
+  while I < rounds do
+  begin
+    random.NextBytes(bs);
+
+    for b := 0 to System.Pred(256) do
+    begin
+
+      counts[bs[b]] := counts[bs[b]] + 1;
+
+    end;
+
+    System.Inc(I);
+  end;
+
+  mask := opts[0];
+
+  I := 0;
+  while I < rounds do
+  begin
+    random.NextBytes(bs);
+
+    for b := 0 to System.Pred(256) do
+    begin
+
+      counts[bs[b] xor mask] := counts[bs[b] xor mask] + 1;
+
+    end;
+    System.Inc(mask);
+    System.Inc(I);
+  end;
+
+  shift := opts[1];
+
+  I := 0;
+  while I < rounds do
+  begin
+    random.NextBytes(bs);
+
+    for b := 0 to System.Pred(256) do
+    begin
+
+      counts[Byte(bs[b] + shift)] := counts[Byte(bs[b] + shift)] + 1;
+
+    end;
+    System.Inc(shift);
+    System.Inc(I);
+  end;
+
+  total := 3 * rounds;
+
+  chi2 := 0;
+
+  for k := 0 to System.Pred(System.Length(counts)) do
+  begin
+    temp := counts[k];
+    diff := temp - total;
+    diff2 := diff * diff;
+
+    chi2 := chi2 + diff2;
+  end;
+
+  chi2 := chi2 / total;
+
+  result := chi2;
+end;
+
+function TTestSecureRandom.RunChiSquaredTests(random: ISecureRandom): Boolean;
+var
+  passes, tries: Int32;
+  chi2: Double;
+begin
+  passes := 0;
+
+  tries := 0;
+  while tries < 100 do
+  begin
+    chi2 := MeasureChiSquared(random, 1000);
+
+    // 255 degrees of freedom in test => Q ~ 10.0% for 285
+    if (chi2 < 285.0) then
+    begin
+      System.Inc(passes);
+    end;
+
+    System.Inc(tries);
+  end;
+
+  result := passes > 75;
+end;
+
+procedure TTestSecureRandom.SetUp;
+begin
+  inherited;
+
+end;
+
+procedure TTestSecureRandom.TearDown;
+begin
+  inherited;
+
+end;
+
+procedure TTestSecureRandom.TestCryptoApi;
+var
+  &random: ISecureRandom;
+begin
+  random := TSecureRandom.Create(TCryptoApiRandomGenerator.Create()
+    as ICryptoApiRandomGenerator);
+
+  CheckSecureRandom(random);
+end;
+
+procedure TTestSecureRandom.TestDefault;
+var
+  &random: ISecureRandom;
+begin
+  random := TSecureRandom.Create();
+
+  CheckSecureRandom(random);
+end;
+
+procedure TTestSecureRandom.TestSha1Prng;
+var
+  &random: ISecureRandom;
+begin
+  random := TSecureRandom.GetInstance('SHA1PRNG');
+
+  CheckSecureRandom(random);
+end;
+
+procedure TTestSecureRandom.TestSha256Prng;
+var
+  &random: ISecureRandom;
+begin
+  random := TSecureRandom.GetInstance('SHA256PRNG');
+
+  CheckSecureRandom(random);
+end;
+
+initialization
+
+// Register any test cases with the test runner
+
+{$IFDEF FPC}
+  RegisterTest(TTestSecureRandom);
+{$ELSE}
+  RegisterTest(TTestSecureRandom.Suite);
+{$ENDIF FPC}
+
+end.

+ 483 - 0
CryptoLib.Tests/src/Utils/ClpFixedSecureRandom.pas

@@ -0,0 +1,483 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpFixedSecureRandom;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$WARNINGS OFF}
+{$ENDIF FPC}
+
+uses
+  Classes,
+  SysUtils,
+  ClpHex,
+  ClpCryptoLibTypes,
+  ClpConverters,
+  ClpBigInteger,
+  ClpIFixedSecureRandom,
+  ClpISecureRandom,
+  ClpSecureRandom;
+
+resourcestring
+  SErrorSavingArray = 'can''t save value array.';
+  SErrorSavingSource = 'can''t save value source.';
+  SUnRecognizedImplementation = 'Unrecognized BigIntegerSource Implementation';
+
+type
+  TFixedSecureRandom = class(TSecureRandom, IFixedSecureRandom)
+
+  strict private
+  var
+    F_data: TCryptoLibByteArray;
+    F_index: Int32;
+
+  class var
+
+    FREGULAR, FANDROID, FCLASSPATH: TBigInteger;
+
+    FisAndroidStyle, FisClasspathStyle, FisRegularStyle: Boolean;
+
+    function GetIsExhausted: Boolean; inline;
+
+    class constructor FixedSecureRandom();
+
+  type
+    TRandomChecker = class(TSecureRandom, IRandomChecker)
+
+    public
+    var
+      Fdata: TCryptoLibByteArray;
+      Findex: Int32;
+      constructor Create();
+
+      procedure NextBytes(bytes: TCryptoLibByteArray); override;
+
+    end;
+
+  class function ExpandToBitLength(bitLength: Int32; v: TCryptoLibByteArray)
+    : TCryptoLibByteArray; static;
+
+  strict protected
+    constructor Create(data: TCryptoLibByteArray); overload;
+
+  public
+
+    type
+
+    /// <summary>
+    /// Base class for sources of fixed "Randomness"
+    /// </summary>
+    TSource = class(TInterfacedObject, ISource)
+
+    strict private
+    var
+      Fdata: TCryptoLibByteArray;
+
+      function GetData: TCryptoLibByteArray; inline;
+
+    public
+      property data: TCryptoLibByteArray read GetData;
+      constructor Create(data: TCryptoLibByteArray);
+
+    end;
+
+  type
+
+    /// <summary>
+    /// Data Source - in this case we just expect requests for byte arrays.
+    /// </summary>
+    TData = class(TSource, IData)
+
+    public
+
+      constructor Create(data: TCryptoLibByteArray);
+
+    end;
+
+  type
+
+    /// <summary>
+    /// BigInteger Source - in this case we expect requests for data that
+    /// will be used <br />for BigIntegers. The FixedSecureRandom will
+    /// attempt to compensate for platform differences here.
+    /// </summary>
+    TBigIntegerSource = class(TSource, IBigIntegerSource)
+
+    public
+
+      constructor Create(data: TCryptoLibByteArray); overload;
+      constructor Create(bitLength: Int32; data: TCryptoLibByteArray); overload;
+      constructor Create(const hexData: String); overload;
+      constructor Create(bitLength: Int32; const hexData: String); overload;
+
+    end;
+
+  function GenerateSeed(numBytes: Int32): TCryptoLibByteArray; override;
+
+  procedure NextBytes(buf: TCryptoLibByteArray); overload; override;
+  procedure NextBytes(buf: TCryptoLibByteArray; off, len: Int32);
+    overload; override;
+
+  property IsExhausted: Boolean read GetIsExhausted;
+
+  constructor Create(sources: TCryptoLibGenericArray<ISource>); overload;
+
+  class function From(values: TCryptoLibMatrixByteArray)
+    : IFixedSecureRandom; static;
+
+  end;
+
+implementation
+
+{ TFixedSecureRandom }
+
+constructor TFixedSecureRandom.Create(data: TCryptoLibByteArray);
+begin
+  Inherited Create();
+  F_data := data;
+end;
+
+constructor TFixedSecureRandom.Create(sources: TCryptoLibGenericArray<ISource>);
+var
+  bOut: TMemoryStream;
+  data: TCryptoLibByteArray;
+  i, len, w: Int32;
+begin
+  Inherited Create();
+  bOut := TMemoryStream.Create();
+  try
+    if (FisRegularStyle) then
+    begin
+      if (FisClasspathStyle) then
+
+      begin
+
+        i := 0;
+        while i <> System.Length(sources) do
+
+        begin
+          try
+
+            if (Supports(sources[i], IBigIntegerSource)) then
+            begin
+              data := sources[i].data;
+              len := System.Length(data) - (System.Length(data) mod 4);
+              w := System.Length(data) - len - 1;
+              while w >= 0 do
+
+              begin
+                bOut.Write(TCryptoLibByteArray.Create(data[w]), 1);
+                System.Dec(w);
+              end;
+              w := System.Length(data) - len;
+              while w < System.Length(data) do
+              begin
+                bOut.Write(data[w], 4);
+                System.Inc(w, 4);
+              end;
+            end
+            else
+            begin
+              bOut.Write(sources[i].data[0], System.Length(sources[i].data));
+            end;
+
+          except
+            on e: EIOCryptoLibException do
+            begin
+              raise EArgumentCryptoLibException.CreateRes(@SErrorSavingSource);
+            end;
+          end;
+          System.Inc(i);
+        end
+      end
+      else
+      begin
+        i := 0;
+        while i <> System.Length(sources) do
+        begin
+          try
+
+            bOut.Write(sources[i].data[0], System.Length(sources[i].data));
+          except
+            on e: EIOCryptoLibException do
+            begin
+              raise EArgumentCryptoLibException.CreateRes(@SErrorSavingSource);
+            end;
+          end;
+          System.Inc(i);
+        end
+      end
+    end
+    else if (FisAndroidStyle) then
+    begin
+      i := 0;
+      while i <> System.Length(sources) do
+      begin
+        try
+
+          if (Supports(sources[i], IBigIntegerSource)) then
+          begin
+            data := sources[i].data;
+            len := System.Length(data) - (System.Length(data) mod 4);
+            w := 0;
+            while w < len do
+
+            begin
+              bOut.Write(data[System.Length(data) - (w + 4)], 4);
+              System.Inc(w, 4);
+            end;
+            if ((System.Length(data) - len) <> 0) then
+            begin
+
+              w := 0;
+              while (w <> (4 - (System.Length(data) - len))) do
+
+              begin
+                bOut.Write(TCryptoLibByteArray.Create(0), 1);
+                System.Inc(w);
+              end;
+            end;
+            w := 0;
+            while (w <> (System.Length(data) - len)) do
+            begin
+
+              bOut.Write(TCryptoLibByteArray.Create(data[len + w]), 1);
+              System.Inc(w);
+            end
+          end
+          else
+          begin
+            bOut.Write(sources[i].data[0], System.Length(sources[i].data));
+          end;
+
+        except
+          on e: EIOCryptoLibException do
+          begin
+            raise EArgumentCryptoLibException.CreateRes(@SErrorSavingSource);
+          end;
+        end;
+        System.Inc(i);
+      end;
+
+      System.SetLength(F_data, bOut.Size);
+      bOut.Position := 0;
+      bOut.Read(F_data[0], bOut.Size);
+    end
+    else
+    begin
+      raise EInvalidOperationCryptoLibException.CreateRes
+        (@SUnRecognizedImplementation);
+    end;
+
+  finally
+    bOut.Free;
+
+  end;
+
+end;
+
+class function TFixedSecureRandom.ExpandToBitLength(bitLength: Int32;
+  v: TCryptoLibByteArray): TCryptoLibByteArray;
+var
+  tmp: TCryptoLibByteArray;
+  i: UInt32;
+begin
+  if (((bitLength + 7) div 8) > System.Length(v)) then
+  begin
+    System.SetLength(tmp, (bitLength + 7) div 8);
+
+    System.Move(v[0], tmp[System.Length(tmp) - System.Length(v)],
+      System.Length(v));
+
+    if (FisAndroidStyle) then
+    begin
+      if (bitLength mod 8 <> 0) then
+      begin
+        i := TConverters.ReadBytesAsUInt32BE(PByte(tmp), 0);
+        tmp := TConverters.ReadUInt32AsBytesBE(i shl (8 - (bitLength mod 8)));
+
+      end;
+    end;
+
+    result := tmp;
+    Exit;
+  end
+  else
+  begin
+    if (FisAndroidStyle and (bitLength < (System.Length(v) * 8))) then
+    begin
+      if (bitLength mod 8 <> 0) then
+      begin
+        i := TConverters.ReadBytesAsUInt32BE(PByte(v), 0);
+        v := TConverters.ReadUInt32AsBytesBE(i shl (8 - (bitLength mod 8)));
+
+      end;
+    end;
+  end;
+
+  result := v;
+end;
+
+class constructor TFixedSecureRandom.FixedSecureRandom;
+var
+  Fcheck1, Fcheck2: TBigInteger;
+begin
+  FREGULAR := TBigInteger.Create('01020304ffffffff0506070811111111', 16);
+  FANDROID := TBigInteger.Create('1111111105060708ffffffff01020304', 16);
+  FCLASSPATH := TBigInteger.Create('3020104ffffffff05060708111111', 16);
+
+  Fcheck1 := TBigInteger.Create(128, TRandomChecker.Create());
+  Fcheck2 := TBigInteger.Create(120, TRandomChecker.Create());
+
+  FisAndroidStyle := Fcheck1.Equals(FANDROID);
+  FisRegularStyle := Fcheck1.Equals(FREGULAR);
+  FisClasspathStyle := Fcheck2.Equals(FCLASSPATH);
+end;
+
+class function TFixedSecureRandom.From(values: TCryptoLibMatrixByteArray)
+  : IFixedSecureRandom;
+var
+  bOut: TMemoryStream;
+  i: Int32;
+  v, temp: TCryptoLibByteArray;
+begin
+  bOut := TMemoryStream.Create();
+  try
+
+    i := 0;
+    while i <> System.Length(values) do
+    begin
+      try
+
+        v := values[i];
+        bOut.Write(v[0], System.Length(v));
+
+      except
+        on e: EIOCryptoLibException do
+        begin
+          raise EArgumentCryptoLibException.CreateRes(@SErrorSavingArray);
+        end;
+
+      end;
+
+      System.Inc(i);
+    end;
+
+    System.SetLength(temp, bOut.Size);
+    bOut.Position := 0;
+    bOut.Read(temp[0], bOut.Size);
+    result := TFixedSecureRandom.Create(temp);
+  finally
+    bOut.Free;
+  end;
+end;
+
+function TFixedSecureRandom.GenerateSeed(numBytes: Int32): TCryptoLibByteArray;
+begin
+  result := TSecureRandom.GetNextBytes(Self as ISecureRandom, numBytes);
+end;
+
+function TFixedSecureRandom.GetIsExhausted: Boolean;
+begin
+  result := F_index = System.Length(F_data);
+end;
+
+procedure TFixedSecureRandom.NextBytes(buf: TCryptoLibByteArray);
+begin
+  System.Move(F_data[F_index], buf[0], System.Length(buf) *
+    System.SizeOf(Byte));
+
+  F_index := F_index + System.Length(buf);
+end;
+
+procedure TFixedSecureRandom.NextBytes(buf: TCryptoLibByteArray;
+  off, len: Int32);
+begin
+  System.Move(F_data[F_index], buf[off], len * System.SizeOf(Byte));
+
+  F_index := F_index + len;
+end;
+
+{ TRandomChecker.TFixedSecureRandom }
+
+constructor TFixedSecureRandom.TRandomChecker.Create;
+begin
+  Inherited Create();
+  Fdata := THex.Decode('01020304ffffffff0506070811111111');
+  Findex := 0;
+end;
+
+procedure TFixedSecureRandom.TRandomChecker.NextBytes
+  (bytes: TCryptoLibByteArray);
+begin
+
+  System.Move(Fdata[Findex], bytes[0], System.Length(bytes) *
+    System.SizeOf(Byte));
+
+  Findex := Findex + System.Length(bytes);
+
+end;
+
+{ TFixedSecureRandom.TSource }
+
+constructor TFixedSecureRandom.TSource.Create(data: TCryptoLibByteArray);
+begin
+  Inherited Create();
+  Fdata := data;
+end;
+
+function TFixedSecureRandom.TSource.GetData: TCryptoLibByteArray;
+begin
+  result := Fdata;
+end;
+
+{ TFixedSecureRandom.TData }
+
+constructor TFixedSecureRandom.TData.Create(data: TCryptoLibByteArray);
+begin
+  Inherited Create(data);
+end;
+
+{ TFixedSecureRandom.TBigIntegerSource }
+
+constructor TFixedSecureRandom.TBigIntegerSource.Create(bitLength: Int32;
+  data: TCryptoLibByteArray);
+begin
+  Inherited Create(ExpandToBitLength(bitLength, data));
+end;
+
+constructor TFixedSecureRandom.TBigIntegerSource.Create
+  (data: TCryptoLibByteArray);
+begin
+  Inherited Create(data);
+end;
+
+constructor TFixedSecureRandom.TBigIntegerSource.Create(bitLength: Int32;
+  const hexData: String);
+begin
+  Inherited Create(ExpandToBitLength(bitLength, THex.Decode(hexData)));
+end;
+
+constructor TFixedSecureRandom.TBigIntegerSource.Create(const hexData: String);
+begin
+  Create(THex.Decode(hexData));
+end;
+
+end.

+ 68 - 0
CryptoLib.Tests/src/Utils/ClpIFixedSecureRandom.pas

@@ -0,0 +1,68 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpIFixedSecureRandom;
+
+interface
+
+{$IFDEF FPC}
+{$MODE DELPHI}
+{$WARNINGS OFF}
+{$ENDIF FPC}
+
+uses
+  ClpISecureRandom,
+  ClpCryptoLibTypes;
+
+type
+  IFixedSecureRandom = interface(ISecureRandom)
+    ['{8D3C436D-1E93-487F-9C03-5E0EEFBCBBB4}']
+
+    function GetIsExhausted: Boolean;
+
+    function GenerateSeed(numBytes: Int32): TCryptoLibByteArray;
+
+    procedure NextBytes(buf: TCryptoLibByteArray); overload;
+    procedure NextBytes(buf: TCryptoLibByteArray; off, len: Int32); overload;
+
+    property IsExhausted: Boolean read GetIsExhausted;
+
+  end;
+
+  IRandomChecker = interface(ISecureRandom)
+    ['{EFC0D597-00E4-4DAE-8529-E14C9FE50B41}']
+    procedure NextBytes(bytes: TCryptoLibByteArray);
+  end;
+
+  ISource = interface(IInterface)
+    ['{D4391E69-BA80-4245-BB94-52715BC6D043}']
+    function GetData: TCryptoLibByteArray;
+
+    property Data: TCryptoLibByteArray read GetData;
+  end;
+
+  IData = interface(ISource)
+    ['{CF4AB8B8-724D-4EEA-93F5-0732C81774F0}']
+  end;
+
+  IBigIntegerSource = interface(ISource)
+    ['{202BF4D8-D872-4757-8C0F-D76228CEDB92}']
+  end;
+
+implementation
+
+end.

+ 153 - 0
CryptoLib/src/Asn1/ClpAsn1Encodable.pas

@@ -0,0 +1,153 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpAsn1Encodable;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpAsn1OutputStream,
+  ClpDerOutputStream,
+  ClpIProxiedInterface,
+  ClpCryptoLibTypes;
+
+type
+
+  TAsn1Encodable = class abstract(TInterfacedObject, IAsn1Encodable,
+    IAsn1Convertible)
+
+  public
+
+    const
+    Der = 'DER';
+    Ber = 'BER';
+
+    function GetEncoded(): TCryptoLibByteArray; overload;
+    function GetEncoded(const encoding: String): TCryptoLibByteArray; overload;
+
+    /// <summary>
+    /// Return the DER encoding of the object, null if the DER encoding can
+    /// not be made.
+    /// </summary>
+    /// <returns>
+    /// return a DER byte array, null otherwise.
+    /// </returns>
+    function GetDerEncoded(): TCryptoLibByteArray;
+
+    function Equals(other: IAsn1Convertible): Boolean; reintroduce;
+    function GetHashCode(): {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}override;
+
+    function ToAsn1Object(): IAsn1Object; virtual; abstract;
+
+  end;
+
+implementation
+
+{ TAsn1Encodable }
+
+function TAsn1Encodable.Equals(other: IAsn1Convertible): Boolean;
+var
+  o1, o2: IAsn1Object;
+begin
+
+  if (other = Self as IAsn1Convertible) then
+  begin
+    Result := true;
+    Exit;
+  end;
+
+  if (other = Nil) then
+  begin
+    Result := false;
+    Exit;
+  end;
+  o1 := ToAsn1Object();
+  o2 := other.ToAsn1Object();
+
+  Result := ((o1 = o2) or o1.CallAsn1Equals(o2));
+end;
+
+function TAsn1Encodable.GetDerEncoded: TCryptoLibByteArray;
+begin
+
+  try
+    Result := GetEncoded(Der);
+  except
+    on e: EIOCryptoLibException do
+    begin
+      Result := Nil;
+    end;
+  end;
+end;
+
+function TAsn1Encodable.GetEncoded: TCryptoLibByteArray;
+var
+  bOut: TMemoryStream;
+  aOut: TAsn1OutputStream;
+begin
+
+  bOut := TMemoryStream.Create();
+  aOut := TAsn1OutputStream.Create(bOut);
+  try
+    aOut.WriteObject(Self as IAsn1Encodable);
+    System.SetLength(Result, bOut.Size);
+    bOut.Position := 0;
+    bOut.Read(Result[0], System.Length(Result));
+
+  finally
+    bOut.Free;
+    aOut.Free;
+  end;
+
+end;
+
+function TAsn1Encodable.GetEncoded(const encoding: String): TCryptoLibByteArray;
+var
+  bOut: TMemoryStream;
+  dOut: TDerOutputStream;
+begin
+  if (encoding = Der) then
+  begin
+    bOut := TMemoryStream.Create();
+    dOut := TDerOutputStream.Create(bOut);
+    try
+      dOut.WriteObject(Self as IAsn1Encodable);
+      System.SetLength(Result, bOut.Size);
+      bOut.Position := 0;
+      bOut.Read(Result[0], System.Length(Result));
+
+    finally
+      bOut.Free;
+      dOut.Free;
+    end;
+    Exit;
+  end;
+
+  Result := GetEncoded();
+end;
+
+function TAsn1Encodable.GetHashCode: {$IFDEF DELPHI}Int32; {$ELSE}PtrInt;
+{$ENDIF DELPHI}
+begin
+  Result := ToAsn1Object().CallAsn1GetHashCode();
+end;
+
+end.

+ 140 - 0
CryptoLib/src/Asn1/ClpAsn1EncodableVector.pas

@@ -0,0 +1,140 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpAsn1EncodableVector;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Generics.Collections,
+  ClpCryptoLibTypes,
+  ClpIProxiedInterface,
+  ClpIAsn1EncodableVector;
+
+type
+  TAsn1EncodableVector = class(TInterfacedObject, IAsn1EncodableVector)
+
+  strict private
+  var
+
+    Flist: TList<IAsn1Encodable>;
+
+    function GetCount: Int32;
+    function GetSelf(Index: Int32): IAsn1Encodable;
+
+  public
+    class function FromEnumerable(e: TEnumerable<IAsn1Encodable>)
+      : IAsn1EncodableVector; static;
+
+    constructor Create(); overload;
+    constructor Create(v: array of IAsn1Encodable); overload;
+
+    destructor Destroy(); override;
+
+    procedure Add(objs: array of IAsn1Encodable);
+
+    procedure AddOptional(objs: array of IAsn1Encodable);
+
+    property Self[Index: Int32]: IAsn1Encodable read GetSelf; default;
+
+    property Count: Int32 read GetCount;
+
+    function GetEnumerator: TEnumerator<IAsn1Encodable>;
+
+  end;
+
+implementation
+
+{ TAsn1EncodableVector }
+
+procedure TAsn1EncodableVector.Add(objs: array of IAsn1Encodable);
+var
+  obj: IAsn1Encodable;
+begin
+  for obj in objs do
+  begin
+    Flist.Add(obj);
+  end;
+end;
+
+procedure TAsn1EncodableVector.AddOptional(objs: array of IAsn1Encodable);
+var
+  obj: IAsn1Encodable;
+begin
+  if (System.Length(objs) <> 0) then
+  begin
+    for obj in objs do
+    begin
+      if (obj <> Nil) then
+      begin
+        Flist.Add(obj);
+      end;
+    end;
+  end;
+end;
+
+constructor TAsn1EncodableVector.Create(v: array of IAsn1Encodable);
+begin
+  inherited Create();
+  Flist := TList<IAsn1Encodable>.Create();
+  Add(v);
+end;
+
+constructor TAsn1EncodableVector.Create();
+begin
+  inherited Create();
+  Flist := TList<IAsn1Encodable>.Create();
+end;
+
+destructor TAsn1EncodableVector.Destroy;
+begin
+  Flist.Free;
+  inherited Destroy;
+end;
+
+class function TAsn1EncodableVector.FromEnumerable
+  (e: TEnumerable<IAsn1Encodable>): IAsn1EncodableVector;
+var
+  v: IAsn1EncodableVector;
+  obj: IAsn1Encodable;
+begin
+  v := TAsn1EncodableVector.Create();
+  for obj in e do
+  begin
+    v.Add(obj);
+  end;
+  result := v;
+end;
+
+function TAsn1EncodableVector.GetCount: Int32;
+begin
+  result := Flist.Count;
+end;
+
+function TAsn1EncodableVector.GetEnumerator: TEnumerator<IAsn1Encodable>;
+begin
+  result := Flist.GetEnumerator();
+end;
+
+function TAsn1EncodableVector.GetSelf(Index: Int32): IAsn1Encodable;
+begin
+  result := Flist[index];
+end;
+
+end.

+ 64 - 0
CryptoLib/src/Asn1/ClpAsn1Generator.pas

@@ -0,0 +1,64 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpAsn1Generator;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpIProxiedInterface,
+  ClpIAsn1Generator;
+
+type
+  TAsn1Generator = class abstract(TInterfacedObject, IAsn1Generator)
+
+  strict private
+  var
+    F_out: TStream;
+
+    function GetOut: TStream; inline;
+
+  strict protected
+    constructor Create(outStream: TStream);
+    property &Out: TStream read GetOut;
+
+  public
+    procedure AddObject(obj: IAsn1Encodable); virtual; abstract;
+
+    function GetRawOutputStream(): TStream; virtual; abstract;
+
+    procedure Close(); virtual; abstract;
+  end;
+
+implementation
+
+{ TAsn1Generator }
+
+constructor TAsn1Generator.Create(outStream: TStream);
+begin
+  F_out := outStream;
+end;
+
+function TAsn1Generator.GetOut: TStream;
+begin
+  result := F_out;
+end;
+
+end.

+ 726 - 0
CryptoLib/src/Asn1/ClpAsn1InputStream.pas

@@ -0,0 +1,726 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpAsn1InputStream;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  Generics.Collections,
+  ClpCryptoLibTypes,
+  ClpAsn1Tags,
+  ClpDefiniteLengthInputStream,
+  ClpDerOctetString,
+  ClpIndefiniteLengthInputStream,
+  ClpAsn1StreamParser,
+  ClpIAsn1StreamParser,
+  ClpDerBitString,
+  ClpDerBmpString,
+  // ClpDerGeneralizedTime,
+  // ClpDerUtcTime,
+  ClpDerGeneralString,
+  ClpDerGraphicString,
+  ClpDerIA5String,
+  ClpDerNumericString,
+  ClpDerPrintableString,
+  ClpDerT61String,
+  ClpDerUniversalString,
+  ClpDerUtf8String,
+  ClpDerVideotexString,
+  ClpDerVisibleString,
+  ClpDerBoolean,
+  ClpDerEnumerated,
+  ClpDerApplicationSpecific,
+  ClpDerExternal,
+  ClpDerInteger,
+  ClpDerNull,
+  ClpDerObjectIdentifier,
+  ClpBerOctetString,
+  ClpIProxiedInterface,
+  ClpIDerSequence,
+  ClpIDerOctetString,
+  ClpIDerSet,
+  ClpLimitedInputStream,
+  ClpAsn1EncodableVector,
+  ClpDerSequence,
+  ClpDerSet,
+  ClpIDefiniteLengthInputStream,
+  ClpIAsn1EncodableVector,
+  ClpIAsn1InputStream,
+  ClpFilterStream;
+
+resourcestring
+  SCorruptedStream = 'Corrupted Stream - Invalid High Tag Number Found';
+  SEOFFound = 'EOF Found Inside Tag Value';
+  SInvalidEnd = 'EOF Found When Length Expected';
+  SInvalidDerLength = 'DER Length More Than 4 Bytes: %d';
+  SEndOfStream = 'EOF Found Reading Length';
+  SNegativeLength = 'Corrupted Stream - Negative Length Found';
+  SOutOfBoundsLength = 'Corrupted stream - Out of Bounds Length Found';
+  SUnknownTag = 'Unknown Tag " %d " Encountered';
+  SEndOfContent = 'Unexpected End-of-Contents Marker';
+  SIndefiniteLength = 'Indefinite Length Primitive Encoding Encountered';
+  SUnknownBerObject = 'Unknown BER Object Encountered';
+  SCorruptedStreamTwo = 'Corrupted Stream Detected: %s';
+
+type
+
+  /// <summary>
+  /// a general purpose ASN.1 decoder - note: this class differs from the <br />
+  /// others in that it returns null after it has read the last object in <br />
+  /// the stream. If an ASN.1 Null is encountered a DerBER Null object is <br />
+  /// returned. <br />
+  /// </summary>
+  TAsn1InputStream = class(TFilterStream, IAsn1InputStream)
+
+  strict private
+
+  var
+    Flimit: Int32;
+    FtmpBuffers: TCryptoLibMatrixGenericArray<Byte>;
+    FStream: TStream;
+
+    /// <summary>
+    /// build an object given its tag and the number of bytes to construct it
+    /// from.
+    /// </summary>
+    function BuildObject(tag, tagNo, length: Int32): IAsn1Object;
+
+  public
+
+    constructor Create(inputStream: TStream); overload;
+
+    /// <summary>
+    /// Create an ASN1InputStream where no DER object will be longer than
+    /// limit.
+    /// </summary>
+    /// <param name="inputStream">
+    /// stream containing ASN.1 encoded data.
+    /// </param>
+    /// <param name="limit">
+    /// maximum size of a DER encoded object.
+    /// </param>
+    constructor Create(inputStream: TStream; limit: Int32); overload;
+
+    destructor Destroy(); override;
+
+    /// <summary>
+    /// the stream is automatically limited to the length of the input array.
+    /// </summary>
+    /// <param name="input">
+    /// array containing ASN.1 encoded data.
+    /// </param>
+    constructor Create(input: TCryptoLibByteArray); overload;
+
+    function ReadObject(): IAsn1Object;
+
+    function BuildEncodableVector(): IAsn1EncodableVector;
+
+    function BuildDerEncodableVector(dIn: IDefiniteLengthInputStream)
+      : IAsn1EncodableVector; virtual;
+
+    function CreateDerSequence(dIn: IDefiniteLengthInputStream)
+      : IDerSequence; virtual;
+
+    function CreateDerSet(dIn: IDefiniteLengthInputStream): IDerSet; virtual;
+
+    class function FindLimit(input: TStream): Int32; static;
+
+    class function ReadTagNumber(s: TStream; tag: Int32): Int32; static;
+
+    class function ReadLength(s: TStream; limit: Int32): Int32; static;
+
+    class function GetBuffer(defIn: IDefiniteLengthInputStream;
+      tmpBuffers: TCryptoLibMatrixGenericArray<Byte>): TCryptoLibByteArray;
+      static; inline;
+
+    class function CreatePrimitiveDerObject(tagNo: Int32;
+      defIn: IDefiniteLengthInputStream;
+      tmpBuffers: TCryptoLibMatrixGenericArray<Byte>): IAsn1Object; static;
+  end;
+
+implementation
+
+uses
+  // included here to avoid circular dependency :)
+  ClpStreamSorter,
+  ClpBerOctetStringParser,
+  ClpBerSequenceParser,
+  ClpBerSetParser,
+  ClpDerExternalParser,
+  ClpBerApplicationSpecificParser,
+  ClpBerTaggedObjectParser,
+  ClpIBerOctetStringParser,
+  ClpIBerSequenceParser,
+  ClpIBerSetParser,
+  ClpIDerExternalParser,
+  ClpIBerApplicationSpecificParser,
+  ClpIBerTaggedObjectParser;
+
+{ TAsn1InputStream }
+
+class function TAsn1InputStream.FindLimit(input: TStream): Int32;
+var
+  limitedInputStream: TLimitedInputStream;
+  mem: TMemoryStream;
+begin
+  limitedInputStream := input as TLimitedInputStream;
+  if (limitedInputStream <> Nil) then
+  begin
+    result := limitedInputStream.GetRemaining();
+    Exit;
+  end
+  else if (input is TMemoryStream) then
+  begin
+    mem := input as TMemoryStream;
+    result := Int32(mem.Size - mem.Position);
+    Exit;
+  end;
+
+  result := System.High(Int32);
+end;
+
+class function TAsn1InputStream.GetBuffer(defIn: IDefiniteLengthInputStream;
+  tmpBuffers: TCryptoLibMatrixGenericArray<Byte>): TCryptoLibByteArray;
+var
+  len: Int32;
+  buf, temp: TCryptoLibByteArray;
+begin
+  len := defIn.GetRemaining();
+  if (len >= System.length(tmpBuffers)) then
+  begin
+    result := defIn.ToArray();
+    Exit;
+  end;
+
+  buf := tmpBuffers[len];
+  if (buf = Nil) then
+  begin
+    System.SetLength(temp, len);
+    tmpBuffers[len] := temp;
+    buf := tmpBuffers[len];
+  end;
+
+  defIn.ReadAllIntoByteArray(buf);
+
+  result := buf;
+end;
+
+class function TAsn1InputStream.CreatePrimitiveDerObject(tagNo: Int32;
+  defIn: IDefiniteLengthInputStream;
+  tmpBuffers: TCryptoLibMatrixGenericArray<Byte>): IAsn1Object;
+var
+  bytes: TCryptoLibByteArray;
+begin
+  case tagNo of
+    TAsn1Tags.Boolean:
+      begin
+        result := TDerBoolean.FromOctetString(GetBuffer(defIn, tmpBuffers));
+        Exit;
+      end;
+    TAsn1Tags.Enumerated:
+      begin
+        result := TDerEnumerated.FromOctetString(GetBuffer(defIn, tmpBuffers));
+        Exit;
+      end;
+    TAsn1Tags.ObjectIdentifier:
+      begin
+        result := TDerObjectIdentifier.FromOctetString
+          (GetBuffer(defIn, tmpBuffers));
+        Exit;
+      end;
+
+  end;
+
+  bytes := defIn.ToArray();
+
+  case tagNo of
+
+    TAsn1Tags.BitString:
+      begin
+        result := TDerBitString.FromAsn1Octets(bytes);
+        Exit;
+      end;
+    TAsn1Tags.BmpString:
+      begin
+        result := TDerBmpString.Create(bytes);
+        Exit;
+      end;
+    // TAsn1Tags.GeneralizedTime:
+    // begin
+    // result := TDerGeneralizedTime.Create(bytes);
+    // Exit;
+    // end;
+    TAsn1Tags.GeneralString:
+      begin
+        result := TDerGeneralString.Create(bytes);
+        Exit;
+      end;
+    TAsn1Tags.GraphicString:
+      begin
+        result := TDerGraphicString.Create(bytes);
+        Exit;
+      end;
+    TAsn1Tags.IA5String:
+      begin
+        result := TDerIA5String.Create(bytes);
+        Exit;
+      end;
+    TAsn1Tags.Integer:
+      begin
+        result := TDerInteger.Create(bytes);
+        Exit;
+      end;
+    TAsn1Tags.Null:
+      begin
+        // actual content is ignored (enforce 0 length?)
+        result := TDerNull.Instance;
+        Exit;
+      end;
+    TAsn1Tags.NumericString:
+      begin
+        result := TDerNumericString.Create(bytes);
+        Exit;
+      end;
+    TAsn1Tags.OctetString:
+      begin
+        result := TDerOctetString.Create(bytes);
+        Exit;
+      end;
+    TAsn1Tags.PrintableString:
+      begin
+        result := TDerPrintableString.Create(bytes);
+        Exit;
+      end;
+    TAsn1Tags.T61String:
+      begin
+        result := TDerT61String.Create(bytes);
+        Exit;
+      end;
+    TAsn1Tags.UniversalString:
+      begin
+        result := TDerUniversalString.Create(bytes);
+        Exit;
+      end;
+    // TAsn1Tags.UtcTime:
+    // begin
+    // result := TDerUtcTime.Create(bytes);
+    // Exit;
+    // end;
+    TAsn1Tags.Utf8String:
+      begin
+        result := TDerUtf8String.Create(bytes);
+        Exit;
+      end;
+    TAsn1Tags.VideotexString:
+      begin
+        result := TDerVideotexString.Create(bytes);
+        Exit;
+      end;
+    TAsn1Tags.VisibleString:
+      begin
+        result := TDerVisibleString.Create(bytes);
+        Exit;
+      end;
+  else
+    begin
+      raise EIOCryptoLibException.CreateResFmt(@SUnknownTag, [tagNo]);
+    end;
+
+  end;
+end;
+
+destructor TAsn1InputStream.Destroy;
+begin
+  FStream.Free;
+  inherited Destroy; // dont free
+end;
+
+constructor TAsn1InputStream.Create(inputStream: TStream; limit: Int32);
+begin
+  Inherited Create(inputStream);
+  Flimit := limit;
+  System.SetLength(FtmpBuffers, 16);
+end;
+
+constructor TAsn1InputStream.Create(inputStream: TStream);
+begin
+  Create(inputStream, FindLimit(inputStream));
+end;
+
+constructor TAsn1InputStream.Create(input: TCryptoLibByteArray);
+begin
+  // used TBytesStream here for one pass creation and population with byte array :)
+  FStream := TBytesStream.Create(input);
+  Create(FStream, System.length(input));
+
+end;
+
+class function TAsn1InputStream.ReadLength(s: TStream; limit: Int32): Int32;
+var
+  &length, Size, next, I: Int32;
+begin
+
+  length := TStreamSorter.ReadByte(s);
+
+  if (length < 0) then
+  begin
+    raise EEndOfStreamCryptoLibException.CreateRes(@SInvalidEnd);
+  end;
+
+  if (length = $80) then
+  begin
+    result := -1; // indefinite-length encoding
+    Exit;
+  end;
+
+  if (length > 127) then
+  begin
+    Size := length and $7F;
+
+    // Note: The invalid long form "$ff" (see X.690 8.1.3.5c) will be caught here
+    if (Size > 4) then
+    begin
+      raise EIOCryptoLibException.CreateResFmt(@SInvalidDerLength, [Size]);
+    end;
+
+    length := 0;
+    I := 0;
+    while I < Size do
+    begin
+
+      next := TStreamSorter.ReadByte(s);
+
+      if (next < 0) then
+      begin
+        raise EEndOfStreamCryptoLibException.CreateRes(@SEndOfStream);
+      end;
+
+      length := (length shl 8) + next;
+
+      System.Inc(I);
+    end;
+
+    if (length < 0) then
+    begin
+      raise EIOCryptoLibException.CreateRes(@SNegativeLength);
+    end;
+
+    if (length >= limit) then // after all we must have read at least 1 byte
+    begin
+      raise EIOCryptoLibException.CreateRes(@SOutOfBoundsLength);
+    end;
+  end;
+
+  result := length;
+end;
+
+function TAsn1InputStream.ReadObject: IAsn1Object;
+var
+  tag, tagNo, &length: Int32;
+  isConstructed: Boolean;
+  indIn: TIndefiniteLengthInputStream;
+  sp: IAsn1StreamParser;
+begin
+
+  tag := ReadByte();
+
+  if (tag <= 0) then
+  begin
+    if (tag = 0) then
+    begin
+      raise EIOCryptoLibException.CreateRes(@SEndOfContent);
+    end;
+
+    result := Nil;
+    Exit;
+  end;
+
+  //
+  // calculate tag number
+  //
+  tagNo := ReadTagNumber(Fs, tag);
+
+  isConstructed := (tag and TAsn1Tags.Constructed) <> 0;
+
+  //
+  // calculate length
+  //
+  length := ReadLength(Fs, Flimit);
+
+  if (length < 0) then // indefinite length method
+  begin
+    if (not isConstructed) then
+    begin
+
+      raise EIOCryptoLibException.CreateRes(@SIndefiniteLength);
+
+    end;
+
+    indIn := TIndefiniteLengthInputStream.Create(Fs, Flimit);
+    sp := TAsn1StreamParser.Create(indIn, Flimit);
+
+    if ((tag and TAsn1Tags.Application) <> 0) then
+    begin
+      result := (TBerApplicationSpecificParser.Create(tagNo, sp)
+        as IBerApplicationSpecificParser).ToAsn1Object();
+      Exit;
+    end;
+
+    if ((tag and TAsn1Tags.Tagged) <> 0) then
+    begin
+      result := (TBerTaggedObjectParser.Create(true, tagNo, sp)
+        as IBerTaggedObjectParser).ToAsn1Object();
+      Exit;
+    end;
+
+    // TODO There are other tags that may be constructed (e.g. BitString)
+
+    case tagNo of
+      TAsn1Tags.OctetString:
+        begin
+          result := (TBerOctetStringParser.Create(sp) as IBerOctetStringParser)
+            .ToAsn1Object();
+          Exit;
+        end;
+      TAsn1Tags.Sequence:
+        begin
+          result := (TBerSequenceParser.Create(sp) as IBerSequenceParser)
+            .ToAsn1Object();
+          Exit;
+        end;
+      TAsn1Tags.&Set:
+        begin
+          result := (TBerSetParser.Create(sp) as IBerSetParser).ToAsn1Object();
+          Exit;
+        end;
+      TAsn1Tags.External:
+        begin
+          result := (TDerExternalParser.Create(sp) as IDerExternalParser)
+            .ToAsn1Object();
+          Exit;
+        end;
+    else
+      begin
+        raise EIOCryptoLibException.CreateRes(@SUnknownBerObject);
+      end;
+    end;
+
+  end
+  else
+  begin
+    try
+      result := BuildObject(tag, tagNo, length);
+    except
+      on e: EArgumentCryptoLibException do
+      begin
+        raise EAsn1CryptoLibException.CreateResFmt(@SCorruptedStreamTwo,
+          [e.Message]);
+      end;
+    end;
+  end;
+end;
+
+function TAsn1InputStream.BuildDerEncodableVector
+  (dIn: IDefiniteLengthInputStream): IAsn1EncodableVector;
+var
+  res: TAsn1InputStream;
+begin
+  res := TAsn1InputStream.Create(dIn as TDefiniteLengthInputStream);
+  try
+    result := res.BuildEncodableVector();
+  finally
+    res.Free;
+  end;
+end;
+
+function TAsn1InputStream.BuildEncodableVector: IAsn1EncodableVector;
+var
+  v: IAsn1EncodableVector;
+  o: IAsn1Object;
+begin
+  v := TAsn1EncodableVector.Create();
+
+  o := ReadObject();
+  while (o <> Nil) do
+  begin
+    v.Add([o]);
+    o := ReadObject();
+  end;
+
+  result := v;
+end;
+
+function TAsn1InputStream.BuildObject(tag, tagNo, length: Int32): IAsn1Object;
+var
+  isConstructed: Boolean;
+  defIn: TDefiniteLengthInputStream;
+  v: IAsn1EncodableVector;
+  strings: TList<IDerOctetString>;
+  I: Int32;
+begin
+  isConstructed := (tag and TAsn1Tags.Constructed) <> 0;
+  defIn := TDefiniteLengthInputStream.Create(Fs, length);
+
+  if ((tag and TAsn1Tags.Application) <> 0) then
+  begin
+    try
+      result := TDerApplicationSpecific.Create(isConstructed, tagNo,
+        defIn.ToArray());
+      Exit;
+    finally
+      defIn.Free;
+    end;
+  end;
+
+  if ((tag and TAsn1Tags.Tagged) <> 0) then
+  begin
+
+    result := (TAsn1StreamParser.Create(defIn) as IAsn1StreamParser)
+      .ReadTaggedObject(isConstructed, tagNo);
+    Exit;
+
+  end;
+
+  if (isConstructed) then
+  begin
+    // TODO There are other tags that may be constructed (e.g. BitString)
+    case (tagNo) of
+
+      TAsn1Tags.OctetString:
+        //
+        // yes, people actually do this...
+        //
+        begin
+          try
+            v := BuildDerEncodableVector(defIn);
+            strings := TList<IDerOctetString>.Create;
+            strings.Capacity := v.Count;
+
+            I := 0;
+            while (I <> v.Count) do
+            begin
+              strings.Add(v[I] as IDerOctetString);
+            end;
+
+            result := TBerOctetString.Create(strings);
+            Exit;
+          finally
+            defIn.Free;
+          end;
+        end;
+      TAsn1Tags.Sequence:
+        begin
+          try
+            result := CreateDerSequence(defIn);
+            Exit;
+          finally
+            defIn.Free;
+          end;
+        end;
+      TAsn1Tags.&Set:
+        begin
+          try
+            result := CreateDerSet(defIn);
+            Exit;
+          finally
+            defIn.Free;
+          end;
+        end;
+      TAsn1Tags.External:
+        begin
+          try
+            result := TDerExternal.Create(BuildDerEncodableVector(defIn));
+            Exit;
+          finally
+            defIn.Free;
+          end;
+        end;
+    else
+      begin
+        raise EIOCryptoLibException.CreateResFmt(@SUnknownTag, [tagNo]);
+      end;
+
+    end;
+
+  end;
+
+  try
+    result := CreatePrimitiveDerObject(tagNo, defIn, FtmpBuffers);
+  finally
+    defIn.Free;
+  end;
+
+end;
+
+function TAsn1InputStream.CreateDerSequence(dIn: IDefiniteLengthInputStream)
+  : IDerSequence;
+begin
+  result := TDerSequence.FromVector(BuildDerEncodableVector(dIn));
+end;
+
+function TAsn1InputStream.CreateDerSet(dIn: IDefiniteLengthInputStream)
+  : IDerSet;
+begin
+  result := TDerSet.FromVector(BuildDerEncodableVector(dIn), false);
+end;
+
+class function TAsn1InputStream.ReadTagNumber(s: TStream; tag: Int32): Int32;
+var
+  tagNo, b: Int32;
+begin
+  tagNo := tag and $1F;
+
+  //
+  // with tagged object tag number is bottom 5 bits, or stored at the start of the content
+  //
+  if (tagNo = $1F) then
+  begin
+    tagNo := 0;
+
+    b := TStreamSorter.ReadByte(s);
+
+    // X.690-0207 8.1.2.4.2
+    // "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
+    if ((b and $7F) = 0) then // Note: -1 will pass
+    begin
+      raise EIOCryptoLibException.CreateRes(@SCorruptedStream);
+    end;
+
+    while ((b >= 0) and ((b and $80) <> 0)) do
+    begin
+      tagNo := tagNo or (b and $7F);
+      tagNo := tagNo shl 7;
+
+      b := TStreamSorter.ReadByte(s);
+
+    end;
+
+    if (b < 0) then
+    begin
+      raise EEndOfStreamCryptoLibException.CreateRes(@SEOFFound);
+    end;
+    tagNo := tagNo or (b and $7F);
+  end;
+
+  result := tagNo;
+end;
+
+end.

+ 49 - 0
CryptoLib/src/Asn1/ClpAsn1Null.pas

@@ -0,0 +1,49 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpAsn1Null;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpAsn1Object,
+  ClpIAsn1Null;
+
+type
+  /// <summary>
+  /// A Null object.
+  /// </summary>
+  TAsn1Null = class abstract(TAsn1Object, IAsn1Null)
+
+  public
+
+    function ToString(): String; override;
+
+  end;
+
+implementation
+
+{ TAsn1Null }
+
+function TAsn1Null.ToString: String;
+begin
+  result := 'NULL';
+end;
+
+end.

+ 141 - 0
CryptoLib/src/Asn1/ClpAsn1Object.pas

@@ -0,0 +1,141 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpAsn1Object;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  SysUtils,
+  ClpCryptoLibTypes,
+  ClpIProxiedInterface,
+  ClpAsn1Encodable;
+
+resourcestring
+  SExtraData = 'Extra Data Found After Object';
+  SUnRecognizedObjectStream = 'Cannot Recognise Object in Stream';
+  SUnRecognizedObjectByteArray = 'Cannot Recognise Object in ByteArray';
+
+type
+
+  TAsn1Object = class abstract(TAsn1Encodable, IAsn1Object)
+
+  strict protected
+
+    function Asn1Equals(asn1Object: IAsn1Object): Boolean; virtual; abstract;
+
+    function Asn1GetHashCode(): Int32; virtual; abstract;
+
+  public
+    /// <summary>Create a base ASN.1 object from a byte array.</summary>
+    /// <param name="data">The byte array to parse.</param>
+    /// <returns>The base ASN.1 object represented by the byte array.</returns>
+    /// <exception cref="IOException">
+    /// If there is a problem parsing the data, or parsing an object did not exhaust the available data.
+    /// </exception>
+    class function FromByteArray(data: TCryptoLibByteArray)
+      : IAsn1Object; static;
+
+    /// <summary>Read a base ASN.1 object from a stream.</summary>
+    /// <param name="inStr">The stream to parse.</param>
+    /// <returns>The base ASN.1 object represented by the byte array.</returns>
+    /// <exception cref="IOException">If there is a problem parsing the data.</exception>
+    class function FromStream(inStr: TStream): IAsn1Object; static;
+
+    function ToAsn1Object(): IAsn1Object; override;
+
+    procedure Encode(derOut: IDerOutputStream); virtual; abstract;
+
+    function CallAsn1Equals(obj: IAsn1Object): Boolean;
+
+    function CallAsn1GetHashCode(): Int32;
+
+  end;
+
+implementation
+
+uses
+  // included here to avoid circular dependency :)
+  ClpAsn1InputStream;
+
+{ TAsn1Object }
+
+function TAsn1Object.CallAsn1Equals(obj: IAsn1Object): Boolean;
+begin
+  result := Asn1Equals(obj);
+end;
+
+function TAsn1Object.CallAsn1GetHashCode: Int32;
+begin
+  result := Asn1GetHashCode();
+end;
+
+class function TAsn1Object.FromByteArray(data: TCryptoLibByteArray)
+  : IAsn1Object;
+var
+  asn1: TAsn1InputStream;
+  input: TBytesStream;
+begin
+  try
+    // used TBytesStream here for one pass creation and population with byte array :)
+    input := TBytesStream.Create(data);
+    try
+
+      asn1 := TAsn1InputStream.Create(input, System.Length(data));
+
+      try
+        result := asn1.ReadObject();
+      finally
+        asn1.Free;
+      end;
+      if (input.Position <> input.Size) then
+      begin
+        raise EIOCryptoLibException.CreateRes(@SExtraData);
+      end;
+    finally
+      input.Free;
+    end;
+  except
+    raise EIOCryptoLibException.CreateRes(@SUnRecognizedObjectByteArray);
+  end;
+end;
+
+class function TAsn1Object.FromStream(inStr: TStream): IAsn1Object;
+var
+  asn1Stream: TAsn1InputStream;
+begin
+  asn1Stream := TAsn1InputStream.Create(inStr);
+  try
+    try
+      result := asn1Stream.ReadObject();
+    except
+      raise EIOCryptoLibException.CreateRes(@SUnRecognizedObjectStream);
+    end;
+  finally
+    asn1Stream.Free;
+  end;
+end;
+
+function TAsn1Object.ToAsn1Object: IAsn1Object;
+begin
+  result := Self as IAsn1Object;
+end;
+
+end.

+ 219 - 0
CryptoLib/src/Asn1/ClpAsn1OctetString.pas

@@ -0,0 +1,219 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpAsn1OctetString;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  SysUtils,
+  ClpCryptoLibTypes,
+  ClpArrayUtils,
+  ClpAsn1Object,
+  ClpIProxiedInterface,
+  ClpIAsn1OctetString,
+  ClpIAsn1TaggedObject,
+  ClpAsn1Encodable,
+  ClpAsn1Sequence,
+  ClpConverters,
+  ClpIDerOctetString,
+  ClpIAsn1OctetStringParser;
+
+resourcestring
+  SIllegalObject = 'Illegal Object in GetInstance:  %s, "obj"';
+  SStrNil = '"Str" Cannot be Nil';
+  SProcessingError = 'Error Processing Object : "%s"';
+
+type
+  TAsn1OctetString = class abstract(TAsn1Object, IAsn1OctetString,
+    IAsn1OctetStringParser)
+
+  strict private
+  var
+    FStr: TCryptoLibByteArray;
+    function GetStr: TCryptoLibByteArray; inline;
+    function GetParser: IAsn1OctetStringParser; inline;
+
+  strict protected
+    function Asn1GetHashCode(): Int32; override;
+    function Asn1Equals(asn1Object: IAsn1Object): Boolean; override;
+
+  public
+    property Str: TCryptoLibByteArray read GetStr;
+    property Parser: IAsn1OctetStringParser read GetParser;
+
+    /// <summary>
+    /// return an Octet string from a tagged object.
+    /// </summary>
+    /// <param name="obj">
+    /// the tagged object holding the object we want.
+    /// </param>
+    /// <param name="isExplicit">
+    /// explicitly true if the object is meant to be explicitly tagged false
+    /// otherwise.
+    /// </param>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the tagged object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: IAsn1TaggedObject; isExplicit: Boolean)
+      : IAsn1OctetString; overload; static;
+    /// <summary>
+    /// return an Octet string from the given object.
+    /// </summary>
+    /// <param name="obj">
+    /// the object we want converted.
+    /// </param>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: TObject): IAsn1OctetString;
+      overload; static;
+
+    /// <param name="Str">
+    /// the octets making up the octet string.
+    /// </param>
+    constructor Create(Str: TCryptoLibByteArray); overload;
+
+    constructor Create(obj: IAsn1Encodable); overload;
+
+    function GetOctetStream(): TStream;
+
+    function GetOctets(): TCryptoLibByteArray; virtual;
+
+    function ToString(): String; override;
+
+  end;
+
+implementation
+
+uses
+  ClpBerOctetString; // included here to avoid circular dependency :)
+
+{ TAsn1OctetString }
+
+constructor TAsn1OctetString.Create(Str: TCryptoLibByteArray);
+begin
+  Inherited Create();
+  if (Str = Nil) then
+  begin
+    raise EArgumentNilCryptoLibException.CreateRes(@SStrNil);
+  end;
+
+  FStr := Str;
+end;
+
+function TAsn1OctetString.Asn1Equals(asn1Object: IAsn1Object): Boolean;
+var
+  other: IDerOctetString;
+begin
+
+  if (not Supports(asn1Object, IDerOctetString, other)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  result := TArrayUtils.AreEqual(GetOctets(), other.GetOctets());
+end;
+
+function TAsn1OctetString.Asn1GetHashCode: Int32;
+begin
+  result := TArrayUtils.GetArrayHashCode(GetOctets());
+end;
+
+constructor TAsn1OctetString.Create(obj: IAsn1Encodable);
+begin
+  Inherited Create();
+  try
+    FStr := obj.GetEncoded(TAsn1Encodable.Der);
+  except
+    on e: EIOCryptoLibException do
+    begin
+      raise EArgumentCryptoLibException.CreateResFmt(@SProcessingError,
+        [e.Message]);
+    end;
+  end;
+end;
+
+class function TAsn1OctetString.GetInstance(obj: IAsn1TaggedObject;
+  isExplicit: Boolean): IAsn1OctetString;
+var
+  o: IAsn1Object;
+begin
+  o := obj.GetObject();
+
+  if ((isExplicit) or (Supports(o, IAsn1OctetString))) then
+  begin
+    result := GetInstance(o as TAsn1Object);
+    Exit;
+  end;
+
+  result := TBerOctetString.FromSequence
+    (TAsn1Sequence.GetInstance(o as TAsn1Object));
+end;
+
+class function TAsn1OctetString.GetInstance(obj: TObject): IAsn1OctetString;
+var
+  asn1TaggedObject: IAsn1TaggedObject;
+begin
+  if ((obj = Nil) or (obj is TAsn1OctetString)) then
+  begin
+    result := obj as TAsn1OctetString;
+    Exit;
+  end;
+
+  // TODO: this needs to be deleted in V2
+  if Supports(obj, IAsn1TaggedObject, asn1TaggedObject) then
+  begin
+    result := GetInstance(asn1TaggedObject.GetObject() as TAsn1Object);
+    Exit;
+  end;
+
+  raise EArgumentCryptoLibException.CreateResFmt(@SIllegalObject,
+    [obj.ClassName]);
+end;
+
+function TAsn1OctetString.GetOctets: TCryptoLibByteArray;
+begin
+  result := Str;
+end;
+
+function TAsn1OctetString.GetOctetStream: TStream;
+begin
+  // used TBytesStream here for one pass creation and population with byte array :)
+  result := TBytesStream.Create(Str);
+end;
+
+function TAsn1OctetString.GetParser: IAsn1OctetStringParser;
+begin
+  result := Self as IAsn1OctetStringParser;
+end;
+
+function TAsn1OctetString.GetStr: TCryptoLibByteArray;
+begin
+  result := FStr;
+end;
+
+function TAsn1OctetString.ToString: String;
+begin
+  result := '#' + TConverters.ConvertBytesToHexString(Str, false);
+end;
+
+end.

+ 46 - 0
CryptoLib/src/Asn1/ClpAsn1OutputStream.pas

@@ -0,0 +1,46 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpAsn1OutputStream;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpIAsn1OutputStream,
+  ClpDerOutputStream;
+
+type
+  TAsn1OutputStream = class sealed(TDerOutputStream, IAsn1OutputStream)
+
+  public
+    constructor Create(os: TStream);
+
+  end;
+
+implementation
+
+{ TAsn1OutputStream }
+
+constructor TAsn1OutputStream.Create(os: TStream);
+begin
+  Inherited Create(os);
+end;
+
+end.

+ 419 - 0
CryptoLib/src/Asn1/ClpAsn1Sequence.pas

@@ -0,0 +1,419 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpAsn1Sequence;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  Generics.Collections,
+  ClpCryptoLibTypes,
+  ClpCollectionUtilities,
+  ClpDerNull,
+  ClpIBerTaggedObject,
+  ClpAsn1TaggedObject,
+  ClpIAsn1TaggedObject,
+  ClpIAsn1Set,
+  ClpAsn1Encodable,
+  ClpIProxiedInterface,
+  ClpIAsn1SequenceParser,
+  ClpIAsn1Sequence,
+  ClpAsn1Object;
+
+resourcestring
+  SInvalidObject = 'Object Implicit - Explicit Expected.';
+  SUnknownObject = 'Unknown object in GetInstance:  %s, "obj"';
+  SInvalidSequence = '"Failed to Construct Sequence from byte array: " %s';
+
+type
+  /// <summary>
+  /// return an Asn1Sequence from the given object.
+  /// </summary>
+  TAsn1Sequence = class abstract(TAsn1Object, IAsn1Sequence)
+
+  strict private
+  var
+    FSeq: TList<IAsn1Encodable>;
+
+    function GetCount: Int32; virtual;
+    function GetParser: IAsn1SequenceParser; virtual;
+    function GetSelf(Index: Integer): IAsn1Encodable; virtual;
+    function GetCurrent(e: TEnumerator<IAsn1Encodable>): IAsn1Encodable; inline;
+
+  type
+    TAsn1SequenceParserImpl = class sealed(TInterfacedObject,
+      IAsn1SequenceParserImpl, IAsn1SequenceParser)
+
+    strict private
+    var
+      Fouter: IAsn1Sequence;
+      Fmax, Findex: Int32;
+
+    public
+      constructor Create(outer: IAsn1Sequence);
+      function ReadObject(): IAsn1Convertible;
+      function ToAsn1Object(): IAsn1Object;
+
+    end;
+
+  strict protected
+    function Asn1GetHashCode(): Int32; override;
+    function Asn1Equals(asn1Object: IAsn1Object): Boolean; override;
+    procedure AddObject(obj: IAsn1Encodable); inline;
+
+    constructor Create(capacity: Int32);
+
+  public
+
+    destructor Destroy(); override;
+
+    function ToString(): String; override;
+
+    function GetEnumerator: TEnumerator<IAsn1Encodable>; virtual;
+
+    // /**
+    // * return the object at the sequence position indicated by index.
+    // *
+    // * @param index the sequence number (starting at zero) of the object
+    // * @return the object at the sequence position indicated by index.
+    // */
+    property Self[Index: Int32]: IAsn1Encodable read GetSelf; default;
+
+    /// <summary>
+    /// return an Asn1Sequence from the given object.
+    /// </summary>
+    /// <param name="obj">
+    /// the object we want converted.
+    /// </param>
+    /// <exception cref="EArgumentCryptoLibException">
+    /// if the object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: TObject): IAsn1Sequence; overload; static;
+
+    /// <summary>
+    /// return an Asn1Sequence from the given object.
+    /// </summary>
+    /// <param name="obj">
+    /// the byte array we want converted.
+    /// </param>
+    /// <exception cref="EArgumentCryptoLibException">
+    /// if the object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: TCryptoLibByteArray): IAsn1Sequence;
+      overload; static;
+
+    // /**
+    // * Return an ASN1 sequence from a tagged object. There is a special
+    // * case here, if an object appears to have been explicitly tagged on
+    // * reading but we were expecting it to be implicitly tagged in the
+    // * normal course of events it indicates that we lost the surrounding
+    // * sequence - so we need to add it back (this will happen if the tagged
+    // * object is a sequence that contains other sequences). If you are
+    // * dealing with implicitly tagged sequences you really <b>should</b>
+    // * be using this method.
+    // *
+    // * @param obj the tagged object.
+    // * @param explicitly true if the object is meant to be explicitly tagged,
+    // *          false otherwise.
+    // * @exception ArgumentException if the tagged object cannot
+    // *          be converted.
+    // */
+    class function GetInstance(obj: IAsn1TaggedObject; explicitly: Boolean)
+      : IAsn1Sequence; overload; static;
+
+    property Parser: IAsn1SequenceParser read GetParser;
+    property Count: Int32 read GetCount;
+
+  end;
+
+implementation
+
+uses
+  // included here to avoid circular dependency :)
+  ClpBerSequence,
+  ClpDerSequence;
+
+{ TAsn1Sequence }
+
+function TAsn1Sequence.GetCurrent(e: TEnumerator<IAsn1Encodable>)
+  : IAsn1Encodable;
+var
+  encObj: IAsn1Encodable;
+begin
+  encObj := e.Current;
+
+  // unfortunately null was allowed as a substitute for DER null
+  if (encObj = Nil) then
+  begin
+    result := TDerNull.Instance;
+    Exit;
+  end;
+
+  result := encObj;
+end;
+
+procedure TAsn1Sequence.AddObject(obj: IAsn1Encodable);
+begin
+  FSeq.Add(obj);
+end;
+
+function TAsn1Sequence.Asn1Equals(asn1Object: IAsn1Object): Boolean;
+var
+  other: IAsn1Sequence;
+  s1, s2: TEnumerator<IAsn1Encodable>;
+  o1, o2: IAsn1Object;
+
+begin
+
+  if (not Supports(asn1Object, IAsn1Sequence, other)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  if (Count <> other.Count) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  s1 := GetEnumerator;
+  s2 := other.GetEnumerator;
+
+  while (s1.MoveNext() and s2.MoveNext()) do
+  begin
+    o1 := GetCurrent(s1).ToAsn1Object();
+    o2 := GetCurrent(s2).ToAsn1Object();
+
+    if (not(o1.Equals(o2))) then
+    begin
+      result := false;
+      Exit;
+    end;
+  end;
+
+  result := true;
+end;
+
+function TAsn1Sequence.Asn1GetHashCode: Int32;
+var
+  hc: Int32;
+  // o: TObject;
+  // o: IInterface;
+  o: IAsn1Encodable;
+begin
+  hc := Count;
+
+  for o in Self do
+  begin
+    hc := hc * 17;
+    if (o = Nil) then
+    begin
+      hc := hc xor TDerNull.Instance.GetHashCode();
+    end
+    else
+    begin
+      hc := hc xor o.GetHashCode();
+    end;
+  end;
+
+  result := hc;
+end;
+
+constructor TAsn1Sequence.Create(capacity: Int32);
+begin
+  inherited Create();
+  FSeq := TList<IAsn1Encodable>.Create();
+  FSeq.capacity := capacity;
+end;
+
+destructor TAsn1Sequence.Destroy;
+begin
+  FSeq.Free;
+  inherited Destroy;
+end;
+
+function TAsn1Sequence.GetCount: Int32;
+begin
+  result := FSeq.Count;
+end;
+
+function TAsn1Sequence.GetEnumerator: TEnumerator<IAsn1Encodable>;
+begin
+  result := FSeq.GetEnumerator;
+end;
+
+class function TAsn1Sequence.GetInstance(obj: TObject): IAsn1Sequence;
+var
+  primitive: IAsn1Object;
+  sequence: IAsn1Sequence;
+  res: IAsn1SequenceParser;
+begin
+  if ((obj = Nil) or (obj is TAsn1Sequence)) then
+  begin
+    result := obj as TAsn1Sequence;
+    Exit;
+  end;
+
+  if (Supports(obj, IAsn1SequenceParser, res)) then
+  begin
+    result := TAsn1Sequence.GetInstance(res.ToAsn1Object() as TAsn1Object);
+    Exit;
+
+  end;
+
+  if (obj is TAsn1Encodable) then
+  begin
+    primitive := (obj as TAsn1Encodable).ToAsn1Object();
+
+    if (Supports(primitive, IAsn1Sequence, sequence)) then
+    begin
+      result := sequence;
+      Exit;
+    end;
+  end;
+
+  raise EArgumentCryptoLibException.CreateResFmt(@SUnknownObject,
+    [obj.ClassName]);
+
+end;
+
+class function TAsn1Sequence.GetInstance(obj: TCryptoLibByteArray)
+  : IAsn1Sequence;
+begin
+  try
+    result := TAsn1Sequence.GetInstance(FromByteArray(obj) as TAsn1Object);
+  except
+    on e: EIOCryptoLibException do
+    begin
+      raise EArgumentCryptoLibException.CreateResFmt(@SInvalidSequence,
+        [e.Message]);
+    end;
+  end;
+end;
+
+class function TAsn1Sequence.GetInstance(obj: IAsn1TaggedObject;
+  explicitly: Boolean): IAsn1Sequence;
+var
+  inner: IAsn1Object;
+  sequence: IAsn1Sequence;
+begin
+  inner := obj.GetObject();
+
+  if (explicitly) then
+  begin
+    if (not(obj.IsExplicit())) then
+      raise EArgumentCryptoLibException.CreateRes(@SInvalidObject);
+
+    result := inner as IAsn1Sequence;
+    Exit;
+  end;
+
+  //
+  // constructed object which appears to be explicitly tagged
+  // when it should be implicit means we have to add the
+  // surrounding sequence.
+  //
+  if (obj.IsExplicit()) then
+  begin
+    if (Supports(obj, IBerTaggedObject)) then
+    begin
+      result := TBerSequence.Create(inner);
+      Exit;
+    end;
+
+    result := TDerSequence.Create(inner);
+    Exit;
+  end;
+
+  if (Supports(inner, IAsn1Sequence, sequence)) then
+  begin
+    result := sequence;
+    Exit;
+  end;
+  raise EArgumentCryptoLibException.CreateResFmt(@SUnknownObject,
+    [(obj as TAsn1TaggedObject).ClassName]);
+
+end;
+
+function TAsn1Sequence.GetParser: IAsn1SequenceParser;
+begin
+  result := TAsn1SequenceParserImpl.Create(Self as IAsn1Sequence);
+end;
+
+function TAsn1Sequence.GetSelf(Index: Integer): IAsn1Encodable;
+begin
+  result := FSeq[index];
+end;
+
+function TAsn1Sequence.ToString: String;
+begin
+  result := TCollectionUtilities.ToStructuredString(FSeq);
+end;
+
+{ TAsn1Sequence.TAsn1SequenceParserImpl }
+
+constructor TAsn1Sequence.TAsn1SequenceParserImpl.Create(outer: IAsn1Sequence);
+begin
+  inherited Create();
+  Fouter := outer;
+  Fmax := outer.Count;
+end;
+
+function TAsn1Sequence.TAsn1SequenceParserImpl.ReadObject: IAsn1Convertible;
+var
+  obj: IAsn1Encodable;
+  sequence: IAsn1Sequence;
+  asn1Set: IAsn1Set;
+begin
+  if (Findex = Fmax) then
+  begin
+    result := Nil;
+    Exit;
+  end;
+
+  obj := Fouter[Findex];
+  System.Inc(Findex);
+
+  if (Supports(obj, IAsn1Sequence, sequence)) then
+  begin
+    result := sequence.Parser;
+    Exit;
+  end;
+
+  if (Supports(obj, IAsn1Set, asn1Set)) then
+  begin
+    result := asn1Set.Parser;
+    Exit;
+  end;
+
+  // NB: Asn1OctetString implements Asn1OctetStringParser directly
+  // if (obj is Asn1OctetString)
+  // return ((Asn1OctetString)obj).Parser;
+
+  result := obj;
+end;
+
+function TAsn1Sequence.TAsn1SequenceParserImpl.ToAsn1Object: IAsn1Object;
+begin
+  result := Fouter;
+end;
+
+end.

+ 530 - 0
CryptoLib/src/Asn1/ClpAsn1Set.pas

@@ -0,0 +1,530 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpAsn1Set;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  Math,
+  Generics.Collections,
+  ClpCryptoLibTypes,
+  ClpCollectionUtilities,
+  ClpDerNull,
+  ClpIAsn1TaggedObject,
+  ClpIAsn1EncodableVector,
+  ClpAsn1EncodableVector,
+  ClpIAsn1Sequence,
+  ClpAsn1Encodable,
+  ClpIProxiedInterface,
+  ClpIAsn1SetParser,
+  ClpIAsn1Set,
+  ClpAsn1Object;
+
+resourcestring
+  SInvalidObject = 'Object Implicit - Explicit Expected.';
+  SUnknownObject = 'Unknown object in GetInstance:  %s, "obj"';
+  SInvalidSequence = '"Failed to Construct Sequence from byte array: " %s';
+
+type
+  /// <summary>
+  /// return an Asn1Set from the given object.
+  /// </summary>
+  TAsn1Set = class abstract(TAsn1Object, IAsn1Set)
+
+  strict private
+  var
+    F_set: TList<IAsn1Encodable>;
+    FisSorted: Boolean;
+
+    function GetCount: Int32; virtual;
+    function GetParser: IAsn1SetParser; inline;
+    function GetSelf(Index: Integer): IAsn1Encodable; virtual;
+    function GetCurrent(e: TEnumerator<IAsn1Encodable>): IAsn1Encodable; inline;
+
+    /// <summary>
+    /// return true if a &lt;= b (arrays are assumed padded with zeros).
+    /// </summary>
+    function lessThanOrEqual(a, b: TCryptoLibByteArray): Boolean; inline;
+
+  type
+    TAsn1SetParserImpl = class sealed(TInterfacedObject, IAsn1SetParserImpl,
+      IAsn1SetParser)
+
+    strict private
+      Fouter: IAsn1Set;
+      Fmax, Findex: Int32;
+
+    public
+      constructor Create(outer: IAsn1Set);
+      function ReadObject(): IAsn1Convertible;
+      function ToAsn1Object(): IAsn1Object;
+
+    end;
+
+  strict protected
+    function Asn1GetHashCode(): Int32; override;
+    function Asn1Equals(asn1Object: IAsn1Object): Boolean; override;
+    procedure AddObject(obj: IAsn1Encodable); inline;
+    procedure Sort();
+
+    constructor Create(capacity: Int32);
+
+  public
+    destructor Destroy(); override;
+
+  public
+
+    function ToString(): String; override;
+
+    function ToArray(): TCryptoLibGenericArray<IAsn1Encodable>; virtual;
+
+    function GetEnumerator: TEnumerator<IAsn1Encodable>; virtual;
+
+    // /**
+    // * return the object at the sequence position indicated by index.
+    // *
+    // * @param index the sequence number (starting at zero) of the object
+    // * @return the object at the sequence position indicated by index.
+    // */
+    property Self[Index: Int32]: IAsn1Encodable read GetSelf; default;
+
+    /// <summary>
+    /// return an ASN1Set from the given object.
+    /// </summary>
+    /// <param name="obj">
+    /// the object we want converted.
+    /// </param>
+    /// <exception cref="EArgumentCryptoLibException">
+    /// if the object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: TObject): IAsn1Set; overload; static;
+
+    /// <summary>
+    /// return an Asn1Set from the given object.
+    /// </summary>
+    /// <param name="obj">
+    /// the byte array we want converted.
+    /// </param>
+    /// <exception cref="EArgumentCryptoLibException">
+    /// if the object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: TCryptoLibByteArray): IAsn1Set;
+      overload; static;
+
+    // /**
+    // * Return an ASN1 sequence from a tagged object. There is a special
+    // * case here, if an object appears to have been explicitly tagged on
+    // * reading but we were expecting it to be implicitly tagged in the
+    // * normal course of events it indicates that we lost the surrounding
+    // * sequence - so we need to add it back (this will happen if the tagged
+    // * object is a sequence that contains other sequences). If you are
+    // * dealing with implicitly tagged sequences you really <b>should</b>
+    // * be using this method.
+    // *
+    // * @param obj the tagged object.
+    // * @param explicitly true if the object is meant to be explicitly tagged,
+    // *          false otherwise.
+    // * @exception ArgumentException if the tagged object cannot
+    // *          be converted.
+    // */
+    class function GetInstance(obj: IAsn1TaggedObject; explicitly: Boolean)
+      : IAsn1Set; overload; static;
+
+    property Parser: IAsn1SetParser read GetParser;
+    property Count: Int32 read GetCount;
+
+  end;
+
+implementation
+
+uses
+  // included here to avoid circular dependency :)
+  ClpDerSet,
+  ClpAsn1TaggedObject;
+
+{ TAsn1Set }
+
+procedure TAsn1Set.AddObject(obj: IAsn1Encodable);
+begin
+  F_set.Add(obj);
+end;
+
+function TAsn1Set.GetCurrent(e: TEnumerator<IAsn1Encodable>): IAsn1Encodable;
+var
+  encObj: IAsn1Encodable;
+begin
+  encObj := e.Current;
+
+  // unfortunately null was allowed as a substitute for DER null
+  if (encObj = Nil) then
+  begin
+    result := TDerNull.Instance;
+    Exit;
+  end;
+
+  result := encObj;
+end;
+
+function TAsn1Set.Asn1Equals(asn1Object: IAsn1Object): Boolean;
+var
+  other: IAsn1Set;
+  s1, s2: TEnumerator<IAsn1Encodable>;
+  o1, o2: IAsn1Object;
+begin
+
+  if (not Supports(asn1Object, IAsn1Set, other)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  if (Count <> other.Count) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  s1 := GetEnumerator;
+  s2 := other.GetEnumerator;
+
+  while (s1.MoveNext() and s2.MoveNext()) do
+  begin
+    o1 := GetCurrent(s1).ToAsn1Object();
+    o2 := GetCurrent(s2).ToAsn1Object();
+
+    if (not(o1.Equals(o2))) then
+    begin
+      result := false;
+      Exit;
+    end;
+  end;
+
+  result := true;
+end;
+
+function TAsn1Set.Asn1GetHashCode: Int32;
+var
+  hc: Int32;
+  o: IAsn1Encodable;
+begin
+  hc := Count;
+
+  for o in Self do
+  begin
+    hc := hc * 17;
+    if (o = Nil) then
+    begin
+      hc := hc xor TDerNull.Instance.GetHashCode();
+    end
+    else
+    begin
+      hc := hc xor o.GetHashCode();
+    end;
+  end;
+
+  result := hc;
+end;
+
+constructor TAsn1Set.Create(capacity: Int32);
+begin
+  Inherited Create();
+  F_set := TList<IAsn1Encodable>.Create();
+  F_set.capacity := capacity;
+  FisSorted := false;
+end;
+
+destructor TAsn1Set.Destroy;
+begin
+  F_set.Free;
+  inherited Destroy;
+end;
+
+function TAsn1Set.GetCount: Int32;
+begin
+  result := F_set.Count;
+end;
+
+function TAsn1Set.GetEnumerator: TEnumerator<IAsn1Encodable>;
+begin
+  result := F_set.GetEnumerator;
+end;
+
+class function TAsn1Set.GetInstance(obj: TCryptoLibByteArray): IAsn1Set;
+begin
+  try
+    result := TAsn1Set.GetInstance(FromByteArray(obj) as TAsn1Object);
+  except
+    on e: EIOCryptoLibException do
+    begin
+      raise EArgumentCryptoLibException.CreateResFmt(@SInvalidSequence,
+        [e.Message]);
+    end;
+  end;
+end;
+
+class function TAsn1Set.GetInstance(obj: IAsn1TaggedObject; explicitly: Boolean)
+  : IAsn1Set;
+var
+  inner: IAsn1Object;
+  asn1Set: IAsn1Set;
+  asn1Sequence: IAsn1Sequence;
+  v: IAsn1EncodableVector;
+  ae: IAsn1Encodable;
+begin
+  inner := obj.GetObject();
+
+  if (explicitly) then
+  begin
+    if (not(obj.IsExplicit())) then
+      raise EArgumentCryptoLibException.CreateRes(@SInvalidObject);
+
+    result := inner as IAsn1Set;
+    Exit;
+  end;
+
+  //
+  // constructed object which appears to be explicitly tagged
+  // when it should be implicit means we have to add the
+  // surrounding sequence.
+  //
+  if (obj.IsExplicit()) then
+  begin
+
+    result := TDerSet.Create(inner);
+    Exit;
+  end;
+
+  if (Supports(inner, IAsn1Set, asn1Set)) then
+  begin
+    result := asn1Set;
+    Exit;
+  end;
+  //
+  // in this case the parser returns a sequence, convert it
+  // into a set.
+  //
+
+  if (Supports(inner, IAsn1Sequence, asn1Sequence)) then
+  begin
+    v := TAsn1EncodableVector.Create();
+
+    for ae in asn1Sequence do
+    begin
+      v.Add(ae);
+    end;
+
+    // TODO Should be able to construct set directly from sequence?
+    result := TDerSet.Create(v, false);
+    Exit;
+  end;
+  raise EArgumentCryptoLibException.CreateResFmt(@SUnknownObject,
+    [(obj as TAsn1TaggedObject).ClassName]);
+
+end;
+
+class function TAsn1Set.GetInstance(obj: TObject): IAsn1Set;
+var
+  primitive: IAsn1Object;
+  asn1Set: IAsn1Set;
+  res: IAsn1SetParser;
+begin
+  if ((obj = Nil) or (obj is TAsn1Set)) then
+  begin
+    result := obj as TAsn1Set;
+    Exit;
+  end;
+
+  if (Supports(obj, IAsn1SetParser, res)) then
+  begin
+    result := TAsn1Set.GetInstance(res.ToAsn1Object() as TAsn1Object);
+    Exit;
+
+  end;
+
+  if (obj is TAsn1Encodable) then
+  begin
+    primitive := (obj as TAsn1Encodable).ToAsn1Object();
+
+    if (Supports(primitive, IAsn1Set, asn1Set)) then
+    begin
+      result := asn1Set;
+      Exit;
+    end;
+  end;
+
+  raise EArgumentCryptoLibException.CreateResFmt(@SUnknownObject,
+    [obj.ClassName]);
+
+end;
+
+function TAsn1Set.GetParser: IAsn1SetParser;
+begin
+  result := TAsn1SetParserImpl.Create(Self as IAsn1Set);
+end;
+
+function TAsn1Set.GetSelf(Index: Integer): IAsn1Encodable;
+begin
+  result := F_set[index];
+end;
+
+function TAsn1Set.lessThanOrEqual(a, b: TCryptoLibByteArray): Boolean;
+var
+  len, I: Int32;
+begin
+  len := Math.Min(System.length(a), System.length(b));
+
+  I := 0;
+  while I <> len do
+  begin
+
+    if (a[I] <> b[I]) then
+    begin
+
+      result := (a[I]) < (b[I]);
+      Exit;
+    end;
+    System.Inc(I);
+  end;
+
+  result := len = System.length(a);
+end;
+
+procedure TAsn1Set.Sort;
+var
+  swapped: Boolean;
+  lastSwap, Index, swapIndex: Int32;
+  a, b: TCryptoLibByteArray;
+  temp: IAsn1Encodable;
+
+begin
+  if (not FisSorted) then
+  begin
+    FisSorted := true;
+    if (F_set.Count > 1) then
+    begin
+      swapped := true;
+      lastSwap := F_set.Count - 1;
+
+      while (swapped) do
+      begin
+        index := 0;
+        swapIndex := 0;
+        a := F_set[0].GetEncoded(TAsn1Encodable.Der);
+
+        swapped := false;
+
+        while (index <> lastSwap) do
+        begin
+          b := F_set[index + 1].GetEncoded(TAsn1Encodable.Der);
+
+          if (lessThanOrEqual(a, b)) then
+          begin
+            a := b;
+          end
+          else
+          begin
+            temp := F_set[index];
+            // review being picky for copy
+            // temp := System.Copy(F_set.List, Index, 1)[0];
+            F_set[index] := F_set[index + 1];
+            F_set[index + 1] := temp;
+
+            swapped := true;
+            swapIndex := index;
+          end;
+
+          System.Inc(index);
+        end;
+
+        lastSwap := swapIndex;
+      end;
+    end;
+  end;
+end;
+
+function TAsn1Set.ToArray: TCryptoLibGenericArray<IAsn1Encodable>;
+var
+  values: TCryptoLibGenericArray<IAsn1Encodable>;
+  I: Int32;
+begin
+  System.SetLength(values, Count);
+  for I := 0 to System.Pred(Count) do
+  begin
+    values[I] := Self[I];
+  end;
+
+  result := values;
+end;
+
+function TAsn1Set.ToString: String;
+begin
+  result := TCollectionUtilities.ToStructuredString(F_set);
+end;
+
+{ TAsn1Set.TAsn1SetParserImpl }
+
+constructor TAsn1Set.TAsn1SetParserImpl.Create(outer: IAsn1Set);
+begin
+  Inherited Create();
+  Fouter := outer;
+  Fmax := outer.Count;
+end;
+
+function TAsn1Set.TAsn1SetParserImpl.ReadObject: IAsn1Convertible;
+var
+  obj: IAsn1Encodable;
+  sequence: IAsn1Sequence;
+  asn1Set: IAsn1Set;
+begin
+  if (Findex = Fmax) then
+  begin
+    result := Nil;
+    Exit;
+  end;
+
+  obj := Fouter[Findex];
+  System.Inc(Findex);
+
+  if (Supports(obj, IAsn1Sequence, sequence)) then
+  begin
+    result := sequence.Parser;
+    Exit;
+  end;
+
+  if (Supports(obj, IAsn1Set, asn1Set)) then
+  begin
+    result := asn1Set.Parser;
+    Exit;
+  end;
+
+  // NB: Asn1OctetString implements Asn1OctetStringParser directly
+  // if (obj is Asn1OctetString)
+  // return ((Asn1OctetString)obj).Parser;
+
+  result := obj;
+end;
+
+function TAsn1Set.TAsn1SetParserImpl.ToAsn1Object: IAsn1Object;
+begin
+  result := Fouter;
+end;
+
+end.

+ 456 - 0
CryptoLib/src/Asn1/ClpAsn1StreamParser.pas

@@ -0,0 +1,456 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpAsn1StreamParser;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpCryptoLibTypes,
+  ClpIProxiedInterface,
+  ClpAsn1Tags,
+  ClpIndefiniteLengthInputStream,
+  ClpDerExternalParser,
+  ClpBerOctetStringParser,
+  ClpBerSequenceParser,
+  ClpBerSetParser,
+  ClpBerSequence,
+  ClpBerApplicationSpecificParser,
+  ClpDerSetParser,
+  ClpDerSequenceParser,
+  ClpDerOctetStringParser,
+  ClpDerOctetString,
+  ClpBerTaggedObject,
+  ClpBerTaggedObjectParser,
+  ClpDefiniteLengthInputStream,
+  ClpDerTaggedObject,
+  ClpDerSequence,
+  ClpDerApplicationSpecific,
+  ClpAsn1EncodableVector,
+  ClpIAsn1EncodableVector,
+  ClpIAsn1StreamParser;
+
+resourcestring
+  SUnknownObject = 'Unknown BER Object Encountered: $%x';
+  SIndefiniteLength = 'Indefinite Length Primitive Encoding Encountered';
+  SImplicitTagging = 'Implicit Tagging not Implemented';
+  SUnConstructedEncoding =
+    'Sequences Must Use Constructed Encoding (see X.690 8.9.1/8.10.1)';
+  SUnConstructedEncoding2 =
+    'Sets Must Use Constructed Encoding (see X.690 8.11.1/8.12.1)';
+  SUnknownTag = 'Unknown Tag " %d " Encountered';
+  SCorruptedStream = 'Corrupted Stream Detected: %s';
+
+type
+  TAsn1StreamParser = class(TInterfacedObject, IAsn1StreamParser)
+
+  strict private
+  var
+    F_in: TStream;
+    F_limit: Int32;
+    FtmpBuffers: TCryptoLibMatrixGenericArray<Byte>;
+
+    procedure Set00Check(enabled: Boolean); inline;
+
+  public
+    constructor Create(inStream: TStream); overload;
+    constructor Create(inStream: TStream; limit: Int32); overload;
+    constructor Create(encoding: TCryptoLibByteArray); overload;
+
+    destructor Destroy; override;
+
+    function ReadIndef(tagValue: Int32): IAsn1Convertible;
+    function ReadImplicit(constructed: Boolean; tag: Int32): IAsn1Convertible;
+
+    function ReadTaggedObject(constructed: Boolean; tag: Int32): IAsn1Object;
+
+    function ReadObject(): IAsn1Convertible; virtual;
+
+    function ReadVector(): IAsn1EncodableVector; inline;
+  end;
+
+implementation
+
+uses
+  ClpStreamSorter,
+  ClpAsn1InputStream; // included here to avoid circular dependency :)
+
+{ TAsn1StreamParser }
+
+procedure TAsn1StreamParser.Set00Check(enabled: Boolean);
+var
+  indefiniteLengthInputStream: TIndefiniteLengthInputStream;
+begin
+  if (F_in is TIndefiniteLengthInputStream) then
+  begin
+    indefiniteLengthInputStream := F_in as TIndefiniteLengthInputStream;
+    indefiniteLengthInputStream.SetEofOn00(enabled);
+  end;
+end;
+
+constructor TAsn1StreamParser.Create(inStream: TStream);
+begin
+  Create(inStream, TAsn1InputStream.FindLimit(inStream));
+end;
+
+constructor TAsn1StreamParser.Create(inStream: TStream; limit: Int32);
+begin
+  Inherited Create();
+  F_in := inStream;
+  F_limit := limit;
+  System.SetLength(FtmpBuffers, 16);
+end;
+
+constructor TAsn1StreamParser.Create(encoding: TCryptoLibByteArray);
+begin
+  // used TBytesStream here for one pass creation and population with byte array :)
+  Create(TBytesStream.Create(encoding), System.Length(encoding));
+
+end;
+
+destructor TAsn1StreamParser.Destroy;
+begin
+  F_in.Free;
+  inherited Destroy;
+end;
+
+function TAsn1StreamParser.ReadVector: IAsn1EncodableVector;
+var
+  v: IAsn1EncodableVector;
+  obj: IAsn1Convertible;
+begin
+  v := TAsn1EncodableVector.Create();
+
+  obj := ReadObject();
+  while (obj <> Nil) do
+  begin
+    v.Add([obj.ToAsn1Object()]);
+    obj := ReadObject();
+  end;
+
+  result := v;
+end;
+
+function TAsn1StreamParser.ReadImplicit(constructed: Boolean; tag: Int32)
+  : IAsn1Convertible;
+begin
+  if (F_in is TIndefiniteLengthInputStream) then
+  begin
+    if (not constructed) then
+    begin
+      raise EIOCryptoLibException.CreateRes(@SIndefiniteLength);
+    end;
+
+    result := ReadIndef(tag);
+    Exit;
+  end;
+
+  if (constructed) then
+  begin
+    case tag of
+
+      TAsn1Tags.&Set:
+        begin
+          result := TDerSetParser.Create(Self as IAsn1StreamParser);
+          Exit;
+        end;
+      TAsn1Tags.Sequence:
+        begin
+          result := TDerSequenceParser.Create(Self as IAsn1StreamParser);
+          Exit;
+        end;
+      TAsn1Tags.OctetString:
+        begin
+          result := TBerOctetStringParser.Create(Self as IAsn1StreamParser);
+          Exit;
+        end;
+
+    end;
+  end
+  else
+  begin
+    case tag of
+
+      TAsn1Tags.&Set:
+        begin
+          raise EAsn1CryptoLibException.CreateRes(@SUnConstructedEncoding);
+        end;
+      TAsn1Tags.Sequence:
+        begin
+          raise EAsn1CryptoLibException.CreateRes(@SUnConstructedEncoding2);
+        end;
+      TAsn1Tags.OctetString:
+        begin
+          result := TDerOctetStringParser.Create
+            (F_in as TDefiniteLengthInputStream);
+          Exit;
+        end;
+    end;
+
+  end;
+
+  raise EAsn1CryptoLibException.CreateRes(@SImplicitTagging);
+
+end;
+
+function TAsn1StreamParser.ReadIndef(tagValue: Int32): IAsn1Convertible;
+begin
+  // Note: INDEF => CONSTRUCTED
+
+  // TODO There are other tags that may be constructed (e.g. BIT_STRING)
+  case tagValue of
+    TAsn1Tags.External:
+      begin
+        result := TDerExternalParser.Create(Self as IAsn1StreamParser);
+        Exit;
+      end;
+
+    TAsn1Tags.OctetString:
+      begin
+        result := TBerOctetStringParser.Create(Self as IAsn1StreamParser);
+        Exit;
+      end;
+
+    TAsn1Tags.Sequence:
+      begin
+        result := TBerSequenceParser.Create(Self as IAsn1StreamParser);
+        Exit;
+      end;
+
+    TAsn1Tags.&Set:
+      begin
+        result := TBerSetParser.Create(Self as IAsn1StreamParser);
+        Exit;
+      end;
+
+  else
+    begin
+      raise EAsn1CryptoLibException.CreateResFmt(@SUnknownObject, [tagValue]);
+    end;
+
+  end;
+end;
+
+function TAsn1StreamParser.ReadObject: IAsn1Convertible;
+var
+  tag, tagNo, &length: Int32;
+  isConstructed: Boolean;
+  indIn: TIndefiniteLengthInputStream;
+  sp: IAsn1StreamParser;
+  defIn: TDefiniteLengthInputStream;
+begin
+  tag := TStreamSorter.ReadByte(F_in);
+
+  if (tag = -1) then
+  begin
+    result := Nil;
+    Exit;
+  end;
+
+  // turn off looking for "00" while we resolve the tag
+  Set00Check(false);
+
+  //
+  // calculate tag number
+  //
+  tagNo := TAsn1InputStream.ReadTagNumber(F_in, tag);
+
+  isConstructed := (tag and TAsn1Tags.constructed) <> 0;
+
+  //
+  // calculate length
+  //
+  Length := TAsn1InputStream.ReadLength(F_in, F_limit);
+
+  if (Length < 0) then // indefinite length method
+  begin
+    if (not isConstructed) then
+    begin
+      raise EIOCryptoLibException.CreateRes(@SIndefiniteLength);
+    end;
+
+    indIn := TIndefiniteLengthInputStream.Create(F_in, F_limit);
+
+    sp := TAsn1StreamParser.Create(indIn, F_limit);
+
+    if ((tag and TAsn1Tags.Application) <> 0) then
+    begin
+
+      result := TBerApplicationSpecificParser.Create(tagNo, sp);
+      Exit;
+
+    end;
+
+    if ((tag and TAsn1Tags.Tagged) <> 0) then
+    begin
+
+      result := TBerTaggedObjectParser.Create(true, tagNo, sp);
+      Exit;
+
+    end;
+
+    result := sp.ReadIndef(tagNo);
+    Exit;
+
+  end;
+
+  defIn := TDefiniteLengthInputStream.Create(F_in, Length);
+
+  if ((tag and TAsn1Tags.Application) <> 0) then
+  begin
+    try
+      result := TDerApplicationSpecific.Create(isConstructed, tagNo,
+        defIn.ToArray());
+      Exit;
+    finally
+      defIn.Free;
+    end;
+  end;
+
+  if ((tag and TAsn1Tags.Tagged) <> 0) then
+  begin
+    result := TBerTaggedObjectParser.Create(isConstructed, tagNo,
+      TAsn1StreamParser.Create(defIn));
+    Exit;
+
+  end;
+
+  if (isConstructed) then
+  begin
+    // TODO There are other tags that may be constructed (e.g. BitString)
+    case tagNo of
+
+      TAsn1Tags.OctetString:
+        begin
+          //
+          // yes, people actually do this...
+          //
+
+          result := TBerOctetStringParser.Create
+            (TAsn1StreamParser.Create(defIn));
+          Exit;
+
+        end;
+      TAsn1Tags.Sequence:
+        begin
+
+          result := TDerSequenceParser.Create(TAsn1StreamParser.Create(defIn));
+          Exit;
+
+        end;
+      TAsn1Tags.&Set:
+        begin
+
+          result := TDerSetParser.Create(TAsn1StreamParser.Create(defIn));
+          Exit;
+
+        end;
+
+      TAsn1Tags.External:
+        begin
+
+          result := TDerExternalParser.Create(TAsn1StreamParser.Create(defIn));
+          Exit;
+
+        end;
+    else
+      begin
+        raise EIOCryptoLibException.CreateResFmt(@SUnknownTag, [tagNo]);
+      end;
+
+    end;
+  end;
+
+  // Some primitive encodings can be handled by parsers too...
+  case tagNo of
+    TAsn1Tags.OctetString:
+      begin
+        result := TDerOctetStringParser.Create(defIn);
+        Exit;
+      end;
+  end;
+
+  try
+    try
+      result := TAsn1InputStream.CreatePrimitiveDerObject(tagNo, defIn,
+        FtmpBuffers);
+      Exit;
+
+    except
+
+      on e: EArgumentCryptoLibException do
+      begin
+        raise EAsn1CryptoLibException.CreateResFmt(@SCorruptedStream,
+          [e.Message]);
+      end;
+
+    end;
+  finally
+    defIn.Free;
+  end;
+
+end;
+
+function TAsn1StreamParser.ReadTaggedObject(constructed: Boolean; tag: Int32)
+  : IAsn1Object;
+var
+  defIn: TDefiniteLengthInputStream;
+  v: IAsn1EncodableVector;
+begin
+  if (not constructed) then
+  begin
+    // Note: !CONSTRUCTED => IMPLICIT
+    defIn := F_in as TDefiniteLengthInputStream;
+    result := TDerTaggedObject.Create(false, tag,
+      TDerOctetString.Create(defIn.ToArray()));
+    Exit;
+  end;
+
+  v := ReadVector();
+
+  if (F_in is TIndefiniteLengthInputStream) then
+  begin
+    if v.Count = 1 then
+    begin
+      result := TBerTaggedObject.Create(true, tag, v[0]);
+      Exit;
+    end
+    else
+    begin
+      result := TBerTaggedObject.Create(false, tag, TBerSequence.FromVector(v));
+      Exit;
+    end;
+
+  end;
+
+  if v.Count = 1 then
+  begin
+    result := TDerTaggedObject.Create(true, tag, v[0]);
+    Exit;
+  end
+  else
+  begin
+    result := TDerTaggedObject.Create(false, tag, TDerSequence.FromVector(v));
+    Exit;
+  end;
+
+end;
+
+end.

+ 308 - 0
CryptoLib/src/Asn1/ClpAsn1TaggedObject.pas

@@ -0,0 +1,308 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpAsn1TaggedObject;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpCryptoLibTypes,
+  ClpIAsn1Sequence,
+  ClpAsn1Tags,
+  ClpAsn1Set,
+  ClpIAsn1Set,
+  ClpIAsn1Choice,
+  ClpAsn1Encodable,
+  ClpAsn1Object,
+  ClpIProxiedInterface,
+  ClpIAsn1TaggedObject,
+  ClpIAsn1TaggedObjectParser;
+
+resourcestring
+  SImplicitObject = 'Implicitly Tagged Object';
+  SUnknownObject = 'Unknown object in GetInstance: %s  "obj"';
+  SImplicitTag = 'Implicit Tagging for Tag:  %d';
+
+type
+  /// **
+  // * ASN.1 TaggedObject - in ASN.1 notation this is any object preceded by
+  // * a [n] where n is some number - these are assumed to follow the construction
+  // * rules (as with sequences).
+  // */
+  TAsn1TaggedObject = class abstract(TAsn1Object, IAsn1TaggedObject,
+    IAsn1TaggedObjectParser)
+
+  strict private
+    FtagNo: Int32;
+    Fexplicitly: Boolean;
+    Fobj: IAsn1Encodable;
+
+    function GetTagNo: Int32; inline;
+    function Getexplicitly: Boolean; inline;
+    function Getobj: IAsn1Encodable; inline;
+
+  strict protected
+    // /**
+    // * @param tagNo the tag number for this object.
+    // * @param obj the tagged object.
+    // */
+    constructor Create(tagNo: Int32; obj: IAsn1Encodable); overload;
+    // /**
+    // * @param explicitly true if the object is explicitly tagged.
+    // * @param tagNo the tag number for this object.
+    // * @param obj the tagged object.
+    // */
+    constructor Create(explicitly: Boolean; tagNo: Int32;
+      obj: IAsn1Encodable); overload;
+
+    function Asn1Equals(asn1Object: IAsn1Object): Boolean; override;
+
+    function Asn1GetHashCode(): Int32; override;
+
+  public
+    class function IsConstructed(isExplicit: Boolean; obj: IAsn1Object)
+      : Boolean; static;
+    class function GetInstance(obj: IAsn1TaggedObject; explicitly: Boolean)
+      : IAsn1TaggedObject; overload; static; inline;
+    class function GetInstance(obj: TObject): IAsn1TaggedObject; overload;
+      static; inline;
+
+    property tagNo: Int32 read GetTagNo;
+    property explicitly: Boolean read Getexplicitly;
+    property obj: IAsn1Encodable read Getobj;
+
+    // /**
+    // * return whether or not the object may be explicitly tagged.
+    // * <p>
+    // * Note: if the object has been read from an input stream, the only
+    // * time you can be sure if isExplicit is returning the true state of
+    // * affairs is if it returns false. An implicitly tagged object may appear
+    // * to be explicitly tagged, so you need to understand the context under
+    // * which the reading was done as well, see GetObject below.</p>
+    // */
+
+    function isExplicit(): Boolean; inline;
+
+    function IsEmpty(): Boolean; inline;
+    // /**
+    // * return whatever was following the tag.
+    // * <p>
+    // * Note: tagged objects are generally context dependent if you're
+    // * trying to extract a tagged object you should be going via the
+    // * appropriate GetInstance method.</p>
+    // */
+    function GetObject(): IAsn1Object; inline;
+    // /**
+    // * Return the object held in this tagged object as a parser assuming it has
+    // * the type of the passed in tag. If the object doesn't have a parser
+    // * associated with it, the base object is returned.
+    // */
+    function GetObjectParser(tag: Int32; isExplicit: Boolean): IAsn1Convertible;
+
+    function ToString(): String; override;
+
+  end;
+
+implementation
+
+uses
+  // included here to avoid circular dependency :)
+  ClpAsn1Sequence,
+  ClpAsn1OctetString;
+
+{ TAsn1TaggedObject }
+
+function TAsn1TaggedObject.GetObject: IAsn1Object;
+begin
+  if (Fobj <> Nil) then
+  begin
+    result := Fobj.ToAsn1Object();
+    Exit;
+  end;
+
+  result := Nil;
+end;
+
+function TAsn1TaggedObject.Asn1Equals(asn1Object: IAsn1Object): Boolean;
+var
+  other: IAsn1TaggedObject;
+begin
+
+  if (not Supports(asn1Object, IAsn1TaggedObject, other)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  result := ((tagNo = other.tagNo) and
+    // TODO Should this be part of equality?
+    (explicitly = other.explicitly)) and
+    (GetObject().Equals(other.GetObject()));
+end;
+
+function TAsn1TaggedObject.Asn1GetHashCode: Int32;
+var
+  code: Int32;
+begin
+  code := Abs(tagNo);
+
+  // TODO: actually this is wrong - the problem is that a re-encoded
+  // object may end up with a different hashCode due to implicit
+  // tagging. As implicit tagging is ambiguous if a sequence is involved
+  // it seems the only correct method for both equals and hashCode is to
+  // compare the encodings...
+  // code := code xor explicitly.GetHashCode();
+
+  if (Fobj <> Nil) then
+  begin
+    code := code xor Fobj.GetHashCode();
+  end;
+
+  result := code;
+end;
+
+constructor TAsn1TaggedObject.Create(tagNo: Int32; obj: IAsn1Encodable);
+begin
+  Inherited Create();
+  Fexplicitly := true;
+  FtagNo := tagNo;
+  Fobj := obj;
+end;
+
+constructor TAsn1TaggedObject.Create(explicitly: Boolean; tagNo: Int32;
+  obj: IAsn1Encodable);
+begin
+  Inherited Create();
+  // IAsn1Choice marker interface 'insists' on explicit tagging
+  Fexplicitly := explicitly or (Supports(obj, IAsn1Choice));
+  FtagNo := tagNo;
+  Fobj := obj;
+end;
+
+function TAsn1TaggedObject.Getexplicitly: Boolean;
+begin
+  result := Fexplicitly;
+end;
+
+class function TAsn1TaggedObject.GetInstance(obj: TObject): IAsn1TaggedObject;
+begin
+  if ((obj = Nil) or (obj is TAsn1TaggedObject)) then
+  begin
+    result := obj as TAsn1TaggedObject;
+    Exit;
+  end;
+
+  raise EArgumentCryptoLibException.CreateResFmt(@SUnknownObject,
+    [obj.ClassName]);
+end;
+
+function TAsn1TaggedObject.Getobj: IAsn1Encodable;
+begin
+  result := Fobj;
+end;
+
+class function TAsn1TaggedObject.GetInstance(obj: IAsn1TaggedObject;
+  explicitly: Boolean): IAsn1TaggedObject;
+begin
+  if (explicitly) then
+  begin
+    result := obj.GetObject() as IAsn1TaggedObject;
+    Exit;
+  end;
+
+  raise EArgumentCryptoLibException.CreateRes(@SImplicitObject);
+end;
+
+function TAsn1TaggedObject.GetObjectParser(tag: Int32; isExplicit: Boolean)
+  : IAsn1Convertible;
+begin
+  case tag of
+
+    TAsn1Tags.&Set:
+      begin
+        result := TAsn1Set.GetInstance(Self as IAsn1TaggedObject,
+          isExplicit).Parser;
+        Exit;
+      end;
+    TAsn1Tags.Sequence:
+      begin
+        result := TAsn1Sequence.GetInstance(Self as IAsn1TaggedObject,
+          isExplicit).Parser;
+        Exit;
+      end;
+    TAsn1Tags.OctetString:
+      begin
+        result := TAsn1OctetString.GetInstance(Self as IAsn1TaggedObject,
+          isExplicit).Parser;
+        Exit;
+      end;
+  end;
+
+  if (isExplicit) then
+  begin
+    result := GetObject();
+    Exit;
+  end;
+
+  raise ENotImplementedCryptoLibException.CreateResFmt(@SImplicitTag, [tag]);
+
+end;
+
+function TAsn1TaggedObject.GetTagNo: Int32;
+begin
+  result := FtagNo;
+end;
+
+class function TAsn1TaggedObject.IsConstructed(isExplicit: Boolean;
+  obj: IAsn1Object): Boolean;
+var
+  tagged: IAsn1TaggedObject;
+begin
+  if ((isExplicit) or (Supports(obj, IAsn1Sequence)) or
+    (Supports(obj, IAsn1Set))) then
+  begin
+    result := true;
+    Exit;
+  end;
+
+  if (not Supports(obj, IAsn1TaggedObject, tagged)) then
+  begin
+    result := false;
+    Exit;
+  end;
+  result := IsConstructed(tagged.isExplicit(), tagged.GetObject());
+end;
+
+function TAsn1TaggedObject.IsEmpty: Boolean;
+begin
+  result := false; // empty;
+end;
+
+function TAsn1TaggedObject.isExplicit: Boolean;
+begin
+  result := Fexplicitly;
+end;
+
+function TAsn1TaggedObject.ToString: String;
+begin
+  result := '[' + IntToStr(tagNo) + ']' + (Fobj as TAsn1Encodable).ClassName;
+end;
+
+end.

+ 64 - 0
CryptoLib/src/Asn1/ClpAsn1Tags.pas

@@ -0,0 +1,64 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpAsn1Tags;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+type
+  TAsn1Tags = class sealed(TObject)
+
+  public
+
+    const
+    &Boolean = Int32($01);
+    &Integer = Int32($02);
+    BitString = Int32($03);
+    OctetString = Int32($04);
+    Null = Int32($05);
+    ObjectIdentifier = Int32($06);
+    &External = Int32($08);
+    Enumerated = Int32($0A);
+    Sequence = Int32($10);
+    SequenceOf = Int32($10); // for completeness
+    &Set = Int32($11);
+    SetOf = Int32($11); // for completeness
+
+    NumericString = Int32($12);
+    PrintableString = Int32($13);
+    T61String = Int32($14);
+    VideotexString = Int32($15);
+    IA5String = Int32($16);
+    UtcTime = Int32($17);
+    GeneralizedTime = Int32($18);
+    GraphicString = Int32($19);
+    VisibleString = Int32($1A);
+    GeneralString = Int32($1B);
+    UniversalString = Int32($1C);
+    BmpString = Int32($1E);
+    Utf8String = Int32($0C);
+
+    Constructed = Int32($20);
+    Application = Int32($40);
+    Tagged = Int32($80);
+  end;
+
+implementation
+
+end.

+ 48 - 0
CryptoLib/src/Asn1/ClpBerApplicationSpecific.pas

@@ -0,0 +1,48 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpBerApplicationSpecific;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIAsn1EncodableVector,
+  ClpIBerApplicationSpecific,
+  ClpDerApplicationSpecific;
+
+type
+  TBerApplicationSpecific = class(TDerApplicationSpecific,
+    IBerApplicationSpecific)
+
+  public
+    constructor Create(tagNo: Int32; vec: IAsn1EncodableVector);
+
+  end;
+
+implementation
+
+{ TBerApplicationSpecific }
+
+constructor TBerApplicationSpecific.Create(tagNo: Int32;
+  vec: IAsn1EncodableVector);
+begin
+  inherited Create(tagNo, vec);
+end;
+
+end.

+ 70 - 0
CryptoLib/src/Asn1/ClpBerApplicationSpecificParser.pas

@@ -0,0 +1,70 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpBerApplicationSpecificParser;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIAsn1StreamParser,
+  ClpBerApplicationSpecific,
+  ClpIBerApplicationSpecificParser,
+  ClpIAsn1ApplicationSpecificParser,
+  ClpIProxiedInterface;
+
+type
+  TBerApplicationSpecificParser = class(TInterfacedObject,
+    IAsn1ApplicationSpecificParser, IAsn1Convertible,
+    IBerApplicationSpecificParser)
+
+  strict private
+  var
+    F_tag: Int32;
+    F_parser: IAsn1StreamParser;
+
+  public
+
+    constructor Create(tag: Int32; parser: IAsn1StreamParser);
+    function ReadObject(): IAsn1Convertible; inline;
+    function ToAsn1Object(): IAsn1Object; inline;
+
+  end;
+
+implementation
+
+{ TBerApplicationSpecificParser }
+
+constructor TBerApplicationSpecificParser.Create(tag: Int32;
+  parser: IAsn1StreamParser);
+begin
+  F_tag := tag;
+  F_parser := parser;
+end;
+
+function TBerApplicationSpecificParser.ReadObject: IAsn1Convertible;
+begin
+  result := F_parser.ReadObject();
+end;
+
+function TBerApplicationSpecificParser.ToAsn1Object: IAsn1Object;
+begin
+  result := TBerApplicationSpecific.Create(F_tag, F_parser.ReadVector());
+end;
+
+end.

+ 84 - 0
CryptoLib/src/Asn1/ClpBerBitString.pas

@@ -0,0 +1,84 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpBerBitString;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpCryptoLibTypes,
+  ClpIProxiedInterface,
+  ClpDerBitString,
+  ClpIBerBitString,
+  ClpIAsn1OutputStream,
+  ClpIBerOutputStream,
+  ClpAsn1Tags;
+
+type
+  TBerBitString = class(TDerBitString, IBerBitString)
+
+  public
+    constructor Create(data: TCryptoLibByteArray; padBits: Int32); overload;
+    constructor Create(data: TCryptoLibByteArray); overload;
+    constructor Create(namedBits: Int32); overload;
+    constructor Create(obj: IAsn1Encodable); overload;
+
+    procedure Encode(derOut: IDerOutputStream); override;
+
+  end;
+
+implementation
+
+{ TBerBitString }
+
+constructor TBerBitString.Create(data: TCryptoLibByteArray);
+begin
+  Inherited Create(data);
+end;
+
+constructor TBerBitString.Create(data: TCryptoLibByteArray; padBits: Int32);
+begin
+  Inherited Create(data, padBits);
+end;
+
+constructor TBerBitString.Create(obj: IAsn1Encodable);
+begin
+  Inherited Create(obj);
+end;
+
+constructor TBerBitString.Create(namedBits: Int32);
+begin
+  Inherited Create(namedBits);
+end;
+
+procedure TBerBitString.Encode(derOut: IDerOutputStream);
+begin
+  if ((Supports(derOut, IAsn1OutputStream)) or
+    (Supports(derOut, IBerOutputStream))) then
+  begin
+    derOut.WriteEncoded(TAsn1Tags.BitString, Byte(mPadBits), mData);
+  end
+  else
+  begin
+    Inherited Encode(derOut);
+  end;
+end;
+
+end.

+ 155 - 0
CryptoLib/src/Asn1/ClpBerGenerator.pas

@@ -0,0 +1,155 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpBerGenerator;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpStreams,
+  ClpStreamHelper,
+  ClpIProxiedInterface,
+  ClpAsn1Tags,
+  ClpAsn1Generator,
+  ClpBerOutputStream,
+  ClpIBerOutputStream,
+  ClpIBerGenerator;
+
+type
+  TBerGenerator = class abstract(TAsn1Generator, IBerGenerator)
+
+  strict private
+  var
+    F_tagged, F_isExplicit: Boolean;
+    F_tagNo: Int32;
+
+    procedure WriteHdr(tag: Int32);
+
+  strict protected
+    constructor Create(outStream: TStream); overload;
+    constructor Create(outStream: TStream; tagNo: Int32;
+      isExplicit: Boolean); overload;
+
+    procedure WriteBerHeader(tag: Int32);
+    procedure WriteBerBody(contentStream: TStream);
+    procedure WriteBerEnd();
+
+  public
+    procedure AddObject(obj: IAsn1Encodable); override;
+    function GetRawOutputStream(): TStream; override;
+    procedure Close(); override;
+
+  end;
+
+implementation
+
+{ TBerGenerator }
+
+constructor TBerGenerator.Create(outStream: TStream);
+begin
+  Inherited Create(outStream);
+end;
+
+procedure TBerGenerator.AddObject(obj: IAsn1Encodable);
+var
+  temp: TBerOutputStream;
+begin
+  temp := TBerOutputStream.Create(&Out);
+  try
+    temp.WriteObject(obj);
+  finally
+    temp.Free;
+  end;
+end;
+
+procedure TBerGenerator.Close;
+begin
+  WriteBerEnd();
+end;
+
+constructor TBerGenerator.Create(outStream: TStream; tagNo: Int32;
+  isExplicit: Boolean);
+begin
+  Inherited Create(outStream);
+  F_tagged := true;
+  F_isExplicit := isExplicit;
+  F_tagNo := tagNo;
+end;
+
+function TBerGenerator.GetRawOutputStream: TStream;
+begin
+  result := &Out;
+end;
+
+procedure TBerGenerator.WriteBerBody(contentStream: TStream);
+begin
+  TStreams.PipeAll(contentStream, &Out);
+end;
+
+procedure TBerGenerator.WriteBerEnd;
+begin
+  &Out.WriteByte($00);
+  &Out.WriteByte($00);
+
+  if (F_tagged and F_isExplicit) then // write extra end for tag header
+  begin
+    &Out.WriteByte($00);
+    &Out.WriteByte($00);
+  end;
+end;
+
+procedure TBerGenerator.WriteBerHeader(tag: Int32);
+var
+  tagNum: Int32;
+begin
+  if (F_tagged) then
+  begin
+    tagNum := F_tagNo or TAsn1Tags.Tagged;
+
+    if (F_isExplicit) then
+    begin
+      WriteHdr(tagNum or TAsn1Tags.Constructed);
+      WriteHdr(tag);
+    end
+    else
+    begin
+      if ((tag and TAsn1Tags.Constructed) <> 0) then
+      begin
+        WriteHdr(tagNum or TAsn1Tags.Constructed);
+      end
+      else
+      begin
+        WriteHdr(tagNum);
+      end;
+    end
+  end
+  else
+  begin
+    WriteHdr(tag);
+  end;
+end;
+
+procedure TBerGenerator.WriteHdr(tag: Int32);
+begin
+  &Out.WriteByte(Byte(tag));
+  &Out.WriteByte($80);
+end;
+
+end.

+ 92 - 0
CryptoLib/src/Asn1/ClpBerNull.pas

@@ -0,0 +1,92 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpBerNull;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpAsn1Tags,
+  ClpIProxiedInterface,
+  ClpIBerOutputStream,
+  ClpIAsn1OutputStream,
+  ClpDerNull,
+  ClpIBerNull;
+
+type
+
+  /// <summary>
+  /// A BER Null object.
+  /// </summary>
+  TBerNull = class sealed(TDerNull, IBerNull)
+
+  strict private
+
+    class function GetInstance: IBerNull; static; inline;
+
+    class var
+
+      FInstance: IBerNull;
+
+    constructor Create(dummy: Int32);
+
+    class constructor BerNull();
+
+  public
+
+    procedure Encode(derOut: IDerOutputStream); override;
+    class property Instance: IBerNull read GetInstance;
+
+  end;
+
+implementation
+
+{ TBerNull }
+
+constructor TBerNull.Create(dummy: Int32);
+begin
+  Inherited Create(dummy);
+end;
+
+class constructor TBerNull.BerNull;
+begin
+  FInstance := TBerNull.Create(0);
+end;
+
+procedure TBerNull.Encode(derOut: IDerOutputStream);
+begin
+
+  if (Supports(derOut, IAsn1OutputStream) or Supports(derOut, IBerOutputStream))
+  then
+  begin
+    derOut.WriteByte(TAsn1Tags.Null);
+  end
+  else
+  begin
+    Inherited Encode(derOut);
+  end;
+end;
+
+class function TBerNull.GetInstance: IBerNull;
+begin
+  result := FInstance;
+end;
+
+end.

+ 214 - 0
CryptoLib/src/Asn1/ClpBerOctetString.pas

@@ -0,0 +1,214 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpBerOctetString;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  SysUtils,
+  Math,
+  Generics.Collections,
+  ClpCryptoLibTypes,
+  ClpIProxiedInterface,
+  ClpIAsn1Sequence,
+  ClpAsn1Tags,
+  ClpIAsn1OutputStream,
+  ClpIBerOutputStream,
+  ClpIBerOctetString,
+  ClpIDerOctetString,
+  ClpDerOctetString;
+
+type
+  TBerOctetString = class(TDerOctetString, IBerOctetString)
+
+  strict private
+  const
+    MaxLength = Int32(1000);
+
+  var
+    Focts: TEnumerable<IDerOctetString>;
+
+    function GenerateOcts(): TList<IDerOctetString>;
+
+    class function ToBytes(octs: TEnumerable<IDerOctetString>)
+      : TCryptoLibByteArray; static;
+
+  public
+
+    /// <inheritdoc />
+    /// <param name="str">The octets making up the octet string.</param>
+    constructor Create(str: TCryptoLibByteArray); overload;
+    constructor Create(octets: TEnumerable<IDerOctetString>); overload;
+    constructor Create(obj: IAsn1Object); overload;
+    constructor Create(obj: IAsn1Encodable); overload;
+
+    destructor Destroy(); override;
+
+    function GetOctets(): TCryptoLibByteArray; override;
+
+    /// <summary>
+    /// return the DER octets that make up this string.
+    /// </summary>
+    function GetEnumerator: TEnumerator<IDerOctetString>;
+
+    procedure Encode(derOut: IDerOutputStream); override;
+
+    class function FromSequence(seq: IAsn1Sequence): IBerOctetString; static;
+
+  end;
+
+implementation
+
+{ TBerOctetString }
+
+constructor TBerOctetString.Create(octets: TEnumerable<IDerOctetString>);
+begin
+  Inherited Create(ToBytes(octets));
+  Focts := octets;
+end;
+
+constructor TBerOctetString.Create(str: TCryptoLibByteArray);
+begin
+  Inherited Create(str);
+end;
+
+constructor TBerOctetString.Create(obj: IAsn1Encodable);
+begin
+  Inherited Create(obj.ToAsn1Object());
+end;
+
+destructor TBerOctetString.Destroy;
+begin
+  Focts.Free;
+  inherited Destroy;
+end;
+
+constructor TBerOctetString.Create(obj: IAsn1Object);
+begin
+  Inherited Create(obj);
+end;
+
+procedure TBerOctetString.Encode(derOut: IDerOutputStream);
+var
+  oct: IDerOctetString;
+begin
+  if ((Supports(derOut, IAsn1OutputStream)) or
+    (Supports(derOut, IBerOutputStream))) then
+  begin
+    derOut.WriteByte(TAsn1Tags.Constructed or TAsn1Tags.OctetString);
+
+    derOut.WriteByte($80);
+
+    //
+    // write out the octet array
+    //
+    for oct in Self do
+    begin
+      derOut.WriteObject(oct);
+    end;
+
+    derOut.WriteByte($00);
+    derOut.WriteByte($00);
+  end
+  else
+  begin
+    (Inherited Encode(derOut));
+  end;
+end;
+
+class function TBerOctetString.FromSequence(seq: IAsn1Sequence)
+  : IBerOctetString;
+var
+  v: TList<IDerOctetString>;
+  obj: IAsn1Encodable;
+begin
+  v := TList<IDerOctetString>.Create();
+
+  for obj in seq do
+  begin
+    v.Add(obj as IDerOctetString);
+  end;
+
+  result := TBerOctetString.Create(v);
+
+end;
+
+function TBerOctetString.GenerateOcts: TList<IDerOctetString>;
+var
+  i, endPoint: Int32;
+  nStr: TCryptoLibByteArray;
+  temp: IDerOctetString;
+begin
+  result := TList<IDerOctetString>.Create();
+  i := 0;
+  while i < System.Length(str) do
+  begin
+    endPoint := Min(System.Length(str), i + MaxLength);
+
+    System.SetLength(nStr, endPoint - i);
+
+    System.Move(str[i], nStr[0], System.Length(nStr) * System.SizeOf(Byte));
+    result.Add(TDerOctetString.Create(nStr));
+    System.Inc(i, MaxLength);
+  end;
+  Focts := result; // review removal
+end;
+
+function TBerOctetString.GetEnumerator: TEnumerator<IDerOctetString>;
+begin
+  if (Focts = Nil) then
+  begin
+    result := GenerateOcts().GetEnumerator();
+    Exit;
+  end;
+
+  result := Focts.GetEnumerator();
+end;
+
+function TBerOctetString.GetOctets: TCryptoLibByteArray;
+begin
+  result := str;
+end;
+
+class function TBerOctetString.ToBytes(octs: TEnumerable<IDerOctetString>)
+  : TCryptoLibByteArray;
+var
+  bOut: TMemoryStream;
+  o: IDerOctetString;
+  octets: TCryptoLibByteArray;
+begin
+  bOut := TMemoryStream.Create();
+  try
+    for o in octs do
+    begin
+      octets := o.GetOctets();
+      bOut.Write(octets[0], System.Length(octets));
+    end;
+
+    System.SetLength(result, bOut.Size);
+    bOut.Position := 0;
+    bOut.Read(result[0], bOut.Size);
+  finally
+    bOut.Free;
+  end;
+end;
+
+end.

+ 91 - 0
CryptoLib/src/Asn1/ClpBerOctetStringParser.pas

@@ -0,0 +1,91 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpBerOctetStringParser;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpStreams,
+  ClpCryptoLibTypes,
+  ClpBerOctetString,
+  ClpConstructedOctetStream,
+  ClpIAsn1StreamParser,
+  ClpIProxiedInterface,
+  ClpIBerOctetStringParser,
+  ClpIAsn1OctetStringParser;
+
+resourcestring
+  SConvertError = 'EIOCryptoLibException Converting Stream to Byte Array: %s';
+
+type
+  TBerOctetStringParser = class(TInterfacedObject, IAsn1OctetStringParser,
+    IAsn1Convertible, IBerOctetStringParser)
+
+  strict private
+  var
+    F_parser: IAsn1StreamParser;
+
+  public
+
+    constructor Create(parser: IAsn1StreamParser);
+    function GetOctetStream(): TStream; inline;
+    function ToAsn1Object(): IAsn1Object;
+
+  end;
+
+implementation
+
+{ TBerOctetStringParser }
+
+constructor TBerOctetStringParser.Create(parser: IAsn1StreamParser);
+begin
+  F_parser := parser;
+end;
+
+function TBerOctetStringParser.GetOctetStream: TStream;
+begin
+  result := TConstructedOctetStream.Create(F_parser);
+end;
+
+function TBerOctetStringParser.ToAsn1Object: IAsn1Object;
+var
+  LStream: TStream;
+begin
+  try
+    LStream := GetOctetStream();
+
+    try
+      result := TBerOctetString.Create(TStreams.ReadAll(LStream));
+    finally
+      LStream.Free;
+    end;
+
+  except
+    on e: EIOCryptoLibException do
+    begin
+      raise EAsn1ParsingCryptoLibException.CreateResFmt(@SConvertError,
+        [e.Message]);
+    end;
+
+  end;
+end;
+
+end.

+ 48 - 0
CryptoLib/src/Asn1/ClpBerOutputStream.pas

@@ -0,0 +1,48 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpBerOutputStream;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpDerOutputStream,
+  ClpIBerOutputStream;
+
+type
+  // TODO Make Obsolete in favour of Asn1OutputStream?
+  TBerOutputStream = class sealed(TDerOutputStream, IBerOutputStream)
+
+  public
+
+    constructor Create(os: TStream);
+
+  end;
+
+implementation
+
+{ TBerOutputStream }
+
+constructor TBerOutputStream.Create(os: TStream);
+begin
+  Inherited Create(os);
+end;
+
+end.

+ 162 - 0
CryptoLib/src/Asn1/ClpBerSequence.pas

@@ -0,0 +1,162 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpBerSequence;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  SysUtils,
+  ClpIProxiedInterface,
+  ClpAsn1Tags,
+  ClpDerSequence,
+  ClpIAsn1OutputStream,
+  ClpIBerOutputStream,
+  ClpIAsn1EncodableVector,
+  ClpIBerSequence;
+
+type
+  TBerSequence = class(TDerSequence, IBerSequence)
+
+  strict private
+
+    class var
+
+      FEmpty: IBerSequence;
+
+    class constructor BerSequence();
+    class function GetEmpty: IBerSequence; static; inline;
+
+  public
+
+    class function FromVector(v: IAsn1EncodableVector): IBerSequence; static;
+
+    /// <summary>
+    /// create an empty sequence
+    /// </summary>
+    constructor Create(); overload;
+
+    /// <summary>
+    /// create a sequence containing one object
+    /// </summary>
+    constructor Create(obj: IAsn1Encodable); overload;
+
+    constructor Create(v: array of IAsn1Encodable); overload;
+
+    /// <summary>
+    /// create a sequence containing a vector of objects.
+    /// </summary>
+    constructor Create(v: IAsn1EncodableVector); overload;
+
+    destructor Destroy(); override;
+
+    /// <summary>
+    /// A note on the implementation: <br />As Der requires the constructed,
+    /// definite-length model to <br />be used for structured types, this
+    /// varies slightly from the <br />ASN.1 descriptions given. Rather than
+    /// just outputing Sequence, <br />we also have to specify Constructed,
+    /// and the objects length. <br />
+    /// </summary>
+    procedure Encode(derOut: IDerOutputStream); override;
+
+    class property Empty: IBerSequence read GetEmpty;
+
+  end;
+
+implementation
+
+{ TBerSequence }
+
+constructor TBerSequence.Create(obj: IAsn1Encodable);
+begin
+  Inherited Create(obj);
+end;
+
+constructor TBerSequence.Create;
+begin
+  Inherited Create();
+end;
+
+constructor TBerSequence.Create(v: IAsn1EncodableVector);
+begin
+  Inherited Create(v);
+end;
+
+destructor TBerSequence.Destroy;
+begin
+
+  inherited Destroy;
+end;
+
+constructor TBerSequence.Create(v: array of IAsn1Encodable);
+begin
+  Inherited Create(v);
+end;
+
+class constructor TBerSequence.BerSequence;
+begin
+  FEmpty := TBerSequence.Create();
+end;
+
+procedure TBerSequence.Encode(derOut: IDerOutputStream);
+var
+  o: IAsn1Encodable;
+begin
+
+  if ((Supports(derOut, IAsn1OutputStream)) or
+    (Supports(derOut, IBerOutputStream))) then
+  begin
+    derOut.WriteByte(TAsn1Tags.Sequence or TAsn1Tags.Constructed);
+    derOut.WriteByte($80);
+
+    for o in Self do
+    begin
+      derOut.WriteObject(o);
+    end;
+
+    derOut.WriteByte($00);
+    derOut.WriteByte($00);
+  end
+  else
+  begin
+    (Inherited Encode(derOut));
+  end;
+
+end;
+
+class function TBerSequence.FromVector(v: IAsn1EncodableVector): IBerSequence;
+begin
+  if v.Count < 1 then
+  begin
+    result := Empty;
+  end
+  else
+  begin
+    result := TBerSequence.Create(v);
+  end;
+
+end;
+
+class function TBerSequence.GetEmpty: IBerSequence;
+begin
+  result := FEmpty;
+end;
+
+end.

+ 56 - 0
CryptoLib/src/Asn1/ClpBerSequenceGenerator.pas

@@ -0,0 +1,56 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpBerSequenceGenerator;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpAsn1Tags,
+  ClpBerGenerator,
+  ClpIBerSequenceGenerator;
+
+type
+  TBerSequenceGenerator = class(TBerGenerator, IBerSequenceGenerator)
+
+  public
+    constructor Create(outStream: TStream); overload;
+    constructor Create(outStream: TStream; tagNo: Int32;
+      isExplicit: Boolean); overload;
+  end;
+
+implementation
+
+{ TBerSequenceGenerator }
+
+constructor TBerSequenceGenerator.Create(outStream: TStream);
+begin
+  Inherited Create(outStream);
+  WriteBerHeader(TAsn1Tags.Constructed or TAsn1Tags.Sequence);
+end;
+
+constructor TBerSequenceGenerator.Create(outStream: TStream; tagNo: Int32;
+  isExplicit: Boolean);
+begin
+  Inherited Create(outStream, tagNo, isExplicit);
+  WriteBerHeader(TAsn1Tags.Constructed or TAsn1Tags.Sequence);
+end;
+
+end.

+ 66 - 0
CryptoLib/src/Asn1/ClpBerSequenceParser.pas

@@ -0,0 +1,66 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpBerSequenceParser;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIAsn1StreamParser,
+  ClpIAsn1SequenceParser,
+  ClpIProxiedInterface,
+  ClpIBerSequenceParser,
+  ClpBerSequence;
+
+type
+  TBerSequenceParser = class(TInterfacedObject, IAsn1SequenceParser,
+    IAsn1Convertible, IBerSequenceParser)
+
+  strict private
+  var
+    F_parser: IAsn1StreamParser;
+
+  public
+
+    constructor Create(parser: IAsn1StreamParser);
+    function ReadObject(): IAsn1Convertible; inline;
+    function ToAsn1Object(): IAsn1Object; inline;
+
+  end;
+
+implementation
+
+{ TBerSequenceParser }
+
+constructor TBerSequenceParser.Create(parser: IAsn1StreamParser);
+begin
+  F_parser := parser;
+end;
+
+function TBerSequenceParser.ReadObject: IAsn1Convertible;
+begin
+  result := F_parser.ReadObject();
+end;
+
+function TBerSequenceParser.ToAsn1Object: IAsn1Object;
+begin
+  result := TBerSequence.Create(F_parser.ReadVector());
+end;
+
+end.

+ 179 - 0
CryptoLib/src/Asn1/ClpBerSet.pas

@@ -0,0 +1,179 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpBerSet;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  SysUtils,
+  ClpAsn1Tags,
+  ClpDerSet,
+  ClpIBerSet,
+  ClpIBerOutputStream,
+  ClpIAsn1OutputStream,
+  ClpIProxiedInterface,
+  ClpIAsn1EncodableVector;
+
+type
+
+  /// <summary>
+  /// A Ber encoded set object
+  /// </summary>
+  TBerSet = class sealed(TDerSet, IBerSet)
+
+  strict private
+    class var
+
+      FEmpty: IBerSet;
+    class constructor BerSet();
+    class function GetEmpty: IBerSet; static; inline;
+
+  public
+
+    class function FromVector(v: IAsn1EncodableVector): IBerSet;
+      overload; static;
+    class function FromVector(v: IAsn1EncodableVector; needsSorting: Boolean)
+      : IBerSet; overload; static;
+
+    /// <summary>
+    /// create an empty set
+    /// </summary>
+    constructor Create(); overload;
+
+    /// <param name="obj">
+    /// a single object that makes up the set.
+    /// </param>
+    constructor Create(obj: IAsn1Encodable); overload;
+
+    /// <param name="v">
+    /// a vector of objects making up the set.
+    /// </param>
+    constructor Create(v: IAsn1EncodableVector); overload;
+
+    constructor Create(v: IAsn1EncodableVector; needsSorting: Boolean);
+      overload;
+
+    destructor Destroy(); override;
+
+    /// <summary>
+    /// A note on the implementation: <br />As Ber requires the constructed,
+    /// definite-length model to <br />be used for structured types, this
+    /// varies slightly from the <br />ASN.1 descriptions given. Rather than
+    /// just outputing Set, <br />we also have to specify Constructed, and
+    /// the objects length. <br />
+    /// </summary>
+    procedure Encode(derOut: IDerOutputStream); override;
+
+    class property Empty: IBerSet read GetEmpty;
+
+  end;
+
+implementation
+
+{ TBerSet }
+
+constructor TBerSet.Create;
+begin
+  Inherited Create();
+end;
+
+constructor TBerSet.Create(v: IAsn1EncodableVector; needsSorting: Boolean);
+begin
+  Inherited Create(v, needsSorting);
+end;
+
+destructor TBerSet.Destroy;
+begin
+
+  inherited Destroy;
+end;
+
+constructor TBerSet.Create(obj: IAsn1Encodable);
+begin
+  Inherited Create(obj);
+end;
+
+constructor TBerSet.Create(v: IAsn1EncodableVector);
+begin
+  Inherited Create(v, false);
+end;
+
+class constructor TBerSet.BerSet;
+begin
+  FEmpty := TBerSet.Create();
+end;
+
+procedure TBerSet.Encode(derOut: IDerOutputStream);
+var
+  o: IAsn1Encodable;
+begin
+  if ((Supports(derOut, IAsn1OutputStream)) or
+    (Supports(derOut, IBerOutputStream))) then
+  begin
+    derOut.WriteByte(TAsn1Tags.&Set or TAsn1Tags.Constructed);
+
+    derOut.WriteByte($80);
+
+    for o in Self do
+    begin
+      derOut.WriteObject(o);
+    end;
+
+    derOut.WriteByte($00);
+    derOut.WriteByte($00);
+  end
+  else
+  begin
+    (Inherited Encode(derOut));
+  end;
+end;
+
+class function TBerSet.FromVector(v: IAsn1EncodableVector;
+  needsSorting: Boolean): IBerSet;
+begin
+  if v.Count < 1 then
+  begin
+    result := Empty;
+  end
+  else
+  begin
+    result := TBerSet.Create(v, needsSorting);
+  end;
+end;
+
+class function TBerSet.GetEmpty: IBerSet;
+begin
+  result := FEmpty;
+end;
+
+class function TBerSet.FromVector(v: IAsn1EncodableVector): IBerSet;
+begin
+  if v.Count < 1 then
+  begin
+    result := Empty;
+  end
+  else
+  begin
+    result := TBerSet.Create(v);
+  end;
+end;
+
+end.

+ 66 - 0
CryptoLib/src/Asn1/ClpBerSetParser.pas

@@ -0,0 +1,66 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpBerSetParser;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIAsn1StreamParser,
+  ClpBerSet,
+  ClpIAsn1SetParser,
+  ClpIBerSetParser,
+  ClpIProxiedInterface;
+
+type
+  TBerSetParser = class(TInterfacedObject, IAsn1SetParser, IAsn1Convertible,
+    IBerSetParser)
+
+  strict private
+  var
+    F_parser: IAsn1StreamParser;
+
+  public
+
+    constructor Create(parser: IAsn1StreamParser);
+    function ReadObject(): IAsn1Convertible; inline;
+    function ToAsn1Object(): IAsn1Object; inline;
+
+  end;
+
+implementation
+
+{ TBerSetParser }
+
+constructor TBerSetParser.Create(parser: IAsn1StreamParser);
+begin
+  F_parser := parser;
+end;
+
+function TBerSetParser.ReadObject: IAsn1Convertible;
+begin
+  result := F_parser.ReadObject();
+end;
+
+function TBerSetParser.ToAsn1Object: IAsn1Object;
+begin
+  result := TBerSet.Create(F_parser.ReadVector(), false);
+end;
+
+end.

+ 206 - 0
CryptoLib/src/Asn1/ClpBerTaggedObject.pas

@@ -0,0 +1,206 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpBerTaggedObject;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  Generics.Collections,
+  ClpCryptoLibTypes,
+  ClpAsn1Tags,
+  ClpBerSequence,
+  ClpIAsn1OctetString,
+  ClpAsn1Encodable,
+  ClpBerOctetString,
+  ClpIBerOctetString,
+  ClpIDerOctetString,
+  ClpIAsn1Set,
+  ClpIAsn1Sequence,
+  ClpIAsn1OutputStream,
+  ClpIBerOutputStream,
+  ClpIProxiedInterface,
+  ClpDerTaggedObject,
+  ClpIBerTaggedObject;
+
+resourcestring
+  SNotImplemented = 'Not Implemented %s';
+
+type
+
+  /// <summary>
+  /// BER TaggedObject - in ASN.1 notation this is any object preceded by <br />
+  /// a [n] where n is some number - these are assumed to follow the
+  /// construction <br />rules (as with sequences). <br />
+  /// </summary>
+  TBerTaggedObject = class(TDerTaggedObject, IBerTaggedObject)
+
+  public
+
+    /// <param name="tagNo">
+    /// the tag number for this object.
+    /// </param>
+    /// <param name="obj">
+    /// the tagged object.
+    /// </param>
+    constructor Create(tagNo: Int32; obj: IAsn1Encodable); overload;
+    /// <param name="explicitly">
+    /// true if an explicitly tagged object.
+    /// </param>
+    /// <param name="tagNo">
+    /// the tag number for this object.
+    /// </param>
+    /// <param name="obj">
+    /// the tagged object.
+    /// </param>
+    constructor Create(explicitly: Boolean; tagNo: Int32;
+      obj: IAsn1Encodable); overload;
+
+    /// <summary>
+    /// create an implicitly tagged object that contains a zero length
+    /// sequence.
+    /// </summary>
+    /// <param name="tagNo">
+    /// the tag number for this object.
+    /// </param>
+    constructor Create(tagNo: Int32); overload;
+
+    procedure Encode(derOut: IDerOutputStream); override;
+
+  end;
+
+implementation
+
+{ TBerTaggedObject }
+
+constructor TBerTaggedObject.Create(tagNo: Int32; obj: IAsn1Encodable);
+begin
+  Inherited Create(tagNo, obj);
+end;
+
+constructor TBerTaggedObject.Create(explicitly: Boolean; tagNo: Int32;
+  obj: IAsn1Encodable);
+begin
+  Inherited Create(explicitly, tagNo, obj)
+end;
+
+constructor TBerTaggedObject.Create(tagNo: Int32);
+begin
+  Inherited Create(false, tagNo, TBerSequence.Empty)
+end;
+
+procedure TBerTaggedObject.Encode(derOut: IDerOutputStream);
+var
+  eObj: TList<IAsn1Encodable>;
+  enumeratorIBerOctetString: TEnumerator<IDerOctetString>;
+  enumeratorIAsn1Sequence, enumeratorIAsn1Set: TEnumerator<IAsn1Encodable>;
+  asn1OctetString: IAsn1OctetString;
+  berOctetString: IBerOctetString;
+  asn1Sequence: IAsn1Sequence;
+  asn1Set: IAsn1Set;
+  o: IAsn1Encodable;
+begin
+  eObj := TList<IAsn1Encodable>.Create();
+  try
+    if ((Supports(derOut, IAsn1OutputStream)) or
+      (Supports(derOut, IBerOutputStream))) then
+    begin
+      derOut.WriteTag(Byte(TAsn1Tags.Constructed or TAsn1Tags.Tagged), tagNo);
+      derOut.WriteByte($80);
+
+      if (not IsEmpty()) then
+      begin
+        if (not explicitly) then
+        begin
+
+          // asn1OctetString := obj as IAsn1OctetString;
+          if (Supports(obj, IAsn1OctetString, asn1OctetString)) then
+          begin
+            // berOctetString := asn1OctetString as IBerOctetString;
+            if (Supports(asn1OctetString, IBerOctetString, berOctetString)) then
+            begin
+              enumeratorIBerOctetString := berOctetString.GetEnumerator;
+              while enumeratorIBerOctetString.MoveNext do
+              begin
+                eObj.Add(enumeratorIBerOctetString.Current as IAsn1Encodable);
+              end;
+            end
+            else
+            begin
+              enumeratorIBerOctetString :=
+                TBerOctetString.Create(asn1OctetString.GetOctets())
+                .GetEnumerator;
+              while enumeratorIBerOctetString.MoveNext do
+              begin
+                eObj.Add(enumeratorIBerOctetString.Current as IAsn1Encodable);
+              end;
+            end
+          end
+          else if Supports(obj, IAsn1Sequence, asn1Sequence) then
+          begin
+            // eObj := obj as IAsn1Sequence;
+            // asn1Sequence := obj as IAsn1Sequence;
+            enumeratorIAsn1Sequence := asn1Sequence.GetEnumerator;
+            while enumeratorIAsn1Sequence.MoveNext do
+            begin
+              eObj.Add(enumeratorIAsn1Sequence.Current);
+            end;
+          end
+          else if Supports(obj, IAsn1Set, asn1Set) then
+          begin
+            // eObj := obj as IAsn1Set;
+            // asn1Set := obj as IAsn1Set;
+            enumeratorIAsn1Set := asn1Set.GetEnumerator;
+            while enumeratorIAsn1Set.MoveNext do
+            begin
+              eObj.Add(enumeratorIAsn1Set.Current);
+            end;
+          end
+          else
+          begin
+            raise ENotImplementedCryptoLibException.CreateResFmt
+              (@SNotImplemented, [(obj as TAsn1Encodable).ClassName]);
+          end;
+
+          for o in eObj do
+          begin
+            derOut.WriteObject(o);
+          end;
+        end
+        else
+        begin
+          derOut.WriteObject(obj);
+        end;
+      end;
+
+      derOut.WriteByte($00);
+      derOut.WriteByte($00);
+    end
+    else
+    begin
+      (Inherited Encode(derOut));
+    end
+  finally
+    eObj.Free;
+  end;
+
+end;
+
+end.

+ 115 - 0
CryptoLib/src/Asn1/ClpBerTaggedObjectParser.pas

@@ -0,0 +1,115 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpBerTaggedObjectParser;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpCryptoLibTypes,
+  ClpIProxiedInterface,
+  ClpIAsn1StreamParser,
+  ClpIBerTaggedObjectParser,
+  ClpIAsn1TaggedObjectParser;
+
+resourcestring
+  SUnConstructedTag = 'Explicit Tags Must be Constructed (see X.690 8.14.2)';
+  SParsingError = '%s';
+
+type
+  TBerTaggedObjectParser = class(TInterfacedObject, IAsn1TaggedObjectParser,
+    IAsn1Convertible, IBerTaggedObjectParser)
+
+  strict private
+  var
+    F_constructed: Boolean;
+    F_tagNumber: Int32;
+    F_parser: IAsn1StreamParser;
+
+    function GetIsConstructed: Boolean; inline;
+    function GetTagNo: Int32; inline;
+
+  public
+    constructor Create(constructed: Boolean; tagNumber: Int32;
+      parser: IAsn1StreamParser);
+
+    function GetObjectParser(tag: Int32; isExplicit: Boolean)
+      : IAsn1Convertible; inline;
+
+    function ToAsn1Object(): IAsn1Object;
+
+    property IsConstructed: Boolean read GetIsConstructed;
+    property TagNo: Int32 read GetTagNo;
+
+  end;
+
+implementation
+
+{ TBerTaggedObjectParser }
+
+constructor TBerTaggedObjectParser.Create(constructed: Boolean;
+  tagNumber: Int32; parser: IAsn1StreamParser);
+begin
+  F_constructed := constructed;
+  F_tagNumber := tagNumber;
+  F_parser := parser;
+end;
+
+function TBerTaggedObjectParser.GetIsConstructed: Boolean;
+begin
+  result := F_constructed;
+end;
+
+function TBerTaggedObjectParser.GetObjectParser(tag: Int32; isExplicit: Boolean)
+  : IAsn1Convertible;
+begin
+  if (isExplicit) then
+  begin
+    if (not F_constructed) then
+    begin
+      raise EIOCryptoLibException.CreateRes(@SUnConstructedTag);
+    end;
+
+    result := F_parser.ReadObject();
+    Exit;
+  end;
+
+  result := F_parser.ReadImplicit(F_constructed, tag);
+end;
+
+function TBerTaggedObjectParser.GetTagNo: Int32;
+begin
+  result := F_tagNumber;
+end;
+
+function TBerTaggedObjectParser.ToAsn1Object: IAsn1Object;
+begin
+  try
+    result := F_parser.ReadTaggedObject(F_constructed, F_tagNumber);
+  except
+    on e: EIOCryptoLibException do
+    begin
+      raise EAsn1ParsingCryptoLibException.CreateResFmt(@SParsingError,
+        [e.Message]);
+    end;
+
+  end;
+end;
+
+end.

+ 171 - 0
CryptoLib/src/Asn1/ClpConstructedOctetStream.pas

@@ -0,0 +1,171 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpConstructedOctetStream;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  SysUtils,
+  ClpCryptoLibTypes,
+  ClpBaseInputStream,
+  ClpIAsn1OctetStringParser,
+  ClpIAsn1StreamParser,
+  ClpIConstructedOctetStream;
+
+type
+  TConstructedOctetStream = class(TBaseInputStream, IConstructedOctetStream)
+
+  strict private
+  var
+    F_parser: IAsn1StreamParser;
+    F_first: Boolean;
+    F_currentStream: TStream;
+
+  public
+    constructor Create(parser: IAsn1StreamParser);
+    function Read(buffer: TCryptoLibByteArray; offset, count: Int32)
+      : Int32; override;
+    function ReadByte(): Int32; override;
+  end;
+
+implementation
+
+uses
+  ClpStreamSorter; // included here to avoid circular dependency :)
+
+{ TConstructedOctetStream }
+
+constructor TConstructedOctetStream.Create(parser: IAsn1StreamParser);
+begin
+  Inherited Create();
+  F_parser := parser;
+  F_first := true;
+end;
+
+function TConstructedOctetStream.Read(buffer: TCryptoLibByteArray;
+  offset, count: Int32): Int32;
+var
+  s, aos: IAsn1OctetStringParser;
+  totalRead, numRead: Int32;
+begin
+  if (F_currentStream = Nil) then
+  begin
+    if (not F_first) then
+    begin
+      result := 0;
+      Exit;
+    end;
+
+    if (not Supports(F_parser.ReadObject(), IAsn1OctetStringParser, s)) then
+    begin
+      result := 0;
+      Exit;
+    end;
+
+    F_first := false;
+    F_currentStream := s.GetOctetStream();
+  end;
+
+  totalRead := 0;
+
+  while true do
+
+  begin
+
+    numRead := TStreamSorter.Read(F_currentStream, buffer, offset + totalRead,
+      count - totalRead);
+
+    if (numRead > 0) then
+    begin
+      totalRead := totalRead + numRead;
+
+      if (totalRead = count) then
+      begin
+        result := totalRead;
+        Exit;
+      end;
+    end
+    else
+    begin
+
+      if (not Supports(F_parser.ReadObject(), IAsn1OctetStringParser, aos)) then
+      begin
+        F_currentStream := Nil;
+        result := totalRead;
+        Exit;
+      end;
+
+      F_currentStream := aos.GetOctetStream();
+    end
+  end;
+  result := 0;
+end;
+
+function TConstructedOctetStream.ReadByte: Int32;
+var
+  s, aos: IAsn1OctetStringParser;
+  b: Int32;
+begin
+  if (F_currentStream = Nil) then
+  begin
+    if (not F_first) then
+    begin
+      result := 0;
+      Exit;
+    end;
+
+    if (not Supports(F_parser.ReadObject(), IAsn1OctetStringParser, s)) then
+    begin
+      result := 0;
+      Exit;
+    end;
+
+    F_first := false;
+    F_currentStream := s.GetOctetStream();
+  end;
+
+  while true do
+
+  begin
+
+    // b := F_currentStream.ReadByte();
+    b := TStreamSorter.ReadByte(F_currentStream);
+
+    if (b >= 0) then
+    begin
+      result := b;
+      Exit;
+    end;
+
+    if (not Supports(F_parser.ReadObject(), IAsn1OctetStringParser, aos)) then
+    begin
+      F_currentStream := Nil;
+      result := -1;
+      Exit;
+    end;
+
+    F_currentStream := aos.GetOctetStream();
+  end;
+
+  result := 0;
+end;
+
+end.

+ 202 - 0
CryptoLib/src/Asn1/ClpDefiniteLengthInputStream.pas

@@ -0,0 +1,202 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDefiniteLengthInputStream;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  Math,
+  ClpCryptoLibTypes,
+  ClpLimitedInputStream,
+  ClpIDefiniteLengthInputStream;
+
+resourcestring
+  SInvalidLength = 'Negative Lengths not Allowed", "Length"';
+  SEndOfStream = 'DEF Length  %d " TObject truncated by " %d';
+  SInvalidBufferLength = 'Buffer Length Not Right For Data';
+
+type
+  TDefiniteLengthInputStream = class sealed(TLimitedInputStream,
+    IDefiniteLengthInputStream)
+
+  strict private
+    class var
+
+      FEmptyBytes: TCryptoLibByteArray;
+
+  var
+    F_originalLength, F_remaining: Int32;
+
+    function GetRemaining: Int32; reintroduce; inline;
+    class function GetEmptyBytes: TCryptoLibByteArray; static; inline;
+
+    class constructor DefiniteLengthInputStream();
+
+  public
+
+    constructor Create(inStream: TStream; length: Int32);
+
+    function ReadByte(): Int32; override;
+
+    function Read(buf: TCryptoLibByteArray; off, len: Int32): Int32; override;
+
+    procedure ReadAllIntoByteArray(buf: TCryptoLibByteArray);
+
+    function ToArray: TCryptoLibByteArray;
+
+    property Remaining: Int32 read GetRemaining;
+    class property EmptyBytes: TCryptoLibByteArray read GetEmptyBytes;
+
+  end;
+
+implementation
+
+uses
+  ClpStreams,
+  ClpStreamSorter; // included here to avoid circular dependency :)
+
+{ TDefiniteLengthInputStream }
+
+constructor TDefiniteLengthInputStream.Create(inStream: TStream; length: Int32);
+begin
+  Inherited Create(inStream, length);
+  if (length < 0) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SInvalidLength);
+  end;
+
+  F_originalLength := length;
+  F_remaining := length;
+
+  if (length = 0) then
+  begin
+    SetParentEofDetect(true);
+  end;
+end;
+
+class constructor TDefiniteLengthInputStream.DefiniteLengthInputStream;
+begin
+  System.SetLength(FEmptyBytes, 0);
+end;
+
+class function TDefiniteLengthInputStream.GetEmptyBytes: TCryptoLibByteArray;
+begin
+  result := FEmptyBytes;
+end;
+
+function TDefiniteLengthInputStream.GetRemaining: Int32;
+begin
+  result := F_remaining;
+end;
+
+function TDefiniteLengthInputStream.Read(buf: TCryptoLibByteArray;
+  off, len: Int32): Int32;
+var
+  toRead, numRead: Int32;
+
+begin
+  if (F_remaining = 0) then
+  begin
+    result := 0;
+    Exit;
+  end;
+
+  toRead := Min(len, F_remaining);
+
+  numRead := TStreamSorter.Read(F_in, buf, off, toRead);
+
+  if (numRead < 1) then
+  begin
+    raise EEndOfStreamCryptoLibException.CreateResFmt(@SEndOfStream,
+      [F_originalLength, F_remaining]);
+  end;
+  F_remaining := F_remaining - numRead;
+
+  if (F_remaining = 0) then
+  begin
+    SetParentEofDetect(true);
+  end;
+
+  result := numRead;
+end;
+
+procedure TDefiniteLengthInputStream.ReadAllIntoByteArray
+  (buf: TCryptoLibByteArray);
+begin
+  if (F_remaining <> System.length(buf)) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SInvalidBufferLength);
+  end;
+  F_remaining := F_remaining - TStreams.ReadFully(F_in, buf);
+  if ((F_remaining <> 0)) then
+  begin
+    raise EEndOfStreamCryptoLibException.CreateResFmt(@SEndOfStream,
+      [F_originalLength, F_remaining]);
+  end;
+  SetParentEofDetect(true);
+end;
+
+function TDefiniteLengthInputStream.ReadByte: Int32;
+begin
+  if (F_remaining = 0) then
+  begin
+    result := -1;
+    Exit;
+  end;
+
+  // result := F_in.ReadByte();
+  result := TStreamSorter.ReadByte(F_in);
+
+  if (result < 0) then
+  begin
+    raise EEndOfStreamCryptoLibException.CreateResFmt(@SEndOfStream,
+      [F_originalLength, F_remaining]);
+  end;
+
+  System.Dec(F_remaining);
+  if (F_remaining = 0) then
+  begin
+    SetParentEofDetect(true);
+  end;
+
+end;
+
+function TDefiniteLengthInputStream.ToArray: TCryptoLibByteArray;
+var
+  bytes: TCryptoLibByteArray;
+begin
+  if (F_remaining = 0) then
+  begin
+    result := EmptyBytes;
+    Exit;
+  end;
+  System.SetLength(bytes, F_remaining);
+  F_remaining := F_remaining - TStreams.ReadFully(F_in, bytes);
+  if (F_remaining <> 0) then
+  begin
+    raise EEndOfStreamCryptoLibException.CreateResFmt(@SEndOfStream,
+      [F_originalLength, F_remaining]);
+  end;
+  SetParentEofDetect(true);
+  result := bytes;
+end;
+
+end.

+ 363 - 0
CryptoLib/src/Asn1/ClpDerApplicationSpecific.pas

@@ -0,0 +1,363 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerApplicationSpecific;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  SysUtils,
+  ClpCryptoLibTypes,
+  ClpArrayUtils,
+  ClpAsn1TaggedObject,
+  ClpAsn1Tags,
+  ClpIProxiedInterface,
+  ClpIDerApplicationSpecific,
+  ClpIAsn1EncodableVector,
+  ClpAsn1Object;
+
+resourcestring
+  SMalformedObject = 'Malformed Object %s';
+  SUnSupportedTag = 'Unsupported Tag Number';
+  SInvalidDerLength = 'DER Length More Than 4 Bytes: %d';
+  SCorruptedStream = 'Corrupted Stream - Invalid High Tag Number Found';
+
+type
+
+  /// <summary>
+  /// Base class for an application specific object
+  /// </summary>
+  TDerApplicationSpecific = class(TAsn1Object, IDerApplicationSpecific)
+
+  strict private
+  var
+    FisConstructed: Boolean;
+    Ftag: Int32;
+    Foctets: TCryptoLibByteArray;
+
+    function GetApplicationTag: Int32; inline;
+    function GetLengthOfHeader(data: TCryptoLibByteArray): Int32; inline;
+
+    class function ReplaceTagNumber(newTag: Int32; input: TCryptoLibByteArray)
+      : TCryptoLibByteArray; static;
+
+  strict protected
+    function Asn1Equals(asn1Object: IAsn1Object): Boolean; override;
+    function Asn1GetHashCode(): Int32; override;
+
+  public
+    constructor Create(isConstructed: Boolean; tag: Int32;
+      octets: TCryptoLibByteArray); overload;
+    constructor Create(tag: Int32; octets: TCryptoLibByteArray); overload;
+    constructor Create(tag: Int32; obj: IAsn1Encodable); overload;
+    constructor Create(isExplicit: Boolean; tag: Int32;
+      obj: IAsn1Encodable); overload;
+    constructor Create(tagNo: Int32; vec: IAsn1EncodableVector); overload;
+
+    function isConstructed(): Boolean; inline;
+    function GetContents(): TCryptoLibByteArray; inline;
+
+    /// <summary>
+    /// Return the enclosed object assuming explicit tagging.
+    /// </summary>
+    /// <returns>
+    /// the resulting object
+    /// </returns>
+    /// <exception cref="ClpCryptoLibTypes|EIOCryptoLibException">
+    /// if reconstruction fails.
+    /// </exception>
+    function GetObject(): IAsn1Object; overload; inline;
+
+    /// <summary>
+    /// Return the enclosed object assuming implicit tagging.
+    /// </summary>
+    /// <param name="derTagNo">
+    /// the type tag that should be applied to the object's contents.
+    /// </param>
+    /// <returns>
+    /// the resulting object
+    /// </returns>
+    /// <exception cref="ClpCryptoLibTypes|EIOCryptoLibException">
+    /// if reconstruction fails.
+    /// </exception>
+    function GetObject(derTagNo: Int32): IAsn1Object; overload; inline;
+
+    procedure Encode(derOut: IDerOutputStream); override;
+
+    property ApplicationTag: Int32 read GetApplicationTag;
+  end;
+
+implementation
+
+{ TDerApplicationSpecific }
+
+function TDerApplicationSpecific.GetLengthOfHeader
+  (data: TCryptoLibByteArray): Int32;
+var
+  &length, Size: Int32;
+begin
+  Length := data[1]; // TODO: assumes 1 byte tag
+
+  if (Length = $80) then
+  begin
+    result := 2; // indefinite-length encoding
+    Exit;
+  end;
+
+  if (Length > 127) then
+  begin
+    Size := Length and $7F;
+
+    // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
+    if (Size > 4) then
+    begin
+      raise EInvalidOperationCryptoLibException.CreateResFmt
+        (@SInvalidDerLength, [Size]);
+    end;
+
+    result := Size + 2;
+    Exit;
+  end;
+
+  result := 2;
+end;
+
+constructor TDerApplicationSpecific.Create(tag: Int32; obj: IAsn1Encodable);
+begin
+  Create(true, tag, obj);
+end;
+
+constructor TDerApplicationSpecific.Create(tag: Int32;
+  octets: TCryptoLibByteArray);
+begin
+  Create(false, tag, octets);
+end;
+
+constructor TDerApplicationSpecific.Create(isConstructed: Boolean; tag: Int32;
+  octets: TCryptoLibByteArray);
+begin
+  Inherited Create();
+  FisConstructed := isConstructed;
+  Ftag := tag;
+  Foctets := octets;
+end;
+
+function TDerApplicationSpecific.Asn1Equals(asn1Object: IAsn1Object): Boolean;
+var
+  other: IDerApplicationSpecific;
+begin
+
+  if (not Supports(asn1Object, IDerApplicationSpecific, other)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  result := (isConstructed = other.isConstructed) and
+    (ApplicationTag = other.ApplicationTag) and
+    TArrayUtils.AreEqual(GetContents, other.GetContents);
+end;
+
+function TDerApplicationSpecific.Asn1GetHashCode: Int32;
+var
+  HashCode: Int32;
+begin
+  if isConstructed then
+  begin
+    HashCode := 1
+  end
+  else
+  begin
+    HashCode := 0;
+  end;
+  result := HashCode xor Ftag xor TArrayUtils.GetArrayHashCode(Foctets);
+end;
+
+constructor TDerApplicationSpecific.Create(tagNo: Int32;
+  vec: IAsn1EncodableVector);
+var
+  bOut: TMemoryStream;
+  bs: TCryptoLibByteArray;
+  i: Int32;
+  val: IAsn1Encodable;
+begin
+  Inherited Create();
+  Ftag := tagNo;
+  FisConstructed := true;
+
+  bOut := TMemoryStream.Create();
+  try
+    i := 0;
+    while i <> vec.Count do
+
+    begin
+      try
+        val := vec[i];
+        bs := val.GetDerEncoded();
+        bOut.Write(bs[0], System.Length(bs));
+      except
+        on e: EIOCryptoLibException do
+        begin
+          raise EInvalidOperationCryptoLibException.CreateResFmt
+            (@SMalformedObject, [e.Message]);
+        end;
+      end;
+      System.Inc(i);
+    end;
+
+    System.SetLength(Foctets, bOut.Size);
+    bOut.Position := 0;
+    bOut.Read(Foctets[0], bOut.Size);
+
+  finally
+    bOut.Free;
+  end;
+
+end;
+
+procedure TDerApplicationSpecific.Encode(derOut: IDerOutputStream);
+var
+  classBits: Int32;
+begin
+  classBits := TAsn1Tags.Application;
+  if (isConstructed) then
+  begin
+    classBits := classBits or TAsn1Tags.Constructed;
+  end;
+
+  derOut.WriteEncoded(classBits, Ftag, Foctets);
+end;
+
+constructor TDerApplicationSpecific.Create(isExplicit: Boolean; tag: Int32;
+  obj: IAsn1Encodable);
+var
+  asn1Obj: IAsn1Object;
+  data, tmp: TCryptoLibByteArray;
+  lenBytes: Int32;
+begin
+  Inherited Create();
+  asn1Obj := obj.ToAsn1Object();
+
+  data := asn1Obj.GetDerEncoded();
+
+  FisConstructed := TAsn1TaggedObject.isConstructed(isExplicit, asn1Obj);
+  Ftag := tag;
+
+  if (isExplicit) then
+  begin
+    Foctets := data;
+  end
+  else
+  begin
+    lenBytes := GetLengthOfHeader(data);
+    System.SetLength(tmp, System.Length(data) - lenBytes);
+    System.Move(data[lenBytes], tmp[0], System.Length(tmp) *
+      System.SizeOf(Byte));
+    Foctets := tmp;
+  end;
+end;
+
+function TDerApplicationSpecific.GetApplicationTag: Int32;
+begin
+  result := Ftag;
+end;
+
+function TDerApplicationSpecific.GetContents: TCryptoLibByteArray;
+begin
+  result := Foctets;
+end;
+
+function TDerApplicationSpecific.GetObject: IAsn1Object;
+begin
+  result := FromByteArray(GetContents());
+end;
+
+function TDerApplicationSpecific.GetObject(derTagNo: Int32): IAsn1Object;
+var
+  orig, tmp: TCryptoLibByteArray;
+begin
+  if (derTagNo >= $1F) then
+  begin
+    raise EIOCryptoLibException.CreateRes(@SUnSupportedTag);
+  end;
+
+  orig := GetEncoded();
+  tmp := ReplaceTagNumber(derTagNo, orig);
+
+  if ((orig[0] and TAsn1Tags.Constructed) <> 0) then
+  begin
+    tmp[0] := tmp[0] or TAsn1Tags.Constructed;
+  end;
+
+  result := FromByteArray(tmp);
+end;
+
+function TDerApplicationSpecific.isConstructed: Boolean;
+begin
+  result := FisConstructed;
+end;
+
+class function TDerApplicationSpecific.ReplaceTagNumber(newTag: Int32;
+  input: TCryptoLibByteArray): TCryptoLibByteArray;
+var
+  tagNo, index, b: Int32;
+  tmp: TCryptoLibByteArray;
+begin
+  tagNo := input[0] and $1F;
+  index := 1;
+  //
+  // with tagged object tag number is bottom 5 bits, or stored at the start of the content
+  //
+  if (tagNo = $1F) then
+  begin
+    tagNo := 0;
+
+    b := input[index] and $FF;
+    System.Inc(index);
+
+    // X.690-0207 8.1.2.4.2
+    // "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
+    if ((b and $7F) = 0) then // Note: -1 will pass
+    begin
+      raise EInvalidOperationCryptoLibException.CreateRes(@SCorruptedStream);
+    end;
+
+    while ((b >= 0) and ((b and $80) <> 0)) do
+    begin
+      tagNo := tagNo or ((b and $7F));
+      tagNo := tagNo shl 7;
+      b := input[index] and $FF;
+      System.Inc(index);
+    end;
+
+    tagNo := tagNo or (b and $7F);
+  end;
+
+  System.SetLength(tmp, System.Length(input) - index + 1);
+
+  System.Move(input[index], tmp[1], System.Length(tmp) - 1 *
+    System.SizeOf(Byte));
+
+  tmp[0] := Byte(newTag);
+
+  result := tmp;
+end;
+
+end.

+ 417 - 0
CryptoLib/src/Asn1/ClpDerBitString.pas

@@ -0,0 +1,417 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerBitString;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  Classes,
+  Math,
+  ClpBits,
+  ClpArrayUtils,
+  ClpDerStringBase,
+  ClpAsn1Tags,
+  ClpBigInteger,
+  ClpAsn1Object,
+  ClpIProxiedInterface,
+  ClpCryptoLibTypes,
+  ClpIAsn1TaggedObject,
+  ClpIAsn1OctetString,
+  ClpIDerBitString;
+
+resourcestring
+  SIllegalObject = 'Illegal Object in GetInstance: %s';
+  SEncodingError = 'Encoding Error in GetInstance:  %s  "obj"';
+  SDataNil = '"data"';
+  SInvalidRange = 'Must be in the Range 0 to 7", "padBits"';
+  SPadBitError = 'If ''data'' is Empty, ''padBits'' Must be 0';
+  SUnalignedData = 'Attempt to Get non-octet Aligned Data from BIT STRING"';
+  STruncatedBitString = 'Truncated BIT STRING Detected", "octets"';
+
+type
+
+  /// <summary>
+  /// Der Bit string object.
+  /// </summary>
+  TDerBitString = class(TDerStringBase, IDerBitString)
+
+  strict private
+  const
+    FTable: array [0 .. 15] of Char = ('0', '1', '2', '3', '4', '5', '6', '7',
+      '8', '9', 'A', 'B', 'C', 'D', 'E', 'F');
+
+  strict protected
+  var
+    FmData: TCryptoLibByteArray;
+    FmPadBits: Int32;
+
+    function GetmData: TCryptoLibByteArray; inline;
+    property mData: TCryptoLibByteArray read GetmData;
+
+    function GetmPadBits: Int32; inline;
+    property mPadBits: Int32 read GetmPadBits;
+
+    function Asn1GetHashCode(): Int32; override;
+    function Asn1Equals(asn1Object: IAsn1Object): Boolean; override;
+  public
+
+    constructor Create(data: TCryptoLibByteArray; padBits: Int32); overload;
+
+    constructor Create(data: TCryptoLibByteArray); overload;
+
+    constructor Create(namedBits: Int32); overload;
+
+    constructor Create(obj: IAsn1Encodable); overload;
+
+    function GetString(): String; override;
+
+    function GetOctets(): TCryptoLibByteArray; virtual;
+
+    function GetBytes(): TCryptoLibByteArray; virtual;
+
+    procedure Encode(derOut: IDerOutputStream); override;
+
+    function GetInt32Value: Int32; virtual;
+    property Int32Value: Int32 read GetInt32Value;
+
+    /// <summary>
+    /// return a Der Bit string from the passed in object
+    /// </summary>
+    /// <param name="obj">
+    /// a Bit string or an object that can be converted into one.
+    /// </param>
+    /// <returns>
+    /// return a Der Bit string instance, or null.
+    /// </returns>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: TObject): IDerBitString; overload;
+      static; inline;
+
+    class function GetInstance(obj: TCryptoLibByteArray): IDerBitString;
+      overload; static;
+
+    /// <summary>
+    /// return a Der Bit string from a tagged object.
+    /// </summary>
+    /// <param name="obj">
+    /// the tagged object holding the object we want
+    /// </param>
+    /// <param name="isExplicit">
+    /// true if the object is meant to be explicitly tagged false otherwise.
+    /// </param>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the tagged object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: IAsn1TaggedObject; isExplicit: Boolean)
+      : IDerBitString; overload; static; inline;
+
+    class function FromAsn1Octets(octets: TCryptoLibByteArray)
+      : IDerBitString; static;
+
+  end;
+
+implementation
+
+uses
+  // included here to avoid circular dependency :)
+  ClpBerBitString;
+
+{ TDerBitString }
+
+class function TDerBitString.GetInstance(obj: TCryptoLibByteArray)
+  : IDerBitString;
+begin
+  try
+    result := FromByteArray(obj) as IDerBitString;
+  except
+    on e: Exception do
+    begin
+      raise EArgumentCryptoLibException.CreateResFmt(@SEncodingError,
+        [e.Message]);
+    end;
+
+  end;
+end;
+
+function TDerBitString.GetOctets: TCryptoLibByteArray;
+begin
+  if (mPadBits <> 0) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes(@SUnalignedData);
+  end;
+  result := System.Copy(mData);
+end;
+
+function TDerBitString.Asn1Equals(asn1Object: IAsn1Object): Boolean;
+var
+  other: IDerBitString;
+begin
+
+  if (not Supports(asn1Object, IDerBitString, other)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  result := (mPadBits = other.mPadBits) and
+    (TArrayUtils.AreEqual(mData, other.mData));
+end;
+
+constructor TDerBitString.Create(data: TCryptoLibByteArray; padBits: Int32);
+begin
+  Inherited Create();
+  if (data = Nil) then
+  begin
+    raise EArgumentNilCryptoLibException.CreateRes(@SDataNil);
+  end;
+
+  if ((padBits < 0) or (padBits > 7)) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SInvalidRange);
+  end;
+
+  if ((System.Length(data) = 0) and (padBits <> 0)) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SPadBitError);
+  end;
+
+  FmData := System.Copy(data);
+  FmPadBits := padBits;
+
+end;
+
+constructor TDerBitString.Create(data: TCryptoLibByteArray);
+begin
+  Create(data, 0);
+end;
+
+constructor TDerBitString.Create(namedBits: Int32);
+var
+  bits, bytes, i, padBits: Int32;
+  data: TCryptoLibByteArray;
+begin
+  Inherited Create();
+  if (namedBits = 0) then
+  begin
+    System.SetLength(FmData, 0);
+    FmPadBits := 0;
+    Exit;
+  end;
+  bits := TBigInteger.BitLen(namedBits);
+  bytes := (bits + 7) div 8;
+
+{$IFDEF DEBUG}
+  System.Assert((0 < bytes) and (bytes <= 4));
+{$ENDIF DEBUG}
+  System.SetLength(data, bytes);
+
+  System.Dec(bytes);
+
+  for i := 0 to System.Pred(bytes) do
+  begin
+    data[i] := Byte(namedBits);
+    namedBits := TBits.Asr32(namedBits, 8);
+  end;
+
+{$IFDEF DEBUG}
+  System.Assert((namedBits and $FF) <> 0);
+{$ENDIF DEBUG}
+  data[bytes] := Byte(namedBits);
+
+  padBits := 0;
+  while ((namedBits and (1 shl padBits)) = 0) do
+  begin
+    System.Inc(padBits);
+  end;
+
+{$IFDEF DEBUG}
+  System.Assert(padBits < 8);
+{$ENDIF DEBUG}
+  FmData := data;
+  FmPadBits := padBits;
+end;
+
+procedure TDerBitString.Encode(derOut: IDerOutputStream);
+var
+  last, mask, unusedBits: Int32;
+  contents: TCryptoLibByteArray;
+begin
+  if (mPadBits > 0) then
+  begin
+    last := mData[System.Length(mData) - 1];
+    mask := (1 shl mPadBits) - 1;
+    unusedBits := last and mask;
+
+    if (unusedBits <> 0) then
+    begin
+      contents := TArrayUtils.Prepend(mData, Byte(mPadBits));
+
+      // /*
+      // * X.690-0207 11.2.1: Each unused bit in the final octet of the encoding of a bit string value shall be set to zero.
+      // */
+      contents[System.Length(contents) - 1] := Byte(last xor unusedBits);
+
+      derOut.WriteEncoded(TAsn1Tags.BitString, contents);
+      Exit;
+    end;
+  end;
+
+  derOut.WriteEncoded(TAsn1Tags.BitString, Byte(mPadBits), mData);
+end;
+
+class function TDerBitString.FromAsn1Octets(octets: TCryptoLibByteArray)
+  : IDerBitString;
+var
+  padBits, last, mask: Int32;
+  data: TCryptoLibByteArray;
+begin
+  if (System.Length(octets) < 1) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@STruncatedBitString);
+  end;
+
+  padBits := octets[0];
+  data := TArrayUtils.CopyOfRange(octets, 1, System.Length(octets));
+
+  if ((padBits > 0) and (padBits < 8) and (System.Length(data) > 0)) then
+  begin
+    last := data[System.Length(data) - 1];
+    mask := (1 shl padBits) - 1;
+
+    if ((last and mask) <> 0) then
+    begin
+      result := TBerBitString.Create(data, padBits);
+      Exit;
+    end;
+  end;
+
+  result := TDerBitString.Create(data, padBits);
+end;
+
+function TDerBitString.GetBytes: TCryptoLibByteArray;
+begin
+  result := System.Copy(mData);
+
+  // DER requires pad bits be zero
+  if (mPadBits > 0) then
+  begin
+    result[System.Length(result) - 1] := result[System.Length(result) - 1] and
+      Byte($FF shl mPadBits);
+  end;
+
+end;
+
+class function TDerBitString.GetInstance(obj: IAsn1TaggedObject;
+  isExplicit: Boolean): IDerBitString;
+var
+  o: IAsn1Object;
+begin
+  o := obj.GetObject();
+
+  if ((isExplicit) or (Supports(o, IDerBitString))) then
+  begin
+    result := GetInstance(o as TAsn1Object);
+    Exit;
+  end;
+
+  result := FromAsn1Octets((o as IAsn1OctetString).GetOctets());
+end;
+
+function TDerBitString.GetInt32Value: Int32;
+var
+  value, &length, i, mask: Int32;
+begin
+  value := 0;
+  Length := Min(4, System.Length(mData));
+  for i := 0 to System.Pred(Length) do
+  begin
+    value := value or (Int32(mData[i]) shl (8 * i));
+  end;
+
+  if ((mPadBits > 0) and (Length = System.Length(mData))) then
+  begin
+    mask := (1 shl mPadBits) - 1;
+    value := value and (not(mask shl (8 * (Length - 1))));
+  end;
+  result := value;
+end;
+
+function TDerBitString.GetmData: TCryptoLibByteArray;
+begin
+  result := FmData;
+end;
+
+function TDerBitString.GetmPadBits: Int32;
+begin
+  result := FmPadBits;
+end;
+
+class function TDerBitString.GetInstance(obj: TObject): IDerBitString;
+begin
+  if ((obj = Nil) or (obj is TDerBitString)) then
+  begin
+    result := obj as TDerBitString;
+    Exit;
+  end;
+
+  raise EArgumentCryptoLibException.CreateResFmt(@SIllegalObject,
+    [obj.ClassName]);
+end;
+
+function TDerBitString.GetString: String;
+var
+  buffer: TStringList;
+  i: Int32;
+  str: TCryptoLibByteArray;
+  ubyte: UInt32;
+begin
+  buffer := TStringList.Create();
+  buffer.LineBreak := '';
+  str := GetDerEncoded();
+  buffer.Add('#');
+  i := 0;
+  try
+    while i <> System.Length(str) do
+    begin
+      ubyte := str[i];
+      buffer.Add(FTable[(ubyte shr 4) and $F]);
+      buffer.Add(FTable[str[i] and $F]);
+      System.Inc(i);
+    end;
+    result := buffer.Text;
+  finally
+    buffer.Free;
+  end;
+end;
+
+function TDerBitString.Asn1GetHashCode: Int32;
+begin
+  result := mPadBits xor TArrayUtils.GetArrayHashCode(mData);
+end;
+
+constructor TDerBitString.Create(obj: IAsn1Encodable);
+begin
+  Create(obj.GetDerEncoded());
+end;
+
+end.

+ 211 - 0
CryptoLib/src/Asn1/ClpDerBmpString.pas

@@ -0,0 +1,211 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerBmpString;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpCryptoLibTypes,
+  ClpAsn1Object,
+  ClpAsn1Tags,
+  ClpAsn1OctetString,
+  ClpIProxiedInterface,
+  ClpIDerBmpString,
+  ClpIAsn1TaggedObject,
+  ClpDerStringBase;
+
+resourcestring
+  SIllegalObject = 'Illegal Object in GetInstance: %s';
+  SEmptyInput = 'Input Cannot be Empty "astr"';
+
+type
+  TDerBmpString = class(TDerStringBase, IDerBmpString)
+
+  strict private
+  var
+    FStr: String;
+
+    function GetStr: String; inline;
+
+  strict protected
+    function Asn1Equals(asn1Object: IAsn1Object): Boolean; override;
+
+  public
+    property Str: String read GetStr;
+
+    /// <summary>
+    /// basic constructor - byte encoded string.
+    /// </summary>
+    constructor Create(astr: TCryptoLibByteArray); overload;
+
+    /// <summary>
+    /// basic constructor
+    /// </summary>
+    constructor Create(const astr: String); overload;
+
+    function GetString(): String; override;
+
+    procedure Encode(derOut: IDerOutputStream); override;
+
+    /// <summary>
+    /// return a BMP string from the given object.
+    /// </summary>
+    /// <param name="obj">
+    /// the object we want converted.
+    /// </param>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: TObject): IDerBmpString; overload;
+      static; inline;
+
+    /// <summary>
+    /// return a BMP string from a tagged object.
+    /// </summary>
+    /// <param name="obj">
+    /// the tagged object holding the object we want
+    /// </param>
+    /// <param name="isExplicit">
+    /// true if the object is meant to be explicitly tagged false otherwise.
+    /// </param>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the tagged object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: IAsn1TaggedObject; isExplicit: Boolean)
+      : IDerBmpString; overload; static; inline;
+
+  end;
+
+implementation
+
+{ TDerBmpString }
+
+function TDerBmpString.Asn1Equals(asn1Object: IAsn1Object): Boolean;
+var
+  other: IDerBmpString;
+begin
+
+  if (not Supports(asn1Object, IDerBmpString, other)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  result := Str = other.Str;
+end;
+
+constructor TDerBmpString.Create(astr: TCryptoLibByteArray);
+var
+  cs: TCryptoLibCharArray;
+  i: Int32;
+begin
+  Inherited Create();
+  if (astr = Nil) then
+  begin
+    raise EArgumentNilCryptoLibException.CreateRes(@SEmptyInput);
+  end;
+
+  System.SetLength(cs, System.Length(astr) div 2);
+
+  i := 0;
+
+  while i <> System.Length(cs) do
+  begin
+    cs[i] := Char((astr[2 * i] shl 8) or (astr[2 * i + 1] and $FF));
+    System.Inc(i);
+  end;
+
+  System.SetString(FStr, PChar(@cs[0]), System.Length(cs));
+end;
+
+constructor TDerBmpString.Create(const astr: String);
+begin
+  Inherited Create();
+  if (astr = '') then
+  begin
+    raise EArgumentNilCryptoLibException.CreateRes(@SEmptyInput);
+  end;
+
+  FStr := astr;
+end;
+
+procedure TDerBmpString.Encode(derOut: IDerOutputStream);
+var
+  c: TCryptoLibCharArray;
+  b: TCryptoLibByteArray;
+  i: Int32;
+begin
+  System.SetLength(c, System.Length(Str));
+  StrPLCopy(PChar(@c[0]), Str, System.Length(c));
+  System.SetLength(b, System.Length(c) * 2);
+
+  i := 0;
+
+  while i <> System.Length(c) do
+  begin
+    b[2 * i] := Byte(Ord(c[i]) shr 8);
+    b[2 * i + 1] := Byte(c[i]);
+    System.Inc(i);
+  end;
+
+  derOut.WriteEncoded(TAsn1Tags.BmpString, b);
+end;
+
+class function TDerBmpString.GetInstance(obj: TObject): IDerBmpString;
+begin
+  if ((obj = Nil) or (obj is TDerBmpString)) then
+  begin
+    result := obj as TDerBmpString;
+    Exit;
+  end;
+
+  raise EArgumentCryptoLibException.CreateResFmt(@SIllegalObject,
+    [obj.ClassName]);
+end;
+
+class function TDerBmpString.GetInstance(obj: IAsn1TaggedObject;
+  isExplicit: Boolean): IDerBmpString;
+var
+  o: IAsn1Object;
+begin
+  o := obj.GetObject();
+
+  if ((isExplicit) or (Supports(o, IDerBmpString))) then
+  begin
+    result := GetInstance(o as TAsn1Object);
+    Exit;
+  end;
+
+  result := TDerBmpString.Create(TAsn1OctetString.GetInstance(o as TAsn1Object)
+    .GetOctets());
+end;
+
+function TDerBmpString.GetStr: String;
+begin
+  result := FStr;
+end;
+
+function TDerBmpString.GetString: String;
+begin
+  result := FStr;
+end;
+
+end.

+ 261 - 0
CryptoLib/src/Asn1/ClpDerBoolean.pas

@@ -0,0 +1,261 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerBoolean;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpAsn1Tags,
+  ClpIAsn1OctetString,
+  ClpIDerBoolean,
+  ClpCryptoLibTypes,
+  ClpIProxiedInterface,
+  ClpIAsn1TaggedObject,
+  ClpAsn1Object;
+
+resourcestring
+  SIllegalObject = 'Illegal Object in GetInstance: %s';
+  SInvalidValue = 'Byte Value Should Have 1 Byte in it'', "val"';
+  SInvalidBooleanValue = 'BOOLEAN Value Should Have 1 Byte in it", "Value"';
+
+type
+  TDerBoolean = class(TAsn1Object, IDerBoolean)
+
+  strict private
+  var
+
+    Fvalue: Byte;
+
+    class var
+
+      FFalse, FTrue: IDerBoolean;
+
+    function GetIsTrue: Boolean; inline;
+
+    constructor Create(value: Boolean); overload;
+
+    class function GetFalse: IDerBoolean; static; inline;
+    class function GetTrue: IDerBoolean; static; inline;
+
+    class constructor DerBoolean();
+
+  strict protected
+    function Asn1Equals(asn1Object: IAsn1Object): Boolean; override;
+    function Asn1GetHashCode(): Int32; override;
+
+  public
+
+    constructor Create(val: TCryptoLibByteArray); overload;
+
+    procedure Encode(derOut: IDerOutputStream); override;
+
+    function ToString(): String; override;
+
+    property IsTrue: Boolean read GetIsTrue;
+
+    class property True: IDerBoolean read GetTrue;
+
+    class property False: IDerBoolean read GetFalse;
+
+    /// <summary>
+    /// return a DerBoolean from the passed in object.
+    /// </summary>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: TObject): IDerBoolean; overload;
+      static; inline;
+
+    /// <summary>
+    /// return a DerBoolean from the passed in boolean.
+    /// </summary>
+    class function GetInstance(value: Boolean): IDerBoolean; overload;
+      static; inline;
+
+    /// <summary>
+    /// return a Boolean from a tagged object.
+    /// </summary>
+    /// <param name="obj">
+    /// the tagged object holding the object we want
+    /// </param>
+    /// <param name="isExplicit">
+    /// explicitly true if the object is meant to be explicitly tagged false
+    /// otherwise.
+    /// </param>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the tagged object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: IAsn1TaggedObject; isExplicit: Boolean)
+      : IDerBoolean; overload; static; inline;
+
+    class function FromOctetString(value: TCryptoLibByteArray)
+      : IDerBoolean; static;
+
+  end;
+
+implementation
+
+{ TDerBoolean }
+
+function TDerBoolean.Asn1Equals(asn1Object: IAsn1Object): Boolean;
+var
+  other: IDerBoolean;
+begin
+
+  if (not Supports(asn1Object, IDerBoolean, other)) then
+  begin
+    result := System.False;
+    Exit;
+  end;
+
+  result := IsTrue = other.IsTrue;
+end;
+
+function TDerBoolean.Asn1GetHashCode: Int32;
+begin
+  result := Ord(IsTrue);
+end;
+
+constructor TDerBoolean.Create(val: TCryptoLibByteArray);
+begin
+  Inherited Create();
+  if (System.Length(val) <> 1) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SInvalidValue);
+  end;
+
+  // TODO Are there any constraints on the possible byte values?
+  Fvalue := val[0];
+end;
+
+constructor TDerBoolean.Create(value: Boolean);
+begin
+  Inherited Create();
+  if value then
+  begin
+    Fvalue := Byte($FF)
+  end
+  else
+  begin
+    Fvalue := Byte(0)
+  end;
+end;
+
+class constructor TDerBoolean.DerBoolean;
+begin
+  FFalse := TDerBoolean.Create(System.False);
+  FTrue := TDerBoolean.Create(System.True);
+end;
+
+procedure TDerBoolean.Encode(derOut: IDerOutputStream);
+begin
+  // TODO Should we make sure the byte value is one of '0' or '0xff' here?
+  derOut.WriteEncoded(TAsn1Tags.Boolean, TCryptoLibByteArray.Create(Fvalue));
+end;
+
+class function TDerBoolean.FromOctetString(value: TCryptoLibByteArray)
+  : IDerBoolean;
+var
+  b: Byte;
+begin
+  if (System.Length(value) <> 1) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SInvalidBooleanValue);
+  end;
+
+  b := value[0];
+
+  if b = 0 then
+  begin
+    result := FFalse;
+  end
+  else if b = $FF then
+  begin
+    result := FTrue;
+  end
+  else
+  begin
+    result := TDerBoolean.Create(value);
+  end;
+
+end;
+
+class function TDerBoolean.GetInstance(value: Boolean): IDerBoolean;
+begin
+  if value then
+  begin
+    result := FTrue;
+  end
+  else
+  begin
+    result := FFalse;
+  end;
+end;
+
+class function TDerBoolean.GetInstance(obj: TObject): IDerBoolean;
+begin
+  if ((obj = Nil) or (obj is TDerBoolean)) then
+  begin
+    Supports(obj, IDerBoolean, result);
+    Exit;
+  end;
+
+  raise EArgumentCryptoLibException.CreateResFmt(@SIllegalObject,
+    [obj.ClassName]);
+end;
+
+class function TDerBoolean.GetFalse: IDerBoolean;
+begin
+  result := FFalse;
+end;
+
+class function TDerBoolean.GetInstance(obj: IAsn1TaggedObject;
+  isExplicit: Boolean): IDerBoolean;
+var
+  o: IAsn1Object;
+begin
+  o := obj.GetObject();
+
+  if ((isExplicit) or (Supports(o, IDerBoolean))) then
+  begin
+    result := GetInstance(o as TAsn1Object);
+    Exit;
+  end;
+
+  result := FromOctetString((o as IAsn1OctetString).GetOctets());
+end;
+
+function TDerBoolean.GetIsTrue: Boolean;
+begin
+  result := Fvalue <> 0;
+end;
+
+class function TDerBoolean.GetTrue: IDerBoolean;
+begin
+  result := FTrue;
+end;
+
+function TDerBoolean.ToString: String;
+begin
+  result := BoolToStr(IsTrue, System.True);
+end;
+
+end.

+ 234 - 0
CryptoLib/src/Asn1/ClpDerEnumerated.pas

@@ -0,0 +1,234 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerEnumerated;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpCryptoLibTypes,
+  ClpArrayUtils,
+  ClpBigInteger,
+  ClpIAsn1OctetString,
+  ClpAsn1Tags,
+  ClpIProxiedInterface,
+  ClpIDerEnumerated,
+  ClpIAsn1TaggedObject,
+  ClpAsn1Object;
+
+resourcestring
+  SMalformedEnumerated = 'Malformed Enumerated';
+  SZeroLength = 'Enumerated has Zero Length, "enc"';
+  SIllegalObject = 'Illegal Object in GetInstance: %s';
+
+type
+  TDerEnumerated = class(TAsn1Object, IDerEnumerated)
+
+  strict private
+
+    class var
+
+      Fcache: TCryptoLibGenericArray<IDerEnumerated>;
+
+    function GetValue: TBigInteger; inline;
+    function GetBytes: TCryptoLibByteArray; inline;
+    class constructor DerEnumerated();
+
+  var
+    Fbytes: TCryptoLibByteArray;
+
+  strict protected
+
+    function Asn1Equals(asn1Object: IAsn1Object): Boolean; override;
+    function Asn1GetHashCode(): Int32; override;
+
+  public
+
+    constructor Create(val: Int32); overload;
+    constructor Create(val: TBigInteger); overload;
+    constructor Create(bytes: TCryptoLibByteArray); overload;
+
+    procedure Encode(derOut: IDerOutputStream); override;
+
+    property Value: TBigInteger read GetValue;
+    property bytes: TCryptoLibByteArray read GetBytes;
+
+    /// <summary>
+    /// return an integer from the passed in object
+    /// </summary>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the object cannot be converted.
+    /// </exception>
+
+    class function GetInstance(obj: TObject): IDerEnumerated; overload;
+      static; inline;
+
+    /// <summary>
+    /// return an Enumerated from a tagged object.
+    /// </summary>
+    /// <param name="obj">
+    /// the tagged object holding the object we want
+    /// </param>
+    /// <param name="isExplicit">
+    /// true if the object is meant to be explicitly tagged false otherwise.
+    /// </param>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the tagged object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: IAsn1TaggedObject; isExplicit: Boolean)
+      : IDerEnumerated; overload; static; inline;
+
+    class function FromOctetString(enc: TCryptoLibByteArray)
+      : IDerEnumerated; static;
+
+  end;
+
+implementation
+
+{ TDerEnumerated }
+
+function TDerEnumerated.Asn1Equals(asn1Object: IAsn1Object): Boolean;
+var
+  other: IDerEnumerated;
+begin
+
+  if (not Supports(asn1Object, IDerEnumerated, other)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  result := TArrayUtils.AreEqual(bytes, other.bytes);
+end;
+
+function TDerEnumerated.Asn1GetHashCode: Int32;
+begin
+  result := TArrayUtils.GetArrayHashCode(bytes);
+end;
+
+constructor TDerEnumerated.Create(val: Int32);
+begin
+  Inherited Create();
+  Fbytes := TBigInteger.ValueOf(val).ToByteArray();
+end;
+
+constructor TDerEnumerated.Create(val: TBigInteger);
+begin
+  Inherited Create();
+  Fbytes := val.ToByteArray();
+end;
+
+constructor TDerEnumerated.Create(bytes: TCryptoLibByteArray);
+begin
+  Inherited Create();
+  if (System.Length(bytes) > 1) then
+  begin
+    if ((bytes[0] = 0) and ((bytes[1] and $80) = 0)) then
+    begin
+      raise EArgumentCryptoLibException.CreateRes(@SMalformedEnumerated);
+    end;
+    if ((bytes[0] = Byte($FF)) and ((bytes[1] and $80) <> 0)) then
+    begin
+      raise EArgumentCryptoLibException.CreateRes(@SMalformedEnumerated);
+    end;
+  end;
+  Fbytes := System.Copy(bytes);
+end;
+
+class constructor TDerEnumerated.DerEnumerated;
+begin
+  System.SetLength(Fcache, 12);
+end;
+
+procedure TDerEnumerated.Encode(derOut: IDerOutputStream);
+begin
+  derOut.WriteEncoded(TAsn1Tags.Enumerated, Fbytes);
+end;
+
+class function TDerEnumerated.FromOctetString(enc: TCryptoLibByteArray)
+  : IDerEnumerated;
+var
+  LValue: Int32;
+  cached: IDerEnumerated;
+begin
+  if (System.Length(enc) = 0) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SZeroLength);
+  end;
+
+  if (System.Length(enc) = 1) then
+  begin
+    LValue := enc[0];
+    if (LValue < System.Length(Fcache)) then
+    begin
+      cached := Fcache[LValue];
+      if (cached <> Nil) then
+      begin
+        result := cached;
+        Exit;
+      end;
+      Fcache[LValue] := TDerEnumerated.Create(System.Copy(enc));
+      result := Fcache[LValue];
+      Exit;
+    end;
+  end;
+
+  result := TDerEnumerated.Create(System.Copy(enc));
+end;
+
+function TDerEnumerated.GetBytes: TCryptoLibByteArray;
+begin
+  result := Fbytes;
+end;
+
+class function TDerEnumerated.GetInstance(obj: TObject): IDerEnumerated;
+begin
+  if ((obj = Nil) or (obj is TDerEnumerated)) then
+  begin
+    result := obj as TDerEnumerated;
+    Exit;
+  end;
+
+  raise EArgumentCryptoLibException.CreateResFmt(@SIllegalObject,
+    [obj.ClassName]);
+end;
+
+class function TDerEnumerated.GetInstance(obj: IAsn1TaggedObject;
+  isExplicit: Boolean): IDerEnumerated;
+var
+  o: IAsn1Object;
+begin
+  o := obj.GetObject();
+
+  if (isExplicit or (Supports(o, IDerEnumerated))) then
+  begin
+    result := GetInstance(o as TObject);
+    Exit;
+  end;
+
+  result := FromOctetString((o as IAsn1OctetString).GetOctets());
+end;
+
+function TDerEnumerated.GetValue: TBigInteger;
+begin
+  result := TBigInteger.Create(Fbytes);
+end;
+
+end.

+ 363 - 0
CryptoLib/src/Asn1/ClpDerExternal.pas

@@ -0,0 +1,363 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerExternal;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  SysUtils,
+  ClpCryptoLibTypes,
+  ClpAsn1Object,
+  ClpIAsn1TaggedObject,
+  ClpDerTaggedObject,
+  ClpAsn1Tags,
+  ClpIAsn1EncodableVector,
+  ClpIDerTaggedObject,
+  ClpIProxiedInterface,
+  ClpIDerObjectIdentifier,
+  ClpIDerInteger,
+  ClpIDerExternal;
+
+resourcestring
+  SInvalidEncoding = 'Invalid Encoding Value: %d';
+  SFewObject = 'Too Few Objects in Input Vector, "v"';
+  SVectorTooLarge = 'Input Vector too Large", "vector"';
+  SNoTaggedObjectFound =
+    'No Tagged Object Found in Vector. Structure Doesn ''t Seem to be of Type External, "Vector"';
+  SInvalidEncodingValue = 'Invalid Encoding Value';
+
+type
+
+  /// <summary>
+  /// Class representing the DER-type External
+  /// </summary>
+  TDerExternal = class(TAsn1Object, IDerExternal)
+
+  strict private
+  var
+    FdirectReference: IDerObjectIdentifier;
+    FindirectReference: IDerInteger;
+    FdataValueDescriptor, FexternalContent: IAsn1Object;
+    Fencoding: Int32;
+
+    function GetDataValueDescriptor: IAsn1Object;
+    function GetDirectReference: IDerObjectIdentifier;
+
+    /// <summary>
+    /// <para>
+    /// The encoding of the content. Valid values are
+    /// </para>
+    /// <para>
+    /// &lt;ul&gt; <br />&lt;li&gt;&lt;code&gt;0&lt;/code&gt;
+    /// single-ASN1-type&lt;/li&gt; <br />
+    /// &lt;li&gt;&lt;code&gt;1&lt;/code&gt; OCTET STRING&lt;/li&gt; <br />
+    /// &lt;li&gt;&lt;code&gt;2&lt;/code&gt; BIT STRING&lt;/li&gt; <br />
+    /// &lt;/ul&gt;
+    /// </para>
+    /// </summary>
+    function GetEncoding: Int32;
+    function GetExternalContent: IAsn1Object;
+    function GetIndirectReference: IDerInteger;
+    procedure SetDataValueDescriptor(const Value: IAsn1Object);
+    procedure SetDirectReference(const Value: IDerObjectIdentifier);
+    procedure SetEncoding(const Value: Int32);
+    procedure SetExternalContent(const Value: IAsn1Object);
+    procedure SetIndirectReference(const Value: IDerInteger);
+
+    class function GetObjFromVector(v: IAsn1EncodableVector; index: Int32)
+      : IAsn1Object; static; inline;
+    class procedure WriteEncodable(ms: TMemoryStream; e: IAsn1Encodable);
+      static; inline;
+
+  strict protected
+    function Asn1GetHashCode(): Int32; override;
+    function Asn1Equals(asn1Object: IAsn1Object): Boolean; override;
+
+  public
+    constructor Create(vector: IAsn1EncodableVector); overload;
+
+    /// <summary>
+    /// Creates a new instance of DerExternal <br />See X.690 for more
+    /// informations about the meaning of these parameters
+    /// </summary>
+    /// <param name="directReference">
+    /// The direct reference or &lt;code&gt;null&lt;/code&gt; if not set.
+    /// </param>
+    /// <param name="indirectReference">
+    /// The indirect reference or &lt;code&gt;null&lt;/code&gt; if not set.
+    /// </param>
+    /// <param name="dataValueDescriptor">
+    /// The data value descriptor or &lt;code&gt;null&lt;/code&gt; if not
+    /// set.
+    /// </param>
+    /// <param name="externalData">
+    /// The external data in its encoded form.
+    /// </param>
+    constructor Create(directReference: IDerObjectIdentifier;
+      indirectReference: IDerInteger; dataValueDescriptor: IAsn1Object;
+      externalData: IDerTaggedObject); overload;
+
+    constructor Create(directReference: IDerObjectIdentifier;
+      indirectReference: IDerInteger; dataValueDescriptor: IAsn1Object;
+      encoding: Int32; externalData: IAsn1Object); overload;
+
+    procedure Encode(derOut: IDerOutputStream); override;
+
+    property dataValueDescriptor: IAsn1Object read GetDataValueDescriptor
+      write SetDataValueDescriptor;
+
+    property directReference: IDerObjectIdentifier read GetDirectReference
+      write SetDirectReference;
+
+    property encoding: Int32 read GetEncoding write SetEncoding;
+
+    property ExternalContent: IAsn1Object read GetExternalContent
+      write SetExternalContent;
+
+    property indirectReference: IDerInteger read GetIndirectReference
+      write SetIndirectReference;
+
+  end;
+
+implementation
+
+{ TDerExternal }
+
+class function TDerExternal.GetObjFromVector(v: IAsn1EncodableVector;
+  index: Int32): IAsn1Object;
+var
+  val: IAsn1Encodable;
+begin
+  if (v.Count <= index) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SFewObject);
+  end;
+
+  val := v[index];
+  result := val.ToAsn1Object();
+end;
+
+class procedure TDerExternal.WriteEncodable(ms: TMemoryStream;
+  e: IAsn1Encodable);
+var
+  bs: TCryptoLibByteArray;
+begin
+  if (e <> Nil) then
+  begin
+    bs := e.GetDerEncoded();
+    ms.Write(bs[0], System.Length(bs));
+  end;
+end;
+
+function TDerExternal.Asn1Equals(asn1Object: IAsn1Object): Boolean;
+var
+  other: IDerExternal;
+begin
+  if (Self.Equals(asn1Object)) then
+  begin
+    result := true;
+    Exit;
+  end;
+
+  if (not Supports(asn1Object, IDerExternal, other)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  result := directReference.Equals(other.directReference) and
+    indirectReference.Equals(other.indirectReference) and
+    dataValueDescriptor.Equals(other.dataValueDescriptor) and
+    ExternalContent.Equals(other.ExternalContent);
+end;
+
+function TDerExternal.Asn1GetHashCode: Int32;
+var
+  ret: Int32;
+begin
+  ret := ExternalContent.GetHashCode();
+  if (directReference <> Nil) then
+  begin
+    ret := ret xor directReference.GetHashCode();
+  end;
+  if (indirectReference <> Nil) then
+  begin
+    ret := ret xor indirectReference.GetHashCode();
+  end;
+  if (dataValueDescriptor <> Nil) then
+  begin
+    ret := ret xor dataValueDescriptor.GetHashCode();
+  end;
+  result := ret;
+end;
+
+constructor TDerExternal.Create(directReference: IDerObjectIdentifier;
+  indirectReference: IDerInteger; dataValueDescriptor: IAsn1Object;
+  encoding: Int32; externalData: IAsn1Object);
+begin
+  Inherited Create();
+  FdirectReference := directReference;
+  FindirectReference := indirectReference;
+  FdataValueDescriptor := dataValueDescriptor;
+  Fencoding := encoding;
+  FexternalContent := externalData.ToAsn1Object();
+end;
+
+constructor TDerExternal.Create(vector: IAsn1EncodableVector);
+var
+  offset: Int32;
+  enc: IAsn1Object;
+  derObjectIdentifier: IDerObjectIdentifier;
+  derInteger: IDerInteger;
+  obj: IAsn1TaggedObject;
+begin
+  Inherited Create();
+  offset := 0;
+  enc := GetObjFromVector(vector, offset);
+
+  if (Supports(enc, IDerObjectIdentifier, derObjectIdentifier)) then
+  begin
+    directReference := derObjectIdentifier;
+    System.Inc(offset);
+    enc := GetObjFromVector(vector, offset);
+  end;
+
+  if (Supports(enc, IDerInteger, derInteger)) then
+  begin
+    indirectReference := derInteger;
+    System.Inc(offset);
+    enc := GetObjFromVector(vector, offset);
+  end;
+  if (not(Supports(enc, IAsn1TaggedObject))) then
+  begin
+    dataValueDescriptor := enc;
+    System.Inc(offset);
+    enc := GetObjFromVector(vector, offset);
+  end;
+
+  if (vector.Count <> (offset + 1)) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SVectorTooLarge);
+  end;
+
+  if (not(Supports(enc, IAsn1TaggedObject, obj))) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SNoTaggedObjectFound);
+  end;
+
+  // Use property accessor to include check on value
+  encoding := obj.TagNo;
+
+  if ((Fencoding < 0) or (Fencoding > 2)) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateRes(@SInvalidEncodingValue);
+  end;
+
+  FexternalContent := obj.GetObject();
+end;
+
+constructor TDerExternal.Create(directReference: IDerObjectIdentifier;
+  indirectReference: IDerInteger; dataValueDescriptor: IAsn1Object;
+  externalData: IDerTaggedObject);
+begin
+  Create(directReference, indirectReference, dataValueDescriptor,
+    externalData.TagNo, externalData.ToAsn1Object());
+end;
+
+procedure TDerExternal.Encode(derOut: IDerOutputStream);
+var
+  ms: TMemoryStream;
+  Buffer: TCryptoLibByteArray;
+begin
+  ms := TMemoryStream.Create();
+  try
+    WriteEncodable(ms, directReference);
+    WriteEncodable(ms, indirectReference);
+    WriteEncodable(ms, dataValueDescriptor);
+    WriteEncodable(ms, TDerTaggedObject.Create(TAsn1Tags.External,
+      ExternalContent));
+
+    System.SetLength(Buffer, ms.Size);
+    ms.Position := 0;
+    ms.Read(Buffer[0], ms.Size);
+    derOut.WriteEncoded(TAsn1Tags.Constructed, TAsn1Tags.External, Buffer);
+  finally
+    ms.Free;
+  end;
+end;
+
+function TDerExternal.GetDataValueDescriptor: IAsn1Object;
+begin
+  result := FdataValueDescriptor;
+end;
+
+function TDerExternal.GetDirectReference: IDerObjectIdentifier;
+begin
+  result := FdirectReference;
+end;
+
+function TDerExternal.GetEncoding: Int32;
+begin
+  result := Fencoding;
+end;
+
+function TDerExternal.GetExternalContent: IAsn1Object;
+begin
+  result := FexternalContent;
+end;
+
+function TDerExternal.GetIndirectReference: IDerInteger;
+begin
+  result := FindirectReference;
+end;
+
+procedure TDerExternal.SetDataValueDescriptor(const Value: IAsn1Object);
+begin
+  FdataValueDescriptor := Value;
+end;
+
+procedure TDerExternal.SetDirectReference(const Value: IDerObjectIdentifier);
+begin
+  FdirectReference := Value;
+end;
+
+procedure TDerExternal.SetEncoding(const Value: Int32);
+begin
+  if ((Fencoding < 0) or (Fencoding > 2)) then
+  begin
+    raise EInvalidOperationCryptoLibException.CreateResFmt
+      (@SInvalidEncoding, [Value]);
+  end;
+
+  Fencoding := Value;
+end;
+
+procedure TDerExternal.SetExternalContent(const Value: IAsn1Object);
+begin
+  FexternalContent := Value;
+end;
+
+procedure TDerExternal.SetIndirectReference(const Value: IDerInteger);
+begin
+  FindirectReference := Value;
+end;
+
+end.

+ 66 - 0
CryptoLib/src/Asn1/ClpDerExternalParser.pas

@@ -0,0 +1,66 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerExternalParser;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIAsn1StreamParser,
+  ClpDerExternal,
+  ClpIProxiedInterface,
+  ClpIDerExternalParser,
+  ClpAsn1Encodable;
+
+type
+  TDerExternalParser = class(TAsn1Encodable, IDerExternalParser)
+
+  strict private
+  var
+    F_parser: IAsn1StreamParser;
+
+  public
+
+    constructor Create(parser: IAsn1StreamParser);
+    function ReadObject(): IAsn1Convertible; inline;
+    function ToAsn1Object(): IAsn1Object; override;
+
+  end;
+
+implementation
+
+{ TDerExternalParser }
+
+constructor TDerExternalParser.Create(parser: IAsn1StreamParser);
+begin
+  Inherited Create();
+  F_parser := parser;
+end;
+
+function TDerExternalParser.ReadObject: IAsn1Convertible;
+begin
+  result := F_parser.ReadObject();
+end;
+
+function TDerExternalParser.ToAsn1Object: IAsn1Object;
+begin
+  result := TDerExternal.Create(F_parser.ReadVector());
+end;
+
+end.

+ 164 - 0
CryptoLib/src/Asn1/ClpDerGeneralString.pas

@@ -0,0 +1,164 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerGeneralString;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpDerStringBase,
+  ClpAsn1Tags,
+  ClpAsn1OctetString,
+  ClpAsn1Object,
+  ClpIProxiedInterface,
+  ClpCryptoLibTypes,
+  ClpIAsn1TaggedObject,
+  ClpIDerGeneralString;
+
+resourcestring
+  SIllegalObject = 'Illegal Object in GetInstance: %s';
+  SStrNil = '"str"';
+
+type
+
+  TDerGeneralString = class(TDerStringBase, IDerGeneralString)
+
+  strict private
+  var
+    FStr: String;
+
+    function GetStr: String; inline;
+
+    property Str: String read GetStr;
+
+  strict protected
+    function Asn1Equals(asn1Object: IAsn1Object): Boolean; override;
+  public
+
+    constructor Create(Str: TCryptoLibByteArray); overload;
+
+    constructor Create(const Str: String); overload;
+
+    function GetString(): String; override;
+
+    function GetOctets(): TCryptoLibByteArray; inline;
+
+    procedure Encode(derOut: IDerOutputStream); override;
+
+    class function GetInstance(obj: TObject): IDerGeneralString; overload;
+      static; inline;
+
+    class function GetInstance(obj: IAsn1TaggedObject; isExplicit: Boolean)
+      : IDerGeneralString; overload; static; inline;
+
+  end;
+
+implementation
+
+{ TDerGeneralString }
+
+function TDerGeneralString.GetOctets: TCryptoLibByteArray;
+begin
+{$IFDEF FPC}
+  result := TEncoding.ASCII.GetBytes(UnicodeString(Str));
+{$ELSE}
+  result := TEncoding.ASCII.GetBytes(Str);
+{$ENDIF FPC}
+end;
+
+function TDerGeneralString.Asn1Equals(asn1Object: IAsn1Object): Boolean;
+var
+  other: IDerGeneralString;
+begin
+
+  if (not Supports(asn1Object, IDerGeneralString, other)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  result := Str = other.Str;
+end;
+
+constructor TDerGeneralString.Create(Str: TCryptoLibByteArray);
+begin
+{$IFDEF FPC}
+  Create(String(TEncoding.ASCII.GetString(Str)));
+{$ELSE}
+  Create(TEncoding.ASCII.GetString(Str));
+{$ENDIF FPC}
+end;
+
+constructor TDerGeneralString.Create(const Str: String);
+begin
+  Inherited Create();
+  if (Str = '') then
+  begin
+    raise EArgumentNilCryptoLibException.CreateRes(@SStrNil);
+  end;
+
+  FStr := Str;
+end;
+
+procedure TDerGeneralString.Encode(derOut: IDerOutputStream);
+begin
+  derOut.WriteEncoded(TAsn1Tags.GeneralString, GetOctets());
+end;
+
+class function TDerGeneralString.GetInstance(obj: IAsn1TaggedObject;
+  isExplicit: Boolean): IDerGeneralString;
+var
+  o: IAsn1Object;
+begin
+  o := obj.GetObject();
+
+  if ((isExplicit) or (Supports(o, IDerGeneralString))) then
+  begin
+    result := GetInstance(o as TAsn1Object);
+    Exit;
+  end;
+
+  result := TDerGeneralString.Create
+    (TAsn1OctetString.GetInstance(o as TAsn1Object).GetOctets());
+end;
+
+class function TDerGeneralString.GetInstance(obj: TObject): IDerGeneralString;
+begin
+  if ((obj = Nil) or (obj is TDerGeneralString)) then
+  begin
+    result := obj as TDerGeneralString;
+    Exit;
+  end;
+
+  raise EArgumentCryptoLibException.CreateResFmt(@SIllegalObject,
+    [obj.ClassName]);
+end;
+
+function TDerGeneralString.GetStr: String;
+begin
+  result := FStr;
+end;
+
+function TDerGeneralString.GetString: String;
+begin
+  result := Str;
+end;
+
+end.

+ 163 - 0
CryptoLib/src/Asn1/ClpDerGenerator.pas

@@ -0,0 +1,163 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerGenerator;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpBits,
+  ClpCryptoLibTypes,
+  ClpStreams,
+  ClpStreamHelper,
+  ClpAsn1Tags,
+  ClpAsn1Generator,
+  ClpIDerGenerator;
+
+type
+  TDerGenerator = class abstract(TAsn1Generator, IDerGenerator)
+
+  strict private
+  var
+    F_tagged, F_isExplicit: Boolean;
+    F_tagNo: Int32;
+
+    class procedure WriteLength(outStr: TStream; length: Int32); static;
+
+  strict protected
+    constructor Create(outStream: TStream); overload;
+    constructor Create(outStream: TStream; tagNo: Int32;
+      isExplicit: Boolean); overload;
+
+  public
+    procedure WriteDerEncoded(tag: Int32; bytes: TCryptoLibByteArray); overload;
+    class procedure WriteDerEncoded(outStream: TStream; tag: Int32;
+      bytes: TCryptoLibByteArray); overload; static;
+
+    class procedure WriteDerEncoded(outStr: TStream; tag: Int32;
+      inStr: TStream); overload; static;
+
+  end;
+
+implementation
+
+{ TDerGenerator }
+
+constructor TDerGenerator.Create(outStream: TStream);
+begin
+  Inherited Create(outStream);
+end;
+
+constructor TDerGenerator.Create(outStream: TStream; tagNo: Int32;
+  isExplicit: Boolean);
+begin
+  Inherited Create(outStream);
+  F_tagged := true;
+  F_isExplicit := isExplicit;
+  F_tagNo := tagNo;
+end;
+
+class procedure TDerGenerator.WriteDerEncoded(outStream: TStream; tag: Int32;
+  bytes: TCryptoLibByteArray);
+begin
+  outStream.WriteByte(Byte(tag));
+  WriteLength(outStream, System.length(bytes));
+  outStream.Write(bytes[0], System.length(bytes));
+end;
+
+procedure TDerGenerator.WriteDerEncoded(tag: Int32; bytes: TCryptoLibByteArray);
+var
+  tagNum, newTag: Int32;
+  bOut: TMemoryStream;
+  temp: TCryptoLibByteArray;
+begin
+  if (F_tagged) then
+  begin
+    tagNum := F_tagNo or TAsn1Tags.Tagged;
+
+    if (F_isExplicit) then
+    begin
+      newTag := F_tagNo or TAsn1Tags.Constructed or TAsn1Tags.Tagged;
+      bOut := TMemoryStream.Create();
+      try
+        WriteDerEncoded(bOut, tag, bytes);
+        bOut.Position := 0;
+        System.SetLength(temp, bOut.Size);
+        bOut.Read(temp[0], bOut.Size);
+        WriteDerEncoded(&Out, newTag, temp);
+      finally
+        bOut.Free;
+      end;
+    end
+    else
+    begin
+      if ((tag and TAsn1Tags.Constructed) <> 0) then
+      begin
+        tagNum := tagNum or TAsn1Tags.Constructed;
+      end;
+
+      WriteDerEncoded(&Out, tagNum, bytes);
+    end;
+  end
+  else
+  begin
+    WriteDerEncoded(&Out, tag, bytes);
+  end;
+end;
+
+class procedure TDerGenerator.WriteDerEncoded(outStr: TStream; tag: Int32;
+  inStr: TStream);
+begin
+  WriteDerEncoded(outStr, tag, TStreams.ReadAll(inStr));
+end;
+
+class procedure TDerGenerator.WriteLength(outStr: TStream; length: Int32);
+var
+  Size, val, i: Int32;
+begin
+  if (length > 127) then
+  begin
+    Size := 1;
+    val := length;
+
+    val := TBits.Asr32(val, 8);
+    while (val <> 0) do
+    begin
+      System.Inc(Size);
+      val := TBits.Asr32(val, 8);
+    end;
+
+    outStr.WriteByte(Byte(Size or $80));
+
+    i := (Size - 1) * 8;
+
+    while i >= 0 do
+    begin
+      outStr.WriteByte(Byte(TBits.Asr32(length, i)));
+      System.Dec(i, 8);
+    end;
+  end
+  else
+  begin
+    outStr.WriteByte(Byte(length));
+  end;
+end;
+
+end.

+ 202 - 0
CryptoLib/src/Asn1/ClpDerGraphicString.pas

@@ -0,0 +1,202 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerGraphicString;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpArrayUtils,
+  ClpCryptoLibTypes,
+  ClpAsn1Object,
+  ClpAsn1Tags,
+  ClpAsn1OctetString,
+  ClpIProxiedInterface,
+  ClpIDerGraphicString,
+  ClpIAsn1TaggedObject,
+  ClpDerStringBase;
+
+resourcestring
+  SIllegalObject = 'Illegal Object in GetInstance: %s';
+  SEncodingError = 'Encoding Error in GetInstance:  %s  "obj"';
+
+type
+  TDerGraphicString = class(TDerStringBase, IDerGraphicString)
+
+  strict private
+  var
+    FmString: TCryptoLibByteArray;
+
+    function GetmString: TCryptoLibByteArray; inline;
+
+  protected
+    function Asn1GetHashCode(): Int32; override;
+    function Asn1Equals(asn1Object: IAsn1Object): Boolean; override;
+
+  public
+    property mString: TCryptoLibByteArray read GetmString;
+
+    /// <summary>
+    /// basic constructor - with bytes.
+    /// </summary>
+    /// <param name="encoding">
+    /// the byte encoding of the characters making up the string.
+    /// </param>
+    constructor Create(encoding: TCryptoLibByteArray);
+
+    function GetString(): String; override;
+
+    function GetOctets(): TCryptoLibByteArray; inline;
+
+    procedure Encode(derOut: IDerOutputStream); override;
+
+    /// <summary>
+    /// return a Graphic String from the passed in object
+    /// </summary>
+    /// <param name="obj">
+    /// a DerGraphicString or an object that can be converted into one.
+    /// </param>
+    /// <returns>
+    /// return a DerGraphicString instance, or null.
+    /// </returns>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: TObject): IDerGraphicString; overload;
+      static; inline;
+
+    class function GetInstance(obj: TCryptoLibByteArray): IDerGraphicString;
+      overload; static;
+
+    /// <summary>
+    /// return a Graphic string from a tagged object.
+    /// </summary>
+    /// <param name="obj">
+    /// the tagged object holding the object we want
+    /// </param>
+    /// <param name="isExplicit">
+    /// true if the object is meant to be explicitly tagged false otherwise.
+    /// </param>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the tagged object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: IAsn1TaggedObject; isExplicit: Boolean)
+      : IDerGraphicString; overload; static; inline;
+
+  end;
+
+implementation
+
+{ TDerGraphicString }
+
+function TDerGraphicString.Asn1Equals(asn1Object: IAsn1Object): Boolean;
+var
+  other: IDerGraphicString;
+begin
+
+  if (not Supports(asn1Object, IDerGraphicString, other)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  result := TArrayUtils.AreEqual(mString, other.mString);
+end;
+
+function TDerGraphicString.Asn1GetHashCode: Int32;
+begin
+  result := TArrayUtils.GetArrayHashCode(mString);
+end;
+
+constructor TDerGraphicString.Create(encoding: TCryptoLibByteArray);
+begin
+  Inherited Create();
+  FmString := System.Copy(encoding);
+end;
+
+procedure TDerGraphicString.Encode(derOut: IDerOutputStream);
+begin
+  derOut.WriteEncoded(TAsn1Tags.GraphicString, mString);
+end;
+
+class function TDerGraphicString.GetInstance(obj: TObject): IDerGraphicString;
+begin
+  if ((obj = Nil) or (obj is TDerGraphicString)) then
+  begin
+    result := obj as TDerGraphicString;
+    Exit;
+  end;
+
+  raise EArgumentCryptoLibException.CreateResFmt(@SIllegalObject,
+    [obj.ClassName]);
+end;
+
+class function TDerGraphicString.GetInstance(obj: IAsn1TaggedObject;
+  isExplicit: Boolean): IDerGraphicString;
+var
+  o: IAsn1Object;
+begin
+  o := obj.GetObject();
+
+  if ((isExplicit) or (Supports(o, IDerGraphicString))) then
+  begin
+    result := GetInstance(o as TAsn1Object);
+    Exit;
+  end;
+
+  result := TDerGraphicString.Create
+    (TAsn1OctetString.GetInstance(o as TAsn1Object).GetOctets());
+end;
+
+class function TDerGraphicString.GetInstance(obj: TCryptoLibByteArray)
+  : IDerGraphicString;
+begin
+  try
+    result := FromByteArray(obj) as IDerGraphicString;
+  except
+    on e: Exception do
+    begin
+      raise EArgumentCryptoLibException.CreateResFmt(@SEncodingError,
+        [e.Message]);
+    end;
+
+  end;
+end;
+
+function TDerGraphicString.GetmString: TCryptoLibByteArray;
+begin
+  result := FmString;
+end;
+
+function TDerGraphicString.GetOctets: TCryptoLibByteArray;
+begin
+  result := System.Copy(mString);
+end;
+
+function TDerGraphicString.GetString: String;
+begin
+{$IFDEF FPC}
+  result := String(TEncoding.ASCII.GetString(mString)); // encoding.default
+{$ELSE}
+  result := TEncoding.ASCII.GetString(mString); // encoding.default
+{$ENDIF FPC}
+end;
+
+end.

+ 253 - 0
CryptoLib/src/Asn1/ClpDerIA5String.pas

@@ -0,0 +1,253 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerIA5String;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpDerStringBase,
+  ClpAsn1Tags,
+  ClpAsn1OctetString,
+  ClpAsn1Object,
+  ClpStringHelper,
+  ClpIProxiedInterface,
+  ClpCryptoLibTypes,
+  ClpIAsn1TaggedObject,
+  ClpIDerIA5String;
+
+resourcestring
+  SIllegalObject = 'Illegal Object in GetInstance: %s';
+  SIllegalCharacters = 'String Contains Illegal Characters "str"';
+  SStrNil = '"str"';
+
+type
+
+  /// <summary>
+  /// Der IA5String object - this is an ascii string.
+  /// </summary>
+  TDerIA5String = class(TDerStringBase, IDerIA5String)
+
+  strict private
+  var
+    FStr: String;
+
+    function GetStr: String; inline;
+    property Str: String read GetStr;
+
+  strict protected
+    function Asn1GetHashCode(): Int32; override;
+    function Asn1Equals(asn1Object: IAsn1Object): Boolean; override;
+  public
+
+    /// <summary>
+    /// basic constructor - with bytes.
+    /// </summary>
+    constructor Create(Str: TCryptoLibByteArray); overload;
+
+    /// <summary>
+    /// basic constructor - without validation.
+    /// </summary>
+    constructor Create(const Str: String); overload;
+
+    /// <summary>
+    /// Constructor with optional validation.
+    /// </summary>
+    /// <param name="Str">
+    /// the base string to wrap.
+    /// </param>
+    /// <param name="validate">
+    /// whether or not to check the string.
+    /// </param>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if validate is true and the string contains characters that should
+    /// not be in an IA5String.
+    /// </exception>
+    constructor Create(const Str: String; validate: Boolean); overload;
+
+    function GetString(): String; override;
+
+    function GetOctets(): TCryptoLibByteArray; inline;
+
+    procedure Encode(derOut: IDerOutputStream); override;
+
+    /// <summary>
+    /// return a DerIA5String from the passed in object
+    /// </summary>
+    /// <param name="obj">
+    /// a DerIA5String or an object that can be converted into one.
+    /// </param>
+    /// <returns>
+    /// return a DerIA5String instance, or null.
+    /// </returns>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: TObject): IDerIA5String; overload;
+      static; inline;
+
+    /// <summary>
+    /// return a DerIA5String from a tagged object.
+    /// </summary>
+    /// <param name="obj">
+    /// the tagged object holding the object we want
+    /// </param>
+    /// <param name="isExplicit">
+    /// true if the object is meant to be explicitly tagged false otherwise.
+    /// </param>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the tagged object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: IAsn1TaggedObject; isExplicit: Boolean)
+      : IDerIA5String; overload; static; inline;
+
+    /// <summary>
+    /// return true if the passed in String can be represented without loss
+    /// as an IA5String, false otherwise.
+    /// </summary>
+    /// <param name="Str">
+    /// true if in printable set, false otherwise.
+    /// </param>
+    class function IsIA5String(const Str: String): Boolean; static; inline;
+
+  end;
+
+implementation
+
+{ TDerIA5String }
+
+function TDerIA5String.GetOctets: TCryptoLibByteArray;
+begin
+{$IFDEF FPC}
+  result := TEncoding.ASCII.GetBytes(UnicodeString(Str));
+{$ELSE}
+  result := TEncoding.ASCII.GetBytes(Str);
+{$ENDIF FPC}
+end;
+
+class function TDerIA5String.IsIA5String(const Str: String): Boolean;
+var
+  ch: Char;
+begin
+  for ch in Str do
+  begin
+    if (Ord(ch) > $007F) then
+    begin
+      result := false;
+      Exit;
+    end;
+  end;
+
+  result := true;
+end;
+
+function TDerIA5String.Asn1Equals(asn1Object: IAsn1Object): Boolean;
+var
+  other: IDerIA5String;
+begin
+
+  if (not Supports(asn1Object, IDerIA5String, other)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  result := Str = other.Str;
+end;
+
+function TDerIA5String.Asn1GetHashCode: Int32;
+begin
+  result := Str.GetHashCode;
+end;
+
+constructor TDerIA5String.Create(Str: TCryptoLibByteArray);
+begin
+{$IFDEF FPC}
+  Create(String(TEncoding.ASCII.GetString(Str)), false);
+{$ELSE}
+  Create(TEncoding.ASCII.GetString(Str), false);
+{$ENDIF FPC}
+end;
+
+constructor TDerIA5String.Create(const Str: String);
+begin
+  Create(Str, false);
+end;
+
+constructor TDerIA5String.Create(const Str: String; validate: Boolean);
+begin
+  Inherited Create();
+  if (Str = '') then
+  begin
+    raise EArgumentNilCryptoLibException.CreateRes(@SStrNil);
+  end;
+  if (validate and (not IsIA5String(Str))) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SIllegalCharacters);
+  end;
+
+  FStr := Str;
+end;
+
+procedure TDerIA5String.Encode(derOut: IDerOutputStream);
+begin
+  derOut.WriteEncoded(TAsn1Tags.IA5String, GetOctets());
+end;
+
+class function TDerIA5String.GetInstance(obj: IAsn1TaggedObject;
+  isExplicit: Boolean): IDerIA5String;
+var
+  o: IAsn1Object;
+begin
+  o := obj.GetObject();
+
+  if ((isExplicit) or (Supports(o, IDerIA5String))) then
+  begin
+    result := GetInstance(o as TAsn1Object);
+    Exit;
+  end;
+
+  result := TDerIA5String.Create(TAsn1OctetString.GetInstance(o as TAsn1Object)
+    .GetOctets());
+end;
+
+class function TDerIA5String.GetInstance(obj: TObject): IDerIA5String;
+begin
+  if ((obj = Nil) or (obj is TDerIA5String)) then
+  begin
+    result := obj as TDerIA5String;
+    Exit;
+  end;
+
+  raise EArgumentCryptoLibException.CreateResFmt(@SIllegalObject,
+    [obj.ClassName]);
+end;
+
+function TDerIA5String.GetStr: String;
+begin
+  result := FStr;
+end;
+
+function TDerIA5String.GetString: String;
+begin
+  result := Str;
+end;
+
+end.

+ 209 - 0
CryptoLib/src/Asn1/ClpDerInteger.pas

@@ -0,0 +1,209 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerInteger;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpCryptoLibTypes,
+  ClpBigInteger,
+  ClpAsn1Object,
+  ClpIProxiedInterface,
+  ClpIAsn1TaggedObject,
+  ClpAsn1OctetString,
+  ClpAsn1Tags,
+  ClpArrayUtils,
+  ClpIDerInteger;
+
+resourcestring
+  SIllegalObject = 'Illegal Object in GetInstance: %s';
+  SObjectNil = ' "obj" Can''t be Nil';
+  SValueNil = ' "value" Can''t be Nil';
+  SMalformedInteger = 'Malformed Integer';
+
+type
+  TDerInteger = class sealed(TAsn1Object, IDerInteger)
+
+  strict private
+  var
+    Fbytes: TCryptoLibByteArray;
+
+    function GetBytes: TCryptoLibByteArray; inline;
+    function GetPositiveValue: TBigInteger; inline;
+    function GetValue: TBigInteger; inline;
+  strict protected
+    function Asn1GetHashCode(): Int32; override;
+    function Asn1Equals(asn1Object: IAsn1Object): Boolean; override;
+
+  public
+
+    constructor Create(value: Int32); overload;
+    constructor Create(value: TBigInteger); overload;
+    constructor Create(bytes: TCryptoLibByteArray); overload;
+
+    property value: TBigInteger read GetValue;
+    property PositiveValue: TBigInteger read GetPositiveValue;
+    property bytes: TCryptoLibByteArray read GetBytes;
+
+    procedure Encode(derOut: IDerOutputStream); override;
+
+    function ToString(): String; override;
+
+    // /**
+    // * return an integer from the passed in object
+    // *
+    // * @exception ArgumentException if the object cannot be converted.
+    // */
+
+    class function GetInstance(obj: TObject): IDerInteger; overload;
+      static; inline;
+
+    // /**
+    // * return an Integer from a tagged object.
+    // *
+    // * @param obj the tagged object holding the object we want
+    // * @param isExplicit true if the object is meant to be explicitly
+    // *              tagged false otherwise.
+    // * @exception ArgumentException if the tagged object cannot
+    // *               be converted.
+    // */
+    class function GetInstance(obj: IAsn1TaggedObject; isExplicit: Boolean)
+      : IDerInteger; overload; static; inline;
+
+  end;
+
+implementation
+
+{ TDerInteger }
+
+class function TDerInteger.GetInstance(obj: TObject): IDerInteger;
+begin
+  if ((obj = Nil) or (obj is TDerInteger)) then
+  begin
+    Result := obj as TDerInteger;
+    Exit;
+  end;
+
+  raise EArgumentCryptoLibException.CreateResFmt(@SIllegalObject,
+    [obj.ClassName]);
+
+end;
+
+function TDerInteger.Asn1Equals(asn1Object: IAsn1Object): Boolean;
+var
+  other: IDerInteger;
+begin
+
+  if (not Supports(asn1Object, IDerInteger, other)) then
+  begin
+    Result := false;
+    Exit;
+  end;
+
+  Result := TArrayUtils.AreEqual(bytes, other.bytes);
+end;
+
+function TDerInteger.Asn1GetHashCode: Int32;
+begin
+  Result := TArrayUtils.GetArrayHashCode(Fbytes);
+end;
+
+constructor TDerInteger.Create(value: TBigInteger);
+begin
+  inherited Create();
+  if (not value.IsInitialized) then
+  begin
+    raise EArgumentNilCryptoLibException.CreateRes(@SValueNil);
+  end;
+
+  Fbytes := value.ToByteArray();
+end;
+
+constructor TDerInteger.Create(value: Int32);
+begin
+  inherited Create();
+  Fbytes := TBigInteger.ValueOf(value).ToByteArray();
+end;
+
+constructor TDerInteger.Create(bytes: TCryptoLibByteArray);
+begin
+  inherited Create();
+  if (System.Length(bytes) > 1) then
+  begin
+    if ((bytes[0] = 0) and ((bytes[1] and $80) = 0)) then
+    begin
+      raise EArgumentCryptoLibException.CreateRes(@SMalformedInteger);
+    end;
+    if ((bytes[0] = Byte($FF)) and ((bytes[1] and $80) <> 0)) then
+    begin
+      raise EArgumentCryptoLibException.CreateRes(@SMalformedInteger);
+    end;
+  end;
+  Fbytes := System.Copy(bytes);
+end;
+
+procedure TDerInteger.Encode(derOut: IDerOutputStream);
+begin
+  derOut.WriteEncoded(TAsn1Tags.Integer, Fbytes);
+end;
+
+function TDerInteger.GetBytes: TCryptoLibByteArray;
+begin
+  Result := Fbytes;
+end;
+
+class function TDerInteger.GetInstance(obj: IAsn1TaggedObject;
+  isExplicit: Boolean): IDerInteger;
+var
+  o: IAsn1Object;
+begin
+  if (obj = Nil) then
+    raise EArgumentNilCryptoLibException.CreateRes(@SObjectNil);
+
+  o := obj.GetObject();
+
+  if ((isExplicit) or (Supports(o, IDerInteger))) then
+  begin
+    Result := GetInstance(o as TAsn1Object);
+    Exit;
+  end;
+
+  Result := TDerInteger.Create(TAsn1OctetString.GetInstance(o as TAsn1Object)
+    .GetOctets());
+
+end;
+
+function TDerInteger.GetPositiveValue: TBigInteger;
+begin
+  Result := TBigInteger.Create(1, Fbytes);
+end;
+
+function TDerInteger.GetValue: TBigInteger;
+begin
+  Result := TBigInteger.Create(Fbytes);
+end;
+
+function TDerInteger.ToString: String;
+begin
+  Result := value.ToString();
+end;
+
+end.

+ 100 - 0
CryptoLib/src/Asn1/ClpDerNull.pas

@@ -0,0 +1,100 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerNull;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpCryptoLibTypes,
+  ClpAsn1Tags,
+  ClpIProxiedInterface,
+  ClpAsn1Null,
+  ClpIDerNull;
+
+type
+
+  /// <summary>
+  /// A Null object.
+  /// </summary>
+  TDerNull = class(TAsn1Null, IDerNull)
+
+  strict private
+
+    class function GetInstance: IDerNull; static; inline;
+
+  class var
+
+    FInstance: IDerNull;
+    FZeroBytes: TCryptoLibByteArray;
+
+    class constructor DerNull();
+
+  strict protected
+    constructor Create(dummy: Int32);
+    function Asn1Equals(asn1Object: IAsn1Object): Boolean; override;
+    function Asn1GetHashCode(): Int32; override;
+
+  public
+
+    procedure Encode(derOut: IDerOutputStream); override;
+    class property Instance: IDerNull read GetInstance;
+
+  end;
+
+implementation
+
+{ TDerNull }
+
+function TDerNull.Asn1Equals(asn1Object: IAsn1Object): Boolean;
+begin
+  result := Supports(asn1Object, IDerNull);
+end;
+
+function TDerNull.Asn1GetHashCode: Int32;
+begin
+  result := -1;
+end;
+
+{$IFNDEF _FIXINSIGHT_}
+
+constructor TDerNull.Create(dummy: Int32);
+begin
+  Inherited Create();
+end;
+{$ENDIF}
+
+class constructor TDerNull.DerNull;
+begin
+  FInstance := TDerNull.Create(0);
+  System.SetLength(FZeroBytes, 0);
+end;
+
+procedure TDerNull.Encode(derOut: IDerOutputStream);
+begin
+  derOut.WriteEncoded(TAsn1Tags.Null, FZeroBytes);
+end;
+
+class function TDerNull.GetInstance: IDerNull;
+begin
+  result := FInstance;
+end;
+
+end.

+ 252 - 0
CryptoLib/src/Asn1/ClpDerNumericString.pas

@@ -0,0 +1,252 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerNumericString;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpDerStringBase,
+  ClpAsn1Tags,
+  ClpAsn1OctetString,
+  ClpAsn1Object,
+  ClpIProxiedInterface,
+  ClpCryptoLibTypes,
+  ClpIAsn1TaggedObject,
+  ClpIDerNumericString;
+
+resourcestring
+  SIllegalObject = 'Illegal Object in GetInstance: %s';
+  SIllegalCharacters = 'String Contains Illegal Characters "str"';
+  SStrNil = '"str"';
+
+type
+
+  /// <summary>
+  /// Der NumericString object - this is an ascii string of characters
+  /// {0,1,2,3,4,5,6,7,8,9, }.
+  /// </summary>
+  TDerNumericString = class(TDerStringBase, IDerNumericString)
+
+  strict private
+  var
+    FStr: String;
+
+    function GetStr: String; inline;
+    property Str: String read GetStr;
+
+  strict protected
+    function Asn1Equals(asn1Object: IAsn1Object): Boolean; override;
+  public
+
+    /// <summary>
+    /// basic constructor - with bytes.
+    /// </summary>
+    constructor Create(Str: TCryptoLibByteArray); overload;
+
+    /// <summary>
+    /// basic constructor - without validation.
+    /// </summary>
+    constructor Create(const Str: String); overload;
+
+    /// <summary>
+    /// Constructor with optional validation.
+    /// </summary>
+    /// <param name="Str">
+    /// the base string to wrap.
+    /// </param>
+    /// <param name="validate">
+    /// whether or not to check the string.
+    /// </param>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if validate is true and the string contains characters that should
+    /// not be in an IA5String.
+    /// </exception>
+    constructor Create(const Str: String; validate: Boolean); overload;
+
+    function GetString(): String; override;
+
+    function GetOctets(): TCryptoLibByteArray; inline;
+
+    procedure Encode(derOut: IDerOutputStream); override;
+
+    /// <summary>
+    /// return a Numeric string from the passed in object
+    /// </summary>
+    /// <param name="obj">
+    /// a DerNumericString or an object that can be converted into one.
+    /// </param>
+    /// <returns>
+    /// return a DerNumericString instance, or null.
+    /// </returns>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: TObject): IDerNumericString; overload;
+      static; inline;
+
+    /// <summary>
+    /// return a Numeric String from a tagged object.
+    /// </summary>
+    /// <param name="obj">
+    /// the tagged object holding the object we want
+    /// </param>
+    /// <param name="isExplicit">
+    /// true if the object is meant to be explicitly tagged false otherwise.
+    /// </param>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the tagged object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: IAsn1TaggedObject; isExplicit: Boolean)
+      : IDerNumericString; overload; static; inline;
+
+    /// <summary>
+    /// Return true if the string can be represented as a NumericString
+    /// ('0'..'9', ' ')
+    /// </summary>
+    /// <param name="Str">
+    /// string to validate.
+    /// </param>
+    /// <returns>
+    /// true if numeric, false otherwise.
+    /// </returns>
+    class function IsNumericString(const Str: String): Boolean; static; inline;
+
+  end;
+
+implementation
+
+{ TDerNumericString }
+
+function TDerNumericString.GetOctets: TCryptoLibByteArray;
+begin
+{$IFDEF FPC}
+  result := TEncoding.ASCII.GetBytes(UnicodeString(Str));
+{$ELSE}
+  result := TEncoding.ASCII.GetBytes(Str);
+{$ENDIF FPC}
+end;
+
+class function TDerNumericString.IsNumericString(const Str: String): Boolean;
+var
+  ch: Char;
+begin
+  for ch in Str do
+  begin
+    // char.IsDigit(ch)
+    if ((Ord(ch) > $007F) or ((ch <> ' ') and (not CharInSet(ch, ['0' .. '9']))))
+    then
+    begin
+      result := false;
+      Exit;
+    end;
+  end;
+
+  result := true;
+end;
+
+function TDerNumericString.Asn1Equals(asn1Object: IAsn1Object): Boolean;
+var
+  other: IDerNumericString;
+begin
+
+  if (not Supports(asn1Object, IDerNumericString, other)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  result := Str = other.Str;
+end;
+
+constructor TDerNumericString.Create(Str: TCryptoLibByteArray);
+begin
+{$IFDEF FPC}
+  Create(String(TEncoding.ASCII.GetString(Str)), false);
+{$ELSE}
+  Create(TEncoding.ASCII.GetString(Str), false);
+{$ENDIF FPC}
+end;
+
+constructor TDerNumericString.Create(const Str: String);
+begin
+  Create(Str, false);
+end;
+
+constructor TDerNumericString.Create(const Str: String; validate: Boolean);
+begin
+  Inherited Create();
+  if (Str = '') then
+  begin
+    raise EArgumentNilCryptoLibException.CreateRes(@SStrNil);
+  end;
+  if (validate and (not IsNumericString(Str))) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SIllegalCharacters);
+  end;
+
+  FStr := Str;
+end;
+
+procedure TDerNumericString.Encode(derOut: IDerOutputStream);
+begin
+  derOut.WriteEncoded(TAsn1Tags.NumericString, GetOctets());
+end;
+
+class function TDerNumericString.GetInstance(obj: IAsn1TaggedObject;
+  isExplicit: Boolean): IDerNumericString;
+var
+  o: IAsn1Object;
+begin
+  o := obj.GetObject();
+
+  if ((isExplicit) or (Supports(o, IDerNumericString))) then
+  begin
+    result := GetInstance(o as TAsn1Object);
+    Exit;
+  end;
+
+  result := TDerNumericString.Create
+    (TAsn1OctetString.GetInstance(o as TAsn1Object).GetOctets());
+end;
+
+class function TDerNumericString.GetInstance(obj: TObject): IDerNumericString;
+begin
+  if ((obj = Nil) or (obj is TDerNumericString)) then
+  begin
+    result := obj as TDerNumericString;
+    Exit;
+  end;
+
+  raise EArgumentCryptoLibException.CreateResFmt(@SIllegalObject,
+    [obj.ClassName]);
+end;
+
+function TDerNumericString.GetStr: String;
+begin
+  result := FStr;
+end;
+
+function TDerNumericString.GetString: String;
+begin
+  result := Str;
+end;
+
+end.

+ 578 - 0
CryptoLib/src/Asn1/ClpDerObjectIdentifier.pas

@@ -0,0 +1,578 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerObjectIdentifier;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  SysUtils,
+  StrUtils,
+  SyncObjs,
+  ClpBits,
+  ClpArrayUtils,
+  ClpStringHelper,
+  ClpStreamHelper,
+  ClpBigInteger,
+  ClpCryptoLibTypes,
+  ClpAsn1Tags,
+  ClpOidTokenizer,
+  ClpIOidTokenizer,
+  ClpAsn1Object,
+  ClpAsn1OctetString,
+  ClpIAsn1TaggedObject,
+  ClpIProxiedInterface,
+  ClpIDerObjectIdentifier;
+
+resourcestring
+  SIllegalObject = 'Illegal Object in GetInstance: %s';
+  SIdentifierNil = 'Identifier Cannot be Empty';
+  SInvalidOID = '"String " %s is " not an OID"';
+  SInvalidBranchId = '"String " %s " not a valid OID branch", "branchID"';
+
+type
+  TDerObjectIdentifier = class(TAsn1Object, IDerObjectIdentifier)
+
+  strict private
+
+  const
+    LONG_LIMIT = Int64((Int64($7FFFFFFFFFFFFFFF) shr 7) - $7F);
+
+  class var
+
+    FLock: TCriticalSection;
+    Fcache: TCryptoLibGenericArray<IDerObjectIdentifier>;
+
+  var
+    Fidentifier: String;
+    Fbody: TCryptoLibByteArray;
+
+    class constructor CreateDerObjectIdentifier();
+    class destructor DestroyDerObjectIdentifier();
+
+    constructor Create(oid: IDerObjectIdentifier;
+      const branchID: String); overload;
+    constructor Create(bytes: TCryptoLibByteArray); overload;
+
+    function GetID: String; inline;
+
+    procedure WriteField(outputStream: TStream; fieldValue: Int64); overload;
+    procedure WriteField(outputStream: TStream;
+      fieldValue: TBigInteger); overload;
+    procedure DoOutput(bOut: TMemoryStream); overload;
+    function GetBody(): TCryptoLibByteArray;
+    class function IsValidBranchID(const branchID: String; start: Int32)
+      : Boolean; static;
+    class function IsValidIdentifier(const identifier: String): Boolean; static;
+    class function MakeOidStringFromBytes(bytes: TCryptoLibByteArray)
+      : String; static;
+
+  strict protected
+    function Asn1GetHashCode(): Int32; override;
+    function Asn1Equals(asn1Object: IAsn1Object): Boolean; override;
+
+  public
+    // /**
+    // * return an Oid from the passed in object
+    // *
+    // * @exception ArgumentException if the object cannot be converted.
+    // */
+    class function GetInstance(obj: TObject): IDerObjectIdentifier;
+      overload; static;
+
+    // /**
+    // * return an Oid from the passed in byte array
+    // */
+    class function GetInstance(obj: TCryptoLibByteArray): IDerObjectIdentifier;
+      overload; static; inline;
+
+    // /**
+    // * return an object Identifier from a tagged object.
+    // *
+    // * @param obj the tagged object holding the object we want
+    // * @param explicitly true if the object is meant to be explicitly
+    // *              tagged false otherwise.
+    // * @exception ArgumentException if the tagged object cannot
+    // *               be converted.
+    // */
+    class function GetInstance(obj: IAsn1TaggedObject; explicitly: Boolean)
+      : IDerObjectIdentifier; overload; static; inline;
+
+    class function FromOctetString(enc: TCryptoLibByteArray)
+      : IDerObjectIdentifier; static;
+
+    constructor Create(const identifier: String); overload;
+
+    property ID: String read GetID;
+
+    function Branch(const branchID: String): IDerObjectIdentifier; virtual;
+
+    // /**
+    // * Return  true if this oid is an extension of the passed in branch, stem.
+    // * @param stem the arc or branch that is a possible parent.
+    // * @return  true if the branch is on the passed in stem, false otherwise.
+    // */
+
+    function &On(stem: IDerObjectIdentifier): Boolean; virtual;
+
+    procedure Encode(derOut: IDerOutputStream); override;
+
+    function ToString(): String; override;
+
+  end;
+
+implementation
+
+{ TDerObjectIdentifier }
+
+function TDerObjectIdentifier.Asn1Equals(asn1Object: IAsn1Object): Boolean;
+var
+  other: IDerObjectIdentifier;
+begin
+  if (not Supports(asn1Object, IDerObjectIdentifier, other)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  result := ID = other.ID;
+end;
+
+function TDerObjectIdentifier.Asn1GetHashCode: Int32;
+begin
+  result := Fidentifier.GetHashCode();
+end;
+
+function TDerObjectIdentifier.Branch(const branchID: String)
+  : IDerObjectIdentifier;
+begin
+  result := TDerObjectIdentifier.Create(Self as IDerObjectIdentifier, branchID);
+end;
+
+constructor TDerObjectIdentifier.Create(oid: IDerObjectIdentifier;
+  const branchID: String);
+begin
+  Inherited Create();
+  if (not(IsValidBranchID(branchID, 1))) then
+    raise EArgumentCryptoLibException.CreateResFmt(@SInvalidBranchId,
+      [branchID]);
+
+  Fidentifier := oid.ID + '.' + branchID;
+end;
+
+constructor TDerObjectIdentifier.Create(const identifier: String);
+begin
+  Inherited Create();
+  if (identifier = '') then
+    raise EArgumentNilCryptoLibException.CreateRes(@SIdentifierNil);
+  if (not(IsValidIdentifier(identifier))) then
+    raise EFormatCryptoLibException.CreateResFmt(@SInvalidOID, [identifier]);
+
+  Fidentifier := identifier;
+end;
+
+constructor TDerObjectIdentifier.Create(bytes: TCryptoLibByteArray);
+begin
+  Inherited Create();
+  Fidentifier := MakeOidStringFromBytes(bytes);
+  Fbody := System.Copy(bytes);
+end;
+
+function TDerObjectIdentifier.&On(stem: IDerObjectIdentifier): Boolean;
+var
+  LocalId, stemId: String;
+begin
+  LocalId := ID;
+  stemId := stem.ID;
+  result := (System.Length(LocalId) > System.Length(stemId)) and
+    (LocalId[System.Length(stemId) + 1] = '.') and
+    (AnsiStartsStr(stemId, LocalId));
+end;
+
+class constructor TDerObjectIdentifier.CreateDerObjectIdentifier;
+begin
+  FLock := TCriticalSection.Create;
+  System.SetLength(Fcache, 1024);
+end;
+
+class destructor TDerObjectIdentifier.DestroyDerObjectIdentifier;
+begin
+  FLock.Free;
+end;
+
+procedure TDerObjectIdentifier.DoOutput(bOut: TMemoryStream);
+var
+  tok: IOidTokenizer;
+  token: String;
+  first: Int32;
+begin
+  tok := TOidTokenizer.Create(Fidentifier);
+  token := tok.NextToken();
+  first := StrToInt(token) * 40;
+  token := tok.NextToken();
+  if (System.Length(token) <= 18) then
+  begin
+    WriteField(bOut, Int64(first + StrToInt64(token)));
+  end
+  else
+  begin
+    WriteField(bOut, TBigInteger.Create(token).Add(TBigInteger.ValueOf(first)));
+  end;
+
+  while (tok.HasMoreTokens) do
+  begin
+    token := tok.NextToken();
+    if (System.Length(token) <= 18) then
+    begin
+      WriteField(bOut, StrToInt64(token));
+    end
+    else
+    begin
+
+      WriteField(bOut, TBigInteger.Create(token));
+    end;
+  end;
+end;
+
+procedure TDerObjectIdentifier.Encode(derOut: IDerOutputStream);
+begin
+  derOut.WriteEncoded(TAsn1Tags.ObjectIdentifier, GetBody());
+end;
+
+class function TDerObjectIdentifier.FromOctetString(enc: TCryptoLibByteArray)
+  : IDerObjectIdentifier;
+var
+  hashCode, first: Int32;
+  entry: IDerObjectIdentifier;
+begin
+
+  hashCode := TArrayUtils.GetArrayHashCode(enc);
+  first := hashCode and 1023;
+
+  FLock.Acquire;
+  try
+    entry := Fcache[first];
+    if ((entry <> Nil) and (TArrayUtils.AreEqual(enc, entry.GetBody()))) then
+    begin
+      result := entry;
+      Exit;
+    end;
+
+    Fcache[first] := TDerObjectIdentifier.Create(enc);
+    result := Fcache[first];
+
+  finally
+    FLock.Release;
+  end;
+
+end;
+
+function TDerObjectIdentifier.GetBody: TCryptoLibByteArray;
+var
+  bOut: TMemoryStream;
+begin
+  FLock.Acquire;
+  try
+    if (Fbody = Nil) then
+    begin
+      bOut := TMemoryStream.Create();
+      try
+        DoOutput(bOut);
+        System.SetLength(Fbody, bOut.Size);
+        bOut.Position := 0;
+        bOut.Read(Fbody[0], System.Length(Fbody));
+      finally
+        bOut.Free;
+      end;
+    end;
+
+  finally
+    FLock.Release;
+  end;
+
+  result := Fbody;
+end;
+
+function TDerObjectIdentifier.GetID: String;
+begin
+  result := Fidentifier;
+end;
+
+class function TDerObjectIdentifier.GetInstance(obj: IAsn1TaggedObject;
+  explicitly: Boolean): IDerObjectIdentifier;
+var
+  o: IAsn1Object;
+begin
+
+  o := obj.GetObject();
+
+  if ((explicitly) or (Supports(o, IDerObjectIdentifier))) then
+  begin
+    result := GetInstance(o as TAsn1Object);
+    Exit;
+  end;
+
+  result := FromOctetString(TAsn1OctetString.GetInstance(o as TAsn1Object)
+    .GetOctets());
+end;
+
+class function TDerObjectIdentifier.GetInstance(obj: TObject)
+  : IDerObjectIdentifier;
+begin
+  if ((obj = Nil) or (obj is TDerObjectIdentifier)) then
+  begin
+    result := obj as TDerObjectIdentifier;
+    Exit;
+  end;
+
+  raise EArgumentCryptoLibException.CreateResFmt(@SIllegalObject,
+    [obj.ClassName]);
+end;
+
+class function TDerObjectIdentifier.GetInstance(obj: TCryptoLibByteArray)
+  : IDerObjectIdentifier;
+begin
+  result := FromOctetString(obj);
+end;
+
+class function TDerObjectIdentifier.IsValidBranchID(const branchID: String;
+  start: Int32): Boolean;
+var
+  periodAllowed: Boolean;
+  pos: Int32;
+  ch: Char;
+begin
+  periodAllowed := false;
+
+  pos := System.Length(branchID) + 1;
+  System.Dec(pos);
+  while (pos >= start) do
+  begin
+    ch := branchID[pos];
+
+    // TODO Leading zeroes?
+    // if (('0' <= ch) and (ch <= '9')) then
+    // begin
+    // periodAllowed := true;
+    // continue;
+    // end;
+
+    // TODO Leading zeroes?
+    if (CharInSet(ch, ['0' .. '9'])) then
+    begin
+      periodAllowed := true;
+      System.Dec(pos);
+      continue;
+    end;
+
+    if (ch = '.') then
+    begin
+      if (not(periodAllowed)) then
+      begin
+        result := false;
+        Exit;
+      end;
+
+      periodAllowed := false;
+      System.Dec(pos);
+      continue;
+    end;
+
+    result := false;
+    Exit;
+  end;
+
+  result := periodAllowed;
+end;
+
+class function TDerObjectIdentifier.IsValidIdentifier(const identifier
+  : String): Boolean;
+var
+  first: Char;
+begin
+  if ((System.Length(identifier) < 3) or (identifier[2] <> '.')) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  first := identifier[1];
+  // if ((first < '0') or (first > '2')) then
+  // begin
+  // result := false;
+  // Exit;
+  // end;
+  if (not CharInSet(first, ['0' .. '2'])) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  result := IsValidBranchID(identifier, 3);
+end;
+
+class function TDerObjectIdentifier.MakeOidStringFromBytes
+  (bytes: TCryptoLibByteArray): String;
+var
+  objId: TStringList;
+  value: Int64;
+  bigValue: TBigInteger;
+  first: Boolean;
+  i, b: Int32;
+begin
+  value := 0;
+  // bigValue := null;
+  bigValue := Default (TBigInteger);
+  first := true;
+  objId := TStringList.Create();
+  objId.LineBreak := '';
+  try
+    i := 0;
+    while i <> System.Length(bytes) do
+    begin
+      b := Int32(bytes[i]);
+
+      if (value <= LONG_LIMIT) then
+      begin
+        value := value + (b and $7F);
+        if ((b and $80) = 0) then // end of number reached
+        begin
+          if (first) then
+          begin
+            if (value < 40) then
+            begin
+              objId.Add('0');
+            end
+            else if (value < 80) then
+            begin
+              objId.Add('1');
+              value := value - 40;
+            end
+            else
+            begin
+              objId.Add('2');
+              value := value - 80;
+            end;
+            first := false;
+          end;
+
+          objId.Add('.');
+          objId.Add(IntToStr(value));
+          value := 0;
+        end
+        else
+        begin
+          value := value shl 7;
+        end;
+      end
+      else
+      begin
+        if (not bigValue.IsInitialized) then
+        begin
+          bigValue := TBigInteger.ValueOf(value);
+        end;
+        bigValue := bigValue.&Or(TBigInteger.ValueOf(b and $7F));
+        if ((b and $80) = 0) then
+        begin
+          if (first) then
+          begin
+            objId.Add('2');
+            bigValue := bigValue.Subtract(TBigInteger.ValueOf(80));
+            first := false;
+          end;
+
+          objId.Add('.');
+          objId.Add(bigValue.ToString());
+          bigValue := Default (TBigInteger);
+          value := 0;
+        end
+        else
+        begin
+          bigValue := bigValue.ShiftLeft(7);
+        end
+      end;
+
+      System.Inc(i);
+    end;
+
+    result := objId.Text;
+
+  finally
+    objId.Free;
+  end;
+
+end;
+
+function TDerObjectIdentifier.ToString: String;
+begin
+  result := ID;
+end;
+
+procedure TDerObjectIdentifier.WriteField(outputStream: TStream;
+  fieldValue: TBigInteger);
+var
+  byteCount, i: Int32;
+  tmpValue: TBigInteger;
+  tmp: TCryptoLibByteArray;
+begin
+  byteCount := (fieldValue.BitLength + 6) div 7;
+  if (byteCount = 0) then
+  begin
+    // outputStream.Write(TCryptoLibByteArray.Create(0)[0], 1);
+    outputStream.WriteByte(0);
+  end
+  else
+  begin
+    tmpValue := fieldValue;
+    System.SetLength(tmp, byteCount);
+
+    i := byteCount - 1;
+
+    while i >= 0 do
+    begin
+      tmp[i] := Byte((tmpValue.Int32Value and $7F) or $80);
+      tmpValue := tmpValue.ShiftRight(7);
+      System.Dec(i);
+    end;
+
+    tmp[byteCount - 1] := tmp[byteCount - 1] and $7F;
+    outputStream.Write(tmp[0], System.Length(tmp));
+  end;
+end;
+
+procedure TDerObjectIdentifier.WriteField(outputStream: TStream;
+  fieldValue: Int64);
+var
+  tempRes: TCryptoLibByteArray;
+  pos: Int32;
+begin
+  System.SetLength(tempRes, 9);
+  pos := 8;
+  tempRes[pos] := Byte(fieldValue and $7F);
+  while (fieldValue >= (Int64(1) shl 7)) do
+  begin
+    fieldValue := TBits.Asr64(fieldValue, 7);
+    System.Dec(pos);
+    tempRes[pos] := Byte((fieldValue and $7F) or $80);
+  end;
+  outputStream.Write(tempRes[pos], 9 - pos);
+end;
+
+end.

+ 77 - 0
CryptoLib/src/Asn1/ClpDerOctetString.pas

@@ -0,0 +1,77 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerOctetString;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpCryptoLibTypes,
+  ClpAsn1Tags,
+  ClpIProxiedInterface,
+  ClpAsn1OctetString,
+  ClpIDerOctetString;
+
+type
+  TDerOctetString = class(TAsn1OctetString, IDerOctetString)
+
+  public
+    /// <param name="str">The octets making up the octet string.</param>
+    constructor Create(str: TCryptoLibByteArray); overload;
+    constructor Create(obj: IAsn1Encodable); overload;
+
+    destructor Destroy(); override;
+
+    procedure Encode(derOut: IDerOutputStream); overload; override;
+    class procedure Encode(derOut: IDerOutputStream; bytes: TCryptoLibByteArray;
+      offset, length: Int32); reintroduce; overload; static; inline;
+
+  end;
+
+implementation
+
+{ TDerOctetString }
+
+constructor TDerOctetString.Create(str: TCryptoLibByteArray);
+begin
+  Inherited Create(str);
+end;
+
+constructor TDerOctetString.Create(obj: IAsn1Encodable);
+begin
+  Inherited Create(obj);
+end;
+
+destructor TDerOctetString.Destroy;
+begin
+  inherited Destroy;
+end;
+
+procedure TDerOctetString.Encode(derOut: IDerOutputStream);
+begin
+  derOut.WriteEncoded(TAsn1Tags.OctetString, str);
+end;
+
+class procedure TDerOctetString.Encode(derOut: IDerOutputStream;
+  bytes: TCryptoLibByteArray; offset, length: Int32);
+begin
+  derOut.WriteEncoded(TAsn1Tags.OctetString, bytes, offset, length);
+end;
+
+end.

+ 86 - 0
CryptoLib/src/Asn1/ClpDerOctetStringParser.pas

@@ -0,0 +1,86 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerOctetStringParser;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpCryptoLibTypes,
+  ClpDerOctetString,
+  ClpDefiniteLengthInputStream,
+  ClpIProxiedInterface,
+  ClpIDerOctetStringParser,
+  ClpIAsn1OctetStringParser;
+
+resourcestring
+  SConvertError = 'EIOCryptoLibException Converting Stream to Byte Array: %s';
+
+type
+  TDerOctetStringParser = class(TInterfacedObject, IAsn1OctetStringParser,
+    IAsn1Convertible, IDerOctetStringParser)
+
+  strict private
+  var
+    Fstream: TDefiniteLengthInputStream;
+
+  public
+
+    constructor Create(stream: TDefiniteLengthInputStream);
+    destructor Destroy(); override;
+    function GetOctetStream(): TStream; inline;
+    function ToAsn1Object(): IAsn1Object;
+
+  end;
+
+implementation
+
+{ TDerOctetStringParser }
+
+constructor TDerOctetStringParser.Create(stream: TDefiniteLengthInputStream);
+begin
+  Fstream := stream;
+end;
+
+destructor TDerOctetStringParser.Destroy;
+begin
+  Fstream.Free;
+  inherited Destroy;
+end;
+
+function TDerOctetStringParser.GetOctetStream: TStream;
+begin
+  result := Fstream;
+end;
+
+function TDerOctetStringParser.ToAsn1Object: IAsn1Object;
+begin
+  try
+    result := TDerOctetString.Create(Fstream.ToArray());
+  except
+    on e: EIOCryptoLibException do
+    begin
+      raise EInvalidOperationCryptoLibException.CreateResFmt(@SConvertError,
+        [e.Message]);
+    end;
+  end;
+end;
+
+end.

+ 199 - 0
CryptoLib/src/Asn1/ClpDerOutputStream.pas

@@ -0,0 +1,199 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerOutputStream;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpBits,
+  ClpAsn1Tags,
+  ClpCryptoLibTypes,
+  ClpIProxiedInterface,
+  ClpFilterStream;
+
+type
+  TDerOutputStream = class(TFilterStream, IInterface, IDerOutputStream)
+
+  strict private
+    procedure WriteLength(length: Int32);
+
+  strict protected
+    procedure WriteNull();
+
+  public
+    constructor Create(os: TStream);
+    procedure WriteEncoded(tag: Int32; bytes: TCryptoLibByteArray); overload;
+    procedure WriteEncoded(tag: Int32; first: Byte;
+      bytes: TCryptoLibByteArray); overload;
+    procedure WriteEncoded(tag: Int32; bytes: TCryptoLibByteArray;
+      offset, length: Int32); overload;
+    procedure WriteEncoded(flags, tagNo: Int32;
+      bytes: TCryptoLibByteArray); overload;
+    procedure WriteTag(flags, tagNo: Int32);
+
+    procedure WriteObject(obj: IAsn1Encodable); overload; virtual;
+    procedure WriteObject(obj: IAsn1Object); overload; virtual;
+
+  end;
+
+implementation
+
+{ TDerOutputStream }
+
+constructor TDerOutputStream.Create(os: TStream);
+begin
+  Inherited Create(os);
+end;
+
+procedure TDerOutputStream.WriteEncoded(tag: Int32; first: Byte;
+  bytes: TCryptoLibByteArray);
+begin
+  WriteByte(Byte(tag));
+  WriteLength(System.length(bytes) + 1);
+  WriteByte(first);
+  Write(bytes[0], System.length(bytes));
+end;
+
+procedure TDerOutputStream.WriteEncoded(tag: Int32; bytes: TCryptoLibByteArray);
+begin
+  WriteByte(Byte(tag));
+  WriteLength(System.length(bytes));
+  Write(bytes[0], System.length(bytes));
+end;
+
+procedure TDerOutputStream.WriteEncoded(flags, tagNo: Int32;
+  bytes: TCryptoLibByteArray);
+begin
+  WriteTag(flags, tagNo);
+  WriteLength(System.length(bytes));
+  Write(bytes[0], System.length(bytes));
+end;
+
+procedure TDerOutputStream.WriteEncoded(tag: Int32; bytes: TCryptoLibByteArray;
+  offset, length: Int32);
+begin
+  WriteByte(Byte(tag));
+  WriteLength(length);
+  Write(bytes[offset], length);
+end;
+
+procedure TDerOutputStream.WriteLength(length: Int32);
+var
+  size, i: Int32;
+  val: UInt32;
+begin
+  if (length > 127) then
+  begin
+    size := 1;
+    val := UInt32(length);
+    val := val shr 8;
+    while (val <> 0) do
+    begin
+      System.Inc(size);
+      val := val shr 8;
+    end;
+
+    WriteByte(Byte(size or $80));
+
+    i := (size - 1) * 8;
+
+    while i >= 0 do
+    begin
+      WriteByte(Byte(TBits.Asr32(length, i)));
+      System.Dec(i, 8);
+    end;
+
+  end
+  else
+  begin
+    WriteByte(Byte(length));
+  end;
+end;
+
+procedure TDerOutputStream.WriteNull;
+begin
+  WriteByte(TAsn1Tags.Null);
+  WriteByte($00);
+end;
+
+procedure TDerOutputStream.WriteObject(obj: IAsn1Encodable);
+var
+  asn1: IAsn1Object;
+begin
+  if (obj = Nil) then
+  begin
+    WriteNull();
+  end
+  else
+  begin
+    asn1 := obj.ToAsn1Object();
+    asn1.Encode(Self as IDerOutputStream);
+  end;
+end;
+
+procedure TDerOutputStream.WriteObject(obj: IAsn1Object);
+begin
+  if (obj = Nil) then
+  begin
+    WriteNull();
+  end
+  else
+  begin
+    obj.Encode(Self as IDerOutputStream);
+  end;
+end;
+
+procedure TDerOutputStream.WriteTag(flags, tagNo: Int32);
+var
+  stack: TCryptoLibByteArray;
+  pos: Int32;
+begin
+  if (tagNo < 31) then
+  begin
+    WriteByte(Byte(flags or tagNo));
+  end
+  else
+  begin
+    WriteByte(Byte(flags or $1F));
+    if (tagNo < 128) then
+    begin
+      WriteByte(Byte(tagNo));
+    end
+    else
+    begin
+      System.SetLength(stack, 5);
+      pos := System.length(stack);
+
+      System.Dec(pos);
+      stack[pos] := Byte(tagNo and $7F);
+
+      repeat
+        tagNo := TBits.Asr32(tagNo, 7);
+        System.Dec(pos);
+        stack[pos] := Byte(tagNo and $7F or $80);
+      until (not(tagNo > 127));
+
+      Write(stack[pos], System.length(stack) - pos);
+    end;
+  end;
+end;
+
+end.

+ 272 - 0
CryptoLib/src/Asn1/ClpDerPrintableString.pas

@@ -0,0 +1,272 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerPrintableString;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  StrUtils,
+  ClpDerStringBase,
+  ClpAsn1Tags,
+  ClpAsn1OctetString,
+  ClpAsn1Object,
+  ClpIProxiedInterface,
+  ClpCryptoLibTypes,
+  ClpIAsn1TaggedObject,
+  ClpIDerPrintableString;
+
+resourcestring
+  SIllegalObject = 'Illegal Object in GetInstance: %s';
+  SIllegalCharacters = 'String Contains Illegal Characters "str"';
+  SStrNil = '"str"';
+
+type
+
+  /// <summary>
+  /// Der PrintableString object.
+  /// </summary>
+  TDerPrintableString = class(TDerStringBase, IDerPrintableString)
+
+  strict private
+  var
+    FStr: String;
+
+    function GetStr: String; inline;
+
+  strict protected
+    function Asn1Equals(asn1Object: IAsn1Object): Boolean; override;
+  public
+
+    /// <summary>
+    /// basic constructor - with bytes.
+    /// </summary>
+    constructor Create(Str: TCryptoLibByteArray); overload;
+
+    /// <summary>
+    /// basic constructor - without validation.
+    /// </summary>
+    constructor Create(const Str: String); overload;
+
+    /// <summary>
+    /// Constructor with optional validation.
+    /// </summary>
+    /// <param name="Str">
+    /// the base string to wrap.
+    /// </param>
+    /// <param name="validate">
+    /// whether or not to check the string.
+    /// </param>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if validate is true and the string contains characters that should
+    /// not be in an PrintableString.
+    /// </exception>
+    constructor Create(const Str: String; validate: Boolean); overload;
+
+    function GetString(): String; override;
+
+    function GetOctets(): TCryptoLibByteArray; inline;
+
+    procedure Encode(derOut: IDerOutputStream); override;
+
+    property Str: String read GetStr;
+
+    /// <summary>
+    /// return a printable string from the passed in object.
+    /// </summary>
+    /// <param name="obj">
+    /// a DerPrintableString or an object that can be converted into one.
+    /// </param>
+    /// <returns>
+    /// return a DerPrintableString instance, or null.
+    /// </returns>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: TObject): IDerPrintableString; overload;
+      static; inline;
+
+    /// <summary>
+    /// return a Printable string from a tagged object.
+    /// </summary>
+    /// <param name="obj">
+    /// the tagged object holding the object we want
+    /// </param>
+    /// <param name="isExplicit">
+    /// true if the object is meant to be explicitly tagged false otherwise.
+    /// </param>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the tagged object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: IAsn1TaggedObject; isExplicit: Boolean)
+      : IDerPrintableString; overload; static; inline;
+
+    /// <summary>
+    /// return true if the passed in String can be represented without loss
+    /// as a PrintableString, false otherwise.
+    /// </summary>
+    /// <param name="Str">
+    /// string to validate.
+    /// </param>
+    /// <returns>
+    /// return true if in printable set, false otherwise.
+    /// </returns>
+    class function IsPrintableString(const Str: String): Boolean;
+      static; inline;
+
+  end;
+
+implementation
+
+{ TDerPrintableString }
+
+function TDerPrintableString.GetOctets: TCryptoLibByteArray;
+begin
+{$IFDEF FPC}
+  result := TEncoding.ASCII.GetBytes(UnicodeString(Str));
+{$ELSE}
+  result := TEncoding.ASCII.GetBytes(Str);
+{$ENDIF FPC}
+end;
+
+class function TDerPrintableString.IsPrintableString(const Str: String)
+  : Boolean;
+var
+  ch: Char;
+begin
+  for ch in Str do
+  begin
+
+    if ((Ord(ch) > $007F)) then
+    begin
+      result := false;
+      Exit;
+    end;
+
+    // if (char.IsLetterOrDigit(ch))
+    if CharInSet(ch, ['a' .. 'z', 'A' .. 'Z', '0' .. '9']) then
+    begin
+      continue;
+    end;
+
+    case AnsiIndexStr(ch, [''' ''', '\', '(', ')', '+', '-', '.', ':', '=', '?',
+      '/', ',']) of
+      0 .. 11:
+        begin
+          continue;
+        end;
+    end;
+
+    result := false;
+    Exit;
+  end;
+
+  result := true;
+end;
+
+function TDerPrintableString.Asn1Equals(asn1Object: IAsn1Object): Boolean;
+var
+  other: IDerPrintableString;
+begin
+
+  if (not Supports(asn1Object, IDerPrintableString, other)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  result := Str = other.Str;
+end;
+
+constructor TDerPrintableString.Create(Str: TCryptoLibByteArray);
+begin
+{$IFDEF FPC}
+  Create(String(TEncoding.ASCII.GetString(Str)), false);
+{$ELSE}
+  Create(TEncoding.ASCII.GetString(Str), false);
+{$ENDIF FPC}
+end;
+
+constructor TDerPrintableString.Create(const Str: String);
+begin
+  Create(Str, false);
+end;
+
+constructor TDerPrintableString.Create(const Str: String; validate: Boolean);
+begin
+  Inherited Create();
+  if (Str = '') then
+  begin
+    raise EArgumentNilCryptoLibException.CreateRes(@SStrNil);
+  end;
+  if (validate and (not IsPrintableString(Str))) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SIllegalCharacters);
+  end;
+
+  FStr := Str;
+end;
+
+procedure TDerPrintableString.Encode(derOut: IDerOutputStream);
+begin
+  derOut.WriteEncoded(TAsn1Tags.PrintableString, GetOctets());
+end;
+
+class function TDerPrintableString.GetInstance(obj: IAsn1TaggedObject;
+  isExplicit: Boolean): IDerPrintableString;
+var
+  o: IAsn1Object;
+begin
+  o := obj.GetObject();
+
+  if ((isExplicit) or (Supports(o, IDerPrintableString))) then
+  begin
+    result := GetInstance(o as TAsn1Object);
+    Exit;
+  end;
+
+  result := TDerPrintableString.Create
+    (TAsn1OctetString.GetInstance(o as TAsn1Object).GetOctets());
+end;
+
+class function TDerPrintableString.GetInstance(obj: TObject)
+  : IDerPrintableString;
+begin
+  if ((obj = Nil) or (obj is TDerPrintableString)) then
+  begin
+    result := obj as TDerPrintableString;
+    Exit;
+  end;
+
+  raise EArgumentCryptoLibException.CreateResFmt(@SIllegalObject,
+    [obj.ClassName]);
+end;
+
+function TDerPrintableString.GetStr: String;
+begin
+  result := FStr;
+end;
+
+function TDerPrintableString.GetString: String;
+begin
+  result := Str;
+end;
+
+end.

+ 177 - 0
CryptoLib/src/Asn1/ClpDerSequence.pas

@@ -0,0 +1,177 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerSequence;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpCryptoLibTypes,
+  ClpDerOutputStream,
+  ClpIProxiedInterface,
+  ClpAsn1Tags,
+  ClpIAsn1EncodableVector,
+  ClpAsn1Sequence,
+  ClpIDerSequence;
+
+type
+  TDerSequence = class(TAsn1Sequence, IDerSequence)
+
+  strict private
+
+    class var
+
+      FEmpty: IDerSequence;
+
+    class constructor DerSequence();
+
+    class function GetEmpty: IDerSequence; static; inline;
+
+  public
+
+    class function FromVector(v: IAsn1EncodableVector): IDerSequence; static;
+
+    /// <summary>
+    /// create an empty sequence
+    /// </summary>
+    constructor Create(); overload;
+
+    /// <summary>
+    /// create a sequence containing one object
+    /// </summary>
+    constructor Create(obj: IAsn1Encodable); overload;
+
+    constructor Create(v: array of IAsn1Encodable); overload;
+
+    /// <summary>
+    /// create a sequence containing a vector of objects.
+    /// </summary>
+    constructor Create(v: IAsn1EncodableVector); overload;
+
+    destructor Destroy(); override;
+
+    /// <summary>
+    /// A note on the implementation: <br />As Der requires the constructed,
+    /// definite-length model to <br />be used for structured types, this
+    /// varies slightly from the <br />ASN.1 descriptions given. Rather than
+    /// just outputing Sequence, <br />we also have to specify Constructed,
+    /// and the objects length. <br />
+    /// </summary>
+    procedure Encode(derOut: IDerOutputStream); override;
+
+    class property Empty: IDerSequence read GetEmpty;
+
+  end;
+
+implementation
+
+{ TDerSequence }
+
+constructor TDerSequence.Create(obj: IAsn1Encodable);
+begin
+  Inherited Create(1);
+  AddObject(obj);
+end;
+
+constructor TDerSequence.Create;
+begin
+  Inherited Create(0);
+end;
+
+constructor TDerSequence.Create(v: IAsn1EncodableVector);
+var
+  ae: IAsn1Encodable;
+begin
+  Inherited Create(v.Count);
+  for ae in v do
+  begin
+    AddObject(ae);
+  end;
+end;
+
+constructor TDerSequence.Create(v: array of IAsn1Encodable);
+var
+  ae: IAsn1Encodable;
+begin
+  Inherited Create(System.Length(v));
+  for ae in v do
+  begin
+    AddObject(ae);
+  end;
+end;
+
+class constructor TDerSequence.DerSequence;
+begin
+  FEmpty := TDerSequence.Create();
+end;
+
+destructor TDerSequence.Destroy;
+begin
+
+  inherited Destroy;
+end;
+
+procedure TDerSequence.Encode(derOut: IDerOutputStream);
+var
+  bOut: TMemoryStream;
+  dOut: TDerOutputStream;
+  obj: IAsn1Encodable;
+  bytes: TCryptoLibByteArray;
+begin
+  // TODO Intermediate buffer could be avoided if we could calculate expected length
+  bOut := TMemoryStream.Create();
+  dOut := TDerOutputStream.Create(bOut);
+  try
+
+    for obj in Self do
+    begin
+      dOut.WriteObject(obj);
+    end;
+
+    System.SetLength(bytes, bOut.Size);
+    bOut.Position := 0;
+    bOut.Read(bytes[0], bOut.Size);
+  finally
+    bOut.Free;
+    dOut.Free;
+  end;
+
+  derOut.WriteEncoded(TAsn1Tags.Sequence or TAsn1Tags.Constructed, bytes);
+end;
+
+class function TDerSequence.FromVector(v: IAsn1EncodableVector): IDerSequence;
+begin
+  if v.Count < 1 then
+  begin
+    result := Empty;
+  end
+  else
+  begin
+    result := TDerSequence.Create(v);
+  end;
+
+end;
+
+class function TDerSequence.GetEmpty: IDerSequence;
+begin
+  result := FEmpty;
+end;
+
+end.

+ 100 - 0
CryptoLib/src/Asn1/ClpDerSequenceGenerator.pas

@@ -0,0 +1,100 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerSequenceGenerator;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpCryptoLibTypes,
+  ClpAsn1Tags,
+  ClpDerOutputStream,
+  ClpDerGenerator,
+  ClpIProxiedInterface,
+  ClpIDerSequenceGenerator;
+
+type
+  TDerSequenceGenerator = class(TDerGenerator, IDerSequenceGenerator)
+
+  strict private
+  var
+    F_bOut: TMemoryStream;
+
+  public
+    constructor Create(outStream: TStream); overload;
+    constructor Create(outStream: TStream; tagNo: Int32;
+      isExplicit: Boolean); overload;
+    destructor Destroy(); override;
+    procedure AddObject(obj: IAsn1Encodable); override;
+    function GetRawOutputStream(): TStream; override;
+    procedure Close(); override;
+  end;
+
+implementation
+
+{ TDerSequenceGenerator }
+
+procedure TDerSequenceGenerator.AddObject(obj: IAsn1Encodable);
+var
+  temp: TDerOutputStream;
+begin
+  temp := TDerOutputStream.Create(F_bOut);
+  try
+    temp.WriteObject(obj);
+  finally
+    temp.Free;
+  end;
+end;
+
+procedure TDerSequenceGenerator.Close;
+var
+  temp: TCryptoLibByteArray;
+begin
+  F_bOut.Position := 0;
+  System.SetLength(temp, F_bOut.Size);
+  F_bOut.Read(temp[0], F_bOut.Size);
+  WriteDerEncoded(TAsn1Tags.Constructed or TAsn1Tags.Sequence, temp);
+end;
+
+constructor TDerSequenceGenerator.Create(outStream: TStream);
+begin
+  Inherited Create(outStream);
+  F_bOut := TMemoryStream.Create();
+end;
+
+constructor TDerSequenceGenerator.Create(outStream: TStream; tagNo: Int32;
+  isExplicit: Boolean);
+begin
+  Inherited Create(outStream, tagNo, isExplicit);
+  F_bOut := TMemoryStream.Create();
+end;
+
+destructor TDerSequenceGenerator.Destroy;
+begin
+  F_bOut.Free;
+  inherited Destroy;
+end;
+
+function TDerSequenceGenerator.GetRawOutputStream: TStream;
+begin
+  result := F_bOut;
+end;
+
+end.

+ 66 - 0
CryptoLib/src/Asn1/ClpDerSequenceParser.pas

@@ -0,0 +1,66 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerSequenceParser;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIAsn1StreamParser,
+  ClpIAsn1SequenceParser,
+  ClpIProxiedInterface,
+  ClpIDerSequenceParser,
+  ClpDerSequence;
+
+type
+  TDerSequenceParser = class(TInterfacedObject, IAsn1SequenceParser,
+    IAsn1Convertible, IDerSequenceParser)
+
+  strict private
+  var
+    F_parser: IAsn1StreamParser;
+
+  public
+
+    constructor Create(parser: IAsn1StreamParser);
+    function ReadObject(): IAsn1Convertible; inline;
+    function ToAsn1Object(): IAsn1Object; inline;
+
+  end;
+
+implementation
+
+{ TDerSequenceParser }
+
+constructor TDerSequenceParser.Create(parser: IAsn1StreamParser);
+begin
+  F_parser := parser;
+end;
+
+function TDerSequenceParser.ReadObject: IAsn1Convertible;
+begin
+  result := F_parser.ReadObject();
+end;
+
+function TDerSequenceParser.ToAsn1Object: IAsn1Object;
+begin
+  result := TDerSequence.Create(F_parser.ReadVector());
+end;
+
+end.

+ 208 - 0
CryptoLib/src/Asn1/ClpDerSet.pas

@@ -0,0 +1,208 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerSet;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpCryptoLibTypes,
+  ClpDerOutputStream,
+  ClpAsn1Tags,
+  ClpAsn1Set,
+  ClpIDerSet,
+  ClpIProxiedInterface,
+  ClpIAsn1EncodableVector;
+
+type
+
+  /// <summary>
+  /// A Der encoded set object
+  /// </summary>
+  TDerSet = class(TAsn1Set, IDerSet)
+
+  strict private
+    class var
+
+      FEmpty: IDerSet;
+    class constructor DerSet();
+    class function GetEmpty: IDerSet; static; inline;
+
+  public
+
+    class function FromVector(v: IAsn1EncodableVector): IDerSet;
+      overload; static;
+    class function FromVector(v: IAsn1EncodableVector; needsSorting: Boolean)
+      : IDerSet; overload; static;
+
+    /// <summary>
+    /// create an empty set
+    /// </summary>
+    constructor Create(); overload;
+
+    /// <param name="obj">
+    /// a single object that makes up the set.
+    /// </param>
+    constructor Create(obj: IAsn1Encodable); overload;
+
+    constructor Create(v: array of IAsn1Encodable); overload;
+
+    /// <param name="v">
+    /// a vector of objects making up the set.
+    /// </param>
+    constructor Create(v: IAsn1EncodableVector); overload;
+
+    constructor Create(v: IAsn1EncodableVector; needsSorting: Boolean);
+      overload;
+
+    destructor Destroy(); override;
+
+    /// <summary>
+    /// A note on the implementation: <br />As Der requires the constructed,
+    /// definite-length model to <br />be used for structured types, this
+    /// varies slightly from the <br />ASN.1 descriptions given. Rather than
+    /// just outputing Set, <br />we also have to specify Constructed, and
+    /// the objects length. <br />
+    /// </summary>
+    procedure Encode(derOut: IDerOutputStream); override;
+
+    class property Empty: IDerSet read GetEmpty;
+
+  end;
+
+implementation
+
+{ TDerSet }
+
+constructor TDerSet.Create(v: array of IAsn1Encodable);
+var
+  o: IAsn1Encodable;
+begin
+  Inherited Create(System.Length(v));
+  for o in v do
+  begin
+    AddObject(o);
+  end;
+
+  Sort();
+end;
+
+constructor TDerSet.Create;
+begin
+  Inherited Create(0);
+end;
+
+constructor TDerSet.Create(v: IAsn1EncodableVector; needsSorting: Boolean);
+var
+  o: IAsn1Encodable;
+begin
+  Inherited Create(v.Count);
+  for o in v do
+  begin
+    AddObject(o);
+  end;
+
+  if (needsSorting) then
+  begin
+    Sort();
+  end;
+end;
+
+constructor TDerSet.Create(obj: IAsn1Encodable);
+begin
+  Inherited Create(1);
+  AddObject(obj);
+end;
+
+constructor TDerSet.Create(v: IAsn1EncodableVector);
+begin
+  Create(v, true);
+end;
+
+class constructor TDerSet.DerSet;
+begin
+  FEmpty := TDerSet.Create();
+end;
+
+destructor TDerSet.Destroy;
+begin
+
+  inherited Destroy;
+end;
+
+procedure TDerSet.Encode(derOut: IDerOutputStream);
+var
+  bOut: TMemoryStream;
+  dOut: TDerOutputStream;
+  obj: IAsn1Encodable;
+  bytes: TCryptoLibByteArray;
+begin
+  // TODO Intermediate buffer could be avoided if we could calculate expected length
+  bOut := TMemoryStream.Create();
+  dOut := TDerOutputStream.Create(bOut);
+
+  try
+    for obj in Self do
+    begin
+      dOut.WriteObject(obj);
+    end;
+
+    System.SetLength(bytes, bOut.Size);
+    bOut.Position := 0;
+    bOut.Read(bytes[0], bOut.Size);
+  finally
+    bOut.Free;
+    dOut.Free;
+  end;
+
+  derOut.WriteEncoded(TAsn1Tags.&Set or TAsn1Tags.Constructed, bytes);
+end;
+
+class function TDerSet.FromVector(v: IAsn1EncodableVector;
+  needsSorting: Boolean): IDerSet;
+begin
+  if v.Count < 1 then
+  begin
+    result := Empty;
+  end
+  else
+  begin
+    result := TDerSet.Create(v, needsSorting);
+  end;
+end;
+
+class function TDerSet.GetEmpty: IDerSet;
+begin
+  result := FEmpty;
+end;
+
+class function TDerSet.FromVector(v: IAsn1EncodableVector): IDerSet;
+begin
+  if v.Count < 1 then
+  begin
+    result := Empty;
+  end
+  else
+  begin
+    result := TDerSet.Create(v);
+  end;
+end;
+
+end.

+ 66 - 0
CryptoLib/src/Asn1/ClpDerSetParser.pas

@@ -0,0 +1,66 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerSetParser;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIAsn1StreamParser,
+  ClpDerSet,
+  ClpIAsn1SetParser,
+  ClpIDerSetParser,
+  ClpIProxiedInterface;
+
+type
+  TDerSetParser = class(TInterfacedObject, IAsn1SetParser, IAsn1Convertible,
+    IDerSetParser)
+
+  strict private
+  var
+    F_parser: IAsn1StreamParser;
+
+  public
+
+    constructor Create(parser: IAsn1StreamParser);
+    function ReadObject(): IAsn1Convertible; inline;
+    function ToAsn1Object(): IAsn1Object; inline;
+
+  end;
+
+implementation
+
+{ TDerSetParser }
+
+constructor TDerSetParser.Create(parser: IAsn1StreamParser);
+begin
+  F_parser := parser;
+end;
+
+function TDerSetParser.ReadObject: IAsn1Convertible;
+begin
+  result := F_parser.ReadObject();
+end;
+
+function TDerSetParser.ToAsn1Object: IAsn1Object;
+begin
+  result := TDerSet.Create(F_parser.ReadVector(), false);
+end;
+
+end.

+ 60 - 0
CryptoLib/src/Asn1/ClpDerStringBase.pas

@@ -0,0 +1,60 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerStringBase;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIAsn1String,
+  ClpAsn1Object,
+  ClpStringHelper,
+  ClpIDerStringBase;
+
+type
+  TDerStringBase = class abstract(TAsn1Object, IAsn1String, IDerStringBase)
+
+  strict protected
+    constructor Create();
+    function Asn1GetHashCode(): Int32; override;
+  public
+    function GetString(): String; virtual; abstract;
+    function ToString(): String; override;
+  end;
+
+implementation
+
+{ TDerStringBase }
+
+function TDerStringBase.Asn1GetHashCode: Int32;
+begin
+  Result := GetString().GetHashCode;
+end;
+
+constructor TDerStringBase.Create;
+begin
+  Inherited Create();
+end;
+
+function TDerStringBase.ToString: String;
+begin
+  Result := GetString();
+end;
+
+end.

+ 196 - 0
CryptoLib/src/Asn1/ClpDerT61String.pas

@@ -0,0 +1,196 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerT61String;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpDerStringBase,
+  ClpAsn1Tags,
+  ClpAsn1OctetString,
+  ClpAsn1Object,
+  ClpIProxiedInterface,
+  ClpCryptoLibTypes,
+  ClpIAsn1TaggedObject,
+  ClpIDerT61String;
+
+resourcestring
+  SIllegalObject = 'Illegal Object in GetInstance: %s';
+  SStrNil = '"str"';
+
+type
+
+  /// <summary>
+  /// Der T61String (also the teletex string) - 8-bit characters
+  /// </summary>
+  TDerT61String = class(TDerStringBase, IDerT61String)
+
+  strict private
+  var
+    FStr: String;
+
+    function GetStr: String; inline;
+    property Str: String read GetStr;
+
+  strict protected
+    function Asn1Equals(asn1Object: IAsn1Object): Boolean; override;
+  public
+
+    /// <summary>
+    /// basic constructor - with bytes.
+    /// </summary>
+    constructor Create(Str: TCryptoLibByteArray); overload;
+
+    /// <summary>
+    /// basic constructor
+    /// </summary>
+    constructor Create(const Str: String); overload;
+
+    function GetString(): String; override;
+
+    function GetOctets(): TCryptoLibByteArray; inline;
+
+    procedure Encode(derOut: IDerOutputStream); override;
+
+    /// <summary>
+    /// return a T61 string from the passed in object.
+    /// </summary>
+    /// <param name="obj">
+    /// a Der T61 string or an object that can be converted into one.
+    /// </param>
+    /// <returns>
+    /// return a Der T61 string instance, or null.
+    /// </returns>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: TObject): IDerT61String; overload;
+      static; inline;
+
+    /// <summary>
+    /// return a Der T61 string from a tagged object.
+    /// </summary>
+    /// <param name="obj">
+    /// the tagged object holding the object we want
+    /// </param>
+    /// <param name="isExplicit">
+    /// true if the object is meant to be explicitly tagged false otherwise.
+    /// </param>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the tagged object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: IAsn1TaggedObject; isExplicit: Boolean)
+      : IDerT61String; overload; static; inline;
+
+  end;
+
+implementation
+
+{ TDerT61String }
+
+function TDerT61String.GetOctets: TCryptoLibByteArray;
+begin
+{$IFDEF FPC}
+  result := TEncoding.ASCII.GetBytes(UnicodeString(Str));
+{$ELSE}
+  result := TEncoding.ASCII.GetBytes(Str);
+{$ENDIF FPC}
+end;
+
+function TDerT61String.Asn1Equals(asn1Object: IAsn1Object): Boolean;
+var
+  other: IDerT61String;
+begin
+
+  if (not Supports(asn1Object, IDerT61String, other)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  result := Str = other.Str;
+end;
+
+constructor TDerT61String.Create(Str: TCryptoLibByteArray);
+begin
+{$IFDEF FPC}
+  Create(String(TEncoding.ASCII.GetString(Str)));
+{$ELSE}
+  Create(TEncoding.ASCII.GetString(Str));
+{$ENDIF FPC}
+end;
+
+constructor TDerT61String.Create(const Str: String);
+begin
+  Inherited Create();
+  if (Str = '') then
+  begin
+    raise EArgumentNilCryptoLibException.CreateRes(@SStrNil);
+  end;
+
+  FStr := Str;
+end;
+
+procedure TDerT61String.Encode(derOut: IDerOutputStream);
+begin
+  derOut.WriteEncoded(TAsn1Tags.T61String, GetOctets());
+end;
+
+class function TDerT61String.GetInstance(obj: IAsn1TaggedObject;
+  isExplicit: Boolean): IDerT61String;
+var
+  o: IAsn1Object;
+begin
+  o := obj.GetObject();
+
+  if ((isExplicit) or (Supports(o, IDerT61String))) then
+  begin
+    result := GetInstance(o as TAsn1Object);
+    Exit;
+  end;
+
+  result := TDerT61String.Create(TAsn1OctetString.GetInstance(o as TAsn1Object)
+    .GetOctets());
+end;
+
+class function TDerT61String.GetInstance(obj: TObject): IDerT61String;
+begin
+  if ((obj = Nil) or (obj is TDerT61String)) then
+  begin
+    result := obj as TDerT61String;
+    Exit;
+  end;
+
+  raise EArgumentCryptoLibException.CreateResFmt(@SIllegalObject,
+    [obj.ClassName]);
+end;
+
+function TDerT61String.GetStr: String;
+begin
+  result := FStr;
+end;
+
+function TDerT61String.GetString: String;
+begin
+  result := Str;
+end;
+
+end.

+ 128 - 0
CryptoLib/src/Asn1/ClpDerTaggedObject.pas

@@ -0,0 +1,128 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerTaggedObject;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpCryptoLibTypes,
+  ClpAsn1Tags,
+  ClpDerSequence,
+{$IFDEF DELPHI}
+  ClpIDerSequence,
+{$ENDIF DELPHI}
+  ClpIProxiedInterface,
+  ClpAsn1TaggedObject,
+  ClpIDerTaggedObject;
+
+type
+
+  /// <summary>
+  /// DER TaggedObject - in ASN.1 notation this is any object preceded by <br />
+  /// a [n] where n is some number - these are assumed to follow the
+  /// construction <br />rules (as with sequences). <br />
+  /// </summary>
+  TDerTaggedObject = class(TAsn1TaggedObject, IDerTaggedObject)
+
+  public
+
+    /// <param name="tagNo">
+    /// the tag number for this object.
+    /// </param>
+    /// <param name="obj">
+    /// the tagged object.
+    /// </param>
+    constructor Create(tagNo: Int32; obj: IAsn1Encodable); overload;
+    /// <param name="explicitly">
+    /// true if an explicitly tagged object.
+    /// </param>
+    /// <param name="tagNo">
+    /// the tag number for this object.
+    /// </param>
+    /// <param name="obj">
+    /// the tagged object.
+    /// </param>
+    constructor Create(explicitly: Boolean; tagNo: Int32;
+      obj: IAsn1Encodable); overload;
+
+    /// <summary>
+    /// create an implicitly tagged object that contains a zero length
+    /// sequence.
+    /// </summary>
+    /// <param name="tagNo">
+    /// the tag number for this object.
+    /// </param>
+    constructor Create(tagNo: Int32); overload;
+
+    procedure Encode(derOut: IDerOutputStream); override;
+
+  end;
+
+implementation
+
+{ TDerTaggedObject }
+
+constructor TDerTaggedObject.Create(tagNo: Int32; obj: IAsn1Encodable);
+begin
+  Inherited Create(tagNo, obj);
+end;
+
+constructor TDerTaggedObject.Create(explicitly: Boolean; tagNo: Int32;
+  obj: IAsn1Encodable);
+begin
+  Inherited Create(explicitly, tagNo, obj)
+end;
+
+constructor TDerTaggedObject.Create(tagNo: Int32);
+begin
+  Inherited Create(false, tagNo, TDerSequence.Empty)
+end;
+
+procedure TDerTaggedObject.Encode(derOut: IDerOutputStream);
+var
+  bytes: TCryptoLibByteArray;
+  flags: Int32;
+begin
+  if (not IsEmpty()) then
+  begin
+    bytes := obj.GetDerEncoded();
+
+    if (explicitly) then
+    begin
+      derOut.WriteEncoded(TAsn1Tags.Constructed or TAsn1Tags.Tagged,
+        tagNo, bytes);
+    end
+    else
+    begin
+      //
+      // need to mark constructed types... (preserve Constructed tag)
+      //
+      flags := (bytes[0] and TAsn1Tags.Constructed) or TAsn1Tags.Tagged;
+      derOut.WriteTag(flags, tagNo);
+      derOut.Write(bytes[1], System.Length(bytes) - 1);
+    end
+  end
+  else
+  begin
+    derOut.WriteEncoded(TAsn1Tags.Constructed or TAsn1Tags.Tagged, tagNo, Nil);
+  end;
+end;
+
+end.

+ 206 - 0
CryptoLib/src/Asn1/ClpDerUniversalString.pas

@@ -0,0 +1,206 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerUniversalString;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  Classes,
+  ClpArrayUtils,
+  ClpDerStringBase,
+  ClpAsn1Tags,
+  ClpAsn1OctetString,
+  ClpAsn1Object,
+  ClpIProxiedInterface,
+  ClpCryptoLibTypes,
+  ClpIAsn1TaggedObject,
+  ClpIDerUniversalString;
+
+resourcestring
+  SIllegalObject = 'Illegal Object in GetInstance: %s';
+  SStrNil = '"str"';
+
+type
+
+  /// <summary>
+  /// Der UniversalString object.
+  /// </summary>
+  TDerUniversalString = class(TDerStringBase, IDerUniversalString)
+
+  strict private
+  var
+    FStr: TCryptoLibByteArray;
+
+  const
+    FTable: array [0 .. 15] of Char = ('0', '1', '2', '3', '4', '5', '6', '7',
+      '8', '9', 'A', 'B', 'C', 'D', 'E', 'F');
+
+    function GetStr: TCryptoLibByteArray; inline;
+    property Str: TCryptoLibByteArray read GetStr;
+
+  strict protected
+    function Asn1Equals(asn1Object: IAsn1Object): Boolean; override;
+  public
+
+    /// <summary>
+    /// basic constructor - byte encoded string.
+    /// </summary>
+    constructor Create(Str: TCryptoLibByteArray); overload;
+
+    function GetString(): String; override;
+
+    function GetOctets(): TCryptoLibByteArray; inline;
+
+    procedure Encode(derOut: IDerOutputStream); override;
+
+    /// <summary>
+    /// return a Universal String from the passed in object.
+    /// </summary>
+    /// <param name="obj">
+    /// a Der T61 string or an object that can be converted into one.
+    /// </param>
+    /// <returns>
+    /// return a Der UniversalString instance, or null.
+    /// </returns>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: TObject): IDerUniversalString; overload;
+      static; inline;
+
+    /// <summary>
+    /// return a Der UniversalString from a tagged object.
+    /// </summary>
+    /// <param name="obj">
+    /// the tagged object holding the object we want
+    /// </param>
+    /// <param name="isExplicit">
+    /// true if the object is meant to be explicitly tagged false otherwise.
+    /// </param>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the tagged object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: IAsn1TaggedObject; isExplicit: Boolean)
+      : IDerUniversalString; overload; static; inline;
+
+  end;
+
+implementation
+
+{ TDerUniversalString }
+
+function TDerUniversalString.GetOctets: TCryptoLibByteArray;
+begin
+  result := System.Copy(Str);
+end;
+
+function TDerUniversalString.Asn1Equals(asn1Object: IAsn1Object): Boolean;
+var
+  other: IDerUniversalString;
+begin
+
+  if (not Supports(asn1Object, IDerUniversalString, other)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  result := TArrayUtils.AreEqual(Str, other.Str);
+end;
+
+constructor TDerUniversalString.Create(Str: TCryptoLibByteArray);
+begin
+  Inherited Create();
+  if (Str = Nil) then
+  begin
+    raise EArgumentNilCryptoLibException.CreateRes(@SStrNil);
+  end;
+
+  FStr := Str;
+end;
+
+procedure TDerUniversalString.Encode(derOut: IDerOutputStream);
+begin
+  derOut.WriteEncoded(TAsn1Tags.UniversalString, Str);
+end;
+
+class function TDerUniversalString.GetInstance(obj: IAsn1TaggedObject;
+  isExplicit: Boolean): IDerUniversalString;
+var
+  o: IAsn1Object;
+begin
+  o := obj.GetObject();
+
+  if ((isExplicit) or (Supports(o, IDerUniversalString))) then
+  begin
+    result := GetInstance(o as TAsn1Object);
+    Exit;
+  end;
+
+  result := TDerUniversalString.Create
+    (TAsn1OctetString.GetInstance(o as TAsn1Object).GetOctets());
+end;
+
+class function TDerUniversalString.GetInstance(obj: TObject)
+  : IDerUniversalString;
+begin
+  if ((obj = Nil) or (obj is TDerUniversalString)) then
+  begin
+    result := obj as TDerUniversalString;
+    Exit;
+  end;
+
+  raise EArgumentCryptoLibException.CreateResFmt(@SIllegalObject,
+    [obj.ClassName]);
+end;
+
+function TDerUniversalString.GetStr: TCryptoLibByteArray;
+begin
+  result := FStr;
+end;
+
+function TDerUniversalString.GetString: String;
+var
+  buffer: TStringList;
+  i: Int32;
+  enc: TCryptoLibByteArray;
+  ubyte: UInt32;
+begin
+  buffer := TStringList.Create();
+  buffer.LineBreak := '';
+  enc := GetDerEncoded();
+  buffer.Add('#');
+  i := 0;
+  try
+    while i <> System.Length(enc) do
+    begin
+      ubyte := enc[i];
+      buffer.Add(FTable[(ubyte shr 4) and $F]);
+      buffer.Add(FTable[enc[i] and $F]);
+      System.Inc(i);
+    end;
+    result := buffer.Text;
+  finally
+    buffer.Free;
+  end;
+end;
+
+end.

+ 201 - 0
CryptoLib/src/Asn1/ClpDerUtf8String.pas

@@ -0,0 +1,201 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerUtf8String;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpDerStringBase,
+  ClpAsn1Tags,
+  ClpAsn1OctetString,
+  ClpAsn1Object,
+  ClpIProxiedInterface,
+  ClpCryptoLibTypes,
+  ClpIAsn1TaggedObject,
+  ClpIDerUtf8String;
+
+resourcestring
+  SIllegalObject = 'Illegal Object in GetInstance: %s';
+  SStrNil = '"str"';
+
+type
+
+  /// <summary>
+  /// Der UTF8String object.
+  /// </summary>
+  TDerUtf8String = class(TDerStringBase, IDerUtf8String)
+
+  strict private
+  var
+    FStr: String;
+
+    function GetStr: String; inline;
+    property Str: String read GetStr;
+
+  strict protected
+    function Asn1Equals(asn1Object: IAsn1Object): Boolean; override;
+  public
+
+    /// <summary>
+    /// basic constructor - with bytes.
+    /// </summary>
+    constructor Create(Str: TCryptoLibByteArray); overload;
+
+    /// <summary>
+    /// basic constructor
+    /// </summary>
+    constructor Create(const Str: String); overload;
+
+    function GetString(): String; override;
+
+    function GetOctets(): TCryptoLibByteArray; inline;
+
+    procedure Encode(derOut: IDerOutputStream); override;
+
+    /// <summary>
+    /// return an UTF8 string from the passed in object.
+    /// </summary>
+    /// <param name="obj">
+    /// a Der UTF8String or an object that can be converted into one.
+    /// </param>
+    /// <returns>
+    /// return a Der UTF8String instance, or null.
+    /// </returns>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: TObject): IDerUtf8String; overload;
+      static; inline;
+
+    /// <summary>
+    /// return a Der UTF8String from a tagged object.
+    /// </summary>
+    /// <param name="obj">
+    /// the tagged object holding the object we want
+    /// </param>
+    /// <param name="isExplicit">
+    /// true if the object is meant to be explicitly tagged false otherwise.
+    /// </param>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the tagged object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: IAsn1TaggedObject; isExplicit: Boolean)
+      : IDerUtf8String; overload; static; inline;
+
+  end;
+
+implementation
+
+{ TDerUtf8String }
+
+function TDerUtf8String.GetOctets: TCryptoLibByteArray;
+begin
+{$IFDEF FPC}
+  result := TEncoding.ASCII.GetBytes(UnicodeString(Str));
+{$ELSE}
+  result := TEncoding.ASCII.GetBytes(Str);
+{$ENDIF FPC}
+end;
+
+function TDerUtf8String.Asn1Equals(asn1Object: IAsn1Object): Boolean;
+var
+  other: IDerUtf8String;
+begin
+
+  if (not Supports(asn1Object, IDerUtf8String, other)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  result := Str = other.Str;
+end;
+
+constructor TDerUtf8String.Create(Str: TCryptoLibByteArray);
+begin
+{$IFDEF FPC}
+  Create(String(TEncoding.UTF8.GetString(Str)));
+{$ELSE}
+  Create(TEncoding.UTF8.GetString(Str));
+{$ENDIF FPC}
+end;
+
+constructor TDerUtf8String.Create(const Str: String);
+begin
+  Inherited Create();
+  if (Str = '') then
+  begin
+    raise EArgumentNilCryptoLibException.CreateRes(@SStrNil);
+  end;
+
+  FStr := Str;
+end;
+
+procedure TDerUtf8String.Encode(derOut: IDerOutputStream);
+begin
+{$IFDEF FPC}
+  derOut.WriteEncoded(TAsn1Tags.Utf8String,
+    TEncoding.UTF8.GetBytes(UnicodeString(Str)));
+{$ELSE}
+  derOut.WriteEncoded(TAsn1Tags.Utf8String, TEncoding.UTF8.GetBytes(Str));
+{$ENDIF FPC}
+end;
+
+class function TDerUtf8String.GetInstance(obj: IAsn1TaggedObject;
+  isExplicit: Boolean): IDerUtf8String;
+var
+  o: IAsn1Object;
+begin
+  o := obj.GetObject();
+
+  if ((isExplicit) or (Supports(o, IDerUtf8String))) then
+  begin
+    result := GetInstance(o as TAsn1Object);
+    Exit;
+  end;
+
+  result := TDerUtf8String.Create(TAsn1OctetString.GetInstance(o as TAsn1Object)
+    .GetOctets());
+end;
+
+class function TDerUtf8String.GetInstance(obj: TObject): IDerUtf8String;
+begin
+  if ((obj = Nil) or (obj is TDerUtf8String)) then
+  begin
+    result := obj as TDerUtf8String;
+    Exit;
+  end;
+
+  raise EArgumentCryptoLibException.CreateResFmt(@SIllegalObject,
+    [obj.ClassName]);
+end;
+
+function TDerUtf8String.GetStr: String;
+begin
+  result := FStr;
+end;
+
+function TDerUtf8String.GetString: String;
+begin
+  result := Str;
+end;
+
+end.

+ 202 - 0
CryptoLib/src/Asn1/ClpDerVideotexString.pas

@@ -0,0 +1,202 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerVideotexString;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpArrayUtils,
+  ClpCryptoLibTypes,
+  ClpAsn1Object,
+  ClpAsn1Tags,
+  ClpAsn1OctetString,
+  ClpIProxiedInterface,
+  ClpIDerVideotexString,
+  ClpIAsn1TaggedObject,
+  ClpDerStringBase;
+
+resourcestring
+  SIllegalObject = 'Illegal Object in GetInstance: %s';
+  SEncodingError = 'Encoding Error in GetInstance:  %s  "obj"';
+
+type
+  TDerVideotexString = class(TDerStringBase, IDerVideotexString)
+
+  strict private
+  var
+    FmString: TCryptoLibByteArray;
+
+    function GetmString: TCryptoLibByteArray; inline;
+
+  protected
+    function Asn1GetHashCode(): Int32; override;
+    function Asn1Equals(asn1Object: IAsn1Object): Boolean; override;
+
+  public
+    property mString: TCryptoLibByteArray read GetmString;
+
+    /// <summary>
+    /// basic constructor - with bytes.
+    /// </summary>
+    /// <param name="encoding">
+    /// the byte encoding of the characters making up the string.
+    /// </param>
+    constructor Create(encoding: TCryptoLibByteArray);
+
+    function GetString(): String; override;
+
+    function GetOctets(): TCryptoLibByteArray; inline;
+
+    procedure Encode(derOut: IDerOutputStream); override;
+
+    /// <summary>
+    /// return a Videotex String from the passed in object
+    /// </summary>
+    /// <param name="obj">
+    /// a DerVideotexString or an object that can be converted into one.
+    /// </param>
+    /// <returns>
+    /// return a DerVideotexString instance, or null.
+    /// </returns>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: TObject): IDerVideotexString; overload;
+      static; inline;
+
+    class function GetInstance(obj: TCryptoLibByteArray): IDerVideotexString;
+      overload; static;
+
+    /// <summary>
+    /// return a Videotex string from a tagged object.
+    /// </summary>
+    /// <param name="obj">
+    /// the tagged object holding the object we want
+    /// </param>
+    /// <param name="isExplicit">
+    /// true if the object is meant to be explicitly tagged false otherwise.
+    /// </param>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the tagged object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: IAsn1TaggedObject; isExplicit: Boolean)
+      : IDerVideotexString; overload; static; inline;
+
+  end;
+
+implementation
+
+{ TDerVideotexString }
+
+function TDerVideotexString.Asn1Equals(asn1Object: IAsn1Object): Boolean;
+var
+  other: IDerVideotexString;
+begin
+
+  if (not Supports(asn1Object, IDerVideotexString, other)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  result := TArrayUtils.AreEqual(mString, other.mString);
+end;
+
+function TDerVideotexString.Asn1GetHashCode: Int32;
+begin
+  result := TArrayUtils.GetArrayHashCode(mString);
+end;
+
+constructor TDerVideotexString.Create(encoding: TCryptoLibByteArray);
+begin
+  Inherited Create();
+  FmString := System.Copy(encoding);
+end;
+
+procedure TDerVideotexString.Encode(derOut: IDerOutputStream);
+begin
+  derOut.WriteEncoded(TAsn1Tags.VideotexString, mString);
+end;
+
+class function TDerVideotexString.GetInstance(obj: TObject): IDerVideotexString;
+begin
+  if ((obj = Nil) or (obj is TDerVideotexString)) then
+  begin
+    result := obj as TDerVideotexString;
+    Exit;
+  end;
+
+  raise EArgumentCryptoLibException.CreateResFmt(@SIllegalObject,
+    [obj.ClassName]);
+end;
+
+class function TDerVideotexString.GetInstance(obj: IAsn1TaggedObject;
+  isExplicit: Boolean): IDerVideotexString;
+var
+  o: IAsn1Object;
+begin
+  o := obj.GetObject();
+
+  if ((isExplicit) or (Supports(o, IDerVideotexString))) then
+  begin
+    result := GetInstance(o as TAsn1Object);
+    Exit;
+  end;
+
+  result := TDerVideotexString.Create
+    (TAsn1OctetString.GetInstance(o as TAsn1Object).GetOctets());
+end;
+
+class function TDerVideotexString.GetInstance(obj: TCryptoLibByteArray)
+  : IDerVideotexString;
+begin
+  try
+    result := FromByteArray(obj) as IDerVideotexString;
+  except
+    on e: Exception do
+    begin
+      raise EArgumentCryptoLibException.CreateResFmt(@SEncodingError,
+        [e.Message]);
+    end;
+
+  end;
+end;
+
+function TDerVideotexString.GetmString: TCryptoLibByteArray;
+begin
+  result := FmString;
+end;
+
+function TDerVideotexString.GetOctets: TCryptoLibByteArray;
+begin
+  result := System.Copy(mString);
+end;
+
+function TDerVideotexString.GetString: String;
+begin
+{$IFDEF FPC}
+  result := String(TEncoding.ASCII.GetString(mString)); // encoding.default
+{$ELSE}
+  result := TEncoding.ASCII.GetString(mString); // encoding.default
+{$ENDIF FPC}
+end;
+
+end.

+ 210 - 0
CryptoLib/src/Asn1/ClpDerVisibleString.pas

@@ -0,0 +1,210 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpDerVisibleString;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpDerStringBase,
+  ClpAsn1Tags,
+  ClpAsn1Object,
+  ClpIAsn1OctetString,
+  ClpStringHelper,
+  ClpIProxiedInterface,
+  ClpCryptoLibTypes,
+  ClpIAsn1TaggedObject,
+  ClpIDerVisibleString;
+
+resourcestring
+  SIllegalObject = 'Illegal Object in GetInstance: %s';
+  SStrNil = '"str"';
+
+type
+
+  /// <summary>
+  /// Der VisibleString object.
+  /// </summary>
+  TDerVisibleString = class(TDerStringBase, IDerVisibleString)
+
+  strict private
+  var
+    FStr: String;
+
+    function GetStr: String; inline;
+    property Str: String read GetStr;
+
+  strict protected
+    function Asn1GetHashCode(): Int32; override;
+    function Asn1Equals(asn1Object: IAsn1Object): Boolean; override;
+  public
+
+    /// <summary>
+    /// basic constructor - byte encoded string.
+    /// </summary>
+    constructor Create(Str: TCryptoLibByteArray); overload;
+
+    /// <summary>
+    /// basic constructor
+    /// </summary>
+    constructor Create(const Str: String); overload;
+
+    function GetString(): String; override;
+
+    function GetOctets(): TCryptoLibByteArray; inline;
+
+    procedure Encode(derOut: IDerOutputStream); override;
+
+    /// <summary>
+    /// return a DerVisibleString from the passed in object
+    /// </summary>
+    /// <param name="obj">
+    /// a DerVisibleString or an object that can be converted into one.
+    /// </param>
+    /// <returns>
+    /// return a DerVisibleString instance, or null.
+    /// </returns>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: TObject): IDerVisibleString; overload;
+      static; inline;
+
+    /// <summary>
+    /// return a DerVisibleString from a tagged object.
+    /// </summary>
+    /// <param name="obj">
+    /// the tagged object holding the object we want
+    /// </param>
+    /// <param name="isExplicit">
+    /// true if the object is meant to be explicitly tagged false otherwise.
+    /// </param>
+    /// <exception cref="ClpCryptoLibTypes|EArgumentCryptoLibException">
+    /// if the tagged object cannot be converted.
+    /// </exception>
+    class function GetInstance(obj: IAsn1TaggedObject; isExplicit: Boolean)
+      : IDerVisibleString; overload; static; inline;
+
+  end;
+
+implementation
+
+{ TDerVisibleString }
+
+function TDerVisibleString.GetOctets: TCryptoLibByteArray;
+begin
+{$IFDEF FPC}
+  result := TEncoding.ASCII.GetBytes(UnicodeString(Str));
+{$ELSE}
+  result := TEncoding.ASCII.GetBytes(Str);
+{$ENDIF FPC}
+end;
+
+function TDerVisibleString.Asn1Equals(asn1Object: IAsn1Object): Boolean;
+var
+  other: IDerVisibleString;
+begin
+
+  if (not Supports(asn1Object, IDerVisibleString, other)) then
+  begin
+    result := false;
+    Exit;
+  end;
+
+  result := Str = other.Str;
+end;
+
+function TDerVisibleString.Asn1GetHashCode: Int32;
+begin
+  result := Str.GetHashCode;
+end;
+
+constructor TDerVisibleString.Create(Str: TCryptoLibByteArray);
+begin
+{$IFDEF FPC}
+  Create(String(TEncoding.ASCII.GetString(Str)));
+{$ELSE}
+  Create(TEncoding.ASCII.GetString(Str));
+{$ENDIF FPC}
+end;
+
+constructor TDerVisibleString.Create(const Str: String);
+begin
+  Inherited Create();
+  if (Str = '') then
+  begin
+    raise EArgumentNilCryptoLibException.CreateRes(@SStrNil);
+  end;
+
+  FStr := Str;
+end;
+
+procedure TDerVisibleString.Encode(derOut: IDerOutputStream);
+begin
+  derOut.WriteEncoded(TAsn1Tags.VisibleString, GetOctets());
+end;
+
+{$IFNDEF _FIXINSIGHT_}
+
+class function TDerVisibleString.GetInstance(obj: IAsn1TaggedObject;
+  isExplicit: Boolean): IDerVisibleString;
+begin
+  result := GetInstance(obj.GetObject() as TAsn1Object);
+end;
+{$ENDIF}
+
+class function TDerVisibleString.GetInstance(obj: TObject): IDerVisibleString;
+var
+  asn1OctetString: IAsn1OctetString;
+  asn1TaggedObject: IAsn1TaggedObject;
+begin
+  if ((obj = Nil) or (obj is TDerVisibleString)) then
+  begin
+    result := obj as TDerVisibleString;
+    Exit;
+  end;
+
+  if Supports(obj, IAsn1OctetString, asn1OctetString) then
+  begin
+    result := TDerVisibleString.Create(asn1OctetString.GetOctets());
+    Exit;
+  end;
+
+  if Supports(obj, IAsn1TaggedObject, asn1TaggedObject) then
+  begin
+    result := GetInstance(asn1TaggedObject.GetObject() as TAsn1Object);
+    Exit;
+  end;
+
+  raise EArgumentCryptoLibException.CreateResFmt(@SIllegalObject,
+    [obj.ClassName]);
+end;
+
+function TDerVisibleString.GetStr: String;
+begin
+  result := FStr;
+end;
+
+function TDerVisibleString.GetString: String;
+begin
+  result := Str;
+end;
+
+end.

+ 158 - 0
CryptoLib/src/Asn1/ClpIndefiniteLengthInputStream.pas

@@ -0,0 +1,158 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpIndefiniteLengthInputStream;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpCryptoLibTypes,
+  ClpLimitedInputStream,
+  ClpIIndefiniteLengthInputStream;
+
+resourcestring
+  SMalformedContent = 'Malformed End-of-Contents Marker';
+
+type
+  TIndefiniteLengthInputStream = class(TLimitedInputStream,
+    IIndefiniteLengthInputStream)
+
+  strict private
+  var
+    F_lookAhead: Int32;
+    F_eofOn00: Boolean;
+
+    function CheckForEof(): Boolean; inline;
+    function RequireByte(): Int32; inline;
+
+  public
+    constructor Create(inStream: TStream; limit: Int32);
+    procedure SetEofOn00(eofOn00: Boolean);
+
+    function Read(buffer: TCryptoLibByteArray; offset, count: Int32)
+      : Int32; override;
+
+    function ReadByte(): Int32; override;
+
+  end;
+
+implementation
+
+uses
+  ClpStreamSorter; // included here to avoid circular dependency :)
+
+{ TIndefiniteLengthInputStream }
+
+function TIndefiniteLengthInputStream.RequireByte: Int32;
+begin
+
+  // result := F_in.ReadByte();
+  result := TStreamSorter.ReadByte(F_in);
+
+  if (result < 0) then
+  begin
+    // Corrupted stream
+    raise EEndOfStreamCryptoLibException.Create('');
+  end;
+end;
+
+function TIndefiniteLengthInputStream.CheckForEof: Boolean;
+var
+  extra: Int32;
+begin
+  if (F_lookAhead = $00) then
+  begin
+    extra := RequireByte();
+    if (extra <> 0) then
+    begin
+      raise EIOCryptoLibException.CreateRes(@SMalformedContent);
+    end;
+
+    F_lookAhead := -1;
+    SetParentEofDetect(true);
+    result := true;
+    Exit;
+  end;
+  result := F_lookAhead < 0;
+end;
+
+constructor TIndefiniteLengthInputStream.Create(inStream: TStream;
+  limit: Int32);
+begin
+  Inherited Create(inStream, limit);
+  F_lookAhead := RequireByte();
+  CheckForEof();
+end;
+
+function TIndefiniteLengthInputStream.Read(buffer: TCryptoLibByteArray;
+  offset, count: Int32): Int32;
+var
+  numRead: Int32;
+begin
+  // Only use this optimisation if we aren't checking for 00
+  if ((F_eofOn00) or (count <= 1)) then
+  begin
+    result := (Inherited Read(buffer, offset, count));
+    Exit;
+  end;
+
+  if (F_lookAhead < 0) then
+  begin
+    result := 0;
+    Exit;
+  end;
+
+  numRead := TStreamSorter.Read(F_in, buffer, offset + 1, count - 1);
+
+  if (numRead <= 0) then
+  begin
+    // Corrupted stream
+    raise EEndOfStreamCryptoLibException.Create('');
+  end;
+
+  buffer[offset] := Byte(F_lookAhead);
+  F_lookAhead := RequireByte();
+
+  result := numRead + 1;
+end;
+
+function TIndefiniteLengthInputStream.ReadByte: Int32;
+begin
+  if (F_eofOn00 and CheckForEof()) then
+  begin
+    result := -1;
+    Exit;
+  end;
+
+  result := F_lookAhead;
+  F_lookAhead := RequireByte();
+
+end;
+
+procedure TIndefiniteLengthInputStream.SetEofOn00(eofOn00: Boolean);
+begin
+  F_eofOn00 := eofOn00;
+  if (F_eofOn00) then
+  begin
+    CheckForEof();
+  end;
+end;
+
+end.

+ 81 - 0
CryptoLib/src/Asn1/ClpLimitedInputStream.pas

@@ -0,0 +1,81 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpLimitedInputStream;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Classes,
+  ClpBaseInputStream,
+  ClpILimitedInputStream;
+
+type
+  TLimitedInputStream = class abstract(TBaseInputStream, ILimitedInputStream)
+
+  strict private
+  var
+    F_limit: Int32;
+  strict protected
+  var
+    F_in: TStream;
+
+    procedure SetParentEofDetect(&on: Boolean);
+
+  public
+    constructor Create(inStream: TStream; limit: Int32);
+    function GetRemaining(): Int32; virtual;
+
+  end;
+
+implementation
+
+uses
+  // included here to avoid circular dependency :)
+  ClpIndefiniteLengthInputStream;
+
+{ TLimitedInputStream }
+
+constructor TLimitedInputStream.Create(inStream: TStream; limit: Int32);
+begin
+  Inherited Create();
+  F_in := inStream;
+  F_limit := limit;
+end;
+
+function TLimitedInputStream.GetRemaining: Int32;
+begin
+  // TODO: maybe one day this can become more accurate
+  Result := F_limit;
+end;
+
+procedure TLimitedInputStream.SetParentEofDetect(&on: Boolean);
+var
+  indefiniteLengthInputStream: TIndefiniteLengthInputStream;
+begin
+
+  if F_in is TIndefiniteLengthInputStream then
+  begin
+    indefiniteLengthInputStream := F_in as TIndefiniteLengthInputStream;
+    indefiniteLengthInputStream.SetEofOn00(&on);
+  end;
+
+end;
+
+end.

+ 92 - 0
CryptoLib/src/Asn1/ClpOidTokenizer.pas

@@ -0,0 +1,92 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpOidTokenizer;
+
+{$I ..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  StrUtils,
+  ClpIOidTokenizer;
+
+type
+
+  /// <summary>
+  /// class for breaking up an Oid into it's component tokens
+  /// </summary>
+  TOidTokenizer = class sealed(TInterfacedObject, IOidTokenizer)
+
+  strict private
+  var
+    Foid: String;
+    Findex: Int32;
+
+    function GetHasMoreTokens: Boolean; inline;
+
+  public
+    constructor Create(const oid: String);
+
+    function NextToken(): String; inline;
+
+    property HasMoreTokens: Boolean read GetHasMoreTokens;
+
+  end;
+
+implementation
+
+{ TOidTokenizer }
+
+constructor TOidTokenizer.Create(const oid: String);
+begin
+  Foid := oid;
+  Findex := 1;
+end;
+
+function TOidTokenizer.GetHasMoreTokens: Boolean;
+begin
+  result := Findex <> 0;
+end;
+
+function TOidTokenizer.NextToken: String;
+var
+  endPoint: Int32;
+  LNextToken, lastToken: string;
+begin
+  if (Findex = 0) then
+  begin
+    result := '';
+    Exit;
+  end;
+
+  endPoint := PosEx('.', Foid, Findex);
+
+  if (endPoint = 0) then
+  begin
+    lastToken := System.Copy(Foid, Findex, System.Length(Foid) - (Findex - 1));
+    Findex := 0;
+    result := lastToken;
+    Exit;
+  end;
+
+  LNextToken := System.Copy(Foid, Findex, endPoint - Findex);
+  Findex := endPoint + 1;
+  result := LNextToken;
+end;
+
+end.

+ 351 - 0
CryptoLib/src/Asn1/CryptoPro/ClpCryptoProObjectIdentifiers.pas

@@ -0,0 +1,351 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpCryptoProObjectIdentifiers;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpDerObjectIdentifier,
+  ClpIDerObjectIdentifier;
+
+type
+  TCryptoProObjectIdentifiers = class abstract(TObject)
+
+  strict private
+    class var
+
+      FGostR3411, FGostR3410x2001, FGostR3410x94, FGostR28147Cbc,
+      FID_Gost28147_89_CryptoPro_A_ParamSet, FGostR3411x94CryptoProParam,
+      FGostR3411Hmac, FGostR3410x2001CryptoProA, FGostElSgDH3410Default,
+      FGostR3410x94CryptoProXchB, FGostR3410x94CryptoProXchC,
+      FGostR3411x94WithGostR3410x94, FGostR3410x94CryptoProXchA,
+      FGostR3410x94CryptoProB, FGostR3410x94CryptoProC, FGostR3410x94CryptoProA,
+      FGostR3410x94CryptoProD, FGostR3411x94CryptoProParamSet,
+      FGostR3410x2001CryptoProXchB, FGostR3411x94WithGostR3410x2001,
+      FGostR3410x2001CryptoProXchA, FGostR3410x2001CryptoProB,
+      FGostR3410x2001CryptoProC, FGostElSgDH3410x1: IDerObjectIdentifier;
+
+    class constructor CryptoProObjectIdentifiers();
+
+    class function GetGostR3411: IDerObjectIdentifier; static; inline;
+
+    class function GetGostR28147Cbc: IDerObjectIdentifier; static; inline;
+    class function GetGostR3410x94: IDerObjectIdentifier; static; inline;
+    class function GetGostR3411Hmac: IDerObjectIdentifier; static; inline;
+    class function GetID_Gost28147_89_CryptoPro_A_ParamSet
+      : IDerObjectIdentifier; static; inline;
+    class function GetGostR3410x2001: IDerObjectIdentifier; static; inline;
+
+    class function GetGostElSgDH3410Default: IDerObjectIdentifier;
+      static; inline;
+    class function GetGostElSgDH3410x1: IDerObjectIdentifier; static; inline;
+    class function GetGostR3410x2001CryptoProA: IDerObjectIdentifier;
+      static; inline;
+    class function GetGostR3410x2001CryptoProB: IDerObjectIdentifier;
+      static; inline;
+    class function GetGostR3410x2001CryptoProC: IDerObjectIdentifier;
+      static; inline;
+    class function GetGostR3410x2001CryptoProXchA: IDerObjectIdentifier;
+      static; inline;
+    class function GetGostR3410x2001CryptoProXchB: IDerObjectIdentifier;
+      static; inline;
+    class function GetGostR3410x94CryptoProA: IDerObjectIdentifier;
+      static; inline;
+    class function GetGostR3410x94CryptoProB: IDerObjectIdentifier;
+      static; inline;
+    class function GetGostR3410x94CryptoProC: IDerObjectIdentifier;
+      static; inline;
+    class function GetGostR3410x94CryptoProD: IDerObjectIdentifier;
+      static; inline;
+    class function GetGostR3410x94CryptoProXchA: IDerObjectIdentifier;
+      static; inline;
+    class function GetGostR3410x94CryptoProXchB: IDerObjectIdentifier;
+      static; inline;
+    class function GetGostR3410x94CryptoProXchC: IDerObjectIdentifier;
+      static; inline;
+    class function GetGostR3411x94CryptoProParam: IDerObjectIdentifier;
+      static; inline;
+    class function GetGostR3411x94WithGostR3410x2001: IDerObjectIdentifier;
+      static; inline;
+    class function GetGostR3411x94WithGostR3410x94: IDerObjectIdentifier;
+      static; inline;
+    class function GetGostR3411x94CryptoProParamSet: IDerObjectIdentifier;
+      static; inline;
+
+  public
+
+    const
+    // GOST Algorithms OBJECT IDENTIFIERS :
+    // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2)}
+    GostID = '1.2.643.2.2';
+
+    class property GostR3411: IDerObjectIdentifier read GetGostR3411;
+    class property GostR3411Hmac: IDerObjectIdentifier read GetGostR3411Hmac;
+    class property GostR28147Cbc: IDerObjectIdentifier read GetGostR28147Cbc;
+    class property ID_Gost28147_89_CryptoPro_A_ParamSet: IDerObjectIdentifier
+      read GetID_Gost28147_89_CryptoPro_A_ParamSet;
+    class property GostR3410x94: IDerObjectIdentifier read GetGostR3410x94;
+
+    class property GostR3410x2001: IDerObjectIdentifier read GetGostR3410x2001;
+    class property GostR3411x94WithGostR3410x94: IDerObjectIdentifier
+      read GetGostR3411x94WithGostR3410x94;
+    class property GostR3411x94WithGostR3410x2001: IDerObjectIdentifier
+      read GetGostR3411x94WithGostR3410x2001;
+    // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) hashes(30) }
+    class property GostR3411x94CryptoProParamSet: IDerObjectIdentifier
+      read GetGostR3411x94CryptoProParamSet;
+    // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) signs(32) }
+    class property GostR3410x94CryptoProA: IDerObjectIdentifier
+      read GetGostR3410x94CryptoProA;
+
+    class property GostR3410x94CryptoProB: IDerObjectIdentifier
+      read GetGostR3410x94CryptoProB;
+    class property GostR3410x94CryptoProC: IDerObjectIdentifier
+      read GetGostR3410x94CryptoProC;
+    class property GostR3410x94CryptoProD: IDerObjectIdentifier
+      read GetGostR3410x94CryptoProD;
+    // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) exchanges(33) }
+    class property GostR3410x94CryptoProXchA: IDerObjectIdentifier
+      read GetGostR3410x94CryptoProXchA;
+    class property GostR3410x94CryptoProXchB: IDerObjectIdentifier
+      read GetGostR3410x94CryptoProXchB;
+    class property GostR3410x94CryptoProXchC: IDerObjectIdentifier
+      read GetGostR3410x94CryptoProXchC;
+    // { iso(1) member-body(2)ru(643) rans(2) cryptopro(2) ecc-signs(35) }
+    class property GostR3410x2001CryptoProA: IDerObjectIdentifier
+      read GetGostR3410x2001CryptoProA;
+    class property GostR3410x2001CryptoProB: IDerObjectIdentifier
+      read GetGostR3410x2001CryptoProB;
+    class property GostR3410x2001CryptoProC: IDerObjectIdentifier
+      read GetGostR3410x2001CryptoProC;
+    // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) ecc-exchanges(36) }
+    class property GostR3410x2001CryptoProXchA: IDerObjectIdentifier
+      read GetGostR3410x2001CryptoProXchA;
+    class property GostR3410x2001CryptoProXchB: IDerObjectIdentifier
+      read GetGostR3410x2001CryptoProXchB;
+
+    class property GostElSgDH3410Default: IDerObjectIdentifier
+      read GetGostElSgDH3410Default;
+    class property GostElSgDH3410x1: IDerObjectIdentifier
+      read GetGostElSgDH3410x1;
+
+    class property GostR3411x94CryptoProParam: IDerObjectIdentifier
+      read GetGostR3411x94CryptoProParam;
+
+    class procedure Boot(); static;
+
+  end;
+
+implementation
+
+{ TCryptoProObjectIdentifiers }
+
+class procedure TCryptoProObjectIdentifiers.Boot;
+begin
+  FGostR3411 := TDerObjectIdentifier.Create(GostID + '.9');
+  FGostR3411Hmac := TDerObjectIdentifier.Create(GostID + '.10');
+
+  FGostR28147Cbc := TDerObjectIdentifier.Create(GostID + '.21');
+
+  FID_Gost28147_89_CryptoPro_A_ParamSet := TDerObjectIdentifier.Create
+    (GostID + '.31.1');
+
+  FGostR3410x94 := TDerObjectIdentifier.Create(GostID + '.20');
+  FGostR3410x2001 := TDerObjectIdentifier.Create(GostID + '.19');
+  FGostR3411x94WithGostR3410x94 := TDerObjectIdentifier.Create(GostID + '.4');
+  FGostR3411x94WithGostR3410x2001 := TDerObjectIdentifier.Create(GostID + '.3');
+
+  // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) hashes(30) }
+  FGostR3411x94CryptoProParamSet := TDerObjectIdentifier.Create
+    (GostID + '.30.1');
+
+  // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) signs(32) }
+  FGostR3410x94CryptoProA := TDerObjectIdentifier.Create(GostID + '.32.2');
+  FGostR3410x94CryptoProB := TDerObjectIdentifier.Create(GostID + '.32.3');
+  FGostR3410x94CryptoProC := TDerObjectIdentifier.Create(GostID + '.32.4');
+  FGostR3410x94CryptoProD := TDerObjectIdentifier.Create(GostID + '.32.5');
+
+  // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) exchanges(33) }
+  FGostR3410x94CryptoProXchA := TDerObjectIdentifier.Create(GostID + '.33.1');
+  FGostR3410x94CryptoProXchB := TDerObjectIdentifier.Create(GostID + '.33.2');
+  FGostR3410x94CryptoProXchC := TDerObjectIdentifier.Create(GostID + '.33.3');
+
+  // { iso(1) member-body(2)ru(643) rans(2) cryptopro(2) ecc-signs(35) }
+  FGostR3410x2001CryptoProA := TDerObjectIdentifier.Create(GostID + '.35.1');
+  FGostR3410x2001CryptoProB := TDerObjectIdentifier.Create(GostID + '.35.2');
+  FGostR3410x2001CryptoProC := TDerObjectIdentifier.Create(GostID + '.35.3');
+
+  // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) ecc-exchanges(36) }
+  FGostR3410x2001CryptoProXchA := TDerObjectIdentifier.Create(GostID + '.36.0');
+  FGostR3410x2001CryptoProXchB := TDerObjectIdentifier.Create(GostID + '.36.1');
+
+  FGostElSgDH3410Default := TDerObjectIdentifier.Create(GostID + '.36.0');
+  FGostElSgDH3410x1 := TDerObjectIdentifier.Create(GostID + '.36.1');
+end;
+
+class constructor TCryptoProObjectIdentifiers.CryptoProObjectIdentifiers;
+begin
+  TCryptoProObjectIdentifiers.Boot;
+end;
+
+class function TCryptoProObjectIdentifiers.GetGostR3411: IDerObjectIdentifier;
+begin
+  result := FGostR3411;
+end;
+
+class function TCryptoProObjectIdentifiers.GetGostElSgDH3410Default
+  : IDerObjectIdentifier;
+begin
+  result := FGostElSgDH3410Default;
+end;
+
+class function TCryptoProObjectIdentifiers.GetGostElSgDH3410x1
+  : IDerObjectIdentifier;
+begin
+  result := FGostElSgDH3410x1;
+end;
+
+class function TCryptoProObjectIdentifiers.GetGostR28147Cbc
+  : IDerObjectIdentifier;
+begin
+  result := FGostR28147Cbc;
+end;
+
+class function TCryptoProObjectIdentifiers.GetGostR3410x2001
+  : IDerObjectIdentifier;
+begin
+  result := FGostR3410x2001;
+end;
+
+class function TCryptoProObjectIdentifiers.GetGostR3410x2001CryptoProA
+  : IDerObjectIdentifier;
+begin
+  result := FGostR3410x2001CryptoProA;
+end;
+
+class function TCryptoProObjectIdentifiers.GetGostR3410x2001CryptoProB
+  : IDerObjectIdentifier;
+begin
+  result := FGostR3410x2001CryptoProB;
+end;
+
+class function TCryptoProObjectIdentifiers.GetGostR3410x2001CryptoProC
+  : IDerObjectIdentifier;
+begin
+  result := FGostR3410x2001CryptoProC;
+end;
+
+class function TCryptoProObjectIdentifiers.GetGostR3410x2001CryptoProXchA
+  : IDerObjectIdentifier;
+begin
+  result := FGostR3410x2001CryptoProXchA;
+end;
+
+class function TCryptoProObjectIdentifiers.GetGostR3410x2001CryptoProXchB
+  : IDerObjectIdentifier;
+begin
+  result := FGostR3410x2001CryptoProXchB;
+end;
+
+class function TCryptoProObjectIdentifiers.GetGostR3410x94
+  : IDerObjectIdentifier;
+begin
+  result := FGostR3410x94;
+end;
+
+class function TCryptoProObjectIdentifiers.GetGostR3410x94CryptoProA
+  : IDerObjectIdentifier;
+begin
+  result := FGostR3410x94CryptoProA;
+end;
+
+class function TCryptoProObjectIdentifiers.GetGostR3410x94CryptoProB
+  : IDerObjectIdentifier;
+begin
+  result := FGostR3410x94CryptoProB;
+end;
+
+class function TCryptoProObjectIdentifiers.GetGostR3410x94CryptoProC
+  : IDerObjectIdentifier;
+begin
+  result := FGostR3410x94CryptoProC;
+end;
+
+class function TCryptoProObjectIdentifiers.GetGostR3410x94CryptoProD
+  : IDerObjectIdentifier;
+begin
+  result := FGostR3410x94CryptoProD;
+end;
+
+class function TCryptoProObjectIdentifiers.GetGostR3410x94CryptoProXchA
+  : IDerObjectIdentifier;
+begin
+  result := FGostR3410x94CryptoProXchA;
+end;
+
+class function TCryptoProObjectIdentifiers.GetGostR3410x94CryptoProXchB
+  : IDerObjectIdentifier;
+begin
+  result := FGostR3410x94CryptoProXchB;
+end;
+
+class function TCryptoProObjectIdentifiers.GetGostR3410x94CryptoProXchC
+  : IDerObjectIdentifier;
+begin
+  result := FGostR3410x94CryptoProXchC;
+end;
+
+class function TCryptoProObjectIdentifiers.GetGostR3411Hmac
+  : IDerObjectIdentifier;
+begin
+  result := FGostR3411Hmac;
+end;
+
+class function TCryptoProObjectIdentifiers.GetGostR3411x94CryptoProParam
+  : IDerObjectIdentifier;
+begin
+  result := FGostR3411x94CryptoProParam;
+end;
+
+class function TCryptoProObjectIdentifiers.GetGostR3411x94CryptoProParamSet
+  : IDerObjectIdentifier;
+begin
+  result := FGostR3411x94CryptoProParamSet;
+end;
+
+class function TCryptoProObjectIdentifiers.GetGostR3411x94WithGostR3410x2001
+  : IDerObjectIdentifier;
+begin
+  result := FGostR3411x94WithGostR3410x2001;
+end;
+
+class function TCryptoProObjectIdentifiers.GetGostR3411x94WithGostR3410x94
+  : IDerObjectIdentifier;
+begin
+  result := FGostR3411x94WithGostR3410x94;
+end;
+
+class function TCryptoProObjectIdentifiers.
+  GetID_Gost28147_89_CryptoPro_A_ParamSet: IDerObjectIdentifier;
+begin
+  result := FID_Gost28147_89_CryptoPro_A_ParamSet;
+end;
+
+end.

+ 410 - 0
CryptoLib/src/Asn1/CryptoPro/ClpECGost3410NamedCurves.pas

@@ -0,0 +1,410 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpECGost3410NamedCurves;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Generics.Collections,
+  ClpCryptoLibTypes,
+  ClpBigInteger,
+  ClpCryptoProObjectIdentifiers,
+  ClpRosstandartObjectIdentifiers,
+  ClpECCurve,
+  ClpIECInterface,
+  ClpECDomainParameters,
+  ClpIECDomainParameters,
+  ClpIDerObjectIdentifier;
+
+type
+  /// <summary>
+  /// Table of the available named parameters for GOST 3410-2001 / 2012.
+  /// </summary>
+  TECGost3410NamedCurves = class sealed(TObject)
+
+  strict private
+  class var
+    Fparameters: TDictionary<IDerObjectIdentifier, IECDomainParameters>;
+    FobjIds: TDictionary<String, IDerObjectIdentifier>;
+    Fnames: TDictionary<IDerObjectIdentifier, String>;
+
+    class constructor CreateECGost3410NamedCurves();
+    class destructor DestroyECGost3410NamedCurves();
+
+    class function GetNames: TCryptoLibStringArray; static; inline;
+
+  public
+    // /**
+    // * return the ECDomainParameters object for the given OID, null if it
+    // * isn't present.
+    // *
+    // * @param oid an object identifier representing a named parameters, if present.
+    // */
+    class function GetByOid(oid: IDerObjectIdentifier): IECDomainParameters;
+      static; inline;
+    // /**
+    // * return the ECDomainParameters object for the given OID, null if it
+    // * isn't present.
+    // *
+    // * @param oid an object identifier representing a named parameters, if present.
+    // */
+    class function GetByName(const name: String): IECDomainParameters;
+      static; inline;
+    // /**
+    // * return the named curve name represented by the given object identifier.
+    // */
+    class function GetName(oid: IDerObjectIdentifier): String; static; inline;
+
+    class function GetOid(const name: String): IDerObjectIdentifier;
+      static; inline;
+
+    class procedure Boot(); static;
+
+    // /**
+    // * returns an enumeration containing the name strings for curves
+    // * contained in this structure.
+    // */
+    class property Names: TCryptoLibStringArray read GetNames;
+
+  end;
+
+implementation
+
+{ TECGost3410NamedCurves }
+
+class procedure TECGost3410NamedCurves.Boot;
+var
+  mod_p, mod_q: TBigInteger;
+  curve: IFPCurve;
+  ecParams: IECDomainParameters;
+begin
+  TBigInteger.Boot;
+  Fparameters := TDictionary<IDerObjectIdentifier,
+    IECDomainParameters>.Create();
+  FobjIds := TDictionary<String, IDerObjectIdentifier>.Create();
+  Fnames := TDictionary<IDerObjectIdentifier, String>.Create();
+
+  mod_p := TBigInteger.Create
+    ('115792089237316195423570985008687907853269984665640564039457584007913129639319');
+  mod_q := TBigInteger.Create
+    ('115792089237316195423570985008687907853073762908499243225378155805079068850323');
+
+  curve := TFpCurve.Create(mod_p, // p
+    TBigInteger.Create
+    ('115792089237316195423570985008687907853269984665640564039457584007913129639316'),
+    // a
+    TBigInteger.Create('166'), // b
+    mod_q, TBigInteger.One);
+
+  ecParams := TECDomainParameters.Create(curve,
+    curve.CreatePoint(TBigInteger.Create('1'), // x
+    TBigInteger.Create
+    ('64033881142927202683649881450433473985931760268884941288852745803908878638612')
+    ), // y
+    mod_q);
+
+  Fparameters.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProA,
+    ecParams);
+
+  mod_p := TBigInteger.Create
+    ('115792089237316195423570985008687907853269984665640564039457584007913129639319');
+  mod_q := TBigInteger.Create
+    ('115792089237316195423570985008687907853073762908499243225378155805079068850323');
+
+  curve := TFpCurve.Create(mod_p, // p
+    TBigInteger.Create
+    ('115792089237316195423570985008687907853269984665640564039457584007913129639316'),
+    TBigInteger.Create('166'), mod_q, TBigInteger.One);
+
+  ecParams := TECDomainParameters.Create(curve,
+    curve.CreatePoint(TBigInteger.Create('1'), // x
+    TBigInteger.Create
+    ('64033881142927202683649881450433473985931760268884941288852745803908878638612')
+    ), // y
+    mod_q);
+
+  Fparameters.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProXchA,
+    ecParams);
+
+  mod_p := TBigInteger.Create
+    ('57896044618658097711785492504343953926634992332820282019728792003956564823193');
+  // p
+  mod_q := TBigInteger.Create
+    ('57896044618658097711785492504343953927102133160255826820068844496087732066703');
+  // q
+
+  curve := TFpCurve.Create(mod_p, // p
+    TBigInteger.Create
+    ('57896044618658097711785492504343953926634992332820282019728792003956564823190'),
+    // a
+    TBigInteger.Create
+    ('28091019353058090096996979000309560759124368558014865957655842872397301267595'),
+    // b
+    mod_q, TBigInteger.One);
+
+  ecParams := TECDomainParameters.Create(curve,
+    curve.CreatePoint(TBigInteger.Create('1'), // x
+    TBigInteger.Create
+    ('28792665814854611296992347458380284135028636778229113005756334730996303888124')
+    ), // y
+    mod_q); // q
+
+  Fparameters.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProB,
+    ecParams);
+
+  mod_p := TBigInteger.Create
+    ('70390085352083305199547718019018437841079516630045180471284346843705633502619');
+  mod_q := TBigInteger.Create
+    ('70390085352083305199547718019018437840920882647164081035322601458352298396601');
+
+  curve := TFpCurve.Create(mod_p, // p
+    TBigInteger.Create
+    ('70390085352083305199547718019018437841079516630045180471284346843705633502616'),
+    TBigInteger.Create('32858'), mod_q, TBigInteger.One);
+
+  ecParams := TECDomainParameters.Create(curve,
+    curve.CreatePoint(TBigInteger.Create('0'),
+    TBigInteger.Create
+    ('29818893917731240733471273240314769927240550812383695689146495261604565990247')
+    ), mod_q);
+
+  Fparameters.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProXchB,
+    ecParams);
+
+  mod_p := TBigInteger.Create
+    ('70390085352083305199547718019018437841079516630045180471284346843705633502619');
+  // p
+  mod_q := TBigInteger.Create
+    ('70390085352083305199547718019018437840920882647164081035322601458352298396601');
+  // q
+  curve := TFpCurve.Create(mod_p, // p
+    TBigInteger.Create
+    ('70390085352083305199547718019018437841079516630045180471284346843705633502616'),
+    // a
+    TBigInteger.Create('32858'), // b
+    mod_q, TBigInteger.One);
+
+  ecParams := TECDomainParameters.Create(curve,
+    curve.CreatePoint(TBigInteger.Create('0'), // x
+    TBigInteger.Create
+    ('29818893917731240733471273240314769927240550812383695689146495261604565990247')
+    ), // y
+    mod_q); // q
+
+  Fparameters.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProC,
+    ecParams);
+
+  // GOST34.10 2012
+  mod_p := TBigInteger.Create
+    ('115792089237316195423570985008687907853269984665640564039457584007913129639319');
+  // p
+  mod_q := TBigInteger.Create
+    ('115792089237316195423570985008687907853073762908499243225378155805079068850323');
+  // q
+  curve := TFpCurve.Create(mod_p, // p
+    TBigInteger.Create
+    ('115792089237316195423570985008687907853269984665640564039457584007913129639316'),
+    // a
+    TBigInteger.Create('166'), // b
+    mod_q, TBigInteger.One);
+
+  ecParams := TECDomainParameters.Create(curve,
+    curve.CreatePoint(TBigInteger.Create('1'), // x
+    TBigInteger.Create
+    ('64033881142927202683649881450433473985931760268884941288852745803908878638612')
+    ), // y
+    mod_q); // q
+
+  Fparameters.Add(TRosstandartObjectIdentifiers.
+    id_tc26_gost_3410_12_256_paramSetA, ecParams);
+
+  mod_p := TBigInteger.Create
+    ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7',
+    16); // p
+  mod_q := TBigInteger.Create
+    ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27E69532F48D89116FF22B8D4E0560609B4B38ABFAD2B85DCACDB1411F10B275',
+    16); // q
+  curve := TFpCurve.Create(mod_p, // p
+    TBigInteger.Create
+    ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC4',
+    16), // a
+    TBigInteger.Create
+    ('E8C2505DEDFC86DDC1BD0B2B6667F1DA34B82574761CB0E879BD081CFD0B6265EE3CB090F30D27614CB4574010DA90DD862EF9D4EBEE4761503190785A71C760',
+    16), // b
+    mod_q, TBigInteger.One);
+
+  ecParams := TECDomainParameters.Create(curve,
+    curve.CreatePoint(TBigInteger.Create
+    ('00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003'),
+    // x
+    TBigInteger.Create
+    ('7503CFE87A836AE3A61B8816E25450E6CE5E1C93ACF1ABC1778064FDCBEFA921DF1626BE4FD036E93D75E6A50E3A41E98028FE5FC235F5B889A589CB5215F2A4',
+    16)), // y
+    mod_q); // q
+
+  Fparameters.Add(TRosstandartObjectIdentifiers.
+    id_tc26_gost_3410_12_512_paramSetA, ecParams);
+
+  mod_p := TBigInteger.Create
+    ('8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006F',
+    16); // p
+  mod_q := TBigInteger.Create
+    ('800000000000000000000000000000000000000000000000000000000000000149A1EC142565A545ACFDB77BD9D40CFA8B996712101BEA0EC6346C54374F25BD',
+    16); // q
+  curve := TFpCurve.Create(mod_p, // p
+    TBigInteger.Create
+    ('8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006C',
+    16), // a
+    TBigInteger.Create
+    ('687D1B459DC841457E3E06CF6F5E2517B97C7D614AF138BCBF85DC806C4B289F3E965D2DB1416D217F8B276FAD1AB69C50F78BEE1FA3106EFB8CCBC7C5140116',
+    16), // b
+    mod_q, TBigInteger.One);
+
+  ecParams := TECDomainParameters.Create(curve,
+    curve.CreatePoint(TBigInteger.Create
+    ('00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002'),
+    // x
+    TBigInteger.Create
+    ('1A8F7EDA389B094C2C071E3647A8940F3C123B697578C213BE6DD9E6C8EC7335DCB228FD1EDF4A39152CBCAAF8C0398828041055F94CEEEC7E21340780FE41BD',
+    16)), // y
+    mod_q); // q
+
+  Fparameters.Add(TRosstandartObjectIdentifiers.
+    id_tc26_gost_3410_12_512_paramSetB, ecParams);
+
+  mod_p := TBigInteger.Create
+    ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7',
+    16); // p
+  mod_q := TBigInteger.Create
+    ('3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC98CDBA46506AB004C33A9FF5147502CC8EDA9E7A769A12694623CEF47F023ED',
+    16); // q
+  curve := TFpCurve.Create(mod_p, // p
+    TBigInteger.Create
+    ('DC9203E514A721875485A529D2C722FB187BC8980EB866644DE41C68E143064546E861C0E2C9EDD92ADE71F46FCF50FF2AD97F951FDA9F2A2EB6546F39689BD3',
+    16), // a
+    TBigInteger.Create
+    ('B4C4EE28CEBC6C2C8AC12952CF37F16AC7EFB6A9F69F4B57FFDA2E4F0DE5ADE038CBC2FFF719D2C18DE0284B8BFEF3B52B8CC7A5F5BF0A3C8D2319A5312557E1',
+    16), // b
+    mod_q, TBigInteger.One);
+
+  ecParams := TECDomainParameters.Create(curve,
+    curve.CreatePoint(TBigInteger.Create
+    ('E2E31EDFC23DE7BDEBE241CE593EF5DE2295B7A9CBAEF021D385F7074CEA043AA27272A7AE602BF2A7B9033DB9ED3610C6FB85487EAE97AAC5BC7928C1950148',
+    16), // x
+    TBigInteger.Create
+    ('F5CE40D95B5EB899ABBCCFF5911CB8577939804D6527378B8C108C3D2090FF9BE18E2D33E3021ED2EF32D85822423B6304F726AA854BAE07D0396E9A9ADDC40F',
+    16)), // y
+    mod_q); // q
+
+  Fparameters.Add(TRosstandartObjectIdentifiers.
+    id_tc26_gost_3410_12_512_paramSetC, ecParams);
+
+  FobjIds.Add('GostR3410-2001-CryptoPro-A',
+    TCryptoProObjectIdentifiers.GostR3410x2001CryptoProA);
+  FobjIds.Add('GostR3410-2001-CryptoPro-B',
+    TCryptoProObjectIdentifiers.GostR3410x2001CryptoProB);
+  FobjIds.Add('GostR3410-2001-CryptoPro-C',
+    TCryptoProObjectIdentifiers.GostR3410x2001CryptoProC);
+  FobjIds.Add('GostR3410-2001-CryptoPro-XchA',
+    TCryptoProObjectIdentifiers.GostR3410x2001CryptoProXchA);
+  FobjIds.Add('GostR3410-2001-CryptoPro-XchB',
+    TCryptoProObjectIdentifiers.GostR3410x2001CryptoProXchB);
+  FobjIds.Add('Tc26-Gost-3410-12-256-paramSetA',
+    TRosstandartObjectIdentifiers.id_tc26_gost_3410_12_256_paramSetA);
+  FobjIds.Add('Tc26-Gost-3410-12-512-paramSetA',
+    TRosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetA);
+  FobjIds.Add('Tc26-Gost-3410-12-512-paramSetB',
+    TRosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetB);
+  FobjIds.Add('Tc26-Gost-3410-12-512-paramSetC',
+    TRosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetC);
+
+  Fnames.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProA,
+    'GostR3410-2001-CryptoPro-A');
+  Fnames.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProB,
+    'GostR3410-2001-CryptoPro-B');
+  Fnames.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProC,
+    'GostR3410-2001-CryptoPro-C');
+  Fnames.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProXchA,
+    'GostR3410-2001-CryptoPro-XchA');
+  Fnames.Add(TCryptoProObjectIdentifiers.GostR3410x2001CryptoProXchB,
+    'GostR3410-2001-CryptoPro-XchB');
+  Fnames.Add(TRosstandartObjectIdentifiers.id_tc26_gost_3410_12_256_paramSetA,
+    'Tc26-Gost-3410-12-256-paramSetA');
+  Fnames.Add(TRosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetA,
+    'Tc26-Gost-3410-12-512-paramSetA');
+  Fnames.Add(TRosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetB,
+    'Tc26-Gost-3410-12-512-paramSetB');
+  Fnames.Add(TRosstandartObjectIdentifiers.id_tc26_gost_3410_12_512_paramSetC,
+    'Tc26-Gost-3410-12-512-paramSetC');
+
+end;
+
+class constructor TECGost3410NamedCurves.CreateECGost3410NamedCurves;
+begin
+  TECGost3410NamedCurves.Boot;
+end;
+
+class destructor TECGost3410NamedCurves.DestroyECGost3410NamedCurves;
+begin
+  Fparameters.Free;
+  FobjIds.Free;
+  Fnames.Free;
+end;
+
+class function TECGost3410NamedCurves.GetByName(const name: String)
+  : IECDomainParameters;
+var
+  oid: IDerObjectIdentifier;
+begin
+  if (FobjIds.TryGetValue(name, oid)) then
+  begin
+    Fparameters.TryGetValue(oid, Result);
+    Exit;
+  end;
+  Result := Nil;
+end;
+
+class function TECGost3410NamedCurves.GetByOid(oid: IDerObjectIdentifier)
+  : IECDomainParameters;
+begin
+  Fparameters.TryGetValue(oid, Result);
+end;
+
+class function TECGost3410NamedCurves.GetName
+  (oid: IDerObjectIdentifier): String;
+begin
+  Fnames.TryGetValue(oid, Result);
+end;
+
+class function TECGost3410NamedCurves.GetNames: TCryptoLibStringArray;
+begin
+  Result := Fnames.Values.ToArray();
+end;
+
+class function TECGost3410NamedCurves.GetOid(const name: String)
+  : IDerObjectIdentifier;
+begin
+  if (not(FobjIds.TryGetValue(name, Result))) then
+  begin
+    Result := Nil;
+  end;
+end;
+
+end.

+ 166 - 0
CryptoLib/src/Asn1/Nist/ClpNistObjectIdentifiers.pas

@@ -0,0 +1,166 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpNistObjectIdentifiers;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpDerObjectIdentifier,
+  ClpIDerObjectIdentifier;
+
+type
+  TNistObjectIdentifiers = class sealed(TObject)
+
+  strict private
+
+    class var
+
+      FNistAlgorithm, FHashAlgs, FIdSha256, FIdSha384, FIdSha512, FIdSha224,
+      FIdSha512_224, FIdSha512_256, FIdSha3_224, FIdSha3_256, FIdSha3_384,
+      FIdSha3_512: IDerObjectIdentifier;
+
+    class function GetHashAlgs: IDerObjectIdentifier; static; inline;
+    class function GetIdSha224: IDerObjectIdentifier; static; inline;
+    class function GetIdSha256: IDerObjectIdentifier; static; inline;
+    class function GetIdSha3_224: IDerObjectIdentifier; static; inline;
+    class function GetIdSha3_256: IDerObjectIdentifier; static; inline;
+    class function GetIdSha3_384: IDerObjectIdentifier; static; inline;
+    class function GetIdSha3_512: IDerObjectIdentifier; static; inline;
+    class function GetIdSha384: IDerObjectIdentifier; static; inline;
+    class function GetIdSha512: IDerObjectIdentifier; static; inline;
+    class function GetIdSha512_224: IDerObjectIdentifier; static; inline;
+    class function GetIdSha512_256: IDerObjectIdentifier; static; inline;
+    class function GetNistAlgorithm: IDerObjectIdentifier; static; inline;
+
+    class constructor NistObjectIdentifiers();
+
+  public
+
+    //
+    // NIST
+    // iso/itu(2) joint-assign(16) us(840) organization(1) gov(101) csor(3)
+
+    //
+    // nistalgorithms(4)
+    //
+    class property NistAlgorithm: IDerObjectIdentifier read GetNistAlgorithm;
+    class property HashAlgs: IDerObjectIdentifier read GetHashAlgs;
+    class property IdSha256: IDerObjectIdentifier read GetIdSha256;
+    class property IdSha384: IDerObjectIdentifier read GetIdSha384;
+    class property IdSha512: IDerObjectIdentifier read GetIdSha512;
+    class property IdSha224: IDerObjectIdentifier read GetIdSha224;
+    class property IdSha512_224: IDerObjectIdentifier read GetIdSha512_224;
+    class property IdSha512_256: IDerObjectIdentifier read GetIdSha512_256;
+    class property IdSha3_224: IDerObjectIdentifier read GetIdSha3_224;
+    class property IdSha3_256: IDerObjectIdentifier read GetIdSha3_256;
+    class property IdSha3_384: IDerObjectIdentifier read GetIdSha3_384;
+    class property IdSha3_512: IDerObjectIdentifier read GetIdSha3_512;
+
+    class procedure Boot(); static;
+
+  end;
+
+implementation
+
+{ TNistObjectIdentifiers }
+
+class procedure TNistObjectIdentifiers.Boot;
+begin
+  FNistAlgorithm := TDerObjectIdentifier.Create('2.16.840.1.101.3.4');
+  FHashAlgs := NistAlgorithm.Branch('2');
+
+  FIdSha256 := HashAlgs.Branch('1');
+  FIdSha384 := HashAlgs.Branch('2');
+  FIdSha512 := HashAlgs.Branch('3');
+  FIdSha224 := HashAlgs.Branch('4');
+  FIdSha512_224 := HashAlgs.Branch('5');
+  FIdSha512_256 := HashAlgs.Branch('6');
+  FIdSha3_224 := HashAlgs.Branch('7');
+  FIdSha3_256 := HashAlgs.Branch('8');
+  FIdSha3_384 := HashAlgs.Branch('9');
+  FIdSha3_512 := HashAlgs.Branch('10');
+end;
+
+class function TNistObjectIdentifiers.GetHashAlgs: IDerObjectIdentifier;
+begin
+  result := FHashAlgs;
+end;
+
+class function TNistObjectIdentifiers.GetIdSha224: IDerObjectIdentifier;
+begin
+  result := FIdSha224;
+end;
+
+class function TNistObjectIdentifiers.GetIdSha256: IDerObjectIdentifier;
+begin
+  result := FIdSha256;
+end;
+
+class function TNistObjectIdentifiers.GetIdSha384: IDerObjectIdentifier;
+begin
+  result := FIdSha384;
+end;
+
+class function TNistObjectIdentifiers.GetIdSha3_224: IDerObjectIdentifier;
+begin
+  result := FIdSha3_224;
+end;
+
+class function TNistObjectIdentifiers.GetIdSha3_256: IDerObjectIdentifier;
+begin
+  result := FIdSha3_256;
+end;
+
+class function TNistObjectIdentifiers.GetIdSha3_384: IDerObjectIdentifier;
+begin
+  result := FIdSha3_384;
+end;
+
+class function TNistObjectIdentifiers.GetIdSha3_512: IDerObjectIdentifier;
+begin
+  result := FIdSha3_512;
+end;
+
+class function TNistObjectIdentifiers.GetIdSha512: IDerObjectIdentifier;
+begin
+  result := FIdSha512;
+end;
+
+class function TNistObjectIdentifiers.GetIdSha512_224: IDerObjectIdentifier;
+begin
+  result := FIdSha512_224;
+end;
+
+class function TNistObjectIdentifiers.GetIdSha512_256: IDerObjectIdentifier;
+begin
+  result := FIdSha512_256;
+end;
+
+class function TNistObjectIdentifiers.GetNistAlgorithm: IDerObjectIdentifier;
+begin
+  result := FNistAlgorithm;
+end;
+
+class constructor TNistObjectIdentifiers.NistObjectIdentifiers;
+begin
+  TNistObjectIdentifiers.Boot;
+end;
+
+end.

+ 70 - 0
CryptoLib/src/Asn1/Oiw/ClpOiwObjectIdentifiers.pas

@@ -0,0 +1,70 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpOiwObjectIdentifiers;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpDerObjectIdentifier,
+  ClpIDerObjectIdentifier;
+
+type
+  TOiwObjectIdentifiers = class abstract(TObject)
+
+  strict private
+
+    class var
+
+      FIdSha1: IDerObjectIdentifier;
+
+    class function GetIdSha1: IDerObjectIdentifier; static; inline;
+
+    class constructor OiwObjectIdentifiers();
+
+  public
+
+    // id-SHA1 OBJECT IDENTIFIER ::=
+    // {iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 }    //
+    class property IdSha1: IDerObjectIdentifier read GetIdSha1;
+
+    class procedure Boot(); static;
+
+  end;
+
+implementation
+
+{ TOiwObjectIdentifiers }
+
+class procedure TOiwObjectIdentifiers.Boot;
+begin
+  FIdSha1 := TDerObjectIdentifier.Create('1.3.14.3.2.26');
+end;
+
+class function TOiwObjectIdentifiers.GetIdSha1: IDerObjectIdentifier;
+begin
+  Result := FIdSha1;
+end;
+
+class constructor TOiwObjectIdentifiers.OiwObjectIdentifiers;
+begin
+  TOiwObjectIdentifiers.Boot;
+end;
+
+end.

+ 102 - 0
CryptoLib/src/Asn1/Pkcs/ClpPkcsObjectIdentifiers.pas

@@ -0,0 +1,102 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpPkcsObjectIdentifiers;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpDerObjectIdentifier,
+  ClpIDerObjectIdentifier;
+
+type
+  TPkcsObjectIdentifiers = class abstract(TObject)
+
+  strict private
+
+    class var
+
+      FMD2, FMD4, FMD5: IDerObjectIdentifier;
+
+    class function GetMD2: IDerObjectIdentifier; static; inline;
+    class function GetMD4: IDerObjectIdentifier; static; inline;
+    class function GetMD5: IDerObjectIdentifier; static; inline;
+
+    class constructor PkcsObjectIdentifiers();
+
+  public
+
+    const
+    //
+    // object identifiers for digests
+    //
+    DigestAlgorithm = '1.2.840.113549.2';
+
+    //
+    // md2 OBJECT IDENTIFIER ::=
+    // {iso(1) member-body(2) US(840) rsadsi(113549) DigestAlgorithm(2) 2}
+    //
+    class property MD2: IDerObjectIdentifier read GetMD2;
+    //
+    // md4 OBJECT IDENTIFIER ::=
+    // {iso(1) member-body(2) US(840) rsadsi(113549) DigestAlgorithm(2) 4}
+    //
+    class property MD4: IDerObjectIdentifier read GetMD4;
+    //
+    // md5 OBJECT IDENTIFIER ::=
+    // {iso(1) member-body(2) US(840) rsadsi(113549) DigestAlgorithm(2) 5}
+    //
+    class property MD5: IDerObjectIdentifier read GetMD5;
+
+    class procedure Boot(); static;
+
+  end;
+
+implementation
+
+{ TPkcsObjectIdentifiers }
+
+class procedure TPkcsObjectIdentifiers.Boot;
+begin
+  FMD2 := TDerObjectIdentifier.Create(DigestAlgorithm + '.2');
+  FMD4 := TDerObjectIdentifier.Create(DigestAlgorithm + '.4');
+  FMD5 := TDerObjectIdentifier.Create(DigestAlgorithm + '.5');
+end;
+
+class function TPkcsObjectIdentifiers.GetMD2: IDerObjectIdentifier;
+begin
+  result := FMD2;
+end;
+
+class function TPkcsObjectIdentifiers.GetMD4: IDerObjectIdentifier;
+begin
+  result := FMD4;
+end;
+
+class function TPkcsObjectIdentifiers.GetMD5: IDerObjectIdentifier;
+begin
+  result := FMD5;
+end;
+
+class constructor TPkcsObjectIdentifiers.PkcsObjectIdentifiers;
+begin
+  TPkcsObjectIdentifiers.Boot;
+end;
+
+end.

+ 305 - 0
CryptoLib/src/Asn1/RossStandart/ClpRosstandartObjectIdentifiers.pas

@@ -0,0 +1,305 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpRosstandartObjectIdentifiers;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpDerObjectIdentifier,
+  ClpIDerObjectIdentifier;
+
+type
+  TRosstandartObjectIdentifiers = class abstract(TObject)
+  strict private
+
+    class var
+
+      Frosstandart, Fid_tc26_gost_3410_12_512_paramSetC,
+      Fid_tc26_gost_3410_12_512_paramSetA, Fid_tc26_gost_28147_param_Z,
+      Fid_tc26_gost_3410_12_256_paramSetA, Fid_tc26_hmac_gost_3411_12_512,
+      Fid_tc26_hmac_gost_3411_12_256, Fid_tc26_agreement_gost_3410_12_512,
+      Fid_tc26_agreement_gost_3410_12_256, Fid_tc26_agreement,
+      Fid_tc26_signwithdigest_gost_3410_12_512,
+      Fid_tc26_signwithdigest_gost_3410_12_256, Fid_tc26_gost_3410_12_512,
+      Fid_tc26_gost_3410_12_512_paramSet, Fid_tc26_gost_3410_12_256,
+      Fid_tc26_gost_3411_12_512, Fid_tc26_gost_3410_12_256_paramSet,
+      Fid_tc26_gost_3411_12_256, Fid_tc26, Fid_tc26_gost_3410_12_512_paramSetB
+      : IDerObjectIdentifier;
+
+    class function Getid_tc26: IDerObjectIdentifier; static; inline;
+    class function Getid_tc26_agreement: IDerObjectIdentifier; static; inline;
+    class function Getid_tc26_agreement_gost_3410_12_256: IDerObjectIdentifier;
+      static; inline;
+    class function Getid_tc26_agreement_gost_3410_12_512: IDerObjectIdentifier;
+      static; inline;
+    class function Getid_tc26_gost_28147_param_Z: IDerObjectIdentifier;
+      static; inline;
+    class function Getid_tc26_gost_3410_12_256: IDerObjectIdentifier;
+      static; inline;
+    class function Getid_tc26_gost_3410_12_256_paramSet: IDerObjectIdentifier;
+      static; inline;
+    class function Getid_tc26_gost_3410_12_256_paramSetA: IDerObjectIdentifier;
+      static; inline;
+    class function Getid_tc26_gost_3410_12_512: IDerObjectIdentifier;
+      static; inline;
+    class function Getid_tc26_gost_3410_12_512_paramSet: IDerObjectIdentifier;
+      static; inline;
+    class function Getid_tc26_gost_3410_12_512_paramSetA: IDerObjectIdentifier;
+      static; inline;
+    class function Getid_tc26_gost_3410_12_512_paramSetB: IDerObjectIdentifier;
+      static; inline;
+    class function Getid_tc26_gost_3410_12_512_paramSetC: IDerObjectIdentifier;
+      static; inline;
+    class function Getid_tc26_gost_3411_12_256: IDerObjectIdentifier;
+      static; inline;
+    class function Getid_tc26_gost_3411_12_512: IDerObjectIdentifier;
+      static; inline;
+    class function Getid_tc26_hmac_gost_3411_12_256: IDerObjectIdentifier;
+      static; inline;
+    class function Getid_tc26_hmac_gost_3411_12_512: IDerObjectIdentifier;
+      static; inline;
+    class function Getid_tc26_signwithdigest_gost_3410_12_256
+      : IDerObjectIdentifier; static; inline;
+    class function Getid_tc26_signwithdigest_gost_3410_12_512
+      : IDerObjectIdentifier; static; inline;
+    class function Getrosstandart: IDerObjectIdentifier; static; inline;
+
+    class constructor RosstandartObjectIdentifiers();
+
+  public
+    class property rosstandart: IDerObjectIdentifier read Getrosstandart;
+    class property id_tc26: IDerObjectIdentifier read Getid_tc26;
+    class property id_tc26_gost_3411_12_256: IDerObjectIdentifier
+      read Getid_tc26_gost_3411_12_256;
+    class property id_tc26_gost_3411_12_512: IDerObjectIdentifier
+      read Getid_tc26_gost_3411_12_512;
+    class property id_tc26_hmac_gost_3411_12_256: IDerObjectIdentifier
+      read Getid_tc26_hmac_gost_3411_12_256;
+    class property id_tc26_hmac_gost_3411_12_512: IDerObjectIdentifier
+      read Getid_tc26_hmac_gost_3411_12_512;
+    class property id_tc26_gost_3410_12_256: IDerObjectIdentifier
+      read Getid_tc26_gost_3410_12_256;
+    class property id_tc26_gost_3410_12_512: IDerObjectIdentifier
+      read Getid_tc26_gost_3410_12_512;
+    class property id_tc26_signwithdigest_gost_3410_12_256: IDerObjectIdentifier
+      read Getid_tc26_signwithdigest_gost_3410_12_256;
+    class property id_tc26_signwithdigest_gost_3410_12_512: IDerObjectIdentifier
+      read Getid_tc26_signwithdigest_gost_3410_12_512;
+    class property id_tc26_agreement: IDerObjectIdentifier
+      read Getid_tc26_agreement;
+    class property id_tc26_agreement_gost_3410_12_256: IDerObjectIdentifier
+      read Getid_tc26_agreement_gost_3410_12_256;
+    class property id_tc26_agreement_gost_3410_12_512: IDerObjectIdentifier
+      read Getid_tc26_agreement_gost_3410_12_512;
+    class property id_tc26_gost_3410_12_256_paramSet: IDerObjectIdentifier
+      read Getid_tc26_gost_3410_12_256_paramSet;
+    class property id_tc26_gost_3410_12_256_paramSetA: IDerObjectIdentifier
+      read Getid_tc26_gost_3410_12_256_paramSetA;
+    class property id_tc26_gost_3410_12_512_paramSet: IDerObjectIdentifier
+      read Getid_tc26_gost_3410_12_512_paramSet;
+    class property id_tc26_gost_3410_12_512_paramSetA: IDerObjectIdentifier
+      read Getid_tc26_gost_3410_12_512_paramSetA;
+    class property id_tc26_gost_3410_12_512_paramSetB: IDerObjectIdentifier
+      read Getid_tc26_gost_3410_12_512_paramSetB;
+    class property id_tc26_gost_3410_12_512_paramSetC: IDerObjectIdentifier
+      read Getid_tc26_gost_3410_12_512_paramSetC;
+    class property id_tc26_gost_28147_param_Z: IDerObjectIdentifier
+      read Getid_tc26_gost_28147_param_Z;
+
+    class procedure Boot(); static;
+
+  end;
+
+implementation
+
+{ TRosstandartObjectIdentifiers }
+
+class constructor TRosstandartObjectIdentifiers.RosstandartObjectIdentifiers;
+begin
+  TRosstandartObjectIdentifiers.Boot;
+end;
+
+class function TRosstandartObjectIdentifiers.Getrosstandart
+  : IDerObjectIdentifier;
+begin
+  result := Frosstandart;
+end;
+
+class procedure TRosstandartObjectIdentifiers.Boot;
+begin
+  Frosstandart := TDerObjectIdentifier.Create('1.2.643.7');
+
+  Fid_tc26 := rosstandart.Branch('1');
+
+  Fid_tc26_gost_3411_12_256 := id_tc26.Branch('1.2.2');
+
+  Fid_tc26_gost_3411_12_512 := id_tc26.Branch('1.2.3');
+
+  Fid_tc26_hmac_gost_3411_12_256 := id_tc26.Branch('1.4.1');
+
+  Fid_tc26_hmac_gost_3411_12_512 := id_tc26.Branch('1.4.2');
+
+  Fid_tc26_gost_3410_12_256 := id_tc26.Branch('1.1.1');
+
+  Fid_tc26_gost_3410_12_512 := id_tc26.Branch('1.1.2');
+
+  Fid_tc26_signwithdigest_gost_3410_12_256 := id_tc26.Branch('1.3.2');
+
+  Fid_tc26_signwithdigest_gost_3410_12_512 := id_tc26.Branch('1.3.3');
+
+  Fid_tc26_agreement := id_tc26.Branch('1.6');
+
+  Fid_tc26_agreement_gost_3410_12_256 := id_tc26_agreement.Branch('1');
+
+  Fid_tc26_agreement_gost_3410_12_512 := id_tc26_agreement.Branch('2');
+
+  Fid_tc26_gost_3410_12_256_paramSet := id_tc26.Branch('2.1.1');
+
+  Fid_tc26_gost_3410_12_256_paramSetA :=
+    id_tc26_gost_3410_12_256_paramSet.Branch('1');
+
+  Fid_tc26_gost_3410_12_512_paramSet := id_tc26.Branch('2.1.2');
+
+  Fid_tc26_gost_3410_12_512_paramSetA :=
+    id_tc26_gost_3410_12_512_paramSet.Branch('1');
+
+  Fid_tc26_gost_3410_12_512_paramSetB :=
+    id_tc26_gost_3410_12_512_paramSet.Branch('2');
+
+  Fid_tc26_gost_3410_12_512_paramSetC :=
+    id_tc26_gost_3410_12_512_paramSet.Branch('3');
+
+  Fid_tc26_gost_28147_param_Z := id_tc26.Branch('2.5.1.1');
+end;
+
+class function TRosstandartObjectIdentifiers.Getid_tc26: IDerObjectIdentifier;
+begin
+  result := Fid_tc26;
+end;
+
+class function TRosstandartObjectIdentifiers.Getid_tc26_agreement
+  : IDerObjectIdentifier;
+begin
+  result := Fid_tc26_agreement;
+end;
+
+class function TRosstandartObjectIdentifiers.
+  Getid_tc26_agreement_gost_3410_12_256: IDerObjectIdentifier;
+begin
+  result := Fid_tc26_agreement_gost_3410_12_256;
+end;
+
+class function TRosstandartObjectIdentifiers.
+  Getid_tc26_agreement_gost_3410_12_512: IDerObjectIdentifier;
+begin
+  result := Fid_tc26_agreement_gost_3410_12_512;
+end;
+
+class function TRosstandartObjectIdentifiers.Getid_tc26_gost_28147_param_Z
+  : IDerObjectIdentifier;
+begin
+  result := Fid_tc26_gost_28147_param_Z;
+end;
+
+class function TRosstandartObjectIdentifiers.Getid_tc26_gost_3410_12_256
+  : IDerObjectIdentifier;
+begin
+  result := Fid_tc26_gost_3410_12_256;
+end;
+
+class function TRosstandartObjectIdentifiers.
+  Getid_tc26_gost_3410_12_256_paramSet: IDerObjectIdentifier;
+begin
+  result := Fid_tc26_gost_3410_12_256_paramSet;
+end;
+
+class function TRosstandartObjectIdentifiers.
+  Getid_tc26_gost_3410_12_256_paramSetA: IDerObjectIdentifier;
+begin
+  result := Fid_tc26_gost_3410_12_256_paramSetA;
+end;
+
+class function TRosstandartObjectIdentifiers.Getid_tc26_gost_3410_12_512
+  : IDerObjectIdentifier;
+begin
+  result := Fid_tc26_gost_3410_12_512;
+end;
+
+class function TRosstandartObjectIdentifiers.
+  Getid_tc26_gost_3410_12_512_paramSet: IDerObjectIdentifier;
+begin
+  result := Fid_tc26_gost_3410_12_512_paramSet;
+end;
+
+class function TRosstandartObjectIdentifiers.
+  Getid_tc26_gost_3410_12_512_paramSetA: IDerObjectIdentifier;
+begin
+  result := Fid_tc26_gost_3410_12_512_paramSetA;
+end;
+
+class function TRosstandartObjectIdentifiers.
+  Getid_tc26_gost_3410_12_512_paramSetB: IDerObjectIdentifier;
+begin
+  result := Fid_tc26_gost_3410_12_512_paramSetB;
+end;
+
+class function TRosstandartObjectIdentifiers.
+  Getid_tc26_gost_3410_12_512_paramSetC: IDerObjectIdentifier;
+begin
+  result := Fid_tc26_gost_3410_12_512_paramSetC;
+end;
+
+class function TRosstandartObjectIdentifiers.Getid_tc26_gost_3411_12_256
+  : IDerObjectIdentifier;
+begin
+  result := Fid_tc26_gost_3411_12_256;
+end;
+
+class function TRosstandartObjectIdentifiers.Getid_tc26_gost_3411_12_512
+  : IDerObjectIdentifier;
+begin
+  result := Fid_tc26_gost_3411_12_512;
+end;
+
+class function TRosstandartObjectIdentifiers.Getid_tc26_hmac_gost_3411_12_256
+  : IDerObjectIdentifier;
+begin
+  result := Fid_tc26_hmac_gost_3411_12_256;
+end;
+
+class function TRosstandartObjectIdentifiers.Getid_tc26_hmac_gost_3411_12_512
+  : IDerObjectIdentifier;
+begin
+  result := Fid_tc26_hmac_gost_3411_12_512;
+end;
+
+class function TRosstandartObjectIdentifiers.
+  Getid_tc26_signwithdigest_gost_3410_12_256: IDerObjectIdentifier;
+begin
+  result := Fid_tc26_signwithdigest_gost_3410_12_256;
+end;
+
+class function TRosstandartObjectIdentifiers.
+  Getid_tc26_signwithdigest_gost_3410_12_512: IDerObjectIdentifier;
+begin
+  result := Fid_tc26_signwithdigest_gost_3410_12_512;
+end;
+
+end.

+ 420 - 0
CryptoLib/src/Asn1/Sec/ClpSecNamedCurves.pas

@@ -0,0 +1,420 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpSecNamedCurves;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  Generics.Collections,
+  ClpHex,
+  ClpGlvTypeBParameters,
+  ClpIGlvTypeBEndomorphism,
+  ClpSecObjectIdentifiers,
+  ClpCryptoLibTypes,
+  ClpBigInteger,
+  ClpECCurve,
+  ClpIECInterface,
+  ClpX9ECPoint,
+  ClpIX9ECPoint,
+  ClpIDerObjectIdentifier,
+  ClpGlvTypeBEndomorphism,
+  ClpX9ECParameters,
+  ClpIX9ECParameters,
+  ClpX9ECParametersHolder,
+  ClpIX9ECParametersHolder,
+  ClpIGlvTypeBParameters;
+
+type
+  TSecNamedCurves = class sealed(TObject)
+
+  strict private
+
+  class var
+    FobjIds: TDictionary<String, IDerObjectIdentifier>;
+    Fnames: TDictionary<IDerObjectIdentifier, String>;
+    Fcurves: TDictionary<IDerObjectIdentifier, IX9ECParametersHolder>;
+
+    class function GetNames: TCryptoLibStringArray; static; inline;
+    class procedure DefineCurve(const name: String; oid: IDerObjectIdentifier;
+      holder: IX9ECParametersHolder); static; inline;
+
+    class function ConfigureCurve(curve: IECCurve): IECCurve; static; inline;
+    class function ConfigureCurveGlv(c: IECCurve; p: IGlvTypeBParameters)
+      : IECCurve; static; inline;
+    class function FromHex(const Hex: String): TBigInteger; static; inline;
+
+  public
+    class function GetByName(const name: String): IX9ECParameters; static;
+    // /**
+    // * return the X9ECParameters object for the named curve represented by
+    // * the passed in object identifier. Null if the curve isn't present.
+    // *
+    // * @param oid an object identifier representing a named curve, if present.
+    // */
+    class function GetByOid(oid: IDerObjectIdentifier): IX9ECParameters; static;
+    // /**
+    // * return the object identifier signified by the passed in name. Null
+    // * if there is no object identifier associated with name.
+    // *
+    // * @return the object identifier associated with name, if present.
+    // */
+    class function GetOid(const name: String): IDerObjectIdentifier; static;
+    // /**
+    // * return the named curve name represented by the given object identifier.
+    // */
+    class function GetName(oid: IDerObjectIdentifier): String; static; inline;
+    // /**
+    // * returns an enumeration containing the name strings for curves
+    // * contained in this structure.
+    // */
+    class property Names: TCryptoLibStringArray read GetNames;
+
+  type
+
+    /// <summary>
+    /// secp256k1
+    /// </summary>
+    TSecp256k1Holder = class sealed(TX9ECParametersHolder,
+      IX9ECParametersHolder)
+
+    strict protected
+      function CreateParameters(): IX9ECParameters; override;
+
+    public
+      class function Instance(): IX9ECParametersHolder; static; inline;
+
+    end;
+
+  type
+
+    /// <summary>
+    /// secp384r1
+    /// </summary>
+    TSecp384r1Holder = class sealed(TX9ECParametersHolder,
+      IX9ECParametersHolder)
+
+    strict protected
+      function CreateParameters(): IX9ECParameters; override;
+
+    public
+      class function Instance(): IX9ECParametersHolder; static; inline;
+
+    end;
+
+  type
+
+    /// <summary>
+    /// sect283k1
+    /// </summary>
+    TSect283k1Holder = class sealed(TX9ECParametersHolder,
+      IX9ECParametersHolder)
+
+    strict private
+    const
+      Fm = Int32(283);
+      Fk1 = Int32(5);
+      Fk2 = Int32(7);
+      Fk3 = Int32(12);
+
+    strict protected
+      function CreateParameters(): IX9ECParameters; override;
+
+    public
+      class function Instance(): IX9ECParametersHolder; static; inline;
+
+    end;
+
+  type
+
+    /// <summary>
+    /// secp521r1
+    /// </summary>
+    TSecp521r1Holder = class sealed(TX9ECParametersHolder,
+      IX9ECParametersHolder)
+
+    strict protected
+      function CreateParameters(): IX9ECParameters; override;
+
+    public
+      class function Instance(): IX9ECParametersHolder; static; inline;
+
+    end;
+
+  class constructor CreateSecNamedCurves();
+  class destructor DestroySecNamedCurves();
+
+  end;
+
+implementation
+
+{ TSecNamedCurves }
+
+class procedure TSecNamedCurves.DefineCurve(const name: String;
+  oid: IDerObjectIdentifier; holder: IX9ECParametersHolder);
+begin
+  FobjIds.Add(UpperCase(name), oid);
+  Fnames.Add(oid, name);
+  Fcurves.Add(oid, holder);
+end;
+
+class function TSecNamedCurves.ConfigureCurve(curve: IECCurve): IECCurve;
+begin
+  result := curve;
+end;
+
+class function TSecNamedCurves.ConfigureCurveGlv(c: IECCurve;
+  p: IGlvTypeBParameters): IECCurve;
+var
+  glv: IGlvTypeBEndomorphism;
+begin
+  glv := TGlvTypeBEndomorphism.Create(c, p) as IGlvTypeBEndomorphism;
+  result := c.Configure().SetEndomorphism(glv).CreateCurve();
+end;
+
+class constructor TSecNamedCurves.CreateSecNamedCurves;
+begin
+  FobjIds := TDictionary<String, IDerObjectIdentifier>.Create();
+  Fnames := TDictionary<IDerObjectIdentifier, String>.Create();
+  Fcurves := TDictionary<IDerObjectIdentifier, IX9ECParametersHolder>.Create();
+
+  TSecObjectIdentifiers.Boot;
+  DefineCurve('secp256k1', TSecObjectIdentifiers.SecP256k1,
+    TSecp256k1Holder.Instance);
+  DefineCurve('secp384r1', TSecObjectIdentifiers.SecP384r1,
+    TSecp384r1Holder.Instance);
+  DefineCurve('sect283k1', TSecObjectIdentifiers.SecT283k1,
+    TSect283k1Holder.Instance);
+  DefineCurve('secp521r1', TSecObjectIdentifiers.SecP521r1,
+    TSecp521r1Holder.Instance);
+end;
+
+class destructor TSecNamedCurves.DestroySecNamedCurves;
+begin
+  FobjIds.Free;
+  Fnames.Free;
+  Fcurves.Free;
+end;
+
+class function TSecNamedCurves.FromHex(const Hex: String): TBigInteger;
+begin
+  result := TBigInteger.Create(1, THex.Decode(Hex));
+end;
+
+class function TSecNamedCurves.GetByOid(oid: IDerObjectIdentifier)
+  : IX9ECParameters;
+var
+  holder: IX9ECParametersHolder;
+begin
+  if Fcurves.TryGetValue(oid, holder) then
+  begin
+    result := holder.Parameters
+  end
+  else
+  begin
+    result := Nil;
+  end;
+end;
+
+class function TSecNamedCurves.GetOid(const name: String): IDerObjectIdentifier;
+begin
+  if not(FobjIds.TryGetValue(UpperCase(name), result)) then
+  begin
+    result := Nil;
+  end;
+end;
+
+class function TSecNamedCurves.GetByName(const name: String): IX9ECParameters;
+var
+  oid: IDerObjectIdentifier;
+begin
+  oid := GetOid(name);
+  if oid = Nil then
+  begin
+    result := Nil;
+  end
+  else
+  begin
+    result := GetByOid(oid);
+  end;
+
+end;
+
+class function TSecNamedCurves.GetName(oid: IDerObjectIdentifier): String;
+begin
+  if not(Fnames.TryGetValue(oid, result)) then
+  begin
+    result := '';
+  end;
+end;
+
+class function TSecNamedCurves.GetNames: TCryptoLibStringArray;
+begin
+  result := Fnames.Values.ToArray();
+end;
+
+{ TSecNamedCurves.TSecp256k1Holder }
+
+function TSecNamedCurves.TSecp256k1Holder.CreateParameters: IX9ECParameters;
+var
+  p, a, b, n, h: TBigInteger;
+  curve: IECCurve;
+  G: IX9ECPoint;
+  S: TCryptoLibByteArray;
+  glv: IGlvTypeBParameters;
+begin
+  // p := 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
+  p := FromHex
+    ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F');
+  a := TBigInteger.Zero;
+  b := TBigInteger.ValueOf(7);
+  n := FromHex
+    ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141');
+  h := TBigInteger.One;
+
+  glv := TGlvTypeBParameters.Create
+    (TBigInteger.Create
+    ('7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee', 16),
+    TBigInteger.Create
+    ('5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72', 16),
+    TCryptoLibGenericArray<TBigInteger>.Create
+    (TBigInteger.Create('3086d221a7d46bcde86c90e49284eb15', 16),
+    TBigInteger.Create('-e4437ed6010e88286f547fa90abfe4c3', 16)),
+    TCryptoLibGenericArray<TBigInteger>.Create
+    (TBigInteger.Create('114ca50f7a8e2f3f657c1108d9d44cfd8', 16),
+    TBigInteger.Create('3086d221a7d46bcde86c90e49284eb15', 16)),
+    TBigInteger.Create('3086d221a7d46bcde86c90e49284eb153dab', 16),
+    TBigInteger.Create('e4437ed6010e88286f547fa90abfe4c42212', 16), 272);
+
+  curve := ConfigureCurveGlv(TFpCurve.Create(p, a, b, n, h), glv);
+  G := TX9ECPoint.Create(curve,
+    THex.Decode('04' +
+    '79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798' +
+    '483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8'));
+
+  result := TX9ECParameters.Create(curve, G, n, h, S);
+end;
+
+class function TSecNamedCurves.TSecp256k1Holder.Instance: IX9ECParametersHolder;
+begin
+  result := TSecp256k1Holder.Create();
+end;
+
+{ TSecNamedCurves.TSecp384r1Holder }
+
+function TSecNamedCurves.TSecp384r1Holder.CreateParameters: IX9ECParameters;
+var
+  p, a, b, n, h: TBigInteger;
+  curve: IECCurve;
+  G: IX9ECPoint;
+  S: TCryptoLibByteArray;
+begin
+  // p := 2^384 - 2^128 - 2^96 + 2^32 - 1
+  p := FromHex
+    ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF');
+  a := FromHex
+    ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC');
+  b := FromHex
+    ('B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF');
+  S := THex.Decode('A335926AA319A27A1D00896A6773A4827ACDAC73');
+  n := FromHex
+    ('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973');
+  h := TBigInteger.One;
+
+  curve := ConfigureCurve(TFpCurve.Create(p, a, b, n, h));
+  G := TX9ECPoint.Create(curve,
+    THex.Decode('04' +
+    'AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7'
+    + '3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F')
+    );
+
+  result := TX9ECParameters.Create(curve, G, n, h, S);
+end;
+
+class function TSecNamedCurves.TSecp384r1Holder.Instance: IX9ECParametersHolder;
+begin
+  result := TSecp384r1Holder.Create();
+end;
+
+{ TSecNamedCurves.TSect283k1Holder }
+
+function TSecNamedCurves.TSect283k1Holder.CreateParameters: IX9ECParameters;
+var
+  a, b, n, h: TBigInteger;
+  S: TCryptoLibByteArray;
+  curve: IECCurve;
+  G: IX9ECPoint;
+begin
+  a := TBigInteger.Zero;
+  b := TBigInteger.One;
+  n := FromHex
+    ('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61');
+  h := TBigInteger.ValueOf(4);
+
+  curve := TF2mCurve.Create(Fm, Fk1, Fk2, Fk3, a, b, n, h);
+  G := TX9ECPoint.Create(curve,
+    THex.Decode('04' +
+    '0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836' +
+    '01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259')
+    );
+
+  result := TX9ECParameters.Create(curve, G, n, h, S);
+end;
+
+class function TSecNamedCurves.TSect283k1Holder.Instance: IX9ECParametersHolder;
+begin
+  result := TSect283k1Holder.Create();
+end;
+
+function TSecNamedCurves.TSecp521r1Holder.CreateParameters: IX9ECParameters;
+var
+  p, a, b, n, h: TBigInteger;
+  curve: IECCurve;
+  G: IX9ECPoint;
+  S: TCryptoLibByteArray;
+begin
+  // p := 2^521 - 1
+  p := FromHex
+    ('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF');
+  a := FromHex
+    ('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC');
+  b := FromHex
+    ('0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00');
+  S := THex.Decode('D09E8800291CB85396CC6717393284AAA0DA64BA');
+  n := FromHex
+    ('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409');
+  h := TBigInteger.One;
+
+  curve := ConfigureCurve(TFpCurve.Create(p, a, b, n, h));
+  G := TX9ECPoint.Create(curve,
+    THex.Decode('04' +
+    '00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66'
+    + '011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650')
+    );
+
+  result := TX9ECParameters.Create(curve, G, n, h, S);
+end;
+
+class function TSecNamedCurves.TSecp521r1Holder.Instance: IX9ECParametersHolder;
+begin
+  result := TSecp521r1Holder.Create();
+end;
+
+end.

+ 352 - 0
CryptoLib/src/Asn1/Sec/ClpSecObjectIdentifiers.pas

@@ -0,0 +1,352 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpSecObjectIdentifiers;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpDerObjectIdentifier,
+  ClpIDerObjectIdentifier,
+  ClpX9ObjectIdentifiers;
+
+type
+  // /**
+  // *  EllipticCurve OBJECT IDENTIFIER ::= {
+  // *        iso(1) identified-organization(3) certicom(132) curve(0)
+  // *  }
+  // */
+  TSecObjectIdentifiers = class abstract(TObject)
+
+  strict private
+
+    class var
+
+      FSecT193r1, FSecP112r2, FEllipticCurve, FSecP224r1, FSecP160r2,
+      FSecT233r1, FSecP112r1, FSecT409r1, FSecP192k1, FSecT131r2, FSecT283k1,
+      FSecT113r2, FSecT163r2, FSecP160r1, FSecT239k1, FSecP521r1, FSecP256r1,
+      FSecT131r1, FSecT113r1, FSecT163r1, FSecP224k1, FSecT233k1, FSecT409k1,
+      FSecP160k1, FSecT571r1, FSecP256k1, FSecT163k1, FSecP128r2, FSecT571k1,
+      FSecP128r1, FSecP192r1, FSecT283r1, FSecT193r2,
+      FSecP384r1: IDerObjectIdentifier;
+
+    class constructor SecObjectIdentifiers();
+
+    class function GetEllipticCurve: IDerObjectIdentifier; static; inline;
+    class function GetSecP112r1: IDerObjectIdentifier; static; inline;
+    class function GetSecP112r2: IDerObjectIdentifier; static; inline;
+    class function GetSecP128r1: IDerObjectIdentifier; static; inline;
+    class function GetSecP128r2: IDerObjectIdentifier; static; inline;
+    class function GetSecP160k1: IDerObjectIdentifier; static; inline;
+    class function GetSecP160r1: IDerObjectIdentifier; static; inline;
+    class function GetSecP160r2: IDerObjectIdentifier; static; inline;
+    class function GetSecP192k1: IDerObjectIdentifier; static; inline;
+    class function GetSecP192r1: IDerObjectIdentifier; static; inline;
+    class function GetSecP224k1: IDerObjectIdentifier; static; inline;
+    class function GetSecP224r1: IDerObjectIdentifier; static; inline;
+    class function GetSecP256k1: IDerObjectIdentifier; static; inline;
+    class function GetSecP256r1: IDerObjectIdentifier; static; inline;
+    class function GetSecP384r1: IDerObjectIdentifier; static; inline;
+    class function GetSecP521r1: IDerObjectIdentifier; static; inline;
+    class function GetSecT113r1: IDerObjectIdentifier; static; inline;
+    class function GetSecT113r2: IDerObjectIdentifier; static; inline;
+    class function GetSecT131r1: IDerObjectIdentifier; static; inline;
+    class function GetSecT131r2: IDerObjectIdentifier; static; inline;
+    class function GetSecT163k1: IDerObjectIdentifier; static; inline;
+    class function GetSecT163r1: IDerObjectIdentifier; static; inline;
+    class function GetSecT163r2: IDerObjectIdentifier; static; inline;
+    class function GetSecT193r1: IDerObjectIdentifier; static; inline;
+    class function GetSecT193r2: IDerObjectIdentifier; static; inline;
+    class function GetSecT233k1: IDerObjectIdentifier; static; inline;
+    class function GetSecT233r1: IDerObjectIdentifier; static; inline;
+    class function GetSecT239k1: IDerObjectIdentifier; static; inline;
+    class function GetSecT283k1: IDerObjectIdentifier; static; inline;
+    class function GetSecT283r1: IDerObjectIdentifier; static; inline;
+    class function GetSecT409k1: IDerObjectIdentifier; static; inline;
+    class function GetSecT409r1: IDerObjectIdentifier; static; inline;
+    class function GetSecT571k1: IDerObjectIdentifier; static; inline;
+    class function GetSecT571r1: IDerObjectIdentifier; static; inline;
+
+  public
+
+    class property EllipticCurve: IDerObjectIdentifier read GetEllipticCurve;
+
+    class property SecT163k1: IDerObjectIdentifier read GetSecT163k1;
+    class property SecT163r1: IDerObjectIdentifier read GetSecT163r1;
+    class property SecT239k1: IDerObjectIdentifier read GetSecT239k1;
+    class property SecT113r1: IDerObjectIdentifier read GetSecT113r1;
+    class property SecT113r2: IDerObjectIdentifier read GetSecT113r2;
+    class property SecP112r1: IDerObjectIdentifier read GetSecP112r1;
+    class property SecP112r2: IDerObjectIdentifier read GetSecP112r2;
+    class property SecP160r1: IDerObjectIdentifier read GetSecP160r1;
+    class property SecP160k1: IDerObjectIdentifier read GetSecP160k1;
+    class property SecP256k1: IDerObjectIdentifier read GetSecP256k1;
+    class property SecT163r2: IDerObjectIdentifier read GetSecT163r2;
+    class property SecT283k1: IDerObjectIdentifier read GetSecT283k1;
+    class property SecT283r1: IDerObjectIdentifier read GetSecT283r1;
+    class property SecT131r1: IDerObjectIdentifier read GetSecT131r1;
+    class property SecT131r2: IDerObjectIdentifier read GetSecT131r2;
+    class property SecT193r1: IDerObjectIdentifier read GetSecT193r1;
+    class property SecT193r2: IDerObjectIdentifier read GetSecT193r2;
+    class property SecT233k1: IDerObjectIdentifier read GetSecT233k1;
+    class property SecT233r1: IDerObjectIdentifier read GetSecT233r1;
+    class property SecP128r1: IDerObjectIdentifier read GetSecP128r1;
+    class property SecP128r2: IDerObjectIdentifier read GetSecP128r2;
+    class property SecP160r2: IDerObjectIdentifier read GetSecP160r2;
+    class property SecP192k1: IDerObjectIdentifier read GetSecP192k1;
+    class property SecP224k1: IDerObjectIdentifier read GetSecP224k1;
+    class property SecP224r1: IDerObjectIdentifier read GetSecP224r1;
+    class property SecP384r1: IDerObjectIdentifier read GetSecP384r1;
+    class property SecP521r1: IDerObjectIdentifier read GetSecP521r1;
+    class property SecT409k1: IDerObjectIdentifier read GetSecT409k1;
+    class property SecT409r1: IDerObjectIdentifier read GetSecT409r1;
+    class property SecT571k1: IDerObjectIdentifier read GetSecT571k1;
+    class property SecT571r1: IDerObjectIdentifier read GetSecT571r1;
+
+    class property SecP192r1: IDerObjectIdentifier read GetSecP192r1;
+    class property SecP256r1: IDerObjectIdentifier read GetSecP256r1;
+
+    class procedure Boot(); static;
+
+  end;
+
+implementation
+
+{ TClpSecObjectIdentifiers }
+
+class procedure TSecObjectIdentifiers.Boot;
+begin
+  FEllipticCurve := TDerObjectIdentifier.Create('1.3.132.0');
+
+  FSecT163k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.1');
+  FSecT163r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.2');
+  FSecT239k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.3');
+  FSecT113r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.4');
+  FSecT113r2 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.5');
+  FSecP112r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.6');
+  FSecP112r2 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.7');
+  FSecP160r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.8');
+  FSecP160k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.9');
+  FSecP256k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.10');
+  FSecT163r2 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.15');
+  FSecT283k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.16');
+  FSecT283r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.17');
+  FSecT131r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.22');
+  FSecT131r2 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.23');
+  FSecT193r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.24');
+  FSecT193r2 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.25');
+  FSecT233k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.26');
+  FSecT233r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.27');
+  FSecP128r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.28');
+  FSecP128r2 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.29');
+  FSecP160r2 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.30');
+  FSecP192k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.31');
+  FSecP224k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.32');
+  FSecP224r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.33');
+  FSecP384r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.34');
+  FSecP521r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.35');
+  FSecT409k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.36');
+  FSecT409r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.37');
+  FSecT571k1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.38');
+  FSecT571r1 := TDerObjectIdentifier.Create(EllipticCurve.Id + '.39');
+
+  TX9ObjectIdentifiers.Boot;
+
+  FSecP192r1 := TX9ObjectIdentifiers.Prime192v1;
+
+  FSecP256r1 := TX9ObjectIdentifiers.Prime256v1;
+
+end;
+
+class function TSecObjectIdentifiers.GetEllipticCurve: IDerObjectIdentifier;
+begin
+  result := FEllipticCurve;
+end;
+
+class function TSecObjectIdentifiers.GetSecP112r1: IDerObjectIdentifier;
+begin
+  result := FSecP112r1;
+end;
+
+class function TSecObjectIdentifiers.GetSecP112r2: IDerObjectIdentifier;
+begin
+  result := FSecP112r2;
+end;
+
+class function TSecObjectIdentifiers.GetSecP128r1: IDerObjectIdentifier;
+begin
+  result := FSecP128r1;
+end;
+
+class function TSecObjectIdentifiers.GetSecP128r2: IDerObjectIdentifier;
+begin
+  result := FSecP128r2;
+end;
+
+class function TSecObjectIdentifiers.GetSecP160k1: IDerObjectIdentifier;
+begin
+  result := FSecP160k1;
+end;
+
+class function TSecObjectIdentifiers.GetSecP160r1: IDerObjectIdentifier;
+begin
+  result := FSecP160r1;
+end;
+
+class function TSecObjectIdentifiers.GetSecP160r2: IDerObjectIdentifier;
+begin
+  result := FSecP160r2;
+end;
+
+class function TSecObjectIdentifiers.GetSecP192k1: IDerObjectIdentifier;
+begin
+  result := FSecP192k1;
+end;
+
+class function TSecObjectIdentifiers.GetSecP192r1: IDerObjectIdentifier;
+begin
+  result := FSecP192r1;
+end;
+
+class function TSecObjectIdentifiers.GetSecP224k1: IDerObjectIdentifier;
+begin
+  result := FSecP224k1;
+end;
+
+class function TSecObjectIdentifiers.GetSecP224r1: IDerObjectIdentifier;
+begin
+  result := FSecP224r1;
+end;
+
+class function TSecObjectIdentifiers.GetSecP256k1: IDerObjectIdentifier;
+begin
+  result := FSecP256k1;
+end;
+
+class function TSecObjectIdentifiers.GetSecP256r1: IDerObjectIdentifier;
+begin
+  result := FSecP256r1;
+end;
+
+class function TSecObjectIdentifiers.GetSecP384r1: IDerObjectIdentifier;
+begin
+  result := FSecP384r1;
+end;
+
+class function TSecObjectIdentifiers.GetSecP521r1: IDerObjectIdentifier;
+begin
+  result := FSecP521r1;
+end;
+
+class function TSecObjectIdentifiers.GetSecT113r1: IDerObjectIdentifier;
+begin
+  result := FSecT113r1;
+end;
+
+class function TSecObjectIdentifiers.GetSecT113r2: IDerObjectIdentifier;
+begin
+  result := FSecT113r2;
+end;
+
+class function TSecObjectIdentifiers.GetSecT131r1: IDerObjectIdentifier;
+begin
+  result := FSecT131r1;
+end;
+
+class function TSecObjectIdentifiers.GetSecT131r2: IDerObjectIdentifier;
+begin
+  result := FSecT131r2;
+end;
+
+class function TSecObjectIdentifiers.GetSecT163k1: IDerObjectIdentifier;
+begin
+  result := FSecT163k1;
+end;
+
+class function TSecObjectIdentifiers.GetSecT163r1: IDerObjectIdentifier;
+begin
+  result := FSecT163r1;
+end;
+
+class function TSecObjectIdentifiers.GetSecT163r2: IDerObjectIdentifier;
+begin
+  result := FSecT163r2;
+end;
+
+class function TSecObjectIdentifiers.GetSecT193r1: IDerObjectIdentifier;
+begin
+  result := FSecT193r1;
+end;
+
+class function TSecObjectIdentifiers.GetSecT193r2: IDerObjectIdentifier;
+begin
+  result := FSecT193r2;
+end;
+
+class function TSecObjectIdentifiers.GetSecT233k1: IDerObjectIdentifier;
+begin
+  result := FSecT233k1;
+end;
+
+class function TSecObjectIdentifiers.GetSecT233r1: IDerObjectIdentifier;
+begin
+  result := FSecT233r1;
+end;
+
+class function TSecObjectIdentifiers.GetSecT239k1: IDerObjectIdentifier;
+begin
+  result := FSecT239k1;
+end;
+
+class function TSecObjectIdentifiers.GetSecT283k1: IDerObjectIdentifier;
+begin
+  result := FSecT283k1;
+end;
+
+class function TSecObjectIdentifiers.GetSecT283r1: IDerObjectIdentifier;
+begin
+  result := FSecT283r1;
+end;
+
+class function TSecObjectIdentifiers.GetSecT409k1: IDerObjectIdentifier;
+begin
+  result := FSecT409k1;
+end;
+
+class function TSecObjectIdentifiers.GetSecT409r1: IDerObjectIdentifier;
+begin
+  result := FSecT409r1;
+end;
+
+class function TSecObjectIdentifiers.GetSecT571k1: IDerObjectIdentifier;
+begin
+  result := FSecT571k1;
+end;
+
+class function TSecObjectIdentifiers.GetSecT571r1: IDerObjectIdentifier;
+begin
+  result := FSecT571r1;
+end;
+
+class constructor TSecObjectIdentifiers.SecObjectIdentifiers;
+begin
+  TSecObjectIdentifiers.Boot;
+end;
+
+end.

+ 125 - 0
CryptoLib/src/Asn1/TeleTrust/ClpTeleTrusTObjectIdentifiers.pas

@@ -0,0 +1,125 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpTeleTrusTObjectIdentifiers;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpDerObjectIdentifier,
+  ClpIDerObjectIdentifier;
+
+type
+  TTeleTrusTObjectIdentifiers = class sealed(TObject)
+
+  strict private
+
+    class var
+
+      FTeleTrusTAlgorithm, FRipeMD160, FRipeMD128, FRipeMD256, FECSign,
+      FECSignWithSha1, FECSignWithRipeMD160: IDerObjectIdentifier;
+
+    class function GetRipeMD128: IDerObjectIdentifier; static; inline;
+    class function GetRipeMD160: IDerObjectIdentifier; static; inline;
+    class function GetRipeMD256: IDerObjectIdentifier; static; inline;
+    class function GetTeleTrusTAlgorithm: IDerObjectIdentifier; static; inline;
+    class function GetECSign: IDerObjectIdentifier; static; inline;
+    class function GetECSignWithRipeMD160: IDerObjectIdentifier; static; inline;
+    class function GetECSignWithSha1: IDerObjectIdentifier; static; inline;
+
+    class constructor TeleTrusTObjectIdentifiers();
+
+  public
+
+    class property RipeMD160: IDerObjectIdentifier read GetRipeMD160;
+    class property RipeMD128: IDerObjectIdentifier read GetRipeMD128;
+    class property RipeMD256: IDerObjectIdentifier read GetRipeMD256;
+    class property TeleTrusTAlgorithm: IDerObjectIdentifier
+      read GetTeleTrusTAlgorithm;
+    class property ECSign: IDerObjectIdentifier read GetECSign;
+    class property ECSignWithSha1: IDerObjectIdentifier read GetECSignWithSha1;
+    class property ECSignWithRipeMD160: IDerObjectIdentifier
+      read GetECSignWithRipeMD160;
+
+    class procedure Boot(); static;
+
+  end;
+
+implementation
+
+{ TTeleTrusTObjectIdentifiers }
+
+class function TTeleTrusTObjectIdentifiers.GetTeleTrusTAlgorithm
+  : IDerObjectIdentifier;
+begin
+  result := FTeleTrusTAlgorithm;
+end;
+
+class procedure TTeleTrusTObjectIdentifiers.Boot;
+begin
+  FTeleTrusTAlgorithm := TDerObjectIdentifier.Create('1.3.36.3');
+  FRipeMD160 := TDerObjectIdentifier.Create(TeleTrusTAlgorithm.ID + '.2.1');
+  FRipeMD128 := TDerObjectIdentifier.Create(TeleTrusTAlgorithm.ID + '.2.2');
+  FRipeMD256 := TDerObjectIdentifier.Create(TeleTrusTAlgorithm.ID + '.2.3');
+
+  FECSign := TDerObjectIdentifier.Create(TeleTrusTAlgorithm.ID + '.3.2');
+
+  FECSignWithSha1 := TDerObjectIdentifier.Create(ECSign.ID + '.1');
+  FECSignWithRipeMD160 := TDerObjectIdentifier.Create(ECSign.ID + '.2');
+
+end;
+
+class function TTeleTrusTObjectIdentifiers.GetECSign: IDerObjectIdentifier;
+begin
+  result := FECSign;
+end;
+
+class function TTeleTrusTObjectIdentifiers.GetECSignWithRipeMD160
+  : IDerObjectIdentifier;
+begin
+  result := FECSignWithRipeMD160;
+end;
+
+class function TTeleTrusTObjectIdentifiers.GetECSignWithSha1
+  : IDerObjectIdentifier;
+begin
+  result := FECSignWithSha1;
+end;
+
+class function TTeleTrusTObjectIdentifiers.GetRipeMD128: IDerObjectIdentifier;
+begin
+  result := FRipeMD128;
+end;
+
+class function TTeleTrusTObjectIdentifiers.GetRipeMD160: IDerObjectIdentifier;
+begin
+  result := FRipeMD160;
+end;
+
+class function TTeleTrusTObjectIdentifiers.GetRipeMD256: IDerObjectIdentifier;
+begin
+  result := FRipeMD256;
+end;
+
+class constructor TTeleTrusTObjectIdentifiers.TeleTrusTObjectIdentifiers;
+begin
+  TTeleTrusTObjectIdentifiers.Boot;
+end;
+
+end.

+ 171 - 0
CryptoLib/src/Asn1/X9/ClpECNamedCurveTable.pas

@@ -0,0 +1,171 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpECNamedCurveTable;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  Generics.Collections,
+  ClpCryptoLibTypes,
+  // ClpX962NamedCurves,
+  ClpECGost3410NamedCurves,
+  ClpX9ECParameters,
+  ClpSecNamedCurves,
+  ClpIECDomainParameters,
+  ClpIDerObjectIdentifier,
+  ClpIX9ECParameters;
+
+type
+  /// <summary>
+  /// A general class that reads all X9.62 style EC curve tables.
+  /// </summary>
+  TECNamedCurveTable = class sealed(TObject)
+
+  strict private
+
+    class function GetNames: TCryptoLibStringArray; static;
+    class function FromDomainParameters(dp: IECDomainParameters)
+      : IX9ECParameters; static; inline;
+
+  public
+    // /**
+    // * return a X9ECParameters object representing the passed in named
+    // * curve. The routine returns null if the curve is not present.
+    // *
+    // * @param name the name of the curve requested
+    // * @return an X9ECParameters object or null if the curve is not available.
+    // */
+    class function GetByName(const name: String): IX9ECParameters; static;
+
+    class function GetName(oid: IDerObjectIdentifier): String; static;
+    // /**
+    // * return the object identifier signified by the passed in name. Null
+    // * if there is no object identifier associated with name.
+    // *
+    // * @return the object identifier associated with name, if present.
+    // */
+    class function GetOid(const name: String): IDerObjectIdentifier; static;
+
+    // /**
+    // * return a X9ECParameters object representing the passed in named
+    // * curve.
+    // *
+    // * @param oid the object id of the curve requested
+    // * @return an X9ECParameters object or null if the curve is not available.
+    // */
+
+    class function GetByOid(oid: IDerObjectIdentifier): IX9ECParameters; static;
+
+    // /**
+    // * return an enumeration of the names of the available curves.
+    // *
+    // * @return an enumeration of the names of the available curves.
+    // */
+    class property Names: TCryptoLibStringArray read GetNames;
+
+  end;
+
+implementation
+
+{ TECNamedCurveTable }
+
+class function TECNamedCurveTable.FromDomainParameters(dp: IECDomainParameters)
+  : IX9ECParameters;
+begin
+  if dp = Nil then
+  begin
+    result := Nil;
+  end
+  else
+  begin
+    result := TX9ECParameters.Create(dp.Curve, dp.G, dp.N, dp.H, dp.GetSeed())
+  end;
+
+end;
+
+class function TECNamedCurveTable.GetByName(const name: String)
+  : IX9ECParameters;
+var
+  ecP: IX9ECParameters;
+begin
+  // ecP := TX962NamedCurves.GetByName(name);
+  // if (ecP = Nil) then
+  // begin
+  ecP := TSecNamedCurves.GetByName(name);
+  // end;
+
+  result := ecP;
+end;
+
+class function TECNamedCurveTable.GetByOid(oid: IDerObjectIdentifier)
+  : IX9ECParameters;
+var
+  ecP: IX9ECParameters;
+begin
+  // ecP := TX962NamedCurves.GetByOid(oid);
+  // if (ecP = Nil) then
+  // begin
+  ecP := TSecNamedCurves.GetByOid(oid);
+  // end;
+  result := ecP;
+end;
+
+class function TECNamedCurveTable.GetName(oid: IDerObjectIdentifier): String;
+var
+  name: String;
+begin
+  // name := TX962NamedCurves.GetName(oid);
+  // if (name = Nil) then
+  // begin
+  name := TSecNamedCurves.GetName(oid);
+  // end;
+  result := name;
+end;
+
+class function TECNamedCurveTable.GetNames: TCryptoLibStringArray;
+var
+  temp: TList<String>;
+begin
+  temp := TList<String>.Create();
+  try
+    temp.AddRange(TSecNamedCurves.Names);
+    // temp.AddRange(TECGost3410NamedCurves.Names);
+    result := temp.ToArray;
+  finally
+    temp.Free;
+  end;
+
+end;
+
+class function TECNamedCurveTable.GetOid(const name: String)
+  : IDerObjectIdentifier;
+var
+  oid: IDerObjectIdentifier;
+begin
+  // oid := TX962NamedCurves.GetOid(name);
+  // if (oid = Nil) then
+  // begin
+  oid := TSecNamedCurves.GetOid(name);
+  // end;
+
+  result := oid;
+end;
+
+end.

+ 230 - 0
CryptoLib/src/Asn1/X9/ClpX9Curve.pas

@@ -0,0 +1,230 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpX9Curve;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpCryptoLibTypes,
+  ClpBigInteger,
+  ClpIDerSequence,
+  ClpIDerInteger,
+  ClpIDerObjectIdentifier,
+  ClpDerBitString,
+  ClpIDerBitString,
+  ClpDerSequence,
+  ClpX9FieldElement,
+  ClpIX9FieldID,
+  ClpIX9FieldElement,
+  ClpIAsn1OctetString,
+  ClpECAlgorithms,
+  ClpAsn1EncodableVector,
+  ClpIAsn1EncodableVector,
+  ClpX9ObjectIdentifiers,
+  ClpIProxiedInterface,
+  ClpIAsn1Sequence,
+  ClpIX9Curve,
+  ClpECCurve,
+  ClpIECInterface,
+  ClpAsn1Encodable;
+
+resourcestring
+  SCurveNil = 'Curve';
+  SNotImplementedECCurve = 'This Type of ECCurve is not Implemented';
+  SFieldIDNil = 'FieldID';
+  SSeqNil = 'Seq';
+
+type
+
+  /// <summary>
+  /// ASN.1 def for Elliptic-Curve Curve structure. See X9.62, for further
+  /// details.
+  /// </summary>
+  TX9Curve = class(TAsn1Encodable, IX9Curve)
+
+  strict private
+  var
+    FSeed: TCryptoLibByteArray;
+    FfieldIdentifier: IDerObjectIdentifier;
+    Fcurve: IECCurve;
+
+    function GetCurve: IECCurve; inline;
+
+  public
+    constructor Create(curve: IECCurve); overload;
+    constructor Create(curve: IECCurve; seed: TCryptoLibByteArray); overload;
+    constructor Create(fieldID: IX9FieldID; seq: IAsn1Sequence); overload;
+
+    function GetSeed(): TCryptoLibByteArray; inline;
+
+    property curve: IECCurve read GetCurve;
+
+    /// <summary>
+    /// <para>
+    /// Produce an object suitable for an Asn1OutputStream. <br />
+    /// &lt;pre&gt;
+    /// </para>
+    /// <para>
+    /// Curve ::= Sequence { a FieldElement, b FieldElement, seed BIT
+    /// STRING OPTIONAL }
+    /// </para>
+    /// <para>
+    /// <br />&lt;/pre&gt;
+    /// </para>
+    /// </summary>
+    function ToAsn1Object(): IAsn1Object; override;
+
+  end;
+
+implementation
+
+{ TX9Curve }
+
+constructor TX9Curve.Create(curve: IECCurve; seed: TCryptoLibByteArray);
+begin
+  Inherited Create();
+  if (curve = Nil) then
+  begin
+    raise EArgumentNilCryptoLibException.CreateRes(@SCurveNil);
+  end;
+
+  Fcurve := curve;
+  FSeed := System.Copy(seed);
+
+  if (TECAlgorithms.IsFpCurve(curve)) then
+  begin
+    FfieldIdentifier := TX9ObjectIdentifiers.PrimeField;
+  end
+  else if (TECAlgorithms.IsF2mCurve(curve)) then
+  begin
+    FfieldIdentifier := TX9ObjectIdentifiers.CharacteristicTwoField;
+  end
+  else
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SNotImplementedECCurve);
+  end;
+end;
+
+constructor TX9Curve.Create(curve: IECCurve);
+begin
+  Create(curve, Nil);
+end;
+
+constructor TX9Curve.Create(fieldID: IX9FieldID; seq: IAsn1Sequence);
+var
+  q: TBigInteger;
+  x9A, x9B: IX9FieldElement;
+  parameters: IDerSequence;
+  representation: IDerObjectIdentifier;
+  pentanomial: IDerSequence;
+  m, k1, k2, k3: Int32;
+begin
+  Inherited Create();
+  if (fieldID = Nil) then
+  begin
+    raise EArgumentNilCryptoLibException.CreateRes(@SFieldIDNil);
+  end;
+  if (seq = Nil) then
+  begin
+    raise EArgumentNilCryptoLibException.CreateRes(@SSeqNil);
+  end;
+
+  FfieldIdentifier := fieldID.Identifier;
+
+  if (FfieldIdentifier.Equals(TX9ObjectIdentifiers.PrimeField)) then
+  begin
+    q := (fieldID.parameters as IDerInteger).Value;
+    x9A := TX9FieldElement.Create(q, seq[0] as IAsn1OctetString);
+    x9B := TX9FieldElement.Create(q, seq[1] as IAsn1OctetString);
+    Fcurve := TFpCurve.Create(q, x9A.Value.ToBigInteger(),
+      x9B.Value.ToBigInteger());
+  end
+  else
+  begin
+    if (FfieldIdentifier.Equals(TX9ObjectIdentifiers.CharacteristicTwoField))
+    then
+    begin
+      // Characteristic two field
+      parameters := fieldID.parameters as IDerSequence;
+      m := (parameters[0] as IDerInteger).Value.Int32Value;
+      representation := parameters[1] as IDerObjectIdentifier;
+
+      k2 := 0;
+      k3 := 0;
+      if (representation.Equals(TX9ObjectIdentifiers.TPBasis)) then
+      begin
+        // Trinomial basis representation
+        k1 := (parameters[2] as IDerInteger).Value.Int32Value;
+      end
+      else
+      begin
+        // Pentanomial basis representation
+        pentanomial := parameters[2] as IDerSequence;
+        k1 := (pentanomial[0] as IDerInteger).Value.Int32Value;
+        k2 := (pentanomial[1] as IDerInteger).Value.Int32Value;
+        k3 := (pentanomial[2] as IDerInteger).Value.Int32Value;
+      end;
+      x9A := TX9FieldElement.Create(m, k1, k2, k3, seq[0] as IAsn1OctetString);
+      x9B := TX9FieldElement.Create(m, k1, k2, k3, seq[1] as IAsn1OctetString);
+      // TODO Is it possible to get the order (n) and cofactor(h) too?
+      Fcurve := TF2mCurve.Create(m, k1, k2, k3, x9A.Value.ToBigInteger(),
+        x9B.Value.ToBigInteger());
+    end;
+  end;
+
+  if (seq.Count = 3) then
+  begin
+    FSeed := (seq[2] as IDerBitString).GetBytes();
+  end;
+
+end;
+
+function TX9Curve.GetCurve: IECCurve;
+begin
+  result := Fcurve;
+end;
+
+function TX9Curve.GetSeed: TCryptoLibByteArray;
+begin
+  result := System.Copy(FSeed);
+end;
+
+function TX9Curve.ToAsn1Object: IAsn1Object;
+var
+  v: IAsn1EncodableVector;
+begin
+  v := TAsn1EncodableVector.Create();
+
+  if (FfieldIdentifier.Equals(TX9ObjectIdentifiers.PrimeField) or
+    FfieldIdentifier.Equals(TX9ObjectIdentifiers.CharacteristicTwoField)) then
+  begin
+    v.Add([TX9FieldElement.Create(Fcurve.A).ToAsn1Object()]);
+    v.Add([TX9FieldElement.Create(Fcurve.B).ToAsn1Object()]);
+  end;
+
+  if (FSeed <> Nil) then
+  begin
+    v.Add([TDerBitString.Create(FSeed)]);
+  end;
+
+  result := TDerSequence.Create(v);
+end;
+
+end.

+ 308 - 0
CryptoLib/src/Asn1/X9/ClpX9ECParameters.pas

@@ -0,0 +1,308 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpX9ECParameters;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpCryptoLibTypes,
+  ClpBigInteger,
+  ClpIPolynomialExtensionField,
+  ClpIProxiedInterface,
+  ClpIX9ECPoint,
+  ClpAsn1OctetString,
+  ClpIECInterface,
+  ClpAsn1Encodable,
+  ClpDerInteger,
+  ClpDerSequence,
+  ClpAsn1Sequence,
+  ClpIAsn1Sequence,
+  ClpIDerInteger,
+  ClpX9ECPoint,
+  ClpIAsn1OctetString,
+  ClpECAlgorithms,
+  ClpX9Curve,
+  ClpIX9Curve,
+  ClpX9FieldID,
+  ClpIX9FieldID,
+  ClpAsn1EncodableVector,
+  ClpIAsn1EncodableVector,
+  ClpIX9ECParameters;
+
+resourcestring
+  SUnSupportedCurveOne = 'Only trinomial and pentomial curves are supported';
+  SUnSupportedCurveTwo = '"curve" is of an unsupported type';
+  SBadVersion = 'Bad Version in X9ECParameters';
+
+type
+  /// **
+  // * ASN.1 def for Elliptic-Curve ECParameters structure. See
+  // * X9.62, for further details.
+  // */
+  TX9ECParameters = class sealed(TAsn1Encodable, IX9ECParameters)
+
+  strict private
+  var
+    FfieldID: IX9FieldID;
+    Fcurve: IECCurve;
+    Fg: IX9ECPoint;
+    Fn, Fh: TBigInteger;
+    Fseed: TCryptoLibByteArray;
+
+    function GetCurve: IECCurve; inline;
+    function GetG: IECPoint; inline;
+    function GetH: TBigInteger; inline;
+    function GetN: TBigInteger; inline;
+    function GetBaseEntry: IX9ECPoint; inline;
+    function GetCurveEntry: IX9Curve; inline;
+    function GetFieldIDEntry: IX9FieldID; inline;
+
+  public
+
+    constructor Create(seq: IAsn1Sequence); overload;
+    constructor Create(curve: IECCurve; g: IECPoint; n: TBigInteger); overload;
+    constructor Create(curve: IECCurve; g: IX9ECPoint;
+      n, h: TBigInteger); overload;
+    constructor Create(curve: IECCurve; g: IECPoint;
+      n, h: TBigInteger); overload;
+    constructor Create(curve: IECCurve; g: IECPoint; n, h: TBigInteger;
+      seed: TCryptoLibByteArray); overload;
+    constructor Create(curve: IECCurve; g: IX9ECPoint; n, h: TBigInteger;
+      seed: TCryptoLibByteArray); overload;
+
+    property curve: IECCurve read GetCurve;
+    property g: IECPoint read GetG;
+    property n: TBigInteger read GetN;
+    property h: TBigInteger read GetH;
+    property CurveEntry: IX9Curve read GetCurveEntry;
+    property FieldIDEntry: IX9FieldID read GetFieldIDEntry;
+    property BaseEntry: IX9ECPoint read GetBaseEntry;
+
+    function GetSeed(): TCryptoLibByteArray;
+
+    function ToAsn1Object(): IAsn1Object; override;
+
+    class function GetInstance(obj: TObject): IX9ECParameters; static;
+
+  end;
+
+implementation
+
+{ TX9ECParameters }
+
+constructor TX9ECParameters.Create(curve: IECCurve; g: IX9ECPoint;
+  n, h: TBigInteger);
+begin
+  Create(curve, g, n, h, Nil);
+end;
+
+constructor TX9ECParameters.Create(curve: IECCurve; g: IECPoint;
+  n: TBigInteger);
+begin
+  Create(curve, g, n, Default (TBigInteger), Nil);
+end;
+
+constructor TX9ECParameters.Create(seq: IAsn1Sequence);
+var
+  x9c: IX9Curve;
+  p: TObject;
+  ecPoint: IX9ECPoint;
+begin
+  Inherited Create();
+  if ((not(Supports(seq[0], IDerInteger))) or
+    (not(seq[0] as IDerInteger).Value.Equals(TBigInteger.One))) then
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SBadVersion);
+  end;
+
+  x9c := TX9Curve.Create(TX9FieldID.GetInstance(seq[1] as TAsn1Sequence),
+    TAsn1Sequence.GetInstance(seq[2] as TAsn1Sequence));
+
+  Fcurve := x9c.curve;
+  p := seq[3] as TAsn1Sequence;
+
+  ecPoint := p as TX9ECPoint;
+  if (ecPoint <> Nil) then
+  begin
+    Fg := ecPoint;
+  end
+  else
+  begin
+    Fg := TX9ECPoint.Create(curve, p as TAsn1OctetString);
+  end;
+
+  Fn := (seq[4] as IDerInteger).Value;
+  Fseed := x9c.GetSeed();
+
+  if (seq.Count = 6) then
+  begin
+
+    Fh := (seq[5] as IDerInteger).Value;
+  end;
+end;
+
+constructor TX9ECParameters.Create(curve: IECCurve; g: IX9ECPoint;
+  n, h: TBigInteger; seed: TCryptoLibByteArray);
+var
+  exponents: TCryptoLibInt32Array;
+  Field: IPolynomialExtensionField;
+begin
+  Inherited Create();
+  Fcurve := curve;
+  Fg := g;
+  Fn := n;
+  Fh := h;
+  Fseed := seed;
+
+  if (TECAlgorithms.IsFpCurve(curve)) then
+  begin
+    FfieldID := TX9FieldID.Create(curve.Field.Characteristic);
+  end
+  else if (TECAlgorithms.IsF2mCurve(curve)) then
+  begin
+    Field := curve.Field as IPolynomialExtensionField;
+    exponents := Field.MinimalPolynomial.GetExponentsPresent();
+    if (System.Length(exponents) = 3) then
+    begin
+      FfieldID := TX9FieldID.Create(exponents[2], exponents[1]);
+    end
+    else if (System.Length(exponents) = 5) then
+    begin
+      FfieldID := TX9FieldID.Create(exponents[4], exponents[1], exponents[2],
+        exponents[3]);
+    end
+    else
+    begin
+
+      raise EArgumentCryptoLibException.CreateRes(@SUnSupportedCurveOne);
+    end
+  end
+  else
+  begin
+    raise EArgumentCryptoLibException.CreateRes(@SUnSupportedCurveTwo);
+
+  end;
+end;
+
+constructor TX9ECParameters.Create(curve: IECCurve; g: IECPoint;
+  n, h: TBigInteger; seed: TCryptoLibByteArray);
+begin
+  Create(curve, TX9ECPoint.Create(g), n, h, seed)
+end;
+
+constructor TX9ECParameters.Create(curve: IECCurve; g: IECPoint;
+  n, h: TBigInteger);
+begin
+  Create(curve, g, n, h, Nil);
+end;
+
+function TX9ECParameters.GetBaseEntry: IX9ECPoint;
+begin
+  Result := Fg;
+end;
+
+function TX9ECParameters.GetCurve: IECCurve;
+begin
+  Result := Fcurve;
+end;
+
+function TX9ECParameters.GetCurveEntry: IX9Curve;
+begin
+  Result := TX9Curve.Create(Fcurve, Fseed);
+end;
+
+function TX9ECParameters.GetFieldIDEntry: IX9FieldID;
+begin
+  Result := FfieldID;
+end;
+
+function TX9ECParameters.GetG: IECPoint;
+begin
+  Result := Fg.Point;
+end;
+
+function TX9ECParameters.GetH: TBigInteger;
+begin
+  Result := Fh;
+end;
+
+class function TX9ECParameters.GetInstance(obj: TObject): IX9ECParameters;
+var
+  instance: IX9ECParameters;
+begin
+  instance := obj as TX9ECParameters;
+  if (instance <> Nil) then
+  begin
+    Result := instance;
+    Exit;
+  end;
+
+  if (obj <> Nil) then
+  begin
+    Result := TX9ECParameters.Create(TAsn1Sequence.GetInstance(obj));
+    Exit;
+  end;
+
+  Result := Nil;
+end;
+
+function TX9ECParameters.GetN: TBigInteger;
+begin
+  Result := Fn;
+end;
+
+function TX9ECParameters.GetSeed: TCryptoLibByteArray;
+begin
+  Result := Fseed;
+end;
+
+/// * *
+// * Produce an object suitable for an Asn1OutputStream.
+// * <pre>
+// *  ECParameters ::= Sequence {
+// *      version         Integer { ecpVer1(1) } (ecpVer1),
+// *      fieldID         FieldID {{FieldTypes}},
+// *      curve           X9Curve,
+// *      base            X9ECPoint,
+// *      order           Integer,
+// *      cofactor        Integer OPTIONAL
+// *  }
+// * </pre>
+// */
+
+function TX9ECParameters.ToAsn1Object: IAsn1Object;
+var
+  v: IAsn1EncodableVector;
+begin
+
+  v := TAsn1EncodableVector.Create([TDerInteger.Create(TBigInteger.One),
+    FfieldID, TX9Curve.Create(Fcurve, Fseed), Fg, TDerInteger.Create(Fn)]);
+
+  if (Fh.IsInitialized) then
+  begin
+    v.Add([TDerInteger.Create(Fh)]);
+  end;
+
+  Result := TDerSequence.Create(v);
+
+end;
+
+end.

+ 81 - 0
CryptoLib/src/Asn1/X9/ClpX9ECParametersHolder.pas

@@ -0,0 +1,81 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpX9ECParametersHolder;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SyncObjs,
+  ClpIX9ECParameters,
+  ClpIX9ECParametersHolder;
+
+type
+  TX9ECParametersHolder = class abstract(TInterfacedObject,
+    IX9ECParametersHolder)
+
+  strict private
+    Fparameters: IX9ECParameters;
+    function GetParameters: IX9ECParameters; inline;
+
+    class var
+
+      FLock: TCriticalSection;
+
+    class constructor CreateX9ECParametersHolder();
+    class destructor DestroyX9ECParametersHolder();
+
+  strict protected
+    function CreateParameters(): IX9ECParameters; virtual; abstract;
+
+  public
+    property Parameters: IX9ECParameters read GetParameters;
+
+  end;
+
+implementation
+
+{ TX9ECParametersHolder }
+
+class constructor TX9ECParametersHolder.CreateX9ECParametersHolder;
+begin
+  FLock := TCriticalSection.Create;
+end;
+
+class destructor TX9ECParametersHolder.DestroyX9ECParametersHolder;
+begin
+  FLock.Free;
+end;
+
+function TX9ECParametersHolder.GetParameters: IX9ECParameters;
+begin
+  FLock.Acquire;
+  try
+    if (Fparameters = Nil) then
+    begin
+      Fparameters := CreateParameters();
+    end;
+
+  finally
+    FLock.Release;
+  end;
+  Result := Fparameters;
+end;
+
+end.

+ 129 - 0
CryptoLib/src/Asn1/X9/ClpX9ECPoint.pas

@@ -0,0 +1,129 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                    Copyright (c) 2018 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://sphere10.com) for sponsoring        * }
+{ *                        the development of this library                          * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpX9ECPoint;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpCryptoLibTypes,
+  ClpDerOctetString,
+  ClpIAsn1OctetString,
+  ClpIProxiedInterface,
+  ClpIECInterface,
+  ClpIX9ECPoint,
+  ClpAsn1Encodable;
+
+type
+  // /**
+  // * class for describing an ECPoint as a Der object.
+  // */
+  TX9ECPoint = class sealed(TAsn1Encodable, IX9ECPoint)
+
+  strict private
+  var
+    Fencoding: IAsn1OctetString;
+    Fc: IECCurve;
+    Fp: IECPoint;
+
+    function GetIsPointCompressed: Boolean; inline;
+    function GetPoint: IECPoint; inline;
+
+  public
+
+    constructor Create(p: IECPoint); overload;
+    constructor Create(p: IECPoint; compressed: Boolean); overload;
+    constructor Create(c: IECCurve; encoding: TCryptoLibByteArray); overload;
+    constructor Create(c: IECCurve; s: IAsn1OctetString); overload;
+
+    property Point: IECPoint read GetPoint;
+    property IsPointCompressed: Boolean read GetIsPointCompressed;
+
+    function GetPointEncoding(): TCryptoLibByteArray; inline;
+
+    // /**
+    // * Produce an object suitable for an Asn1OutputStream.
+    // * <pre>
+    // *  ECPoint ::= OCTET STRING
+    // * </pre>
+    // * <p>
+    // * Octet string produced using ECPoint.GetEncoded().</p>
+    // */
+    function ToAsn1Object(): IAsn1Object; override;
+
+  end;
+
+implementation
+
+{ TX9ECPoint }
+
+constructor TX9ECPoint.Create(c: IECCurve; encoding: TCryptoLibByteArray);
+begin
+  inherited Create();
+  Fc := c;
+  Fencoding := TDerOctetString.Create(System.Copy(encoding));
+end;
+
+constructor TX9ECPoint.Create(p: IECPoint; compressed: Boolean);
+begin
+  inherited Create();
+  Fp := p.Normalize();
+  Fencoding := TDerOctetString.Create(p.GetEncoded(compressed));
+end;
+
+constructor TX9ECPoint.Create(p: IECPoint);
+begin
+  Create(p, false);
+end;
+
+constructor TX9ECPoint.Create(c: IECCurve; s: IAsn1OctetString);
+begin
+  Create(c, s.GetOctets());
+end;
+
+function TX9ECPoint.GetPointEncoding(): TCryptoLibByteArray;
+begin
+  Result := Fencoding.GetOctets();
+end;
+
+function TX9ECPoint.GetIsPointCompressed: Boolean;
+var
+  octets: TCryptoLibByteArray;
+begin
+  octets := Fencoding.GetOctets();
+  Result := (octets <> Nil) and (System.Length(octets) > 0) and
+    ((octets[0] = 2) or (octets[0] = 3));
+end;
+
+function TX9ECPoint.GetPoint: IECPoint;
+begin
+  if (Fp = Nil) then
+  begin
+    Fp := Fc.DecodePoint(Fencoding.GetOctets()).Normalize();
+  end;
+
+  Result := Fp;
+end;
+
+function TX9ECPoint.ToAsn1Object: IAsn1Object;
+begin
+  Result := Fencoding;
+end;
+
+end.

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio